Source code for easier68k.core.enum.ea_mode_bin

"""
EA Mode Binary Enum
Represents binary translations for various EA modes
"""
from .ea_mode import EAMode
from ..models.assembly_parameter import AssemblyParameter
from enum import IntEnum
from .op_size import OpSize


[docs]class EAModeBinary(IntEnum): # Data register direct MODE_DRD = 0b000 # Address register direct MODE_ARD = 0b001 # Address register indirect MODE_ARI = 0b010 # Address register indirect + post increment MODE_ARIPI = 0b011 # Address register indirect + pre decrement MODE_ARIPD = 0b100 # Immediate MODE_IMM = 0b111 REGISTER_IMM = 0b100 # Absolute long address MODE_ALA = 0b111 REGISTER_ALA = 0b001 # Absolute word address MODE_AWA = 0b111 REGISTER_AWA = 0b000
# currently missing the offset modes VALID_DEST_EA_MODES = [EAModeBinary.MODE_DRD, EAModeBinary.MODE_ARI, EAModeBinary.MODE_ARIPI, EAModeBinary.MODE_ARIPD, EAModeBinary.MODE_ALA, EAModeBinary.MODE_AWA] # currently missing the offset modes VALID_SRC_EA_MODES = VALID_DEST_EA_MODES + [EAModeBinary.MODE_ARD, EAModeBinary.MODE_IMM] # what the hell should I name this? # it's the valid destination registers for the 111 mode # currently missing the offset modes VALID_DEST_EA_111_REGISTERS = [EAModeBinary.REGISTER_ALA, EAModeBinary.REGISTER_AWA] # what the hell should I name this? # it's the valid source registers for the 111 mode # currently missing the offset modes VALID_SRC_EA_111_REGISTERS = VALID_DEST_EA_111_REGISTERS + [EAModeBinary.REGISTER_IMM]
[docs]def get_mode_and_register_values(mode: EAMode) -> (int, int): """ Gets the integer value representing the mode and register values for a given EAMode for use in the assembly process :param mode: EAMode to produce binary from :return:(the integer value of the assembled mode bits, the integer value of the assembled register bits) """ return_mode = 0 return_register = 0 # get the return value for the register if mode.mode in [EAMode.DRD, EAMode.ARD, EAMode.ARI, EAMode.ARIPI, EAMode.ARIPD, EAMode.ARIPD]: return_register = mode.data elif mode.mode == EAMode.IMM: return_register = 0b100 elif mode.mode == EAMode.ALA: return_register = 0b001 elif mode.mode == EAMode.ALA: return_register = 0b000 # get the return value for the mode by converting EAMode into EAModeBinary # this should instead a util method of EAMode if mode.mode == EAMode.DRD: return_mode = EAModeBinary.MODE_DRD if mode.mode == EAMode.ARD: return_mode = EAModeBinary.MODE_ARD if mode.mode == EAMode.ARI: return_mode = EAModeBinary.MODE_ARI if mode.mode == EAMode.ARIPI: return_mode = EAModeBinary.MODE_ARIPI if mode.mode == EAMode.ARIPD: return_mode = EAModeBinary.MODE_ARIPD if mode.mode == EAMode.IMM: return_mode = EAModeBinary.MODE_IMM if mode.mode == EAMode.ALA: return_mode = EAModeBinary.MODE_ALA if mode.mode == EAMode.AWA: return_mode = EAModeBinary.MODE_AWA # return both return return_mode, return_register
[docs]def parse_from_ea_mode_modefirst(mode: EAMode) -> int: """ Parses binary EA mode text from an EAMode class, returning the mode data first. :param mode: The EAMode to produce binary from :return: The parsed binary """ mode, reg = get_mode_and_register_values(mode) return mode << 3 | reg
[docs]def parse_from_ea_mode_regfirst(mode: EAMode) -> int: """ Parses binary EA mode text from an EAMode class, returning the Xn data first. :param mode: The EAMode to produce binary from :return: The parsed binary """ mode, reg = get_mode_and_register_values(mode) return reg << 3 | mode
[docs]def parse_ea_from_binary(mode: int, register: int, size: OpSize, is_source: bool, data : bytearray) -> (EAMode, int): """ Takes in the paramaters and returns a newly constructed EAMode and the amount of words of data that it used. If the paramaters were illegal in any way then (None, 0) is returned Test that it handles source and destination behaviors properly >>> parse_ea_from_binary(EAModeBinary.MODE_IMM, EAModeBinary.REGISTER_IMM, OpSize.BYTE, False, bytearray.fromhex('A0')) (None, 0) >>> m = parse_ea_from_binary(EAModeBinary.MODE_IMM, EAModeBinary.REGISTER_IMM, OpSize.BYTE, True, bytearray.fromhex('A0')) >>> str(m[0]) 'EA Mode: EAMode.IMM, Data: 160' >>> m[1] 1 >>> m = parse_ea_from_binary(EAModeBinary.MODE_DRD, 0b010, OpSize.WORD, True, bytearray()) >>> str(m[0]) 'EA Mode: EAMode.DRD, Data: 2' >>> m[1] 0 >>> m = parse_ea_from_binary(EAModeBinary.MODE_ARI, 0b110, OpSize.LONG, True, bytearray()) >>> str(m[0]) 'EA Mode: EAMode.ARI, Data: 6' >>> m[1] 0 >>> m = parse_ea_from_binary(EAModeBinary.MODE_ALA, EAModeBinary.REGISTER_ALA, OpSize.LONG, False, bytearray.fromhex('00011000')) >>> str(m[0]) 'EA Mode: EAMode.ALA, Data: 69632' >>> m[1] 2 :param mode: the binary mode bits retrieved from the instruction :param register: the binary register bits retrieved from the instruction :param size: the alphabetical size (i.e. one of 'BLW') :param is_source: is this the source or destination ea? :param data: extra data that follows after the command that might be needed :return: an EAMode constructed from the given parameters and how many words were used from data """ bytesUsed = 0 # check source mode if is_source and not mode in VALID_SRC_EA_MODES: return (None, 0) if not is_source and not mode in VALID_DEST_EA_MODES: return (None, 0) ea_data = register # these only differ when mode is 0b111 ea_mode = mode # check source register if mode == 0b111: if is_source and not register in VALID_SRC_EA_111_REGISTERS: return (None, 0) if not is_source and not register in VALID_DEST_EA_111_REGISTERS: return (None, 0) # handle the three special cases for when mode is 7 if register == EAModeBinary.REGISTER_AWA: ea_data = int.from_bytes(data[bytesUsed:bytesUsed+2], 'big') bytesUsed += 2 ea_mode = 7 elif register == EAModeBinary.REGISTER_ALA: ea_data = int.from_bytes(data[bytesUsed:bytesUsed+4], 'big') bytesUsed += 4 ea_mode = 6 elif is_source and register == EAModeBinary.REGISTER_IMM: if size in [OpSize.WORD, OpSize.BYTE]: # TODO: Do we check for bytes that the left byte is all # zeros, or do we do this where we assume the assembler is right ea_data = int.from_bytes(data[bytesUsed:bytesUsed+2], 'big') bytesUsed += 2 else: #must be L ea_data = int.from_bytes(data[bytesUsed:bytesUsed+4], 'big') bytesUsed += 4 ea_mode = 5 else: return (None, 0) # map the ea mode integer to the enum if ea_mode == 0: ea_mode = EAMode.DRD elif ea_mode == 1: ea_mode = EAMode.ARD elif ea_mode == 2: ea_mode = EAMode.ARI elif ea_mode == 3: ea_mode = EAMode.ARIPI elif ea_mode == 4: ea_mode = EAMode.ARIPD elif ea_mode == 5: ea_mode = EAMode.IMM elif ea_mode == 6: ea_mode = EAMode.ALA elif ea_mode == 7: ea_mode = EAMode.AWA return (AssemblyParameter(ea_mode, ea_data), bytesUsed//2)