From f1d4e65c1be2ce8eb6499ce3eefc59a01bf4d8e1 Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Sun, 28 Jul 2024 21:09:42 +0200 Subject: [PATCH] Implemented move with sign extension --- src/build/arch/x64/Move.go | 22 +++++++++++++++++++++- src/build/arch/x64/Move_test.go | 20 ++++++++++++++++++++ tests/programs/negation.q | 2 +- tests/programs/negative.q | 2 +- tests/programs_test.go | 4 ++-- 5 files changed, 45 insertions(+), 5 deletions(-) diff --git a/src/build/arch/x64/Move.go b/src/build/arch/x64/Move.go index ad6dbda..82f5869 100644 --- a/src/build/arch/x64/Move.go +++ b/src/build/arch/x64/Move.go @@ -9,12 +9,17 @@ import ( // MoveRegisterNumber moves an integer into the given register. func MoveRegisterNumber(code []byte, destination cpu.Register, number int) []byte { w := byte(0) - b := byte(0) if SizeOf(int64(number)) == 8 { w = 1 } + if w == 0 && number < 0 { + return MoveRegisterNumber32(code, destination, number) + } + + b := byte(0) + if destination > 0b111 { b = 1 destination &= 0b111 @@ -33,6 +38,21 @@ func MoveRegisterNumber(code []byte, destination cpu.Register, number int) []byt } } +// MoveRegisterNumber32 moves an integer into the given register and sign-extends the register. +func MoveRegisterNumber32(code []byte, destination cpu.Register, number int) []byte { + b := byte(0) + + if destination > 0b111 { + b = 1 + destination &= 0b111 + } + + code = append(code, REX(1, 0, 0, b)) + code = append(code, 0xC7) + code = append(code, ModRM(AddressDirect, 0, byte(destination))) + return binary.LittleEndian.AppendUint32(code, uint32(number)) +} + // MoveRegisterRegister moves a register value into another register. func MoveRegisterRegister(code []byte, destination cpu.Register, source cpu.Register) []byte { return encode(code, AddressDirect, source, destination, 8, 0x89) diff --git a/src/build/arch/x64/Move_test.go b/src/build/arch/x64/Move_test.go index cbbe134..66cfb4a 100644 --- a/src/build/arch/x64/Move_test.go +++ b/src/build/arch/x64/Move_test.go @@ -14,6 +14,7 @@ func TestMoveRegisterNumber(t *testing.T) { Number int Code []byte }{ + // 32 bits {x64.RAX, 0x7FFFFFFF, []byte{0xB8, 0xFF, 0xFF, 0xFF, 0x7F}}, {x64.RCX, 0x7FFFFFFF, []byte{0xB9, 0xFF, 0xFF, 0xFF, 0x7F}}, {x64.RDX, 0x7FFFFFFF, []byte{0xBA, 0xFF, 0xFF, 0xFF, 0x7F}}, @@ -31,6 +32,7 @@ func TestMoveRegisterNumber(t *testing.T) { {x64.R14, 0x7FFFFFFF, []byte{0x41, 0xBE, 0xFF, 0xFF, 0xFF, 0x7F}}, {x64.R15, 0x7FFFFFFF, []byte{0x41, 0xBF, 0xFF, 0xFF, 0xFF, 0x7F}}, + // 64 bits {x64.RAX, 0x7FFFFFFFFFFFFFFF, []byte{0x48, 0xB8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F}}, {x64.RCX, 0x7FFFFFFFFFFFFFFF, []byte{0x48, 0xB9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F}}, {x64.RDX, 0x7FFFFFFFFFFFFFFF, []byte{0x48, 0xBA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F}}, @@ -47,6 +49,24 @@ func TestMoveRegisterNumber(t *testing.T) { {x64.R13, 0x7FFFFFFFFFFFFFFF, []byte{0x49, 0xBD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F}}, {x64.R14, 0x7FFFFFFFFFFFFFFF, []byte{0x49, 0xBE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F}}, {x64.R15, 0x7FFFFFFFFFFFFFFF, []byte{0x49, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F}}, + + // Negative numbers + {x64.RAX, -1, []byte{0x48, 0xC7, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF}}, + {x64.RCX, -1, []byte{0x48, 0xC7, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF}}, + {x64.RDX, -1, []byte{0x48, 0xC7, 0xC2, 0xFF, 0xFF, 0xFF, 0xFF}}, + {x64.RBX, -1, []byte{0x48, 0xC7, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF}}, + {x64.RSP, -1, []byte{0x48, 0xC7, 0xC4, 0xFF, 0xFF, 0xFF, 0xFF}}, + {x64.RBP, -1, []byte{0x48, 0xC7, 0xC5, 0xFF, 0xFF, 0xFF, 0xFF}}, + {x64.RSI, -1, []byte{0x48, 0xC7, 0xC6, 0xFF, 0xFF, 0xFF, 0xFF}}, + {x64.RDI, -1, []byte{0x48, 0xC7, 0xC7, 0xFF, 0xFF, 0xFF, 0xFF}}, + {x64.R8, -1, []byte{0x49, 0xC7, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF}}, + {x64.R9, -1, []byte{0x49, 0xC7, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF}}, + {x64.R10, -1, []byte{0x49, 0xC7, 0xC2, 0xFF, 0xFF, 0xFF, 0xFF}}, + {x64.R11, -1, []byte{0x49, 0xC7, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF}}, + {x64.R12, -1, []byte{0x49, 0xC7, 0xC4, 0xFF, 0xFF, 0xFF, 0xFF}}, + {x64.R13, -1, []byte{0x49, 0xC7, 0xC5, 0xFF, 0xFF, 0xFF, 0xFF}}, + {x64.R14, -1, []byte{0x49, 0xC7, 0xC6, 0xFF, 0xFF, 0xFF, 0xFF}}, + {x64.R15, -1, []byte{0x49, 0xC7, 0xC7, 0xFF, 0xFF, 0xFF, 0xFF}}, } for _, pattern := range usagePatterns { diff --git a/tests/programs/negation.q b/tests/programs/negation.q index aea1133..94e2826 100644 --- a/tests/programs/negation.q +++ b/tests/programs/negation.q @@ -1,5 +1,5 @@ main() { - syscall(60, f(-32)) + assert f(-32) == 32 } f(x) { diff --git a/tests/programs/negative.q b/tests/programs/negative.q index 2bddfb7..f300e48 100644 --- a/tests/programs/negative.q +++ b/tests/programs/negative.q @@ -1,5 +1,5 @@ main() { a := -32 b := 64 - syscall(60, a + b) + assert a + b == 32 } \ No newline at end of file diff --git a/tests/programs_test.go b/tests/programs_test.go index 3a2d801..932c085 100644 --- a/tests/programs_test.go +++ b/tests/programs_test.go @@ -31,8 +31,8 @@ var programs = []struct { {"modulo", "", "", 0}, {"modulo-assign", "", "", 0}, {"division-split", "", "", 0}, - {"negative", "", "", 32}, - {"negation", "", "", 32}, + {"negative", "", "", 0}, + {"negation", "", "", 0}, {"square-sum", "", "", 0}, {"chained-calls", "", "", 0}, {"nested-calls", "", "", 0},