diff --git a/src/arm/SignExtend.go b/src/arm/SignExtend.go new file mode 100644 index 0000000..43d37a6 --- /dev/null +++ b/src/arm/SignExtend.go @@ -0,0 +1,8 @@ +package arm + +import "git.urbach.dev/cli/q/src/cpu" + +// SignExtend sign-extends the value in the source register to 64 bits and writes it to the destination register. +func SignExtend(destination cpu.Register, source cpu.Register, length byte) uint32 { + return 0b10010011010<<21 | uint32(length*8-1)<<10 | uint32(source)<<5 | uint32(destination) +} \ No newline at end of file diff --git a/src/arm/SignExtend_test.go b/src/arm/SignExtend_test.go new file mode 100644 index 0000000..667d594 --- /dev/null +++ b/src/arm/SignExtend_test.go @@ -0,0 +1,34 @@ +package arm_test + +import ( + "testing" + + "git.urbach.dev/cli/q/src/arm" + "git.urbach.dev/cli/q/src/cpu" + "git.urbach.dev/go/assert" +) + +func TestSignExtend(t *testing.T) { + usagePatterns := []struct { + Destination cpu.Register + Source cpu.Register + Length byte + Code uint32 + }{ + {arm.X0, arm.X0, 1, 0x93401C00}, + {arm.X3, arm.X2, 1, 0x93401C43}, + {arm.X15, arm.X8, 1, 0x93401D0F}, + {arm.X0, arm.X0, 2, 0x93403C00}, + {arm.X3, arm.X2, 2, 0x93403C43}, + {arm.ZR, arm.ZR, 2, 0x93403FFF}, + {arm.X0, arm.X0, 4, 0x93407C00}, + {arm.X15, arm.X8, 4, 0x93407D0F}, + {arm.ZR, arm.ZR, 4, 0x93407FFF}, + } + + for _, pattern := range usagePatterns { + t.Logf("sxt %db %s, %s", pattern.Length, pattern.Destination, pattern.Source) + code := arm.SignExtend(pattern.Destination, pattern.Source, pattern.Length) + assert.Equal(t, code, pattern.Code) + } +} \ No newline at end of file