def test_code_alone(self): tokens = self.tokenizer.tokenize('mov ax 0x0100') self.assertListEqual(tokens, [ Token(TokenType.INSTRUCTION, 'MOV', 0), Token(TokenType.WORD_REGISTER, 'AX', 4), Token(TokenType.WORD_LITERAL, 256, 7), ])
def test_invalid(self): opcode = ( get_operand_opcode(Token(TokenType.WORD_LITERAL, 0xABCD, 0)) + get_operand_opcode(Token(TokenType.WORD_REGISTER, 'AX', 0))) inst = MOV(self.cpu, opcode) with self.assertRaises(InvalidWriteOperationError): inst.do()
def test_macro_dat_and_datn(self): opcode = self.assembler.assemble_code(''' MOV AX [stuff] NOP SHUTDOWN stuff: .DAT 0x1234 0x56 'ABC' .DATN 0x05 0xFF .DATN 0x03 0x1234 .DATN 0x02 'ABC' ''') expected_opcode = [0x34] expected_opcode += get_operand_opcode( Token(TokenType.WORD_REGISTER, 'AX', None)) expected_opcode += get_operand_opcode( Token( TokenType.REL_REF_WORD, Reference(7, None, 'W'), None, )) expected_opcode += [0x78] expected_opcode += [0x9A] expected_opcode += [0x12, 0x34, 0x56, 0x41, 0x42, 0x43] expected_opcode += [0xFF, 0xFF, 0xFF, 0xFF, 0xFF] expected_opcode += [0x12, 0x34, 0x12, 0x34, 0x12, 0x34] expected_opcode += [0x41, 0x42, 0x43, 0x41, 0x42, 0x43] self.assertListEqual(opcode, expected_opcode)
def test_random_case(self): tokens = self.tokenizer.tokenize('LabeL: mOv aX 0x00fF') self.assertListEqual(tokens, [ Token(TokenType.LABEL, 'LabeL', 0), Token(TokenType.INSTRUCTION, 'MOV', 7), Token(TokenType.WORD_REGISTER, 'AX', 11), Token(TokenType.WORD_LITERAL, 255, 14), ])
def test_random_whitespace(self): tokens = self.tokenizer.tokenize( ' mov ax 0x0100 ') self.assertListEqual(tokens, [ Token(TokenType.INSTRUCTION, 'MOV', 3), Token(TokenType.WORD_REGISTER, 'AX', 11), Token(TokenType.WORD_LITERAL, 256, 28), ])
def test_byte(self): self.cpu.registers.get_register.return_value = 0xFF opcode = (get_operand_opcode(Token(TokenType.BYTE_REGISTER, 'AL', 0)) + get_operand_opcode(Token(TokenType.BYTE_LITERAL, 0xFE, 0))) inst = MOV(self.cpu, opcode) self.assertEqual(inst.get_operand(0), 255) self.assertEqual(inst.get_signed_operand(0), -1) self.assertEqual(inst.get_operand(1), 254) self.assertEqual(inst.get_signed_operand(1), -2)
def test_almost_keyword_identifiers(self): tokens = self.tokenizer.tokenize('MOVE AXE ALL BEEF FF') self.assertListEqual(tokens, [ Token(TokenType.IDENTIFIER, 'MOVE', 0), Token(TokenType.IDENTIFIER, 'AXE', 5), Token(TokenType.IDENTIFIER, 'ALL', 9), Token(TokenType.IDENTIFIER, 'BEEF', 13), Token(TokenType.IDENTIFIER, 'FF', 18), ])
def test_word(self): self.cpu.registers.get_register.return_value = 0xFFFF opcode = (get_operand_opcode(Token(TokenType.WORD_REGISTER, 'AX', 0)) + get_operand_opcode(Token(TokenType.WORD_LITERAL, 0xFFFE, 0))) inst = MOV(self.cpu, opcode) self.assertEqual(inst.get_operand(0), 65535) self.assertEqual(inst.get_signed_operand(0), -1) self.assertEqual(inst.get_operand(1), 65534) self.assertEqual(inst.get_signed_operand(1), -2)
def test_label_code_comment(self): tokens = self.tokenizer.tokenize( 'labelname: mov ax 0x0100 # comment text') self.assertListEqual(tokens, [ Token(TokenType.LABEL, 'labelname', 0), Token(TokenType.INSTRUCTION, 'MOV', 11), Token(TokenType.WORD_REGISTER, 'AX', 15), Token(TokenType.WORD_LITERAL, 256, 18), Token(TokenType.COMMENT, ' comment text', 26), ])
def test_word(self): opcode = (get_operand_opcode(Token(TokenType.WORD_REGISTER, 'AX', 0)) + get_operand_opcode(Token(TokenType.WORD_LITERAL, 0xABCD, 0))) inst = MOV(self.cpu, opcode) inst.do() self.assertEqual(self.cpu.registers.set_register.call_count, 1) self.assertEqual( self.cpu.registers.set_register.call_args_list[0][0][0], 'AX') self.assertEqual( self.cpu.registers.set_register.call_args_list[0][0][1], 0xABCD)
def test_byte(self): opcode = (get_operand_opcode(Token(TokenType.BYTE_REGISTER, 'AL', 0)) + get_operand_opcode(Token(TokenType.BYTE_LITERAL, 0xAB, 0))) inst = MOV(self.cpu, opcode) inst.do() self.assertEqual(self.cpu.registers.set_register.call_count, 1) self.assertEqual( self.cpu.registers.set_register.call_args_list[0][0][0], 'AL') self.assertEqual( self.cpu.registers.set_register.call_args_list[0][0][1], 0xAB)
def test_register(self): self.assertListEqual(get_operand_opcode(Token(TokenType.WORD_REGISTER, 'AX', 0)), [ _get_opbyte(OpLen.WORD, OpType.REGISTER, 'AX'), ]) self.assertListEqual(get_operand_opcode(Token(TokenType.BYTE_REGISTER, 'AL', 0)), [ _get_opbyte(OpLen.BYTE, OpType.REGISTER, 'AL'), ]) self.assertListEqual(get_operand_opcode(Token(TokenType.BYTE_REGISTER, 'AH', 0)), [ _get_opbyte(OpLen.BYTE, OpType.REGISTER, 'AH'), ]) with self.assertRaises(InvalidRegisterNameError): get_operand_opcode(Token(TokenType.WORD_REGISTER, 'XX', 0))
def test_signed_word(self): opcode = (get_operand_opcode(Token(TokenType.WORD_REGISTER, 'AX', 0)) + get_operand_opcode(Token(TokenType.WORD_LITERAL, 0xABCD, 0))) inst = MOV(self.cpu, opcode) inst.set_signed_operand(0, -1) self.assertEqual(self.cpu.registers.set_register.call_count, 1) self.assertEqual( self.cpu.registers.set_register.call_args_list[0][0][0], 'AX') self.assertEqual( self.cpu.registers.set_register.call_args_list[0][0][1], 0xFFFF) with self.assertRaises(InvalidWriteOperationError): inst.set_signed_operand(1, -1)
def test_signed_byte(self): self.cpu.registers.get_register.return_value = 0xFF opcode = (get_operand_opcode(Token(TokenType.BYTE_REGISTER, 'AL', 0)) + get_operand_opcode(Token(TokenType.BYTE_LITERAL, 0xAB, 0))) inst = MOV(self.cpu, opcode) inst.set_signed_operand(0, -1) self.assertEqual(self.cpu.registers.set_register.call_count, 1) self.assertEqual( self.cpu.registers.set_register.call_args_list[0][0][0], 'AL') self.assertEqual( self.cpu.registers.set_register.call_args_list[0][0][1], 0xFF) with self.assertRaises(InvalidWriteOperationError): inst.set_signed_operand(1, -1)
def test_operands(self): opcode = self.assembler.assemble_code(''' MOV AX 0x1234 NOP SHUTDOWN ''') expected_opcode = [0x34] expected_opcode += get_operand_opcode( Token(TokenType.WORD_REGISTER, 'AX', None)) expected_opcode += get_operand_opcode( Token(TokenType.WORD_LITERAL, 0x1234, None)) expected_opcode += [0x78] expected_opcode += [0x9A] self.assertListEqual(opcode, expected_opcode)
def test_macro_const(self): opcode = self.assembler.assemble_code(''' .CONST $stuff 0x1234 .CONST $other_stuff $stuff MOV AX $other_stuff NOP SHUTDOWN ''') expected_opcode = [0x34] expected_opcode += get_operand_opcode( Token(TokenType.WORD_REGISTER, 'AX', None)) expected_opcode += get_operand_opcode( Token(TokenType.WORD_LITERAL, 0x1234, None)) expected_opcode += [0x78] expected_opcode += [0x9A] self.assertListEqual(opcode, expected_opcode)
def test_abs_ref(self): self.assertListEqual(get_operand_opcode(Token(TokenType.ABS_REF_REG, Reference('BX', 0, 'B'), 0)), [ _get_opbyte(OpLen.BYTE, OpType.ABS_REF_REG, 'BX'), 0x00, ]) self.assertListEqual(get_operand_opcode(Token(TokenType.ABS_REF_REG, Reference('BX', 1, 'B'), 0)), [ _get_opbyte(OpLen.BYTE, OpType.ABS_REF_REG, 'BX'), 0x01, ]) self.assertListEqual(get_operand_opcode(Token(TokenType.ABS_REF_REG, Reference('BX', -1, 'W'), 0)), [ _get_opbyte(OpLen.WORD, OpType.ABS_REF_REG, 'BX'), 0xFF, ]) with self.assertRaises(InvalidRegisterNameError): get_operand_opcode(Token(TokenType.ABS_REF_REG, Reference('XX', 0, 'W'), 0)) with self.assertRaises(ByteOutOfRangeError): get_operand_opcode(Token(TokenType.ABS_REF_REG, Reference('BX', 150, 'W'), 0))
def test_label_ok(self): opcode = self.assembler.assemble_code(''' loop: NOP JMP loop SHUTDOWN ''') expected_opcode = [0x78] expected_opcode += [0x56] expected_opcode += get_operand_opcode( Token(TokenType.ADDRESS_WORD_LITERAL, -1, None)) expected_opcode += [0x9A] self.assertListEqual(opcode, expected_opcode)
def test_rel_ref(self): self.assertListEqual(get_operand_opcode(Token(TokenType.REL_REF_WORD, Reference(-1, 0, 'B'), 0)), [ _get_opbyte(OpLen.BYTE, OpType.REL_REF_WORD), 0xFF, 0xFF, ]) with self.assertRaises(WordOutOfRangeError): get_operand_opcode(Token(TokenType.REL_REF_WORD, Reference(35000, 0, 'B'), 0)) with self.assertRaises(WordOutOfRangeError): get_operand_opcode(Token(TokenType.REL_REF_WORD, Reference(-35000, 0, 'B'), 0)) self.assertListEqual(get_operand_opcode(Token(TokenType.REL_REF_WORD_BYTE, Reference(-1, 255, 'B'), 0)), [ _get_opbyte(OpLen.BYTE, OpType.REL_REF_WORD_BYTE), 0xFF, 0xFF, 0xFF, ]) self.assertListEqual(get_operand_opcode(Token(TokenType.REL_REF_WORD_REG, Reference(-1, 'BX', 'B'), 0)), [ _get_opbyte(OpLen.BYTE, OpType.REL_REF_WORD_REG, 'BX'), 0xFF, 0xFF, ]) with self.assertRaises(InvalidRegisterNameError): get_operand_opcode(Token(TokenType.REL_REF_WORD_REG, Reference(12000, 'XX', 'B'), 0))
def test_literal(self): self.assertListEqual(get_operand_opcode(Token(TokenType.WORD_LITERAL, 65535, 0)), [ _get_opbyte(OpLen.WORD, OpType.VALUE), 0xFF, 0xFF, ]) with self.assertRaises(WordOutOfRangeError): get_operand_opcode(Token(TokenType.WORD_LITERAL, 65536, 0)) self.assertListEqual(get_operand_opcode(Token(TokenType.BYTE_LITERAL, 255, 0)), [ _get_opbyte(OpLen.BYTE, OpType.VALUE), 0xFF, ]) with self.assertRaises(ByteOutOfRangeError): get_operand_opcode(Token(TokenType.BYTE_LITERAL, -1, 0)) self.assertListEqual(get_operand_opcode(Token(TokenType.ADDRESS_WORD_LITERAL, -1, 0)), [ _get_opbyte(OpLen.WORD, OpType.ADDRESS), 0xFF, 0xFF, ]) with self.assertRaises(WordOutOfRangeError): get_operand_opcode(Token(TokenType.ADDRESS_WORD_LITERAL, 35000, 0))
def test_label_alone(self): tokens = self.tokenizer.tokenize('labelname:') self.assertListEqual(tokens, [ Token(TokenType.LABEL, 'labelname', 0), ])
def test_other(self): with self.assertRaises(InvalidTokenError): get_operand_opcode(Token(TokenType.STRING_LITERAL, 0, 0)) with self.assertRaises(InvalidTokenError): get_operand_opcode(Token('unknown', 0, 0))
def _create_scope(bc_params, bc_vars): return Scope([ Token(TokenType.BYTE_LITERAL, bc_params, None), Token(TokenType.BYTE_LITERAL, bc_vars, None), ])
def test_every_token_type(self): tokens = self.tokenizer.tokenize( 'label: other_label: MOV AX AL 0x1234 0x12 ^0x1234 ^label [AX] [AX+0x12]B [AX-0x12]B [0x1234]B [label]B [0x1234+0x56] [label+0x56] [0x1234+AX] [label+AX] JMP third_label .DAT "hello world with kinda # comment" $var $$system_var[abc] # actual comment' ) self.assertListEqual(tokens, [ Token(TokenType.LABEL, 'label', 0), Token(TokenType.LABEL, 'other_label', 7), Token(TokenType.INSTRUCTION, 'MOV', 20), Token(TokenType.WORD_REGISTER, 'AX', 24), Token(TokenType.BYTE_REGISTER, 'AL', 27), Token(TokenType.WORD_LITERAL, 4660, 30), Token(TokenType.BYTE_LITERAL, 18, 37), Token(TokenType.ADDRESS_WORD_LITERAL, 4660, 42), Token(TokenType.ADDRESS_LABEL, 'label', 50), Token(TokenType.ABS_REF_REG, Reference('AX', 0, 'W'), 57), Token(TokenType.ABS_REF_REG, Reference('AX', 18, 'B'), 62), Token(TokenType.ABS_REF_REG, Reference('AX', -18, 'B'), 73), Token(TokenType.REL_REF_WORD, Reference(4660, None, 'B'), 84), Token(TokenType.REL_REF_LABEL, Reference('label', None, 'B'), 94), Token(TokenType.REL_REF_WORD_BYTE, Reference(4660, 86, 'W'), 103), Token(TokenType.REL_REF_LABEL_BYTE, Reference('label', 86, 'W'), 117), Token(TokenType.REL_REF_WORD_REG, Reference(4660, 'AX', 'W'), 130), Token(TokenType.REL_REF_LABEL_REG, Reference('label', 'AX', 'W'), 142), Token(TokenType.INSTRUCTION, 'JMP', 153), Token(TokenType.IDENTIFIER, 'third_label', 157), Token(TokenType.MACRO, 'DAT', 169), Token(TokenType.STRING_LITERAL, 'hello world with kinda # comment', 174), Token(TokenType.VARIABLE, '$var', 209), Token(TokenType.SYSTEM_VARIABLE, '$$system_var[abc]', 214), Token(TokenType.COMMENT, ' actual comment', 233), ])
def test_macro_param_and_var(self): opcode = self.assembler.assemble_code(''' ENTER 0x02 0x04 .CONST $default_value 0x1234 .PARAM $p .VAR $v1 .VAR $v2 $default_value MOV AX $p MOV AX $v1 MOV AX $v2 NOP SHUTDOWN ''') expected_opcode = [0xBC] expected_opcode += get_operand_opcode( Token(TokenType.BYTE_LITERAL, 0x02, None)) expected_opcode += get_operand_opcode( Token(TokenType.BYTE_LITERAL, 0x04, None)) expected_opcode += [0x34] expected_opcode += get_operand_opcode( Token( TokenType.ABS_REF_REG, Reference('BP', -3, 'W'), None, )) expected_opcode += get_operand_opcode( Token(TokenType.WORD_LITERAL, 0x1234, None)) expected_opcode += [0x34] expected_opcode += get_operand_opcode( Token(TokenType.WORD_REGISTER, 'AX', None)) expected_opcode += get_operand_opcode( Token( TokenType.ABS_REF_REG, Reference('BP', 7, 'W'), None, )) expected_opcode += [0x34] expected_opcode += get_operand_opcode( Token(TokenType.WORD_REGISTER, 'AX', None)) expected_opcode += get_operand_opcode( Token( TokenType.ABS_REF_REG, Reference('BP', -1, 'W'), None, )) expected_opcode += [0x34] expected_opcode += get_operand_opcode( Token(TokenType.WORD_REGISTER, 'AX', None)) expected_opcode += get_operand_opcode( Token( TokenType.ABS_REF_REG, Reference('BP', -3, 'W'), None, )) expected_opcode += [0x78] expected_opcode += [0x9A] self.assertListEqual(opcode, expected_opcode)