diff --git a/src/arm/Add.go b/src/arm/Add.go index be6d662..4cacfc0 100644 --- a/src/arm/Add.go +++ b/src/arm/Add.go @@ -4,10 +4,20 @@ import "git.urbach.dev/cli/q/src/cpu" // AddRegisterNumber adds a number to a register. func AddRegisterNumber(destination cpu.Register, source cpu.Register, number int) uint32 { - return addRegisterNumber(0b10, 0, destination, source, number) + return addRegisterNumber(destination, source, number, 0) } // AddRegisterRegister adds a register to a register. func AddRegisterRegister(destination cpu.Register, source cpu.Register, operand cpu.Register) uint32 { - return addRegisterRegister(0b10, 0, destination, source, operand) + return addRegisterRegister(destination, source, operand, 0) +} + +// addRegisterNumber adds the register and optionally updates the condition flags based on the result. +func addRegisterNumber(destination cpu.Register, source cpu.Register, number int, flags uint32) uint32 { + return flags<<29 | 0b100100010<<23 | reg2imm(destination, source, number) +} + +// addRegisterRegister adds the registers and optionally updates the condition flags based on the result. +func addRegisterRegister(destination cpu.Register, source cpu.Register, operand cpu.Register, flags uint32) uint32 { + return flags<<29 | 0b10001011000<<21 | reg3(destination, source, operand) } diff --git a/src/arm/Compare.go b/src/arm/Compare.go index 5bf7d1a..eb5a97e 100644 --- a/src/arm/Compare.go +++ b/src/arm/Compare.go @@ -4,10 +4,14 @@ import "git.urbach.dev/cli/q/src/cpu" // CompareRegisterNumber is an alias for a subtraction that updates the conditional flags and discards the result. func CompareRegisterNumber(register cpu.Register, number int) uint32 { - return addRegisterNumber(0b11, 1, ZR, register, number) + if number < 0 { + return addRegisterNumber(ZR, register, -number, 1) + } + + return subRegisterNumber(ZR, register, number, 1) } // CompareRegisterRegister is an alias for a subtraction that updates the conditional flags and discards the result. func CompareRegisterRegister(reg1 cpu.Register, reg2 cpu.Register) uint32 { - return addRegisterRegister(0b11, 1, ZR, reg1, reg2) + return subRegisterRegister(ZR, reg1, reg2, 1) } diff --git a/src/arm/Compare_test.go b/src/arm/Compare_test.go index 7a3eca1..8224614 100644 --- a/src/arm/Compare_test.go +++ b/src/arm/Compare_test.go @@ -15,6 +15,7 @@ func TestCompareRegisterNumber(t *testing.T) { Code uint32 }{ {arm.X0, 1, 0xF100041F}, + {arm.X0, -1, 0xB100041F}, } for _, pattern := range usagePatterns { diff --git a/src/arm/Sub.go b/src/arm/Sub.go index 415db8d..bf84f50 100644 --- a/src/arm/Sub.go +++ b/src/arm/Sub.go @@ -4,10 +4,20 @@ import "git.urbach.dev/cli/q/src/cpu" // SubRegisterNumber subtracts a number from the given register. func SubRegisterNumber(destination cpu.Register, source cpu.Register, number int) uint32 { - return addRegisterNumber(0b11, 0, destination, source, number) + return subRegisterNumber(destination, source, number, 0) } // SubRegisterRegister subtracts a register from a register. func SubRegisterRegister(destination cpu.Register, source cpu.Register, operand cpu.Register) uint32 { - return addRegisterRegister(0b11, 0, destination, source, operand) + return subRegisterRegister(destination, source, operand, 0) +} + +// subRegisterNumber subtracts the register and optionally updates the condition flags based on the result. +func subRegisterNumber(destination cpu.Register, source cpu.Register, number int, flags uint32) uint32 { + return flags<<29 | 0b110100010<<23 | reg2imm(destination, source, number) +} + +// subRegisterRegister subtracts the registers and optionally updates the condition flags based on the result. +func subRegisterRegister(destination cpu.Register, source cpu.Register, operand cpu.Register, flags uint32) uint32 { + return flags<<29 | 0b11001011000<<21 | reg3(destination, source, operand) } diff --git a/src/arm/encode.go b/src/arm/encode.go index 767573d..38f968d 100644 --- a/src/arm/encode.go +++ b/src/arm/encode.go @@ -2,27 +2,19 @@ package arm import "git.urbach.dev/cli/q/src/cpu" -// addRegisterNumber performs addition or subtraction on the given register -// and optionally updates the condition flags based on the result. -func addRegisterNumber(op uint32, flags uint32, destination cpu.Register, source cpu.Register, number int) uint32 { - number &= 0b1111_1111_1111 - return op<<30 | flags<<29 | 0b100010<<23 | (uint32(number) << 10) | (uint32(source) << 5) | uint32(destination) -} - -// addRegisterRegister performs addition or subtraction on the given registers -// and optionally updates the condition flags based on the result. -func addRegisterRegister(op uint32, flags uint32, destination cpu.Register, source cpu.Register, operand cpu.Register) uint32 { - return op<<30 | flags<<29 | 0b01011000<<21 | reg3(destination, source, operand) -} - // memory encodes an instruction with a register, a base register and an offset. -func memory(destination cpu.Register, base cpu.Register, offset int) uint32 { - return uint32(offset&0b1_1111_1111)<<12 | uint32(base)<<5 | uint32(destination) +func memory(destination cpu.Register, base cpu.Register, imm9 int) uint32 { + return uint32(imm9&0b1_1111_1111)<<12 | uint32(base)<<5 | uint32(destination) } // pair encodes an instruction using a register pair with memory. -func pair(reg1 cpu.Register, reg2 cpu.Register, base cpu.Register, offset int) uint32 { - return uint32(offset&0b111_1111)<<15 | uint32(reg2)<<10 | uint32(base)<<5 | uint32(reg1) +func pair(reg1 cpu.Register, reg2 cpu.Register, base cpu.Register, imm7 int) uint32 { + return uint32(imm7&0b111_1111)<<15 | uint32(reg2)<<10 | uint32(base)<<5 | uint32(reg1) +} + +// reg2imm encodes an instruction with 2 registers and an immediate. +func reg2imm(d cpu.Register, n cpu.Register, imm12 int) uint32 { + return uint32(imm12&0b1111_1111_1111)<<10 | uint32(n)<<5 | uint32(d) } // reg3 encodes an instruction with 3 registers.