diff options
author | Astatin <[email protected]> | 2025-06-10 13:22:11 +0200 |
---|---|---|
committer | Astatin <[email protected]> | 2025-06-10 13:22:11 +0200 |
commit | a7d6e62878245810323787eeb5458e418371b89f (patch) | |
tree | 003d8ce40e1580ec63360e271fd5e9427984ab2b | |
parent | 92ebacf4087babc3766b736aefa99fcaf7b89856 (diff) |
Add support for cross bank labels
-rw-r--r-- | instructions.go | 164 | ||||
-rw-r--r-- | macros.go | 59 | ||||
-rw-r--r-- | main.go | 2 | ||||
-rw-r--r-- | parameters.go | 255 |
4 files changed, 307 insertions, 173 deletions
diff --git a/instructions.go b/instructions.go index 66c6d97..80bedec 100644 --- a/instructions.go +++ b/instructions.go @@ -5,11 +5,11 @@ import ( "strings" ) -type ParamType func(labels *Labels, lastAbsoluteLabel string, defs *Definitions, param string) (uint16, error) +type ParamType func(labels *Labels, lastAbsoluteLabel string, defs *Definitions, currentAddr uint32, param string) (uint32, error) type InstructionParams struct { Types []ParamType - Assembler func(currentAddress uint16, args []uint16) ([]uint8, error) + Assembler func(currentAddress uint32, args []uint32) ([]uint8, error) Wildcard bool MacroForbidden bool LabelsBeforeOnly bool @@ -19,8 +19,8 @@ type InstructionSet map[string][]InstructionParams var Instructions = InstructionSetNew() -func absoluteJPValueToRelative(baseAddress uint16, absoluteAddress uint16) (uint8, error) { - newAddress := (int16(absoluteAddress) - int16(baseAddress) - 2) +func absoluteJPValueToRelative(baseAddress uint32, absoluteAddress uint32) (uint8, error) { + newAddress := (int32(absoluteAddress) - int32(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", @@ -37,7 +37,7 @@ func InstructionSetNew() InstructionSet { result["LD"] = []InstructionParams{ { Types: []ParamType{Reg8, Reg8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{ 0b01000000 | (uint8(uint8(args[0])) << 3) | uint8(uint8(args[1])), }, nil @@ -45,53 +45,53 @@ func InstructionSetNew() InstructionSet { }, // { // Types: []ParamType{HL, Raw8Indirect}, - // Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11111000, uint8(args[1])}, nil }, + // Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11111000, uint8(args[1])}, nil }, // }, { Types: []ParamType{Reg8, Raw8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b00000110 | (uint8(args[0]) << 3), uint8(args[1])}, nil }, }, { Types: []ParamType{A, Raw8Indirect}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11110000, uint8(args[1])}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11110000, uint8(args[1])}, nil }, }, { Types: []ParamType{Raw8Indirect, A}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11100000, uint8(args[0])}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11100000, uint8(args[0])}, nil }, }, { Types: []ParamType{A, Reg16Indirect}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00001010 | uint8(args[1])<<4}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b00001010 | uint8(args[1])<<4}, nil }, }, { Types: []ParamType{Reg16Indirect, A}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00000010 | uint8(args[0])<<4}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b00000010 | uint8(args[0])<<4}, nil }, }, { Types: []ParamType{A, Raw16Indirect}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11111010, uint8(args[1]) & 0xff, uint8(args[1] >> 8)}, nil }, }, { Types: []ParamType{Raw16Indirect, A}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11101010, uint8(args[0]) & 0xff, uint8(args[0] >> 8)}, nil }, }, { Types: []ParamType{A, IndirectC}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11110010}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11110010}, nil }, }, { Types: []ParamType{IndirectC, A}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11100010}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11100010}, nil }, }, { Types: []ParamType{Reg16, Raw16}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{ 0b00000001 | (uint8(args[0]) << 4), uint8(args[1]) & 0xff, @@ -101,171 +101,171 @@ func InstructionSetNew() InstructionSet { }, { Types: []ParamType{Raw16Indirect, SP}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b00001000, uint8(args[0]) & 0xff, uint8(args[0] >> 8)}, nil }, }, { Types: []ParamType{SP, HL}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11111001}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11111001}, nil }, }, } result["PUSH"] = []InstructionParams{ { Types: []ParamType{Reg16}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11000101 | (uint8(args[0]) << 4)}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11000101 | (uint8(args[0]) << 4)}, nil }, }, } result["POP"] = []InstructionParams{ { Types: []ParamType{Reg16}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11000001 | (uint8(args[0]) << 4)}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11000001 | (uint8(args[0]) << 4)}, nil }, }, } result["ADD"] = []InstructionParams{ { Types: []ParamType{Reg8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b10000000 | (uint8(args[0]))}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b10000000 | (uint8(args[0]))}, nil }, }, { Types: []ParamType{Raw8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11000110, uint8(args[0])}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11000110, uint8(args[0])}, nil }, }, { Types: []ParamType{SP, Raw8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11101000, uint8(args[1])}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11101000, uint8(args[1])}, nil }, }, } result["ADC"] = []InstructionParams{ { Types: []ParamType{Reg8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b10001000 | uint8(args[0])}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b10001000 | uint8(args[0])}, nil }, }, { Types: []ParamType{Raw8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11001110, uint8(args[0])}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11001110, uint8(args[0])}, nil }, }, } result["SUB"] = []InstructionParams{ { Types: []ParamType{Reg8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b10010000 | (uint8(args[0]))}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b10010000 | (uint8(args[0]))}, nil }, }, { Types: []ParamType{Raw8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11010110, uint8(args[0])}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11010110, uint8(args[0])}, nil }, }, } result["SBC"] = []InstructionParams{ { Types: []ParamType{Reg8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b10011000 | uint8(args[0])}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b10011000 | uint8(args[0])}, nil }, }, { Types: []ParamType{Raw8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11011110, uint8(args[0])}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11011110, uint8(args[0])}, nil }, }, } result["CP"] = []InstructionParams{ { Types: []ParamType{Reg8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b10111000 | (uint8(args[0]))}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b10111000 | (uint8(args[0]))}, nil }, }, { Types: []ParamType{Raw8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11111110, uint8(args[0])}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11111110, uint8(args[0])}, nil }, }, } result["INC"] = []InstructionParams{ { Types: []ParamType{Reg8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00000100 | (uint8(args[0]) << 3)}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b00000100 | (uint8(args[0]) << 3)}, nil }, }, { Types: []ParamType{Reg16}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00000011 | (uint8(args[0]) << 4)}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b00000011 | (uint8(args[0]) << 4)}, nil }, }, } result["DEC"] = []InstructionParams{ { Types: []ParamType{Reg8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00000101 | (uint8(args[0]) << 3)}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b00000101 | (uint8(args[0]) << 3)}, nil }, }, { Types: []ParamType{Reg16}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00001011 | (uint8(args[0]) << 4)}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b00001011 | (uint8(args[0]) << 4)}, nil }, }, } result["AND"] = []InstructionParams{ { Types: []ParamType{Reg8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b10100000 | (uint8(args[0]))}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b10100000 | (uint8(args[0]))}, nil }, }, { Types: []ParamType{Raw8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11100110, uint8(args[0])}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11100110, uint8(args[0])}, nil }, }, } result["OR"] = []InstructionParams{ { Types: []ParamType{Reg8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b10110000 | (uint8(args[0]))}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b10110000 | (uint8(args[0]))}, nil }, }, { Types: []ParamType{Raw8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11110110, uint8(args[0])}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11110110, uint8(args[0])}, nil }, }, } result["XOR"] = []InstructionParams{ { Types: []ParamType{Reg8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b10101000 | (uint8(args[0]))}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b10101000 | (uint8(args[0]))}, nil }, }, { Types: []ParamType{Raw8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11101110, uint8(args[0])}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11101110, uint8(args[0])}, nil }, }, } result["CCF"] = []InstructionParams{ { Types: []ParamType{}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00111111}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b00111111}, nil }, }, } result["SCF"] = []InstructionParams{ { Types: []ParamType{}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00110111}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b00110111}, nil }, }, } result["DAA"] = []InstructionParams{ { Types: []ParamType{}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00100111}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b00100111}, nil }, }, } result["CPL"] = []InstructionParams{ { Types: []ParamType{}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00101111}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b00101111}, nil }, }, } result["JP"] = []InstructionParams{ { Types: []ParamType{Raw16}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11000011, uint8(args[0]) & 0xff, uint8(args[0] >> 8)}, nil }, }, { Types: []ParamType{HL}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11101001}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11101001}, nil }, }, { Types: []ParamType{Condition, Raw16}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{ 0b11000010 | (uint8(args[0]) << 3), uint8(args[1]) & 0xff, @@ -277,17 +277,17 @@ func InstructionSetNew() InstructionSet { result["JR"] = []InstructionParams{ { Types: []ParamType{Raw8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00011000, uint8(args[0])}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b00011000, uint8(args[0])}, nil }, }, { Types: []ParamType{Condition, Raw8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b00100000 | (uint8(args[0]) << 3), uint8(args[1])}, nil }, }, { Types: []ParamType{Raw16}, - Assembler: func(currentAddress uint16, args []uint16) ([]byte, error) { + Assembler: func(currentAddress uint32, args []uint32) ([]byte, error) { relativeAddress, err := absoluteJPValueToRelative(currentAddress, args[0]) if err != nil { return nil, err @@ -297,7 +297,7 @@ func InstructionSetNew() InstructionSet { }, { Types: []ParamType{Condition, Raw16}, - Assembler: func(currentAddress uint16, args []uint16) ([]byte, error) { + Assembler: func(currentAddress uint32, args []uint32) ([]byte, error) { relativeAddress, err := absoluteJPValueToRelative(currentAddress, args[1]) if err != nil { return nil, err @@ -309,13 +309,13 @@ func InstructionSetNew() InstructionSet { result["CALL"] = []InstructionParams{ { Types: []ParamType{Raw16}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11001101, uint8(args[0]) & 0xff, uint8(args[0] >> 8)}, nil }, }, { Types: []ParamType{Condition, Raw16}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{ 0b11000100 | (uint8(args[0]) << 3), uint8(args[1]) & 0xff, @@ -327,83 +327,83 @@ func InstructionSetNew() InstructionSet { result["RET"] = []InstructionParams{ { Types: []ParamType{}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11001001}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11001001}, nil }, }, { Types: []ParamType{Condition}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11000000 | (uint8(args[0]) << 3)}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11000000 | (uint8(args[0]) << 3)}, nil }, }, } result["RETI"] = []InstructionParams{ { Types: []ParamType{}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11011001}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11011001}, nil }, }, } result["RST"] = []InstructionParams{ { Types: []ParamType{BitOrdinal}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11000111 | (uint8(args[0]) << 3)}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11000111 | (uint8(args[0]) << 3)}, nil }, }, } result["DI"] = []InstructionParams{ { Types: []ParamType{}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11110011}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11110011}, nil }, }, } result["EI"] = []InstructionParams{ { Types: []ParamType{}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b11111011}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11111011}, nil }, }, } result["NOP"] = []InstructionParams{ { Types: []ParamType{}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00000000}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b00000000}, nil }, }, } result["HALT"] = []InstructionParams{ { Types: []ParamType{}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b01110110}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b01110110}, nil }, }, } result["STOP"] = []InstructionParams{ { Types: []ParamType{}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00010000, 0b00000000}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b00010000, 0b00000000}, nil }, }, } result["RLCA"] = []InstructionParams{ { Types: []ParamType{}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00000111}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b00000111}, nil }, }, } result["RLA"] = []InstructionParams{ { Types: []ParamType{}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00010111}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b00010111}, nil }, }, } result["RRCA"] = []InstructionParams{ { Types: []ParamType{}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00001111}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b00001111}, nil }, }, } result["RRA"] = []InstructionParams{ { Types: []ParamType{}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { return []byte{0b00011111}, nil }, + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b00011111}, nil }, }, } result["BIT"] = []InstructionParams{ { Types: []ParamType{BitOrdinal, Reg8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11001011, 0b01000000 | (uint8(args[0]) << 3) | uint8(args[1])}, nil }, }, @@ -411,7 +411,7 @@ func InstructionSetNew() InstructionSet { result["SET"] = []InstructionParams{ { Types: []ParamType{BitOrdinal, Reg8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11001011, 0b11000000 | (uint8(args[0]) << 3) | uint8(args[1])}, nil }, }, @@ -419,7 +419,7 @@ func InstructionSetNew() InstructionSet { result["RES"] = []InstructionParams{ { Types: []ParamType{BitOrdinal, Reg8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11001011, 0b10000000 | (uint8(args[0]) << 3) | uint8(args[1])}, nil }, }, @@ -427,7 +427,7 @@ func InstructionSetNew() InstructionSet { result["RLC"] = []InstructionParams{ { Types: []ParamType{Reg8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11001011, 0b00000000 | uint8(args[0])}, nil }, }, @@ -435,7 +435,7 @@ func InstructionSetNew() InstructionSet { result["RL"] = []InstructionParams{ { Types: []ParamType{Reg8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11001011, 0b00010000 | uint8(args[0])}, nil }, }, @@ -443,7 +443,7 @@ func InstructionSetNew() InstructionSet { result["RRC"] = []InstructionParams{ { Types: []ParamType{Reg8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11001011, 0b00001000 | uint8(args[0])}, nil }, }, @@ -451,7 +451,7 @@ func InstructionSetNew() InstructionSet { result["RR"] = []InstructionParams{ { Types: []ParamType{Reg8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11001011, 0b00011000 | uint8(args[0])}, nil }, }, @@ -459,7 +459,7 @@ func InstructionSetNew() InstructionSet { result["SLA"] = []InstructionParams{ { Types: []ParamType{Reg8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11001011, 0b00100000 | uint8(args[0])}, nil }, }, @@ -467,7 +467,7 @@ func InstructionSetNew() InstructionSet { result["SWAP"] = []InstructionParams{ { Types: []ParamType{Reg8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11001011, 0b00110000 | uint8(args[0])}, nil }, }, @@ -475,7 +475,7 @@ func InstructionSetNew() InstructionSet { result["SRA"] = []InstructionParams{ { Types: []ParamType{Reg8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11001011, 0b00101000 | uint8(args[0])}, nil }, }, @@ -483,7 +483,7 @@ func InstructionSetNew() InstructionSet { result["SRL"] = []InstructionParams{ { Types: []ParamType{Reg8}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11001011, 0b00111000 | uint8(args[0])}, nil }, }, @@ -491,7 +491,7 @@ func InstructionSetNew() InstructionSet { result["DBG"] = []InstructionParams{ { Types: []ParamType{}, - Assembler: func(_ uint16, args []uint16) ([]byte, error) { + Assembler: func(_ uint32, args []uint32) ([]byte, error) { return []byte{0b11010011}, nil }, }, @@ -505,7 +505,7 @@ func (set InstructionSet) Parse( defs *Definitions, isMacro bool, isFirstPass bool, - currentAddress uint16, + currentAddress uint32, lastAbsoluteLabel string, line string, ) ([]byte, error) { @@ -529,7 +529,7 @@ instruction_param_loop: continue } - parsed_params := make([]uint16, len(params)) + parsed_params := make([]uint32, len(params)) for i := range parsed_params { var paramType ParamType if instrParam.Wildcard { @@ -543,7 +543,7 @@ instruction_param_loop: if isFirstPass && !instrParam.LabelsBeforeOnly { accessibleLabels = nil } - parsed, err := paramType(accessibleLabels, lastAbsoluteLabel, defs, params[i]) + parsed, err := paramType(accessibleLabels, lastAbsoluteLabel, defs, currentAddress, params[i]) if err != nil { rejectedError := fmt.Errorf("\t[Rejected] Param Type %v: %w\n", paramType, err) if rejectedErrors == nil { @@ -14,7 +14,7 @@ func InlineMacroAssembler(b []byte) []InstructionParams { return []InstructionParams{ { Types: []ParamType{}, - Assembler: func(currentAddress uint16, args []uint16) ([]uint8, error) { + Assembler: func(currentAddress uint32, args []uint32) ([]uint8, error) { return b, nil }, }, @@ -27,7 +27,7 @@ func NewInstructionSetMacros() InstructionSet { result[".PADTO"] = []InstructionParams{ { Types: []ParamType{Raw16}, - Assembler: func(currentAddress uint16, args []uint16) ([]byte, error) { + Assembler: func(currentAddress uint32, args []uint32) ([]byte, error) { return make([]byte, args[0]-currentAddress), nil }, MacroForbidden: true, @@ -35,7 +35,7 @@ func NewInstructionSetMacros() InstructionSet { }, { Types: []ParamType{Raw16MacroRelativeLabel}, - Assembler: func(currentAddress uint16, args []uint16) ([]byte, error) { + Assembler: func(currentAddress uint32, args []uint32) ([]byte, error) { return make([]byte, args[0]-currentAddress), nil }, MacroForbidden: false, @@ -46,7 +46,7 @@ func NewInstructionSetMacros() InstructionSet { result[".DB"] = []InstructionParams{ { Types: []ParamType{Raw8}, - Assembler: func(currentAddress uint16, args []uint16) ([]byte, error) { + Assembler: func(currentAddress uint32, args []uint32) ([]byte, error) { result := make([]byte, len(args)) for i := range args { result[i] = uint8(args[i]) @@ -57,7 +57,7 @@ func NewInstructionSetMacros() InstructionSet { }, { Types: []ParamType{Raw16}, - Assembler: func(currentAddress uint16, args []uint16) ([]byte, error) { + Assembler: func(currentAddress uint32, args []uint32) ([]byte, error) { result := make([]byte, len(args)*2) for i := range args { result[i*2] = uint8(args[i] >> 8) @@ -73,10 +73,11 @@ func NewInstructionSetMacros() InstructionSet { } type ( - Indirect8b uint16 - Indirect16b uint16 - Raw8b uint16 - Raw16b uint16 + Indirect8b uint32 + Indirect16b uint32 + Raw8b uint32 + Raw16b uint32 + ROMAddressPtr uint32 ) func MacroParse( @@ -102,7 +103,7 @@ func MacroParse( &state.Defs, state.IsMacro, isFirstPass, - uint16(uint(len(*result))+offset), + uint32(uint(len(*result))+offset), LastAbsoluteLabel, line, ) @@ -151,13 +152,13 @@ func MacroParse( } var definedValue any - if v, err := Raw8Indirect(&state.Labels, LastAbsoluteLabel, &state.Defs, words[2]); err == nil { + if v, err := Raw8Indirect(&state.Labels, LastAbsoluteLabel, &state.Defs, 0xffffffff, words[2]); err == nil { definedValue = Indirect8b(v) - } else if v, err := Raw16Indirect(&state.Labels, LastAbsoluteLabel, &state.Defs, words[2]); err == nil { + } else if v, err := Raw16Indirect(&state.Labels, LastAbsoluteLabel, &state.Defs, 0xffffffff, words[2]); err == nil { definedValue = Indirect16b(v) - } else if v, err := Raw8(&state.Labels, LastAbsoluteLabel, &state.Defs, words[2]); err == nil { + } else if v, err := Raw8(&state.Labels, LastAbsoluteLabel, &state.Defs, 0xffffffff, words[2]); err == nil { definedValue = Raw8b(v) - } else if v, err := Raw16(&state.Labels, LastAbsoluteLabel, &state.Defs, words[2]); err == nil { + } else if v, err := Raw16(&state.Labels, LastAbsoluteLabel, &state.Defs, 0xffffffff, words[2]); err == nil { definedValue = Raw16b(v) } else { return fmt.Errorf("\"%s\" could not be parsed as a .DEFINE argument", words[2]) @@ -181,8 +182,12 @@ func MacroParse( } parameterTypes := make([]ParamType, len(definedMacroArguments)) - for i := range definedMacroArguments { - parameterTypes[i] = Raw16 + for i, v := range definedMacroArguments { + if len(v) != 0 && v[0] == '=' { + parameterTypes[i] = ROMAddress + } else { + parameterTypes[i] = Raw16 + } } if isFirstPass { @@ -193,13 +198,18 @@ func MacroParse( MacroInstructions["."+definedMacroName] = []InstructionParams{ { Types: parameterTypes, - Assembler: func(currentAddress uint16, args []uint16) ([]uint8, error) { + Assembler: func(currentAddress uint32, args []uint32) ([]uint8, error) { definitions := Clone(state.Defs) + labels := Clone(state.Labels) for i, macroArg := range definedMacroArguments { - definitions[macroArg] = Raw16b(args[i]) + if len(macroArg) != 0 && macroArg[0] == '=' { + labels[macroArg[1:]] = uint(args[i]) + } else { + definitions[macroArg] = Raw16b(args[i]) + } } state := ProgramState{ - Labels: Clone(state.Labels), + Labels: labels, Defs: definitions, IsMacro: true, } @@ -215,13 +225,18 @@ func MacroParse( MacroInstructions["."+definedMacroName] = []InstructionParams{ { Types: parameterTypes, - Assembler: func(currentAddress uint16, args []uint16) ([]uint8, error) { + Assembler: func(currentAddress uint32, args []uint32) ([]uint8, error) { definitions := Clone(state.Defs) + labels := Clone(state.Labels) for i, macroArg := range definedMacroArguments { - definitions[macroArg] = Raw16b(args[i]) + if len(macroArg) != 0 && macroArg[0] == '=' { + labels[macroArg[1:]] = uint(args[i]) + } else { + definitions[macroArg] = Raw16b(args[i]) + } } state := ProgramState{ - Labels: Clone(state.Labels), + Labels: labels, Defs: definitions, IsMacro: true, } @@ -209,7 +209,7 @@ func secondPass( ) } } else { - nextInstruction, err := Instructions.Parse(&state.Labels, &state.Defs, state.IsMacro, false, uint16(uint(len(result))+offset), lastAbsoluteLabel, line) + nextInstruction, err := Instructions.Parse(&state.Labels, &state.Defs, state.IsMacro, false, uint32(uint(len(result))+offset), lastAbsoluteLabel, line) if err != nil { return nil, fmt.Errorf( "File %s, line %d (2nd pass): %w", diff --git a/parameters.go b/parameters.go index 06202f9..5dffc1c 100644 --- a/parameters.go +++ b/parameters.go @@ -6,7 +6,7 @@ import ( "strings" ) -func parseOffset(param string) (string, uint16, error) { +func parseOffset(param string) (string, uint32, error) { if strings.Contains(param, "+") { labelParts := strings.Split(param, "+") if len(labelParts) != 2 { @@ -16,17 +16,23 @@ func parseOffset(param string) (string, uint16, error) { ) } labelWithoutOffset := labelParts[0] - o, err := strconv.ParseUint(labelParts[1], 0, 16) + o, err := strconv.ParseUint(labelParts[1], 0, 32) if err != nil { return "", 0, fmt.Errorf("Error while parsing label offset: %w", err) } - offset := uint16(o) + offset := uint32(o) return labelWithoutOffset, offset, nil } return param, 0, nil } -func Reg8(_ *Labels, lastAbsoluteLabel string, _ *Definitions, param string) (uint16, error) { +func Reg8( + _ *Labels, + lastAbsoluteLabel string, + _ *Definitions, + _ uint32, + param string, +) (uint32, error) { switch param { case "A": return 7, nil @@ -48,35 +54,65 @@ func Reg8(_ *Labels, lastAbsoluteLabel string, _ *Definitions, param string) (ui return 0, fmt.Errorf("Invalid reg8") } -func A(_ *Labels, lastAbsoluteLabel string, _ *Definitions, param string) (uint16, error) { +func A( + _ *Labels, + lastAbsoluteLabel string, + _ *Definitions, + _ uint32, + param string, +) (uint32, error) { if param == "A" { return 0, nil } return 0, fmt.Errorf("Invalid A") } -func HL(_ *Labels, lastAbsoluteLabel string, _ *Definitions, param string) (uint16, error) { +func HL( + _ *Labels, + lastAbsoluteLabel string, + _ *Definitions, + _ uint32, + param string, +) (uint32, error) { if param == "HL" { return 0, nil } return 0, fmt.Errorf("Invalid HL") } -func SP(_ *Labels, lastAbsoluteLabel string, _ *Definitions, param string) (uint16, error) { +func SP( + _ *Labels, + lastAbsoluteLabel string, + _ *Definitions, + _ uint32, + param string, +) (uint32, error) { if param == "SP" { return 0, nil } return 0, fmt.Errorf("Invalid SP") } -func IndirectC(_ *Labels, lastAbsoluteLabel string, _ *Definitions, param string) (uint16, error) { +func IndirectC( + _ *Labels, + lastAbsoluteLabel string, + _ *Definitions, + _ uint32, + param string, +) (uint32, error) { if param == "(C)" { return 0, nil } return 0, fmt.Errorf("Invalid (C)") } -func Reg16(_ *Labels, lastAbsoluteLabel string, _ *Definitions, param string) (uint16, error) { +func Reg16( + _ *Labels, + lastAbsoluteLabel string, + _ *Definitions, + _ uint32, + param string, +) (uint32, error) { switch param { case "BC": return 0, nil @@ -97,28 +133,36 @@ func Raw8( labels *Labels, lastAbsoluteLabel string, defs *Definitions, + currentAddress uint32, param string, -) (uint16, error) { +) (uint32, error) { if strings.HasPrefix(param, "high(") && strings.HasSuffix(param, ")") { - v, err := Raw16(labels, lastAbsoluteLabel, defs, param[5:len(param)-1]) + v, err := Raw16(labels, lastAbsoluteLabel, defs, currentAddress, param[5:len(param)-1]) if err != nil { return 0, err } - return uint16(v >> 8), nil + return uint32(v >> 8), nil } if strings.HasPrefix(param, "low(") && strings.HasSuffix(param, ")") { - v, err := Raw16(labels, lastAbsoluteLabel, defs, param[4:len(param)-1]) + v, err := Raw16(labels, lastAbsoluteLabel, defs, currentAddress, param[4:len(param)-1]) if err != nil { return 0, err } - return uint16(v & 0xff), nil + return uint32(v & 0xff), nil } if strings.HasPrefix(param, "inv(") && strings.HasSuffix(param, ")") { - v, err := Raw8(labels, lastAbsoluteLabel, defs, param[4:len(param)-1]) + v, err := Raw8(labels, lastAbsoluteLabel, defs, currentAddress, param[4:len(param)-1]) if err != nil { return 0, err } - return uint16((256 / v) & 0xff), nil + return uint32((256 / v) & 0xff), nil + } + if strings.HasPrefix(param, "bank(") && strings.HasSuffix(param, ")") { + v, err := ROMAddress(labels, lastAbsoluteLabel, defs, currentAddress, param[5:len(param)-1]) + if err != nil { + return 0, err + } + return uint32((v / 0x4000) & 0xff), nil } if strings.HasPrefix(param, "$") { param = strings.ToUpper(strings.TrimPrefix(param, "$")) @@ -126,7 +170,7 @@ func Raw8( if len(param) > 2 { return 0, fmt.Errorf("%s is > 8bit", param) } - return uint16(res), nil + return uint32(res), nil } varWithoutOffset, offset, err := parseOffset(param) @@ -148,54 +192,69 @@ func Raw8( ) } - if uint16(res)+offset > 0xff { + if uint32(res)+offset > 0xff { return 0, fmt.Errorf( "overflow: $%s (0x%02x) + 0x%02x exceeds 0xff", varWithoutOffset, - uint16(res), + uint32(res), offset, ) } - return uint16(res) + offset, nil + return uint32(res) + offset, nil } if strings.HasPrefix(param, "0x") && len(param) > 4 { return 0, fmt.Errorf("%s is > 8bit", param) } res, err := strconv.ParseUint(param, 0, 8) - return uint16(res), err + return uint32(res), err } func Raw16( labels *Labels, lastAbsoluteLabel string, defs *Definitions, + currentAddress uint32, param string, -) (uint16, error) { +) (uint32, error) { + if strings.HasPrefix(param, "ptr(") && strings.HasSuffix(param, ")") { + v, err := ROMAddress(labels, lastAbsoluteLabel, defs, currentAddress, param[4:len(param)-1]) + if err != nil { + return 0, err + } + + bank := v / 0x4000 + if bank == 0 { + return v, nil + } + + return v - bank*0x4000 + 0x4000, nil + } + if strings.Contains(param, "-") { spl := strings.Split(param, "-") - v, err := Raw16(labels, lastAbsoluteLabel, defs, spl[0]) + v, err := Raw16(labels, lastAbsoluteLabel, defs, currentAddress, spl[0]) if err != nil { return 0, err } result := v for _, arg := range spl[1:] { - v, err := Raw16(labels, lastAbsoluteLabel, defs, arg) + v, err := Raw16(labels, lastAbsoluteLabel, defs, currentAddress, arg) if err != nil { return 0, err } result -= v } - return result, nil + return result & 0xffff, nil } if strings.HasPrefix(param, "$") { param = strings.ToUpper(strings.TrimPrefix(param, "$")) if res, err := strconv.ParseUint(param, 16, 16); err == nil { - return uint16(res), nil + return uint32(res & 0xffff), nil } varWithoutOffset, offset, err := parseOffset(param) @@ -221,74 +280,63 @@ func Raw16( return 0, fmt.Errorf( "overflow: $%s (0x%04x) + 0x%04x exceeds 0xffff", varWithoutOffset, - uint16(res), + uint32(res), offset, ) } - return uint16(res) + offset, nil + return uint32(res) + offset, nil } - if strings.HasPrefix(param, "=") { - labelWithoutOffset, offset, err := parseOffset(param[1:]) - if err != nil { - return 0, err - } - - if labels == nil { - return 0, nil - } + romAddr, err := ROMAddress(labels, lastAbsoluteLabel, defs, currentAddress, param) + if err == nil { + currentBank := currentAddress / 0x4000 + romAddrBank := romAddr / 0x4000 - if strings.HasPrefix(labelWithoutOffset, ".") { - if lastAbsoluteLabel == "" { - return 0, fmt.Errorf( - "Relative label \"%s\" referenced outside of parent", - labelWithoutOffset, - ) - } - labelWithoutOffset = lastAbsoluteLabel + labelWithoutOffset + if romAddrBank == 0 { + return romAddr, nil } - label := strings.ToUpper(strings.TrimPrefix(labelWithoutOffset, "=")) - labelValue, ok := (*labels)[label] - if !ok { - return 0, fmt.Errorf("Label \"%s\" not found", label) - } - - // TODO: Manage when multiple MBC - if labelValue > 0x8000 { - panic("Switchable ROM banks are not implemented yet") + if currentBank != romAddrBank { + return 0, fmt.Errorf( + "Cannot use an address from another bank (or bank 0). Please change the bank using bank(x) and get the raw bankless ptr using ptr(x). %s in bank %v, but current address is %v", + param, + romAddrBank, + currentBank, + ) } - return uint16(labelValue) + offset, nil + return romAddr - romAddrBank*0x4000 + 0x4000, nil } res, err := strconv.ParseUint(param, 0, 16) - return uint16(res), err + return uint32(res), err } func Raw16MacroRelativeLabel( labels *Labels, lastAbsoluteLabel string, defs *Definitions, + currentAddress uint32, param string, -) (uint16, error) { +) (uint32, error) { if !strings.HasPrefix(param, "=$") { return 0, fmt.Errorf( "label \"%s\" is external to the macro", param, ) } - return Raw16(labels, lastAbsoluteLabel, defs, param) + return Raw16(labels, lastAbsoluteLabel, defs, currentAddress, param) } func Reg16Indirect( _ *Labels, lastAbsoluteLabel string, _ *Definitions, + _ uint32, param string, -) (uint16, error) { +) (uint32, error) { switch param { case "(BC)": return 0, nil @@ -306,8 +354,9 @@ func Raw8Indirect( labels *Labels, lastAbsoluteLabel string, defs *Definitions, + currentAddress uint32, param string, -) (uint16, error) { +) (uint32, error) { if strings.HasPrefix(param, "$") { param = strings.ToUpper(strings.TrimPrefix(param, "$")) @@ -320,14 +369,14 @@ func Raw8Indirect( if !ok { return 0, fmt.Errorf("$%s is of type %T but Indirect8bb is expected", param, definition) } - return uint16(res), nil + return uint32(res), nil } if len(param) < 2 || param[0] != '(' || param[len(param)-1] != ')' { return 0, fmt.Errorf("Invalid raw8indirect") } - res, err := Raw8(labels, lastAbsoluteLabel, defs, param[1:len(param)-1]) + res, err := Raw8(labels, lastAbsoluteLabel, defs, currentAddress, param[1:len(param)-1]) if err == nil { return res, nil } @@ -338,8 +387,9 @@ func Raw16Indirect( labels *Labels, lastAbsoluteLabel string, defs *Definitions, + currentAddress uint32, param string, -) (uint16, error) { +) (uint32, error) { if strings.HasPrefix(param, "$") { param = strings.ToUpper(strings.TrimPrefix(param, "$")) @@ -356,16 +406,79 @@ func Raw16Indirect( if !ok { return 0, fmt.Errorf("$%s is of type %T but Indirect16b expected", param, definition) } - return uint16(res), nil + return uint32(res), nil } if len(param) < 2 || param[0] != '(' || param[len(param)-1] != ')' { return 0, fmt.Errorf("Invalid raw16indirect") } - return Raw16(labels, lastAbsoluteLabel, defs, param[1:len(param)-1]) + return Raw16(labels, lastAbsoluteLabel, defs, currentAddress, param[1:len(param)-1]) } -func Condition(_ *Labels, lastAbsoluteLabel string, _ *Definitions, param string) (uint16, error) { +func ROMAddress( + labels *Labels, + lastAbsoluteLabel string, + defs *Definitions, + currentAddress uint32, + param string, +) (uint32, error) { + if strings.HasPrefix(param, "=") { + labelWithoutOffset, offset, err := parseOffset(param[1:]) + if err != nil { + return 0, err + } + + if labels == nil { + return 0, nil + } + + if strings.HasPrefix(labelWithoutOffset, ".") { + if lastAbsoluteLabel == "" { + return 0, fmt.Errorf( + "Relative label \"%s\" referenced outside of parent", + labelWithoutOffset, + ) + } + labelWithoutOffset = lastAbsoluteLabel + labelWithoutOffset + } + + label := strings.ToUpper(strings.TrimPrefix(labelWithoutOffset, "=")) + labelValue, ok := (*labels)[label] + if !ok { + return 0, fmt.Errorf("Label \"%s\" not found", label) + } + + return uint32(labelValue) + offset, nil + } + + if len(param) != 7 || param[2] != ':' { + return 0, fmt.Errorf("Couldn't parse \"%s\" as a ROM addr", param) + } + + bank, err := strconv.ParseUint(param[0:2], 16, 8) + if err != nil { + return 0, fmt.Errorf( + "Couldn't parse bank number in \"%s\"", param, + ) + } + + addr, err := strconv.ParseUint(param[3:], 16, 8) + if err != nil { + return 0, fmt.Errorf( + "Couldn't parse address in \"%s\"", param, + ) + } + + return uint32(bank*0x4000 + addr), nil +} + +func Condition( + _ *Labels, + lastAbsoluteLabel string, + _ *Definitions, + _ uint32, + param string, +) (uint32, error) { switch param { case "NZ": return 0, nil @@ -379,7 +492,13 @@ func Condition(_ *Labels, lastAbsoluteLabel string, _ *Definitions, param string return 0, fmt.Errorf("Invalid condition") } -func BitOrdinal(_ *Labels, lastAbsoluteLabel string, _ *Definitions, param string) (uint16, error) { +func BitOrdinal( + _ *Labels, + lastAbsoluteLabel string, + _ *Definitions, + _ uint32, + param string, +) (uint32, error) { res, err := strconv.ParseUint(param, 0, 3) - return uint16(res), err + return uint32(res), err } |