Source code for easier68k.core.opcodes.trap

from ..opcodes.opcode import Opcode
from ...simulator.m68k import M68K
from ..util.parsing import parse_assembly_parameter, from_str_util
from ..util.split_bits import split_bits
from ..models.trap_vector import TrapVector
from ..enum.trap_task import TrapTask
from ..enum.register import Register
from ..enum.op_size import OpSize
from ..util.input import get_input
from ..enum.trap_vector import TrapVectors

class Trap(Opcode): # forward declaration
    pass

[docs]class Trap(Opcode): """ TRAP Operation: Trap 1 → S-Bit of SR *SSP – 2 → SSP; Format/Offset → (SSP); SSP – 4 → SSP; PC → (SSP); SSP – 2 → SSP; SR → (SSP); Vector Address → PC *The MC68000 and MC68008 do not write vector offset or format code to the system stack. Syntax: TRAP # < vector > Attributes: Unsized Description: Causes a TRAP # < vector > exception. The instruction adds the immediate operand (vector) of the instruction to 32 to obtain the vector number. The range of vector values is 0 – 15, which provides 16 vectors. Condition Codes: Not affected. """ def __init__(self, param: TrapVectors): assert isinstance(param, TrapVectors) # max size is 4 bit assert 0 <= param.value <= 0b1111 self.trpVector = param # flags to use so that this can be tested easier self.use_debug_input = False self.debug_input = 'debug input'
[docs] def assemble(self) -> bytes: """ Assembles this opcode into hex to be inserted into memory :return: """ # the bottom 4 bits are set to 0 value = 0b0100111001000000 # mask the task to fit in 4 bits masked = self.trpVector.value & 0b1111 # add the masked bits value |= masked # convert this value into a bytearray of len = 1 word return value.to_bytes(2, byteorder='big', signed=False)
[docs] def execute(self, simulator: M68K): """ Executes this command in a simulator :param simulator: :return: """ if self.trpVector.value == TrapVectors.IO: task = TrapTask(simulator.get_register(Register.D0).get_value_unsigned()) if task is TrapTask.DisplayNullTermString: # get the value of A1 location = simulator.get_register(Register.A1).get_value_unsigned() value = simulator.memory.get(1, location).get_value_unsigned() while value != 0: print(chr(value), end='') location += 1 value = simulator.memory.get(1, location).get_value_unsigned() if task is TrapTask.DisplayNullTermStringWithCRLF: # get the value of A1 location = simulator.get_register(Register.A1).get_value_unsigned() value = simulator.memory.get(1, location).get_value_unsigned() while value != 0: print(chr(value), end='') location += 1 value = simulator.memory.get(1, location).get_value_unsigned() print('') if task is TrapTask.DisplayNullTermStringAndReadNumberFromKeyboard: # get the value of A1 location = simulator.get_register(Register.A1).get_value_unsigned() value = simulator.memory.get(1, location).get_value_unsigned() while value != 0: print(chr(value), end='') location += 1 value = simulator.memory.get(1, location).get_value_unsigned() # read a number from the keyboard if task is TrapTask.DisplaySignedNumber: # get the value of D1.L value = simulator.get_register(Register.D1) print(value.get_value_signed(), end='') if task is TrapTask.DisplaySingleCharacter: # get the value of D1.B value = simulator.get_register(Register.D1).get_value_unsigned() # mask it v = 0xFF & value print(chr(v), end='') if task is TrapTask.Terminate: # same as SIMHALT simulator.halt() # increment the program counter simulator.increment_program_counter(OpSize.WORD.value)
def __str__(self): return 'TRAP {}'.format(self.trpVector)
[docs] @classmethod def from_str(cls, command: str, parameters: str): """ Parses a TRAP command from text >>> str(Trap.from_str('TRAP', '#15')) 'TRAP 15' >>> str(Trap.from_str('trap', '#%1111')) 'TRAP 15' :param command: :param parameters: :return: """ assert command.upper() == 'TRAP' # dont care about the size and parts values size, params, parts = from_str_util(command, parameters) assert len(params) == 1 return cls(TrapVectors.parse(params[0]))
[docs] @classmethod def disassemble_instruction(cls, data: bytearray) -> Opcode: """ Parses raw data into an instance of Trap :param data: :return: """ if len(data) < 2: return None # len must be at least 1 word first_word = int.from_bytes(data[0:2], byteorder='big') [opcode_bin, task_num] = split_bits( first_word, [12, 4]) # didnt match if opcode_bin != 0b010011100100: return None # dont need to check that the size is valid, within 4 bits is ok # though some may not do anything return cls(TrapVectors(task_num))
[docs] @classmethod def is_valid(cls, command: str, parameters: str) -> (bool, list): """ Tests whether the given command is valid :param command: :param parameters: :return: """ # dont care about the size and parts values size, params, parts = from_str_util(command, parameters) # have it parse, but not return value, just # check that it works try: TrapVector.parse(params[0]) except: return False return (command.strip().upper() == 'TRAP' and len(params) == 1, []) # TODO: Convert to actually return issues
[docs] @classmethod def get_word_length(cls, command: str, parameters: str) -> int: """ Get the length in words that this will take up in memory :param command: :param parameters: :return: """ # always 1 return 1
[docs] @classmethod def command_matches(cls, command: str) -> bool: """ Checks if a command string matches :param command: :return: """ return command.upper() == 'TRAP'