Added fallback for numbers that can't be encoded on arm64

This commit is contained in:
Eduard Urbach 2025-03-17 13:36:42 +01:00
parent d5118148c9
commit 2a8d4fcc6d
Signed by: eduard
GPG key ID: 49226B848C78F6C8
11 changed files with 138 additions and 90 deletions

View file

@ -8,8 +8,45 @@ import (
"git.urbach.dev/cli/q/src/asm"
)
func (c *compiler) compileARM(x asm.Instruction) {
func (c *compiler) ARM(x asm.Instruction) {
switch x.Mnemonic {
case asm.MOVE:
switch x.Type {
case asm.TypeRegisterRegister:
operands := c.assembler.Param.RegisterRegister[x.Index]
c.append(arm.MoveRegisterRegister(operands.Destination, operands.Source))
case asm.TypeRegisterNumber:
operands := c.assembler.Param.RegisterNumber[x.Index]
c.code = arm.MoveRegisterNumber(c.code, operands.Register, operands.Number)
case asm.TypeRegisterLabel:
operands := c.assembler.Param.RegisterLabel[x.Index]
position := Address(len(c.code))
c.append(arm.LoadAddress(operands.Register, 0))
if operands.Label.Type == asm.DataLabel {
c.dataPointers = append(c.dataPointers, &pointer{
Position: position,
OpSize: 0,
Size: 4,
Resolve: func() Address {
destination, exists := c.dataLabels[operands.Label.Name]
if !exists {
panic("unknown label")
}
destination += c.dataStart - c.codeStart
distance := destination - position + 8
return arm.LoadAddress(operands.Register, int(distance))
},
})
} else {
panic("not implemented")
}
}
case asm.CALL:
switch x.Type {
case asm.TypeLabel:
@ -84,11 +121,19 @@ func (c *compiler) compileARM(x asm.Instruction) {
}
}
case asm.RETURN:
c.append(arm.LoadPair(arm.FP, arm.LR, arm.SP, 16))
c.append(arm.Return())
case asm.SYSCALL:
c.append(arm.Syscall())
case asm.PUSH:
switch x.Type {
case asm.TypeRegister:
operand := c.assembler.Param.Register[x.Index]
c.append(arm.SubRegisterNumber(arm.SP, arm.SP, 16))
code, _ := arm.SubRegisterNumber(arm.SP, arm.SP, 16)
c.append(code)
c.append(arm.StoreRegister(operand.Register, arm.SP, 0, 8))
}
@ -97,7 +142,8 @@ func (c *compiler) compileARM(x asm.Instruction) {
case asm.TypeRegister:
operand := c.assembler.Param.Register[x.Index]
c.append(arm.LoadRegister(operand.Register, arm.SP, 0, 8))
c.append(arm.AddRegisterNumber(arm.SP, arm.SP, 16))
code, _ := arm.AddRegisterNumber(arm.SP, arm.SP, 16)
c.append(code)
}
case asm.AND:
@ -158,7 +204,15 @@ func (c *compiler) compileARM(x asm.Instruction) {
switch x.Type {
case asm.TypeRegisterNumber:
operand := c.assembler.Param.RegisterNumber[x.Index]
c.append(arm.AddRegisterNumber(operand.Register, operand.Register, operand.Number))
code, encodable := arm.AddRegisterNumber(operand.Register, operand.Register, operand.Number)
if encodable {
c.append(code)
} else {
tmp := arm.X28
c.code = arm.MoveRegisterNumber(c.code, tmp, operand.Number)
c.append(arm.AddRegisterRegister(operand.Register, operand.Register, tmp))
}
case asm.TypeRegisterRegister:
operand := c.assembler.Param.RegisterRegister[x.Index]
c.append(arm.AddRegisterRegister(operand.Destination, operand.Destination, operand.Source))
@ -168,7 +222,15 @@ func (c *compiler) compileARM(x asm.Instruction) {
switch x.Type {
case asm.TypeRegisterNumber:
operand := c.assembler.Param.RegisterNumber[x.Index]
c.append(arm.SubRegisterNumber(operand.Register, operand.Register, operand.Number))
code, encodable := arm.SubRegisterNumber(operand.Register, operand.Register, operand.Number)
if encodable {
c.append(code)
} else {
tmp := arm.X28
c.code = arm.MoveRegisterNumber(c.code, tmp, operand.Number)
c.append(arm.SubRegisterRegister(operand.Register, operand.Register, tmp))
}
case asm.TypeRegisterRegister:
operand := c.assembler.Param.RegisterRegister[x.Index]
c.append(arm.SubRegisterRegister(operand.Destination, operand.Destination, operand.Source))
@ -178,7 +240,15 @@ func (c *compiler) compileARM(x asm.Instruction) {
switch x.Type {
case asm.TypeRegisterNumber:
operand := c.assembler.Param.RegisterNumber[x.Index]
c.append(arm.CompareRegisterNumber(operand.Register, operand.Number))
code, encodable := arm.CompareRegisterNumber(operand.Register, operand.Number)
if encodable {
c.append(code)
} else {
tmp := arm.X28
c.code = arm.MoveRegisterNumber(c.code, tmp, operand.Number)
c.append(arm.CompareRegisterRegister(operand.Register, tmp))
}
case asm.TypeRegisterRegister:
operand := c.assembler.Param.RegisterRegister[x.Index]
c.append(arm.CompareRegisterRegister(operand.Destination, operand.Source))
@ -219,43 +289,6 @@ func (c *compiler) compileARM(x asm.Instruction) {
case asm.JE, asm.JNE, asm.JG, asm.JGE, asm.JL, asm.JLE, asm.JUMP:
c.jumpARM(x)
case asm.MOVE:
switch x.Type {
case asm.TypeRegisterRegister:
operands := c.assembler.Param.RegisterRegister[x.Index]
c.append(arm.MoveRegisterRegister(operands.Destination, operands.Source))
case asm.TypeRegisterNumber:
operands := c.assembler.Param.RegisterNumber[x.Index]
c.code = arm.MoveRegisterNumber(c.code, operands.Register, operands.Number)
case asm.TypeRegisterLabel:
operands := c.assembler.Param.RegisterLabel[x.Index]
position := Address(len(c.code))
c.append(arm.LoadAddress(operands.Register, 0))
if operands.Label.Type == asm.DataLabel {
c.dataPointers = append(c.dataPointers, &pointer{
Position: position,
OpSize: 0,
Size: 4,
Resolve: func() Address {
destination, exists := c.dataLabels[operands.Label.Name]
if !exists {
panic("unknown label")
}
destination += c.dataStart - c.codeStart
distance := destination - position + 8
return arm.LoadAddress(operands.Register, int(distance))
},
})
} else {
panic("not implemented")
}
}
case asm.SHIFTL:
switch x.Type {
case asm.TypeRegisterNumber:
@ -274,13 +307,6 @@ func (c *compiler) compileARM(x asm.Instruction) {
panic("not implemented")
}
case asm.RETURN:
c.append(arm.LoadPair(arm.FP, arm.LR, arm.SP, 16))
c.append(arm.Return())
case asm.SYSCALL:
c.append(arm.Syscall())
default:
panic("unknown mnemonic: " + x.Mnemonic.String())
}

View file

@ -28,12 +28,12 @@ func Finalize(a *asm.Assembler, dlls dll.List) ([]byte, []byte) {
switch config.TargetArch {
case config.ARM:
for _, x := range a.Instructions {
c.compileARM(x)
c.ARM(x)
}
case config.X86:
for _, x := range a.Instructions {
c.compileX86(x)
c.X86(x)
}
}

View file

@ -5,8 +5,30 @@ import (
"git.urbach.dev/cli/q/src/x86"
)
func (c *compiler) compileX86(x asm.Instruction) {
func (c *compiler) X86(x asm.Instruction) {
switch x.Mnemonic {
case asm.MOVE:
c.move(x)
case asm.CALL:
c.call(x)
case asm.LABEL:
label := c.assembler.Param.Label[x.Index]
c.codeLabels[label.Name] = Address(len(c.code))
case asm.LOAD:
c.load(x)
case asm.STORE:
c.store(x)
case asm.RETURN:
c.code = x86.Return(c.code)
case asm.SYSCALL:
c.code = x86.Syscall(c.code)
case asm.ADD:
switch x.Type {
case asm.TypeRegisterNumber:
@ -81,9 +103,6 @@ func (c *compiler) compileX86(x asm.Instruction) {
}
}
case asm.CALL:
c.call(x)
case asm.COMMENT:
return
@ -103,16 +122,6 @@ func (c *compiler) compileX86(x asm.Instruction) {
case asm.JE, asm.JNE, asm.JG, asm.JGE, asm.JL, asm.JLE, asm.JUMP:
c.jumpX86(x)
case asm.LABEL:
label := c.assembler.Param.Label[x.Index]
c.codeLabels[label.Name] = Address(len(c.code))
case asm.LOAD:
c.load(x)
case asm.MOVE:
c.move(x)
case asm.NEGATE:
switch x.Type {
case asm.TypeRegister:
@ -147,9 +156,6 @@ func (c *compiler) compileX86(x asm.Instruction) {
c.code = x86.PushRegister(c.code, operands.Register)
}
case asm.RETURN:
c.code = x86.Return(c.code)
case asm.SHIFTL:
switch x.Type {
case asm.TypeRegisterNumber:
@ -168,12 +174,6 @@ func (c *compiler) compileX86(x asm.Instruction) {
panic("not implemented")
}
case asm.STORE:
c.store(x)
case asm.SYSCALL:
c.code = x86.Syscall(c.code)
case asm.XOR:
switch x.Type {
case asm.TypeRegisterNumber:

18
src/asmc/bench_test.go Normal file
View file

@ -0,0 +1,18 @@
package asmc_test
import (
"testing"
"git.urbach.dev/cli/q/src/asm"
"git.urbach.dev/cli/q/src/asmc"
"git.urbach.dev/cli/q/src/cpu"
)
func BenchmarkFinalize(b *testing.B) {
a := asm.Assembler{}
a.RegisterNumber(asm.MOVE, cpu.Register(0), 0)
for b.Loop() {
asmc.Finalize(&a, nil)
}
}