diff options
Diffstat (limited to 'instructions.go')
-rw-r--r-- | instructions.go | 340 |
1 files changed, 224 insertions, 116 deletions
diff --git a/instructions.go b/instructions.go index 32e2794..0a7afb9 100644 --- a/instructions.go +++ b/instructions.go @@ -5,387 +5,486 @@ import ( "strings" ) -type ParamType func(state *ProgramState, param string) (uint16, error) +type ParamType func(labels *Labels, defs *Definitions, param string) (uint16, error) type InstructionParams struct { Types []ParamType - Assembler func(args []uint16) []uint8 + Assembler func(currentAddress uint16, args []uint16) ([]uint8, error) + Wildcard bool } type InstructionSet map[string][]InstructionParams var Instructions = InstructionSetNew() +func absoluteJPValueToRelative(baseAddress uint16, absoluteAddress uint16) (uint8, error) { + newAddress := (int16(absoluteAddress) - int16(baseAddress) - 2) + if newAddress < -127 || newAddress > 128 { + return 0, fmt.Errorf( + "Address 0x%04x and 0x%04x are too far apart to use JR. Please use JP instead", + baseAddress, + absoluteAddress, + ) + } + return uint8(newAddress & 0xff), nil +} + func InstructionSetNew() InstructionSet { result := make(InstructionSet) result["LD"] = []InstructionParams{ { Types: []ParamType{Reg8, Reg8}, - Assembler: func(args []uint16) []byte { - return []byte{0b01000000 | (uint8(uint8(args[0])) << 3) | uint8(uint8(args[1]))} + Assembler: func(_ uint16, args []uint16) ([]byte, error) { + return []byte{ + 0b01000000 | (uint8(uint8(args[0])) << 3) | uint8(uint8(args[1])), + }, nil }, }, + // { + // Types: []ParamType{HL, Raw8Indirect}, + // Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11111000, uint8(args[1])}, nil }, + // }, { - Types: []ParamType{Reg8, Raw8}, - Assembler: func(args []uint16) []byte { return []byte{0b00000110 | (uint8(args[0]) << 3), uint8(args[1])} }, + Types: []ParamType{Reg8, Raw8}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { + return []byte{0b00000110 | (uint8(args[0]) << 3), uint8(args[1])}, nil + }, }, { - Types: []ParamType{A, Reg16Indirect}, - Assembler: func(args []uint16) []byte { return []byte{0b00001010 | uint8(args[1])<<4} }, + Types: []ParamType{A, Raw8Indirect}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11110000, uint8(args[1])}, nil }, }, { - Types: []ParamType{Reg16Indirect, A}, - Assembler: func(args []uint16) []byte { return []byte{0b00000010 | uint8(args[1])<<4} }, + Types: []ParamType{Raw8Indirect, A}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11100000, uint8(args[0])}, nil }, }, { - Types: []ParamType{A, Raw16Indirect}, - Assembler: func(args []uint16) []byte { return []byte{0b11111010, uint8(args[1]) & 0xff, uint8(args[1] >> 8)} }, + Types: []ParamType{A, Reg16Indirect}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00001010 | uint8(args[1])<<4}, nil }, }, { - Types: []ParamType{Raw16Indirect, A}, - Assembler: func(args []uint16) []byte { return []byte{0b11101010, uint8(args[0]) & 0xff, uint8(args[0] >> 8)} }, + Types: []ParamType{Reg16Indirect, A}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00000010 | uint8(args[0])<<4}, nil }, }, { - Types: []ParamType{A, IndirectC}, - Assembler: func(args []uint16) []byte { return []byte{0b11110010} }, + Types: []ParamType{A, Raw16Indirect}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { + return []byte{0b11111010, uint8(args[1]) & 0xff, uint8(args[1] >> 8)}, nil + }, }, { - Types: []ParamType{IndirectC, A}, - Assembler: func(args []uint16) []byte { return []byte{0b11100010} }, + Types: []ParamType{Raw16Indirect, A}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { + return []byte{0b11101010, uint8(args[0]) & 0xff, uint8(args[0] >> 8)}, nil + }, }, { - Types: []ParamType{A, Raw8Indirect}, - Assembler: func(args []uint16) []byte { return []byte{0b11110000, uint8(args[1])} }, + Types: []ParamType{A, IndirectC}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11110010}, nil }, }, { - Types: []ParamType{Raw8Indirect, A}, - Assembler: func(args []uint16) []byte { return []byte{0b11100000, uint8(args[0])} }, + Types: []ParamType{IndirectC, A}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11100010}, nil }, }, { Types: []ParamType{Reg16, Raw16}, - Assembler: func(args []uint16) []byte { + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{ 0b00000001 | (uint8(args[0]) << 4), uint8(args[1]) & 0xff, uint8(args[1] >> 8), - } + }, nil }, }, { - Types: []ParamType{Raw16Indirect, SP}, - Assembler: func(args []uint16) []byte { return []byte{0b00001000, uint8(args[0]) & 0xff, uint8(args[0] >> 8)} }, + Types: []ParamType{Raw16Indirect, SP}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { + return []byte{0b00001000, uint8(args[0]) & 0xff, uint8(args[0] >> 8)}, nil + }, }, { Types: []ParamType{SP, HL}, - Assembler: func(args []uint16) []byte { return []byte{0b11111001} }, - }, - { - Types: []ParamType{HL, Raw8}, - Assembler: func(args []uint16) []byte { return []byte{0b11111000, uint8(args[1])} }, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11111001}, nil }, }, } result["PUSH"] = []InstructionParams{ { Types: []ParamType{Reg16}, - Assembler: func(args []uint16) []byte { return []byte{0b11000101 | (uint8(args[0]) << 4)} }, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11000101 | (uint8(args[0]) << 4)}, nil }, }, } result["POP"] = []InstructionParams{ { Types: []ParamType{Reg16}, - Assembler: func(args []uint16) []byte { return []byte{0b11000001 | (uint8(args[0]) << 4)} }, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11000001 | (uint8(args[0]) << 4)}, nil }, }, } result["ADD"] = []InstructionParams{ { Types: []ParamType{Reg8}, - Assembler: func(args []uint16) []byte { return []byte{0b10000000 | (uint8(args[0]))} }, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b10000000 | (uint8(args[0]))}, nil }, }, { Types: []ParamType{Raw8}, - Assembler: func(args []uint16) []byte { return []byte{0b11000110, uint8(args[0])} }, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11000110, uint8(args[0])}, nil }, }, { Types: []ParamType{SP, Raw8}, - Assembler: func(args []uint16) []byte { return []byte{0b11101000, uint8(args[1])} }, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11101000, uint8(args[1])}, nil }, }, } result["ADC"] = []InstructionParams{ { Types: []ParamType{Reg8}, - Assembler: func(args []uint16) []byte { return []byte{0b10001000 | uint8(args[0])} }, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b10001000 | uint8(args[0])}, nil }, }, { Types: []ParamType{Raw8}, - Assembler: func(args []uint16) []byte { return []byte{0b11001110, uint8(args[0])} }, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11001110, uint8(args[0])}, nil }, }, } result["SUB"] = []InstructionParams{ { Types: []ParamType{Reg8}, - Assembler: func(args []uint16) []byte { return []byte{0b10010000 | (uint8(args[0]))} }, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b10010000 | (uint8(args[0]))}, nil }, }, { Types: []ParamType{Raw8}, - Assembler: func(args []uint16) []byte { return []byte{0b11010110, uint8(args[0])} }, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11010110, uint8(args[0])}, nil }, }, } result["SBC"] = []InstructionParams{ { Types: []ParamType{Reg8}, - Assembler: func(args []uint16) []byte { return []byte{0b10011000 | uint8(args[0])} }, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b10011000 | uint8(args[0])}, nil }, }, { Types: []ParamType{Raw8}, - Assembler: func(args []uint16) []byte { return []byte{0b11011110, uint8(args[0])} }, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11011110, uint8(args[0])}, nil }, }, } result["CP"] = []InstructionParams{ { Types: []ParamType{Reg8}, - Assembler: func(args []uint16) []byte { return []byte{0b10111000 | (uint8(args[0]))} }, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b10111000 | (uint8(args[0]))}, nil }, }, { Types: []ParamType{Raw8}, - Assembler: func(args []uint16) []byte { return []byte{0b11111110, uint8(args[0])} }, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11111110, uint8(args[0])}, nil }, }, } result["INC"] = []InstructionParams{ { Types: []ParamType{Reg8}, - Assembler: func(args []uint16) []byte { return []byte{0b00000100 | (uint8(args[0]) << 3)} }, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00000100 | (uint8(args[0]) << 3)}, nil }, }, { Types: []ParamType{Reg16}, - Assembler: func(args []uint16) []byte { return []byte{0b00000011 | (uint8(args[0]) << 4)} }, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00000011 | (uint8(args[0]) << 4)}, nil }, }, } result["DEC"] = []InstructionParams{ { Types: []ParamType{Reg8}, - Assembler: func(args []uint16) []byte { return []byte{0b00000101 | (uint8(args[0]) << 3)} }, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00000101 | (uint8(args[0]) << 3)}, nil }, }, { Types: []ParamType{Reg16}, - Assembler: func(args []uint16) []byte { return []byte{0b00001011 | (uint8(args[0]) << 4)} }, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00001011 | (uint8(args[0]) << 4)}, nil }, }, } result["AND"] = []InstructionParams{ { Types: []ParamType{Reg8}, - Assembler: func(args []uint16) []byte { return []byte{0b10100000 | (uint8(args[0]))} }, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b10100000 | (uint8(args[0]))}, nil }, }, { Types: []ParamType{Raw8}, - Assembler: func(args []uint16) []byte { return []byte{0b11100110, uint8(args[0])} }, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11100110, uint8(args[0])}, nil }, }, } result["OR"] = []InstructionParams{ { Types: []ParamType{Reg8}, - Assembler: func(args []uint16) []byte { return []byte{0b10110000 | (uint8(args[0]))} }, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b10110000 | (uint8(args[0]))}, nil }, }, { Types: []ParamType{Raw8}, - Assembler: func(args []uint16) []byte { return []byte{0b11110110, uint8(args[0])} }, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11110110, uint8(args[0])}, nil }, }, } result["XOR"] = []InstructionParams{ { Types: []ParamType{Reg8}, - Assembler: func(args []uint16) []byte { return []byte{0b10101000 | (uint8(args[0]))} }, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b10101000 | (uint8(args[0]))}, nil }, }, { Types: []ParamType{Raw8}, - Assembler: func(args []uint16) []byte { return []byte{0b11101110, uint8(args[0])} }, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11101110, uint8(args[0])}, nil }, }, } result["CCF"] = []InstructionParams{ - {Types: []ParamType{}, Assembler: func(args []uint16) []byte { return []byte{0b00111111} }}, + { + Types: []ParamType{}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00111111}, nil }, + }, } result["SCF"] = []InstructionParams{ - {Types: []ParamType{}, Assembler: func(args []uint16) []byte { return []byte{0b00110111} }}, + { + Types: []ParamType{}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00110111}, nil }, + }, } result["DAA"] = []InstructionParams{ - {Types: []ParamType{}, Assembler: func(args []uint16) []byte { return []byte{0b00100111} }}, + { + Types: []ParamType{}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00100111}, nil }, + }, } result["CPL"] = []InstructionParams{ - {Types: []ParamType{}, Assembler: func(args []uint16) []byte { return []byte{0b00101111} }}, + { + Types: []ParamType{}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00101111}, nil }, + }, } result["JP"] = []InstructionParams{ { - Types: []ParamType{Raw16}, - Assembler: func(args []uint16) []byte { return []byte{0b11000011, uint8(args[0]) & 0xff, uint8(args[0] >> 8)} }, + Types: []ParamType{Raw16}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { + return []byte{0b11000011, uint8(args[0]) & 0xff, uint8(args[0] >> 8)}, nil + }, }, { Types: []ParamType{HL}, - Assembler: func(args []uint16) []byte { return []byte{0b11101001} }, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11101001}, nil }, }, { Types: []ParamType{Condition, Raw16}, - Assembler: func(args []uint16) []byte { + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{ 0b11000010 | (uint8(args[0]) << 3), uint8(args[1]) & 0xff, uint8(args[1] >> 8), - } + }, nil }, }, } result["JR"] = []InstructionParams{ { Types: []ParamType{Raw8}, - Assembler: func(args []uint16) []byte { return []byte{0b00011000, uint8(args[0])} }, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00011000, uint8(args[0])}, nil }, + }, + { + Types: []ParamType{Condition, Raw8}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { + return []byte{0b00100000 | (uint8(args[0]) << 3), uint8(args[1])}, nil + }, }, // TODO: Add the relative thingies somehow { - Types: []ParamType{Raw16}, - Assembler: func(args []uint16) []byte { return []byte{0b00011000, uint8(args[0])} }, + Types: []ParamType{Raw16}, + Assembler: func(currentAddress uint16, args []uint16) ([]byte, error) { + relativeAddress, err := absoluteJPValueToRelative(currentAddress, args[0]) + if err != nil { + return nil, err + } + return []byte{0b00011000, relativeAddress}, nil + }, }, { - Types: []ParamType{Condition, Raw8}, - Assembler: func(args []uint16) []byte { return []byte{0b00100000 | (uint8(args[0]) << 3), uint8(args[1])} }, + Types: []ParamType{Condition, Raw16}, + Assembler: func(currentAddress uint16, args []uint16) ([]byte, error) { + relativeAddress, err := absoluteJPValueToRelative(currentAddress, args[1]) + if err != nil { + return nil, err + } + return []byte{0b00100000 | (uint8(args[0]) << 3), relativeAddress}, nil + }, }, - // { - // Types: []ParamType{Condition, Raw16}, - // Assembler: func(args []uint16) []byte { return []byte{0b00100000 | (uint8(args[0]) << 3), uint8(args[1])} }, - // }, } result["CALL"] = []InstructionParams{ { - Types: []ParamType{Raw16}, - Assembler: func(args []uint16) []byte { return []byte{0b11001101, uint8(args[0]) & 0xff, uint8(args[0] >> 8)} }, + Types: []ParamType{Raw16}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { + return []byte{0b11001101, uint8(args[0]) & 0xff, uint8(args[0] >> 8)}, nil + }, }, { Types: []ParamType{Condition, Raw16}, - Assembler: func(args []uint16) []byte { + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{ 0b11000100 | (uint8(args[0]) << 3), uint8(args[1]) & 0xff, uint8(args[1] >> 8), - } + }, nil }, }, } result["RET"] = []InstructionParams{ - {Types: []ParamType{}, Assembler: func(args []uint16) []byte { return []byte{0b11001001} }}, + { + Types: []ParamType{}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11001001}, nil }, + }, { Types: []ParamType{Condition}, - Assembler: func(args []uint16) []byte { return []byte{0b11000000 | (uint8(args[0]) << 3)} }, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11000000 | (uint8(args[0]) << 3)}, nil }, }, } result["RETI"] = []InstructionParams{ - {Types: []ParamType{}, Assembler: func(args []uint16) []byte { return []byte{0b11011001} }}, + { + Types: []ParamType{}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11011001}, nil }, + }, } result["RST"] = []InstructionParams{ { Types: []ParamType{BitOrdinal}, - Assembler: func(args []uint16) []byte { return []byte{0b11000111 | (uint8(args[0]) << 3)} }, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11000111 | (uint8(args[0]) << 3)}, nil }, }, } result["DI"] = []InstructionParams{ - {Types: []ParamType{}, Assembler: func(args []uint16) []byte { return []byte{0b11110011} }}, + { + Types: []ParamType{}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11110011}, nil }, + }, } result["EI"] = []InstructionParams{ - {Types: []ParamType{}, Assembler: func(args []uint16) []byte { return []byte{0b11111011} }}, + { + Types: []ParamType{}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11111011}, nil }, + }, } result["NOP"] = []InstructionParams{ - {Types: []ParamType{}, Assembler: func(args []uint16) []byte { return []byte{0b00000000} }}, + { + Types: []ParamType{}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00000000}, nil }, + }, } result["HALT"] = []InstructionParams{ - {Types: []ParamType{}, Assembler: func(args []uint16) []byte { return []byte{0b01110110} }}, + { + Types: []ParamType{}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b01110110}, nil }, + }, } result["STOP"] = []InstructionParams{ { Types: []ParamType{}, - Assembler: func(args []uint16) []byte { return []byte{0b00010000, 0b00000000} }, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00010000, 0b00000000}, nil }, }, } result["RLCA"] = []InstructionParams{ - {Types: []ParamType{}, Assembler: func(args []uint16) []byte { return []byte{0b00000111} }}, + { + Types: []ParamType{}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00000111}, nil }, + }, } result["RLA"] = []InstructionParams{ - {Types: []ParamType{}, Assembler: func(args []uint16) []byte { return []byte{0b00010111} }}, + { + Types: []ParamType{}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00010111}, nil }, + }, } result["RRCA"] = []InstructionParams{ - {Types: []ParamType{}, Assembler: func(args []uint16) []byte { return []byte{0b00001111} }}, + { + Types: []ParamType{}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00001111}, nil }, + }, } result["RRA"] = []InstructionParams{ - {Types: []ParamType{}, Assembler: func(args []uint16) []byte { return []byte{0b00011111} }}, + { + Types: []ParamType{}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00011111}, nil }, + }, } result["BIT"] = []InstructionParams{ { Types: []ParamType{BitOrdinal, Reg8}, - Assembler: func(args []uint16) []byte { - return []byte{0b11001011, 0b01000000 | (uint8(args[0]) << 3) | uint8(args[1])} + Assembler: func(_ uint16, args []uint16) ([]byte, error) { + return []byte{0b11001011, 0b01000000 | (uint8(args[0]) << 3) | uint8(args[1])}, nil }, }, } result["SET"] = []InstructionParams{ { Types: []ParamType{BitOrdinal, Reg8}, - Assembler: func(args []uint16) []byte { - return []byte{0b11001011, 0b11000000 | (uint8(args[0]) << 3) | uint8(args[1])} + Assembler: func(_ uint16, args []uint16) ([]byte, error) { + return []byte{0b11001011, 0b11000000 | (uint8(args[0]) << 3) | uint8(args[1])}, nil }, }, } result["RES"] = []InstructionParams{ { Types: []ParamType{BitOrdinal, Reg8}, - Assembler: func(args []uint16) []byte { - return []byte{0b11001011, 0b10000000 | (uint8(args[0]) << 3) | uint8(args[1])} + Assembler: func(_ uint16, args []uint16) ([]byte, error) { + return []byte{0b11001011, 0b10000000 | (uint8(args[0]) << 3) | uint8(args[1])}, nil }, }, } result["RLC"] = []InstructionParams{ { - Types: []ParamType{Reg8}, - Assembler: func(args []uint16) []byte { return []byte{0b11001011, 0b00000000 | uint8(args[0])} }, + Types: []ParamType{Reg8}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { + return []byte{0b11001011, 0b00000000 | uint8(args[0])}, nil + }, }, } result["RL"] = []InstructionParams{ { - Types: []ParamType{Reg8}, - Assembler: func(args []uint16) []byte { return []byte{0b11001011, 0b00010000 | uint8(args[0])} }, + Types: []ParamType{Reg8}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { + return []byte{0b11001011, 0b00010000 | uint8(args[0])}, nil + }, }, } result["RRC"] = []InstructionParams{ { - Types: []ParamType{Reg8}, - Assembler: func(args []uint16) []byte { return []byte{0b11001011, 0b00001000 | uint8(args[0])} }, + Types: []ParamType{Reg8}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { + return []byte{0b11001011, 0b00001000 | uint8(args[0])}, nil + }, }, } result["RR"] = []InstructionParams{ { - Types: []ParamType{Reg8}, - Assembler: func(args []uint16) []byte { return []byte{0b11001011, 0b00011000 | uint8(args[0])} }, + Types: []ParamType{Reg8}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { + return []byte{0b11001011, 0b00011000 | uint8(args[0])}, nil + }, }, } result["SLA"] = []InstructionParams{ { - Types: []ParamType{Reg8}, - Assembler: func(args []uint16) []byte { return []byte{0b11001011, 0b00100000 | uint8(args[0])} }, + Types: []ParamType{Reg8}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { + return []byte{0b11001011, 0b00100000 | uint8(args[0])}, nil + }, }, } result["SWAP"] = []InstructionParams{ { - Types: []ParamType{Reg8}, - Assembler: func(args []uint16) []byte { return []byte{0b11001011, 0b00110000 | uint8(args[0])} }, + Types: []ParamType{Reg8}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { + return []byte{0b11001011, 0b00110000 | uint8(args[0])}, nil + }, }, } result["SRA"] = []InstructionParams{ { - Types: []ParamType{Reg8}, - Assembler: func(args []uint16) []byte { return []byte{0b11001011, 0b00101000 | uint8(args[0])} }, + Types: []ParamType{Reg8}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { + return []byte{0b11001011, 0b00101000 | uint8(args[0])}, nil + }, }, } result["SRL"] = []InstructionParams{ { - Types: []ParamType{Reg8}, - Assembler: func(args []uint16) []byte { return []byte{0b11001011, 0b00111000 | uint8(args[0])} }, + Types: []ParamType{Reg8}, + Assembler: func(_ uint16, args []uint16) ([]byte, error) { + return []byte{0b11001011, 0b00111000 | uint8(args[0])}, nil + }, }, } @@ -393,7 +492,9 @@ func InstructionSetNew() InstructionSet { } func (set InstructionSet) Parse( - state *ProgramState, + labels *Labels, + defs *Definitions, + currentAddress uint16, line string, ) ([]byte, error) { words := strings.Fields(strings.ReplaceAll(strings.Trim(line, " \t\n"), ",", " ")) @@ -411,13 +512,20 @@ func (set InstructionSet) Parse( instruction_param_loop: for _, instrParam := range instruction { - if len(instrParam.Types) != len(params) { + if !instrParam.Wildcard && len(instrParam.Types) != len(params) { continue } parsed_params := make([]uint16, len(params)) - for i, paramType := range instrParam.Types { - parsed, err := paramType(state, params[i]) + for i := range parsed_params { + var paramType ParamType + if instrParam.Wildcard { + paramType = instrParam.Types[0] + } else { + paramType = instrParam.Types[i] + } + + parsed, err := paramType(labels, defs, params[i]) if err != nil { continue instruction_param_loop } @@ -425,7 +533,7 @@ instruction_param_loop: parsed_params[i] = parsed } - return instrParam.Assembler(parsed_params), nil + return instrParam.Assembler(currentAddress, parsed_params) } return nil, fmt.Errorf( "Instruction \"%s\" doesn't have a parameter set that can parse \"%s\"", |