def read_word(self, pos, silent=False): ''' Read word from device registry or device status table ''' if self.system_addresses[ 'device_registry_address'] <= pos < self.system_addresses[ 'device_registry_address'] + self.system_addresses[ 'device_registry_size'] - 1: relative_pos = pos - self.system_addresses[ 'device_registry_address'] value = (self._device_registry[relative_pos] << 8) + self._device_registry[relative_pos + 1] elif self.system_addresses[ 'device_status_table_address'] <= pos < self.system_addresses[ 'device_status_table_address'] + self.system_addresses[ 'device_status_table_size'] - 1: relative_pos = pos - self.system_addresses[ 'device_status_table_address'] value = (self._device_status_table[relative_pos] << 8) + self._device_status_table[relative_pos + 1] else: raise SegfaultError( 'Segmentation fault when trying to read word at {}'.format( utils.word_to_str(pos))) if not silent: logger.debug('Read word %s from %s.', utils.word_to_str(value), utils.word_to_str(pos)) return value
def write_word(self, pos, value, silent=False): ''' Write word to Virtual RAM at position `pos` ''' if pos < self.addresses['device_controller']['first'] or pos > self.addresses['device_controller']['last'] - 1: raise SegfaultError('Segmentation fault when trying to write word at {}'.format(utils.word_to_str(pos))) self.device_controller.write_word(pos, value, silent=silent) if not silent: logger.debug('Written word %s to %s.', utils.word_to_str(value), utils.word_to_str(pos))
def read_word(self, pos, silent=False): ''' Read word from Virtual RAM at position `pos` ''' if pos < self.addresses['device_controller']['first'] or pos > self.addresses['device_controller']['last'] - 1: raise SegfaultError('Segmentation fault when trying to read word at {}'.format(utils.word_to_str(pos))) value = self.device_controller.read_word(pos, silent=silent) if not silent: logger.debug('Read word %s from %s.', utils.word_to_str(value), utils.word_to_str(pos)) return value
def write_word(self, pos, value, silent=False): ''' Write word to RAM at position `pos` ''' if pos < 0 or pos > self.size - 2: raise SegfaultError('Segmentation fault when trying to write word at {}'.format(utils.word_to_str(pos))) self._content[pos] = utils.get_high(value) self._content[pos + 1] = utils.get_low(value) if not silent: logger.debug('Written word %s to %s.', utils.word_to_str(value), utils.word_to_str(pos))
def read_word(self, pos, silent=False): ''' Read word from RAM at position `pos` ''' if pos < 0 or pos > self.size - 2: raise SegfaultError('Segmentation fault when trying to read word at {}'.format(utils.word_to_str(pos))) value = (self._content[pos] << 8) + self._content[pos + 1] if not silent: logger.debug('Read word %s from %s.', utils.word_to_str(value), utils.word_to_str(pos)) return value
def write_byte(self, pos, value, silent=False): ''' Write byte to RAM at position `pos` ''' if pos < 0 or pos > self.size - 1: raise SegfaultError( 'Segmentation fault when trying to write byte at {}'.format( utils.word_to_str(pos))) self._content[pos] = value if not silent: logger.debug('Written byte %s to %s.', utils.byte_to_str(value), utils.word_to_str(pos))
def push_word(self, value, silent=False): ''' Push word on stack ''' sp = self._registers.get_register('SP', silent=True) if sp < 2: raise StackOverflowError('Stack overflow: {}'.format( utils.word_to_str(sp))) self._ram.write_word(sp - 1, value, silent=True) if not silent: logger.debug('Pushed word %s', utils.word_to_str(value)) self._registers.set_register('SP', sp - 2, silent=True)
def pop_word(self, silent=False): ''' Pop word from stack ''' sp = self._registers.get_register('SP', silent=True) if sp >= self._bottom_of_stack - 1: raise StackUnderflowError('Stack underflow: {}'.format( utils.word_to_str(sp))) self._registers.set_register('SP', sp + 2, silent=True) value = self._ram.read_word(sp + 2 - 1, silent=True) if not silent: logger.debug('Popped word %s', utils.word_to_str(value)) return value
def read_word(self, pos, silent=False): ''' Read word from RAM at position `pos` ''' if pos < 0 or pos > self.size - 2: raise SegfaultError( 'Segmentation fault when trying to read word at {}'.format( utils.word_to_str(pos))) value = (self._content[pos] << 8) + self._content[pos + 1] if not silent: logger.debug('Read word %s from %s.', utils.word_to_str(value), utils.word_to_str(pos)) return value
def write_word(self, pos, value, silent=False): ''' Write word to RAM at position `pos` ''' if pos < 0 or pos > self.size - 2: raise SegfaultError( 'Segmentation fault when trying to write word at {}'.format( utils.word_to_str(pos))) self._content[pos] = utils.get_high(value) self._content[pos + 1] = utils.get_low(value) if not silent: logger.debug('Written word %s to %s.', utils.word_to_str(value), utils.word_to_str(pos))
def write_byte(self, pos, value, silent=False): ''' Write byte to Virtual RAM at position `pos` ''' if pos < self.addresses['device_controller'][ 'first'] or pos > self.addresses['device_controller']['last']: raise SegfaultError( 'Segmentation fault when trying to write byte at {}'.format( utils.word_to_str(pos))) self.device_controller.write_byte(pos, value, silent=silent) if not silent: logger.debug('Written byte %s to %s.', utils.byte_to_str(value), utils.word_to_str(pos))
def operand_to_str(operand): ''' Get the string representation of an operand ''' if operand.optype == OpType.EXTENDED: raise InvalidOperandError('Extended optype not supported yet.') if operand.optype == OpType.VALUE: if operand.oplen == OpLen.BYTE: return utils.byte_to_str(operand.opvalue) else: return utils.word_to_str(operand.opvalue) if operand.optype == OpType.ADDRESS: if operand.opvalue < 0: return '^-{}'.format(utils.word_to_str(-operand.opvalue)) return '^{}'.format(utils.word_to_str(operand.opvalue)) if operand.optype == OpType.REGISTER: return operand.opreg if operand.oplen == OpLen.BYTE: oplen_str = 'B' else: oplen_str = '' if operand.optype == OpType.ABS_REF_REG: if operand.opoffset == 0: opoffset_str = '' elif operand.opoffset > 0: opoffset_str = '+{}'.format(utils.byte_to_str(operand.opoffset)) else: opoffset_str = '-{}'.format(utils.byte_to_str(-operand.opoffset)) return '[{}{}]{}'.format( operand.opreg, opoffset_str, oplen_str, ) if operand.opbase < 0: opbase_str = '-{}'.format(utils.word_to_str(-operand.opbase)) else: opbase_str = '{}'.format(utils.word_to_str(operand.opbase)) if operand.optype == OpType.REL_REF_WORD_BYTE: opoffset_str = '+{}'.format(utils.byte_to_str(operand.opoffset)) elif operand.optype == OpType.REL_REF_WORD_REG: opoffset_str = '+{}'.format(operand.opreg) else: opoffset_str = '' return '[{}{}]{}'.format( opbase_str, opoffset_str, oplen_str, )
def read_byte(self, pos, silent=False): ''' Read byte from Virtual RAM at position `pos` ''' if pos < self.addresses['device_controller'][ 'first'] or pos > self.addresses['device_controller']['last']: raise SegfaultError( 'Segmentation fault when trying to read byte at {}'.format( utils.word_to_str(pos))) value = self.device_controller.read_byte(pos, silent=silent) if not silent: logger.debug('Read byte %s from %s.', utils.byte_to_str(value), utils.word_to_str(pos)) return value
def operand_to_str(operand): ''' Get the string representation of an operand ''' if operand.optype == OpType.EXTENDED: raise InvalidOperandError('Extended optype not supported yet.') if operand.optype == OpType.VALUE: if operand.oplen == OpLen.BYTE: return utils.byte_to_str(operand.opvalue) else: return utils.word_to_str(operand.opvalue) if operand.optype == OpType.ADDRESS: if operand.opvalue < 0: return '^-{}'.format(utils.word_to_str(-operand.opvalue)) return '^{}'.format(utils.word_to_str(operand.opvalue)) if operand.optype == OpType.REGISTER: return operand.opreg if operand.oplen == OpLen.BYTE: oplen_str = 'B' else: oplen_str = '' if operand.optype == OpType.ABS_REF_REG: if operand.opoffset == 0: opoffset_str = '' elif operand.opoffset > 0: opoffset_str = '+{}'.format(utils.byte_to_str(operand.opoffset)) else: opoffset_str = '-{}'.format(utils.byte_to_str(-operand.opoffset)) return '[{}{}]{}'.format( operand.opreg, opoffset_str, oplen_str, ) if operand.opbase < 0: opbase_str = '-{}'.format(utils.word_to_str(-operand.opbase)) else: opbase_str = '{}'.format(utils.word_to_str(operand.opbase)) if operand.optype == OpType.REL_REF_WORD_BYTE: opoffset_str = '+{}'.format(utils.byte_to_str(operand.opoffset)) elif operand.optype == OpType.REL_REF_WORD_REG: opoffset_str = '+{}'.format(operand.opreg) else: opoffset_str = '' return '[{}{}]{}'.format( opbase_str, opoffset_str, oplen_str, )
def read_word(self, pos, silent=False): ''' Read word from device registry or device status table ''' if self.system_addresses['device_registry_address'] <= pos < self.system_addresses['device_registry_address'] + self.system_addresses['device_registry_size'] - 1: relative_pos = pos - self.system_addresses['device_registry_address'] value = (self._device_registry[relative_pos] << 8) + self._device_registry[relative_pos + 1] elif self.system_addresses['device_status_table_address'] <= pos < self.system_addresses['device_status_table_address'] + self.system_addresses['device_status_table_size'] - 1: relative_pos = pos - self.system_addresses['device_status_table_address'] value = (self._device_status_table[relative_pos] << 8) + self._device_status_table[relative_pos + 1] else: raise SegfaultError('Segmentation fault when trying to read word at {}'.format(utils.word_to_str(pos))) if not silent: logger.debug('Read word %s from %s.', utils.word_to_str(value), utils.word_to_str(pos)) return value
def _get_stack(self): bottom_of_stack = self.cpu.system_addresses['bottom_of_stack'] first_address = max( self.cpu.registers.get_register('SP', silent=True) - 7, 0) length = bottom_of_stack - first_address + 1 return { 'first_address': utils.word_to_str(first_address), 'last_address': utils.word_to_str(bottom_of_stack), 'content': [ utils.byte_to_str(self.memory.read_byte(first_address + idx)) for idx in range(length) ], }
def write_word(self, pos, value, silent=False): ''' Cannot write to device registry device status table ''' raise SegfaultError( 'Segmentation fault when trying to write word at {}'.format( utils.word_to_str(pos)))
def run(self): '''Run instruction''' next_ip = self.do() if next_ip is None: next_ip = self.ip + self.opcode_length else: logger.debug('Jumped to %s', utils.word_to_str(next_ip)) return next_ip
def run(self): '''Run instruction''' next_ip = self.do() if next_ip is None: next_ip = self.ip + self.opcode_length else: logger.debug('Jumped to %s', utils.word_to_str(next_ip)) return next_ip
def _set_word_register(self, register_name, value, silent=False): if value < 0x0000 or value > 0xFFFF: raise InvalidRegisterValueError( 'Invalid register value: {}'.format(value)) self._registers[register_name] = value if not silent: logger.debug('Set register %s = %s', register_name, utils.word_to_str(value))
def write_byte(self, pos, value, silent=False): ''' Write byte to RAM at position `pos` ''' if pos < 0 or pos > self.size - 1: raise SegfaultError('Segmentation fault when trying to write byte at {}'.format(utils.word_to_str(pos))) self._content[pos] = value if not silent: logger.debug('Written byte %s to %s.', utils.byte_to_str(value), utils.word_to_str(pos))
def push_byte(self, value): ''' Push byte on stack ''' sp = self._registers.get_register('SP', silent=True) if sp < 1: raise StackOverflowError('Stack overflow: {}'.format( utils.word_to_str(sp))) self._ram.write_byte(sp, value, silent=True) logger.debug('Pushed byte %s', utils.byte_to_str(value)) self._registers.set_register('SP', sp - 1, silent=True)
def pop_byte(self): ''' Pop byte from stack ''' sp = self._registers.get_register('SP', silent=True) if sp >= self._bottom_of_stack: raise StackUnderflowError('Stack underflow: {}'.format( utils.word_to_str(sp))) self._registers.set_register('SP', sp + 1, silent=True) value = self._ram.read_byte(sp + 1, silent=True) logger.debug('Popped byte %s', utils.byte_to_str(value)) return value
def read_word(self, pos, silent=False): ''' Read word at position `pos` ''' if pos < self.ram_size - 1: return self.ram.read_word(pos, silent=silent) if pos == self.ram_size - 1: # cannot read word half from ram, half from virtual ram raise SegfaultError( 'Segmentation fault when trying to read word at {}'.format( utils.word_to_str(pos))) return self.virtual_ram.read_word(pos, silent=silent)
def _get_internal_state(self): registers = { name: utils.word_to_str( self.cpu.registers.get_register(name, silent=True)) for name in WORD_REGISTERS } registers['IP'] = utils.word_to_str(self.cpu.ip) registers['entry_point'] = utils.word_to_str( self.cpu.system_addresses['entry_point']) if self.cpu.last_ip is not None: last_instruction = self._get_instruction(self.cpu.last_ip) last_ip = utils.word_to_str(self.cpu.last_ip) else: last_instruction = None last_ip = None if self.cpu.shutdown: next_instruction = None next_ip = None else: next_instruction = self._get_instruction(self.cpu.ip) next_ip = utils.word_to_str(self.cpu.ip) return (HTTPStatus.OK, { 'registers': registers, 'stack': self._get_stack(), 'cpu': { 'halt': self.cpu.halt, 'shutdown': self.cpu.shutdown, 'last_instruction': last_instruction, 'last_ip': last_ip, 'next_instruction': next_instruction, 'next_ip': next_ip, }, 'clock': { 'cycle_count': self.clock.cycle_count, }, 'user_log': self._user_log, })
def write_word(self, pos, value, silent=False): ''' Write word at position `pos` ''' if pos < self.ram_size - 1: self.ram.write_word(pos, value, silent=silent) elif pos == self.ram_size - 1: # cannot write word half to ram, half to virtual ram raise SegfaultError( 'Segmentation fault when trying to read word at {}'.format( utils.word_to_str(pos))) else: self.virtual_ram.write_word(pos, value, silent=silent)
def read_byte(self, pos, silent=False): ''' Read byte from device registry or device status table ''' if self.system_addresses['device_registry_address'] <= pos < self.system_addresses['device_registry_address'] + self.system_addresses['device_registry_size']: value = self._device_registry[pos - self.system_addresses['device_registry_address']] elif self.system_addresses['device_status_table_address'] <= pos < self.system_addresses['device_status_table_address'] + self.system_addresses['device_status_table_size']: value = self._device_status_table[pos - self.system_addresses['device_status_table_address']] else: raise SegfaultError('Segmentation fault when trying to read byte at {}'.format(utils.word_to_str(pos))) if not silent: logger.debug('Read byte %s from %s.', utils.byte_to_str(value), utils.word_to_str(pos)) return value
def _get_memory(self, offset, length): if offset >= config.memory_size or offset < 0: return (HTTPStatus.BAD_REQUEST, { 'error': 'Cannot access memory beyond 0000-{}'.format( utils.word_to_str(config.memory_size - 1)), }) if offset + length > config.memory_size: length = config.memory_size - offset first_address = offset content = [] for idx in range(length): try: content.append( utils.byte_to_str( self.memory.read_byte(first_address + idx))) except SegfaultError: content.append(None) return (HTTPStatus.OK, { 'first_address': utils.word_to_str(first_address), 'last_address': utils.word_to_str(first_address + length - 1), 'content': content, })
def read_byte(self, pos, silent=False): ''' Read byte from device registry or device status table ''' if self.system_addresses[ 'device_registry_address'] <= pos < self.system_addresses[ 'device_registry_address'] + self.system_addresses[ 'device_registry_size']: value = self._device_registry[ pos - self.system_addresses['device_registry_address']] elif self.system_addresses[ 'device_status_table_address'] <= pos < self.system_addresses[ 'device_status_table_address'] + self.system_addresses[ 'device_status_table_size']: value = self._device_status_table[ pos - self.system_addresses['device_status_table_address']] else: raise SegfaultError( 'Segmentation fault when trying to read byte at {}'.format( utils.word_to_str(pos))) if not silent: logger.debug('Read byte %s from %s.', utils.byte_to_str(value), utils.word_to_str(pos)) return value
def get_register(self, register_name, silent=False): ''' Get register value ''' value = None hex_value = None if register_name in self._registers: value = self._registers[register_name] hex_value = utils.word_to_str(value) elif register_name in {'AL', 'BL', 'CL', 'DL'}: value = utils.get_low(self._registers[register_name[0] + 'X']) hex_value = utils.byte_to_str(value) elif register_name in {'AH', 'BH', 'CH', 'DH'}: value = utils.get_high(self._registers[register_name[0] + 'X']) hex_value = utils.byte_to_str(value) else: raise InvalidRegisterNameError('Invalid register name: {}'.format(register_name)) if not silent: logger.debug('Get register %s = %s', register_name, hex_value) return value
def get_register(self, register_name, silent=False): ''' Get register value ''' value = None hex_value = None if register_name in self._registers: value = self._registers[register_name] hex_value = utils.word_to_str(value) elif register_name in {'AL', 'BL', 'CL', 'DL'}: value = utils.get_low(self._registers[register_name[0] + 'X']) hex_value = utils.byte_to_str(value) elif register_name in {'AH', 'BH', 'CH', 'DH'}: value = utils.get_high(self._registers[register_name[0] + 'X']) hex_value = utils.byte_to_str(value) else: raise InvalidRegisterNameError( 'Invalid register name: {}'.format(register_name)) if not silent: logger.debug('Get register %s = %s', register_name, hex_value) return value
def _log_code(self): logger.debug('===CODE===') max_line_opcode_length = max( len(line_opcode) for line_number, opcode_pos, line_opcode, source_line, tokens in self.augmented_opcode ) if max_line_opcode_length > MAX_LINE_OPCODE_LENGTH: max_line_opcode_length = MAX_LINE_OPCODE_LENGTH for line_number, opcode_pos, line_opcode, source_line, tokens in self.augmented_opcode: line_label_names = [token.value for token in tokens if token.type == TokenType.LABEL] if not line_label_names and not line_opcode: continue logger.debug( ' '.join([ '{:4}'.format(line_number), utils.word_to_str(opcode_pos), ' '.join([utils.byte_to_str(op) for op in line_opcode]), ' ' if line_opcode else '', ' ' * (max_line_opcode_length - len(line_opcode)), source_line, ]) )
def _log_code(self): logger.debug('===CODE===') max_line_opcode_length = max( len(line_opcode) for line_number, opcode_pos, line_opcode, source_line, tokens in self.augmented_opcode) if max_line_opcode_length > MAX_LINE_OPCODE_LENGTH: max_line_opcode_length = MAX_LINE_OPCODE_LENGTH for line_number, opcode_pos, line_opcode, source_line, tokens in self.augmented_opcode: line_label_names = [ token.value for token in tokens if token.type == TokenType.LABEL ] if not line_label_names and not line_opcode: continue logger.debug(' '.join([ '{:4}'.format(line_number), utils.word_to_str(opcode_pos), ' '.join([utils.byte_to_str(op) for op in line_opcode]), ' ' if line_opcode else '', ' ' * (max_line_opcode_length - len(line_opcode)), source_line, ]))
def crash_dump(self): ''' Print crash dump ''' logger_crash_dump.error('### CRASH DUMP ###') # ip ip = self.cpu.ip logger_crash_dump.error('') logger_crash_dump.error('IP=%s', utils.word_to_str(ip)) logger_crash_dump.error( 'Entry point=%s', utils.word_to_str(self.cpu.system_addresses['entry_point'])) logger_crash_dump.error('Halt=%s', self.cpu.halt) # ram ram_page_size = 16 ram_page = (ip // ram_page_size) * ram_page_size logger_crash_dump.error('') logger_crash_dump.error('RAM:') for page_offset in range(-2, 3): offset = page_offset * ram_page_size if offset + ram_page < 0: continue if offset + ram_page + ram_page_size - 1 > self.ram.size: continue logger_crash_dump.error( '%s: %s', utils.word_to_str(offset + ram_page), ''.join([ ('>' if idx == ip else ' ') + utils.byte_to_str(self.ram.read_byte(idx, silent=True)) for idx in range(offset + ram_page, offset + ram_page + ram_page_size) ]), ) # stack sp = self.cpu.registers.get_register('SP', silent=True) bp = self.cpu.registers.get_register('BP', silent=True) logger_crash_dump.error('') logger_crash_dump.error('SP=%s', utils.word_to_str(sp)) logger_crash_dump.error('BP=%s', utils.word_to_str(bp)) logger_crash_dump.error( 'Bottom of stack=%s', utils.word_to_str(self.cpu.system_addresses['bottom_of_stack'])) logger_crash_dump.error('') logger_crash_dump.error('Stack:') stack_page_size = 16 stack_page = (sp // stack_page_size) * stack_page_size if stack_page < 0: stack_page = 0 for page_offset in range(-1, 4): offset = page_offset * stack_page_size if offset + stack_page < 0: continue if offset + stack_page + stack_page_size - 1 > self.ram.size: continue logger_crash_dump.error( '%s: %s', utils.word_to_str(offset + stack_page), ''.join([ utils.byte_to_str(self.ram.read_byte(idx, silent=True)) + (('{' if idx == bp else '<') if idx == sp else ('[' if idx == bp else ' ')) for idx in range(offset + stack_page, offset + stack_page + stack_page_size) ]), ) # registers logger_crash_dump.error('') logger_crash_dump.error('Registers:') for reg in ['AX', 'BX', 'CX', 'DX', 'SI', 'DI']: logger_crash_dump.error( '%s=%s', reg, utils.word_to_str( self.cpu.registers.get_register(reg, silent=True)))
def write_word(self, pos, value, silent=False): ''' Write word at position `pos` ''' if pos < self.ram_size - 1: self.ram.write_word(pos, value, silent=silent) elif pos == self.ram_size - 1: # cannot write word half to ram, half to virtual ram raise SegfaultError('Segmentation fault when trying to read word at {}'.format(utils.word_to_str(pos))) else: self.virtual_ram.write_word(pos, value, silent=silent)
def _mini_debugger(self): if logger.level != logging.DEBUG: return ram_page_size = 16 stack_page_size = 32 sp = self.registers.get_register('SP', silent=True) bp = self.registers.get_register('BP', silent=True) ram_page = (self.ip // ram_page_size) * ram_page_size rel_sp = self.system_addresses['bottom_of_stack'] - sp stack_page = self.system_addresses['bottom_of_stack'] - ( stack_page_size - 1) - (rel_sp // stack_page_size) * stack_page_size if stack_page < 0: stack_page = 0 logger.debug( 'IP=%s RAM %s-%s: %s', utils.word_to_str(self.ip), utils.word_to_str(ram_page), utils.word_to_str(ram_page + ram_page_size - 1), ''.join([('>' if idx == self.ip else ' ') + utils.byte_to_str(self.memory.read_byte(idx, silent=True)) for idx in range(ram_page, ram_page + ram_page_size)]), ) logger.debug( 'SP=%s BP=%s Stack %s-%s: %s', utils.word_to_str(sp), utils.word_to_str(bp), utils.word_to_str(stack_page), utils.word_to_str(stack_page + stack_page_size - 1), ''.join([ utils.byte_to_str(self.memory.read_byte(idx, silent=True)) + (('{' if idx == bp else '<') if idx == sp else ('[' if idx == bp else ' ')) for idx in range(stack_page, stack_page + stack_page_size) ]), ) logger.debug( 'AX/BX/CX/DX=%s/%s/%s/%s SI/DI=%s/%s', utils.word_to_str(self.registers.get_register('AX', silent=True)), utils.word_to_str(self.registers.get_register('BX', silent=True)), utils.word_to_str(self.registers.get_register('CX', silent=True)), utils.word_to_str(self.registers.get_register('DX', silent=True)), utils.word_to_str(self.registers.get_register('SI', silent=True)), utils.word_to_str(self.registers.get_register('DI', silent=True)), )
def _mini_debugger(self): if logger.level != logging.DEBUG: return ram_page_size = 16 stack_page_size = 32 sp = self.registers.get_register('SP', silent=True) bp = self.registers.get_register('BP', silent=True) ram_page = (self.ip // ram_page_size) * ram_page_size rel_sp = self.system_addresses['bottom_of_stack'] - sp stack_page = self.system_addresses['bottom_of_stack'] - (stack_page_size - 1) - (rel_sp // stack_page_size) * stack_page_size if stack_page < 0: stack_page = 0 logger.debug( 'IP=%s RAM %s-%s: %s', utils.word_to_str(self.ip), utils.word_to_str(ram_page), utils.word_to_str(ram_page + ram_page_size - 1), ''.join([ ('>' if idx == self.ip else ' ') + utils.byte_to_str(self.memory.read_byte(idx, silent=True)) for idx in range(ram_page, ram_page + ram_page_size) ]), ) logger.debug( 'SP=%s BP=%s Stack %s-%s: %s', utils.word_to_str(sp), utils.word_to_str(bp), utils.word_to_str(stack_page), utils.word_to_str(stack_page + stack_page_size - 1), ''.join([utils.byte_to_str(self.memory.read_byte(idx, silent=True)) + ( ( '{' if idx == bp else '<' ) if idx == sp else ( '[' if idx == bp else ' ' ) ) for idx in range(stack_page, stack_page + stack_page_size)]), ) logger.debug( 'AX/BX/CX/DX=%s/%s/%s/%s SI/DI=%s/%s', utils.word_to_str(self.registers.get_register('AX', silent=True)), utils.word_to_str(self.registers.get_register('BX', silent=True)), utils.word_to_str(self.registers.get_register('CX', silent=True)), utils.word_to_str(self.registers.get_register('DX', silent=True)), utils.word_to_str(self.registers.get_register('SI', silent=True)), utils.word_to_str(self.registers.get_register('DI', silent=True)), )
def do(self): self.cpu.user_log(utils.word_to_str(self.get_operand(0)))
def crash_dump(self): ''' Print crash dump ''' logger_crash_dump.error('### CRASH DUMP ###') # ip ip = self.cpu.ip logger_crash_dump.error('') logger_crash_dump.error('IP=%s', utils.word_to_str(ip)) logger_crash_dump.error('Entry point=%s', utils.word_to_str(self.cpu.system_addresses['entry_point'])) logger_crash_dump.error('Halt=%s', self.cpu.halt) # ram ram_page_size = 16 ram_page = (ip // ram_page_size) * ram_page_size logger_crash_dump.error('') logger_crash_dump.error('RAM:') for page_offset in range(-2, 3): offset = page_offset * ram_page_size if offset + ram_page < 0: continue if offset + ram_page + ram_page_size - 1 > self.ram.size: continue logger_crash_dump.error( '%s: %s', utils.word_to_str(offset + ram_page), ''.join([ ('>' if idx == ip else ' ') + utils.byte_to_str(self.ram.read_byte(idx, silent=True)) for idx in range(offset + ram_page, offset + ram_page + ram_page_size) ]), ) # stack sp = self.cpu.registers.get_register('SP', silent=True) bp = self.cpu.registers.get_register('BP', silent=True) logger_crash_dump.error('') logger_crash_dump.error('SP=%s', utils.word_to_str(sp)) logger_crash_dump.error('BP=%s', utils.word_to_str(bp)) logger_crash_dump.error('Bottom of stack=%s', utils.word_to_str(self.cpu.system_addresses['bottom_of_stack'])) logger_crash_dump.error('') logger_crash_dump.error('Stack:') stack_page_size = 16 stack_page = (sp // stack_page_size) * stack_page_size if stack_page < 0: stack_page = 0 for page_offset in range(-1, 4): offset = page_offset * stack_page_size if offset + stack_page < 0: continue if offset + stack_page + stack_page_size - 1 > self.ram.size: continue logger_crash_dump.error( '%s: %s', utils.word_to_str(offset + stack_page), ''.join([utils.byte_to_str(self.ram.read_byte(idx, silent=True)) + ( ( '{' if idx == bp else '<' ) if idx == sp else ( '[' if idx == bp else ' ' ) ) for idx in range(offset + stack_page, offset + stack_page + stack_page_size)]), ) # registers logger_crash_dump.error('') logger_crash_dump.error('Registers:') for reg in ['AX', 'BX', 'CX', 'DX', 'SI', 'DI']: logger_crash_dump.error('%s=%s', reg, utils.word_to_str(self.cpu.registers.get_register(reg, silent=True)))
def _set_word_register(self, register_name, value, silent=False): if value < 0x0000 or value > 0xFFFF: raise InvalidRegisterValueError('Invalid register value: {}'.format(value)) self._registers[register_name] = value if not silent: logger.debug('Set register %s = %s', register_name, utils.word_to_str(value))
def write_byte(self, pos, value, silent=False): ''' Cannot write to device registry device status table ''' raise SegfaultError('Segmentation fault when trying to write byte at {}'.format(utils.word_to_str(pos)))
def read_word(self, pos, silent=False): ''' Read word at position `pos` ''' if pos < self.ram_size - 1: return self.ram.read_word(pos, silent=silent) if pos == self.ram_size - 1: # cannot read word half from ram, half from virtual ram raise SegfaultError('Segmentation fault when trying to read word at {}'.format(utils.word_to_str(pos))) return self.virtual_ram.read_word(pos, silent=silent)