From 1e8a72d826e693db7dcf146af0032757ec1eb041 Mon Sep 17 00:00:00 2001 From: Max Regan Date: Sat, 28 Dec 2019 16:54:59 -0800 Subject: [PATCH] Add support for LD of 16-bit immediates --- src/python/src/gbasm/gbasm.py | 5 +- src/python/src/gbasm/instructions/ld.py | 45 +++++++++++ .../test/cases/instructions/ld_reg16.yaml | 81 +++++++++++++++++++ 3 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 src/python/src/gbasm/instructions/ld.py create mode 100644 src/python/test/cases/instructions/ld_reg16.yaml diff --git a/src/python/src/gbasm/gbasm.py b/src/python/src/gbasm/gbasm.py index e844bc6..a014430 100755 --- a/src/python/src/gbasm/gbasm.py +++ b/src/python/src/gbasm/gbasm.py @@ -10,6 +10,7 @@ from .instructions.dec import Dec from .instructions.nop import Nop from .instructions.stop import Stop from .instructions.jr import Jr +from .instructions.ld import Ld from .arguments import ArgumentType, Argument from typing import Callable, Dict, List, Optional @@ -24,7 +25,8 @@ GB_INSTRUCTIONS = [ Stop(), Inc(), Dec(), - Jr() + Jr(), + Ld(), ] def build_instruction_map() -> Dict[str, Instruction]: @@ -124,7 +126,6 @@ def assemble(lines: str) -> bytes: raise ValueError("Failed to parse line %s,\n%s", line_num, line) byte_offset += parse_line_size(instruction, args) - if step == 'SIZE': logger.info("Program size: %s bytes", byte_offset) logger.debug("Found labels: %s", labels) diff --git a/src/python/src/gbasm/instructions/ld.py b/src/python/src/gbasm/instructions/ld.py new file mode 100644 index 0000000..b91f7fb --- /dev/null +++ b/src/python/src/gbasm/instructions/ld.py @@ -0,0 +1,45 @@ +from .Instruction import Instruction +from ..arguments.ArgumentTypes import Register16, Immediate16 +from ..arguments import Argument +from typing import Callable, List + +class Ld(Instruction): + + def __init__(self): + argtypes = [[Register16(), Immediate16()]] + super().__init__("LD", argtypes) + + def num_bytes(self, arguments) -> int: + # the instruction_address and label_resolver are unused + return len(self.to_bytes(arguments, 0, lambda x: None)) + + def encode_reg_16(self, + register: Register16, + immediate: Immediate16) -> bytes: + reg_dict = { + "BC": 0x01, + "DE": 0x11, + "HL": 0x21, + "SP": 0x31 + } + imm = int(immediate.value, 0) + print("immediate", imm) + out = bytearray() + out.append(reg_dict[register.value]) + out.extend(imm.to_bytes(2, "little", signed=imm < 0)) + return bytes(out) + + def to_bytes(self, + arguments: List[Argument], + instruction_address: int, + label_resolver: Callable[[str], int]) -> bytes: + + # print(arguments) + # print("Register16", type(arguments[0])) + # print("Immediate16", isinstance(arguments[1], Immediate16)) + + # if isinstance(arguments[0], Register16) and \ + # isinstance(arguments[1], Immediate16): + return self.encode_reg_16(arguments[0], arguments[1]) + + raise TypeError("Unhandled argument types") diff --git a/src/python/test/cases/instructions/ld_reg16.yaml b/src/python/test/cases/instructions/ld_reg16.yaml new file mode 100644 index 0000000..790fdf2 --- /dev/null +++ b/src/python/test/cases/instructions/ld_reg16.yaml @@ -0,0 +1,81 @@ +--- +name: ld_bc +program: | + LD BC 0 +expected: + - 0x01 + - 0x00 + - 0x00 +--- +name: ld_de +program: | + LD DE 0 +expected: + - 0x11 + - 0x00 + - 0x00 +--- +name: ld_hl +program: | + LD HL 0 +expected: + - 0x21 + - 0x00 + - 0x00 +--- +name: ld_sp +program: | + LD SP 0 +expected: + - 0x31 + - 0x00 + - 0x00 + +--- +name: ld_16_max +program: | + LD BC 65535 +expected: + - 0x01 + - 0xFF + - 0xFF +--- +name: ld_16_negative +program: | + LD BC -1 +expected: + - 0x01 + - 0xFF + - 0xFF +--- +name: ld_16_min +program: | + LD BC -32768 +expected: + - 0x01 + - 0x00 + - 0x80 +--- +name: ld_16_00FF +program: | + LD BC 0x00FF +expected: + - 0x01 + - 0xFF + - 0x00 +--- +name: ld_16_FF00 +program: | + LD BC 0xFF00 +expected: + - 0x01 + - 0x00 + - 0xFF +--- +name: ld_16_100 +program: | + LD BC 10 +expected: + - 0x01 + - 0x0A + - 0x00