aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAstatin <[email protected]>2025-06-10 13:22:11 +0200
committerAstatin <[email protected]>2025-06-10 13:22:11 +0200
commita7d6e62878245810323787eeb5458e418371b89f (patch)
tree003d8ce40e1580ec63360e271fd5e9427984ab2b
parent92ebacf4087babc3766b736aefa99fcaf7b89856 (diff)
Add support for cross bank labels
-rw-r--r--instructions.go164
-rw-r--r--macros.go59
-rw-r--r--main.go2
-rw-r--r--parameters.go255
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 {
diff --git a/macros.go b/macros.go
index 22c300f..2324a14 100644
--- a/macros.go
+++ b/macros.go
@@ -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,
}
diff --git a/main.go b/main.go
index b118b74..34ddbd9 100644
--- a/main.go
+++ b/main.go
@@ -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
}