diff --git a/src/x86/Add.go b/src/x86/Add.go index e2a81ad..33d4419 100644 --- a/src/x86/Add.go +++ b/src/x86/Add.go @@ -6,7 +6,7 @@ import ( // AddRegisterNumber adds a number to the given register. func AddRegisterNumber(code []byte, register cpu.Register, number int) []byte { - return encodeNum(code, AddressDirect, 0, register, number, 0x83, 0x81) + return encodeNum(code, AddressDirect, 0b000, register, number, 0x83, 0x81) } // AddRegisterRegister adds a register value into another register. diff --git a/src/x86/Call.go b/src/x86/Call.go index 6815b24..4c87f6c 100644 --- a/src/x86/Call.go +++ b/src/x86/Call.go @@ -19,12 +19,8 @@ func Call(code []byte, offset uint32) []byte { // 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), - ) + code = append(code, 0x41) + register &= 0b111 } return append( @@ -50,30 +46,6 @@ func CallAt(code []byte, address uint32) []byte { // CallAtMemory calls a function at the address stored at the given memory address. // The memory address is relative to the next instruction. -func CallAtMemory(code []byte, register cpu.Register, offset int8) []byte { - mod := AddressMemory - - if offset != 0 || register == RBP || register == R13 { - mod = AddressMemoryOffset8 - } - - reg := byte(0b010) - rm := register - - if rm > 0b111 { - code = append(code, 0x41) - rm &= 0b111 - } - - code = append(code, 0xFF, ModRM(mod, reg, byte(rm))) - - if register == RSP || register == R12 { - code = append(code, SIB(Scale1, 0b100, 0b100)) - } - - if mod == AddressMemoryOffset8 { - code = append(code, byte(offset)) - } - - return code +func CallAtMemory(code []byte, base cpu.Register, offset int8) []byte { + return memoryAccess(code, 0xFF, 0xFF, 0b010, base, offset, 4) } diff --git a/src/x86/Load.go b/src/x86/Load.go index f29a08e..83bf558 100644 --- a/src/x86/Load.go +++ b/src/x86/Load.go @@ -4,5 +4,5 @@ import "git.urbach.dev/cli/q/src/cpu" // LoadRegister loads from memory into a register. func LoadRegister(code []byte, destination cpu.Register, base cpu.Register, offset int8, length byte) []byte { - return memoryAccess(code, 0x8A, 0x8B, base, offset, length, destination) + return memoryAccess(code, 0x8A, 0x8B, destination, base, offset, length) } diff --git a/src/x86/LoadDynamic.go b/src/x86/LoadDynamic.go index c06878e..4db16a2 100644 --- a/src/x86/LoadDynamic.go +++ b/src/x86/LoadDynamic.go @@ -4,5 +4,5 @@ import "git.urbach.dev/cli/q/src/cpu" // LoadDynamicRegister loads from memory with a register offset into a register. func LoadDynamicRegister(code []byte, destination cpu.Register, base cpu.Register, offset cpu.Register, length byte) []byte { - return memoryAccessDynamic(code, 0x8A, 0x8B, base, offset, length, destination) + return memoryAccessDynamic(code, 0x8A, 0x8B, destination, base, offset, length) } diff --git a/src/x86/ModRM.go b/src/x86/ModRM.go index 1ab4393..af17ad1 100644 --- a/src/x86/ModRM.go +++ b/src/x86/ModRM.go @@ -10,7 +10,7 @@ const ( AddressDirect = AddressMode(0b11) ) -// ModRM is used to generate a ModRM suffix. +// ModRM is used to generate a mode-register-memory suffix. // - mod: 2 bits. The addressing mode. // - reg: 3 bits. Register reference or opcode extension. // - rm: 3 bits. Register operand. diff --git a/src/x86/Move.go b/src/x86/Move.go index 7e3b103..3087723 100644 --- a/src/x86/Move.go +++ b/src/x86/Move.go @@ -41,16 +41,7 @@ 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))) + code = encode(code, AddressDirect, 0, destination, 8, 0xC7) return binary.LittleEndian.AppendUint32(code, uint32(number)) } diff --git a/src/x86/Store.go b/src/x86/Store.go index 0f57b09..faabf79 100644 --- a/src/x86/Store.go +++ b/src/x86/Store.go @@ -6,9 +6,9 @@ import ( "git.urbach.dev/cli/q/src/cpu" ) -// StoreNumber stores a number into the memory address included in the given register. -func StoreNumber(code []byte, register cpu.Register, offset int8, length byte, number int) []byte { - code = memoryAccess(code, 0xC6, 0xC7, register, offset, length, 0b000) +// StoreNumber writes a number to a memory address. +func StoreNumber(code []byte, base cpu.Register, offset int8, length byte, number int) []byte { + code = memoryAccess(code, 0xC6, 0xC7, 0b000, base, offset, length) switch length { case 8, 4: @@ -21,7 +21,7 @@ func StoreNumber(code []byte, register cpu.Register, offset int8, length byte, n return append(code, byte(number)) } -// StoreRegister stores the contents of the `source` register into the memory address included in the given register. -func StoreRegister(code []byte, register cpu.Register, offset int8, length byte, source cpu.Register) []byte { - return memoryAccess(code, 0x88, 0x89, register, offset, length, source) +// StoreRegister writes the contents of the register to a memory address. +func StoreRegister(code []byte, base cpu.Register, offset int8, length byte, register cpu.Register) []byte { + return memoryAccess(code, 0x88, 0x89, register, base, offset, length) } diff --git a/src/x86/StoreDynamic.go b/src/x86/StoreDynamic.go index 6cb71e9..1b3a664 100644 --- a/src/x86/StoreDynamic.go +++ b/src/x86/StoreDynamic.go @@ -6,9 +6,9 @@ import ( "git.urbach.dev/cli/q/src/cpu" ) -// StoreDynamicNumber stores a number into the memory address at `destination` with a register offset. -func StoreDynamicNumber(code []byte, destination cpu.Register, offset cpu.Register, length byte, number int) []byte { - code = memoryAccessDynamic(code, 0xC6, 0xC7, destination, offset, length, 0b000) +// StoreDynamicNumber writes a number to a memory address with a register offset. +func StoreDynamicNumber(code []byte, base cpu.Register, offset cpu.Register, length byte, number int) []byte { + code = memoryAccessDynamic(code, 0xC6, 0xC7, 0b000, base, offset, length) switch length { case 8, 4: @@ -21,7 +21,7 @@ func StoreDynamicNumber(code []byte, destination cpu.Register, offset cpu.Regist return append(code, byte(number)) } -// StoreDynamicRegister stores the contents of the `source` register into the memory address at `destination` with a register offset. -func StoreDynamicRegister(code []byte, destination cpu.Register, offset cpu.Register, length byte, source cpu.Register) []byte { - return memoryAccessDynamic(code, 0x88, 0x89, destination, offset, length, source) +// StoreDynamicRegister writes the contents of a register to a memory address with a register offset. +func StoreDynamicRegister(code []byte, base cpu.Register, offset cpu.Register, length byte, source cpu.Register) []byte { + return memoryAccessDynamic(code, 0x88, 0x89, source, base, offset, length) } diff --git a/src/x86/memoryAccess.go b/src/x86/memoryAccess.go index 3757ec4..42e6a37 100644 --- a/src/x86/memoryAccess.go +++ b/src/x86/memoryAccess.go @@ -3,26 +3,26 @@ package x86 import "git.urbach.dev/cli/q/src/cpu" // memoryAccess encodes a memory access. -func memoryAccess(code []byte, opCode8 byte, opCode32 byte, register cpu.Register, offset int8, numBytes byte, source cpu.Register) []byte { +func memoryAccess(code []byte, opCode8 byte, opCode32 byte, register cpu.Register, base cpu.Register, offset int8, length byte) []byte { opCode := opCode32 - if numBytes == 1 { + if length == 1 { opCode = opCode8 } mod := AddressMemory - if offset != 0 || register == RBP || register == R13 { + if offset != 0 || base == RBP || base == R13 { mod = AddressMemoryOffset8 } - if numBytes == 2 { + if length == 2 { code = append(code, 0x66) } - code = encode(code, mod, source, register, numBytes, opCode) + code = encode(code, mod, register, base, length, opCode) - if register == RSP || register == R12 { + if base == RSP || base == R12 { code = append(code, SIB(Scale1, 0b100, 0b100)) } diff --git a/src/x86/memoryAccessDynamic.go b/src/x86/memoryAccessDynamic.go index 8282eaa..092fa64 100644 --- a/src/x86/memoryAccessDynamic.go +++ b/src/x86/memoryAccessDynamic.go @@ -3,7 +3,7 @@ package x86 import "git.urbach.dev/cli/q/src/cpu" // memoryAccessDynamic encodes a memory access using the value of a register as an offset. -func memoryAccessDynamic(code []byte, opCode8 byte, opCode32 byte, destination cpu.Register, offset cpu.Register, numBytes byte, source cpu.Register) []byte { +func memoryAccessDynamic(code []byte, opCode8 byte, opCode32 byte, register cpu.Register, base cpu.Register, offset cpu.Register, length byte) []byte { var ( w = byte(0) r = byte(0) @@ -13,21 +13,21 @@ func memoryAccessDynamic(code []byte, opCode8 byte, opCode32 byte, destination c mod = AddressMemory ) - if numBytes == 1 { + if length == 1 { opCode = opCode8 } if offset == RSP { - offset, destination = destination, offset + offset, base = base, offset } - if numBytes == 8 { + if length == 8 { w = 1 } - if source > 0b111 { + if register > 0b111 { r = 1 - source &= 0b111 + register &= 0b111 } if offset > 0b111 { @@ -35,23 +35,23 @@ func memoryAccessDynamic(code []byte, opCode8 byte, opCode32 byte, destination c offset &= 0b111 } - if destination > 0b111 { + if base > 0b111 { b = 1 - destination &= 0b111 + base &= 0b111 } - if destination == RBP || destination == R13 { + if base == RBP || base == R13 { mod = AddressMemoryOffset8 } - if numBytes == 2 { + if length == 2 { code = append(code, 0x66) } code = append(code, REX(w, r, x, b)) code = append(code, opCode) - code = append(code, ModRM(mod, byte(source), 0b100)) - code = append(code, SIB(Scale1, byte(offset), byte(destination))) + code = append(code, ModRM(mod, byte(register), 0b100)) + code = append(code, SIB(Scale1, byte(offset), byte(base))) if mod == AddressMemoryOffset8 { code = append(code, 0x00)