From a85dbc3c3f6f0ee2ac1190884f49737ee59bb2f8 Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Sun, 20 Jul 2025 12:42:53 +0200 Subject: [PATCH] Fixed syscall encoding on arm64 macs --- src/arm/Syscall.go | 4 ++-- src/arm/Syscall_test.go | 24 ++++++++++++++++++++++++ src/arm/arm_test.go | 1 - src/arm/encode.go | 2 +- src/asm/compilerARM.go | 8 +++++++- 5 files changed, 34 insertions(+), 5 deletions(-) create mode 100644 src/arm/Syscall_test.go diff --git a/src/arm/Syscall.go b/src/arm/Syscall.go index 1617a9e..d4dea68 100644 --- a/src/arm/Syscall.go +++ b/src/arm/Syscall.go @@ -1,6 +1,6 @@ package arm // Syscall is the primary way to communicate with the OS kernel. -func Syscall() uint32 { - return 0xD4000001 +func Syscall(imm16 int) uint32 { + return 0b11010100000<<21 | uint32(imm16&mask16)<<5 | 0b00001 } \ No newline at end of file diff --git a/src/arm/Syscall_test.go b/src/arm/Syscall_test.go new file mode 100644 index 0000000..8c0db32 --- /dev/null +++ b/src/arm/Syscall_test.go @@ -0,0 +1,24 @@ +package arm_test + +import ( + "testing" + + "git.urbach.dev/cli/q/src/arm" + "git.urbach.dev/go/assert" +) + +func TestSyscall(t *testing.T) { + usagePatterns := []struct { + Number int + Code uint32 + }{ + {0, 0xD4000001}, + {0xFFFF, 0xD41FFFE1}, + } + + for _, pattern := range usagePatterns { + t.Logf("svc %d", pattern.Number) + code := arm.Syscall(pattern.Number) + assert.Equal(t, code, pattern.Code) + } +} \ No newline at end of file diff --git a/src/arm/arm_test.go b/src/arm/arm_test.go index 100f2a6..dbc29d5 100644 --- a/src/arm/arm_test.go +++ b/src/arm/arm_test.go @@ -10,7 +10,6 @@ import ( func TestConstants(t *testing.T) { assert.DeepEqual(t, arm.Nop(), 0xD503201F) assert.DeepEqual(t, arm.Return(), 0xD65F03C0) - assert.DeepEqual(t, arm.Syscall(), 0xD4000001) } func TestNotEncodable(t *testing.T) { diff --git a/src/arm/encode.go b/src/arm/encode.go index de5ddbb..d66737a 100644 --- a/src/arm/encode.go +++ b/src/arm/encode.go @@ -6,7 +6,7 @@ import ( // memory encodes an instruction with a register, a base register, an addressing mode and an offset. func memory(destination cpu.Register, base cpu.Register, mode AddressMode, imm9 int) uint32 { - return uint32(imm9&mask9)<<12 | uint32(mode<<10) | uint32(base)<<5 | uint32(destination) + return uint32(imm9&mask9)<<12 | uint32(mode)<<10 | uint32(base)<<5 | uint32(destination) } // pair encodes an instruction using a register pair with memory. diff --git a/src/asm/compilerARM.go b/src/asm/compilerARM.go index 684bf11..5c870fe 100644 --- a/src/asm/compilerARM.go +++ b/src/asm/compilerARM.go @@ -5,6 +5,7 @@ import ( "fmt" "git.urbach.dev/cli/q/src/arm" + "git.urbach.dev/cli/q/src/config" "git.urbach.dev/cli/q/src/token" ) @@ -149,7 +150,12 @@ func (c *compilerARM) Compile(instr Instruction) { case *StackFrameEnd: c.append(arm.LoadRegister(arm.LR, arm.SP, arm.PostIndex, 16, 8)) case *Syscall: - c.append(arm.Syscall()) + switch c.build.OS { + case config.Mac: + c.append(arm.Syscall(0xFFFF)) + default: + c.append(arm.Syscall(0)) + } default: panic("unknown instruction") } -- 2.51.2