Implemented register calls

This commit is contained in:
Eduard Urbach 2025-03-02 17:53:18 +01:00
parent 0483176e56
commit c777d73bbb
Signed by: eduard
GPG key ID: 49226B848C78F6C8
16 changed files with 133 additions and 43 deletions

View file

@ -1,5 +1,7 @@
package x86
import "git.urbach.dev/cli/q/src/cpu"
// Call places the return address on the top of the stack and continues
// program flow at the new address.
// The address is relative to the next instruction.
@ -14,8 +16,25 @@ func Call(code []byte, address uint32) []byte {
)
}
// CallAtAddress places the return address on the top of the stack and
// continues program flow at the address stored at the given memory address.
// Calls a function whose address is stored in the given register.
func CallRegister(code []byte, register cpu.Register) []byte {
if register > 0b111 {
return append(
code,
0x41,
0xFF,
0xD0+byte(register&0b111),
)
}
return append(
code,
0xFF,
0xD0+byte(register),
)
}
// CallAtAddress calls a function at the address stored at the given memory address.
// The memory address is relative to the next instruction.
func CallAtAddress(code []byte, address uint32) []byte {
return append(

39
src/x86/Call_test.go Normal file
View file

@ -0,0 +1,39 @@
package x86_test
import (
"testing"
"git.urbach.dev/cli/q/src/cpu"
"git.urbach.dev/cli/q/src/x86"
"git.urbach.dev/go/assert"
)
func TestCallRegister(t *testing.T) {
usagePatterns := []struct {
Register cpu.Register
Code []byte
}{
{x86.RAX, []byte{0xFF, 0xD0}},
{x86.RCX, []byte{0xFF, 0xD1}},
{x86.RDX, []byte{0xFF, 0xD2}},
{x86.RBX, []byte{0xFF, 0xD3}},
{x86.RSP, []byte{0xFF, 0xD4}},
{x86.RBP, []byte{0xFF, 0xD5}},
{x86.RSI, []byte{0xFF, 0xD6}},
{x86.RDI, []byte{0xFF, 0xD7}},
{x86.R8, []byte{0x41, 0xFF, 0xD0}},
{x86.R9, []byte{0x41, 0xFF, 0xD1}},
{x86.R10, []byte{0x41, 0xFF, 0xD2}},
{x86.R11, []byte{0x41, 0xFF, 0xD3}},
{x86.R12, []byte{0x41, 0xFF, 0xD4}},
{x86.R13, []byte{0x41, 0xFF, 0xD5}},
{x86.R14, []byte{0x41, 0xFF, 0xD6}},
{x86.R15, []byte{0x41, 0xFF, 0xD7}},
}
for _, pattern := range usagePatterns {
t.Logf("call %s", pattern.Register)
code := x86.CallRegister(nil, pattern.Register)
assert.DeepEqual(t, code, pattern.Code)
}
}