<reponame>jeffnyman/quendor<filename>quendor/zmachine/instruction.py
"""Abstraction for a zcode instruction."""

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from quendor.zmachine.memory import Memory


class Instruction:
    """Abstraction for a zcode instruction."""

    def __init__(self, memory: "Memory") -> None:
        self._memory = memory

    def decode(self, address: int) -> int:
        """
        Decode a zcode instruction.

        According to the Z-Machine specification, the first byte of an
        instruction can be decoded using this table:

        $00 -- $1f  long      2OP     small constant, small constant
        $20 -- $3f  long      2OP     small constant, variable
        $40 -- $5f  long      2OP     variable, small constant
        $60 -- $7f  long      2OP     variable, variable
        $80 -- $8f  short     1OP     large constant
        $90 -- $9f  short     1OP     small constant
        $a0 -- $af  short     1OP     variable
        $b0 -- $bf  short     0OP
        except $be  extended opcode given in next byte
        $c0 -- $df  variable  2OP     (operand types in next byte)
        $e0 -- $ff  variable  VAR     (operand types in next byte(s))
        """

        print(hex(address))

        op_type = self._memory.read_byte(address)
        print(hex(op_type))

        if op_type < 0x20:
            print("IMP: long 2OP, small constant, small constant")
        elif op_type < 0x40:
            print("IMP: long 2OP, small constant, variable")
        elif op_type < 0x60:
            print("IMG: long 2OP, variable, small constant")
        elif op_type < 0x80:
            print("long 2OP, variable, variable")
        elif op_type < 0x90:
            print("short 1OP, large constant")
        elif op_type < 0xA0:
            print("short 1OP, small constant")
        elif op_type < 0xB0:
            print("short 1OP, variable")
        elif op_type < 0xC0:
            print("short 0OP")
        elif op_type < 0xE0:
            print("variable 2OP")
        elif op_type < 0x100:
            print("variable VAR")

            address += 1
            operand_type = self._memory.read_byte(address)
            operand_type2 = self._memory.read_byte(address + 1)

            print(hex(operand_type))
            print(hex(operand_type2))
        else:
            print("something else")

        address += 1

        return address

    def execute(self, address: int) -> None:
        """Execute a zcode opcode."""

        op_type = self._memory.read_byte(address)
        print(f"Execute: {hex(op_type)}")

"""Abstraction for a zcode instruction."""

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from quendor.zmachine.memory import Memory


class Instruction:
    """Abstraction for a zcode instruction."""

    def __init__(self, memory: "Memory") -> None:
        self._memory = memory

    def decode(self, address: int) -> int:
        """
        Decode a zcode instruction.

        According to the Z-Machine specification, the first byte of an
        instruction can be decoded using this table:

        $00 -- $1f  long      2OP     small constant, small constant
        $20 -- $3f  long      2OP     small constant, variable
        $40 -- $5f  long      2OP     variable, small constant
        $60 -- $7f  long      2OP     variable, variable
        $80 -- $8f  short     1OP     large constant
        $90 -- $9f  short     1OP     small constant
        $a0 -- $af  short     1OP     variable
        $b0 -- $bf  short     0OP
        except $be  extended opcode given in next byte
        $c0 -- $df  variable  2OP     (operand types in next byte)
        $e0 -- $ff  variable  VAR     (operand types in next byte(s))
        """

        print(hex(address))

        op_type = self._memory.read_byte(address)
        print(hex(op_type))

        if op_type < 0x20:
            print("IMP: long 2OP, small constant, small constant")
        elif op_type < 0x40:
            print("IMP: long 2OP, small constant, variable")
        elif op_type < 0x60:
            print("IMG: long 2OP, variable, small constant")
        elif op_type < 0x80:
            print("long 2OP, variable, variable")
        elif op_type < 0x90:
            print("short 1OP, large constant")
        elif op_type < 0xA0:
            print("short 1OP, small constant")
        elif op_type < 0xB0:
            print("short 1OP, variable")
        elif op_type < 0xC0:
            print("short 0OP")
        elif op_type < 0xE0:
            print("variable 2OP")
        elif op_type < 0x100:
            print("variable VAR")

            address += 1
            operand_type = self._memory.read_byte(address)
            operand_type2 = self._memory.read_byte(address + 1)

            print(hex(operand_type))
            print(hex(operand_type2))
        else:
            print("something else")

        address += 1

        return address

    def execute(self, address: int) -> None:
        """Execute a zcode opcode."""

        op_type = self._memory.read_byte(address)
        print(f"Execute: {hex(op_type)}")
Abstraction for a zcode instruction. Abstraction for a zcode instruction. Decode a zcode instruction.          According to the Z-Machine specification, the first byte of an         instruction can be decoded using this table:          $00 -- $1f  long      2OP     small constant, small constant         $20 -- $3f  long      2OP     small constant, variable         $40 -- $5f  long      2OP     variable, small constant         $60 -- $7f  long      2OP     variable, variable         $80 -- $8f  short     1OP     large constant         $90 -- $9f  short     1OP     small constant         $a0 -- $af  short     1OP     variable         $b0 -- $bf  short     0OP         except $be  extended opcode given in next byte         $c0 -- $df  variable  2OP     (operand types in next byte)         $e0 -- $ff  variable  VAR     (operand types in next byte(s)) Execute a zcode opcode.