Fixed add and sub instruction encoding on arm64
This commit is contained in:
@ -14,7 +14,22 @@ func AddRegisterRegister(destination cpu.Register, source cpu.Register, operand
|
||||
|
||||
// addRegisterNumber adds the register and optionally updates the condition flags based on the result.
|
||||
func addRegisterNumber(destination cpu.Register, source cpu.Register, number int, flags uint32) uint32 {
|
||||
return flags<<29 | 0b100100010<<23 | reg2Imm(destination, source, number)
|
||||
shift := uint32(0)
|
||||
|
||||
if number > mask12 {
|
||||
if number&mask12 != 0 {
|
||||
panic("number can't be encoded")
|
||||
}
|
||||
|
||||
shift = 1
|
||||
number >>= 12
|
||||
|
||||
if number > mask12 {
|
||||
panic("number can't be encoded")
|
||||
}
|
||||
}
|
||||
|
||||
return flags<<29 | 0b100100010<<23 | shift<<22 | reg2Imm(destination, source, number)
|
||||
}
|
||||
|
||||
// addRegisterRegister adds the registers and optionally updates the condition flags based on the result.
|
||||
|
@ -16,6 +16,7 @@ func TestAddRegisterNumber(t *testing.T) {
|
||||
Code uint32
|
||||
}{
|
||||
{arm.X0, arm.X0, 1, 0x91000400},
|
||||
{arm.X0, arm.X0, 0x1000, 0x91400400},
|
||||
}
|
||||
|
||||
for _, pattern := range usagePatterns {
|
||||
|
@ -14,8 +14,10 @@ func TestCompareRegisterNumber(t *testing.T) {
|
||||
Number int
|
||||
Code uint32
|
||||
}{
|
||||
{arm.X0, 0, 0xF100001F},
|
||||
{arm.X0, 1, 0xF100041F},
|
||||
{arm.X0, -1, 0xB100041F},
|
||||
{arm.X0, 0x1000, 0xF140041F},
|
||||
}
|
||||
|
||||
for _, pattern := range usagePatterns {
|
||||
|
@ -41,28 +41,28 @@ func MoveRegisterNumberMI(code []byte, destination cpu.Register, number int) []b
|
||||
func MoveRegisterNumberSI(destination cpu.Register, number int) (uint32, bool) {
|
||||
if sizeof.Signed(number) <= 2 {
|
||||
if number < 0 {
|
||||
return MoveInvertedWideImmediate(destination, uint16(^number), 0), true
|
||||
return MoveInvertedNumber(destination, uint16(^number), 0), true
|
||||
}
|
||||
|
||||
return MoveZero(destination, 0, uint16(number)), true
|
||||
}
|
||||
|
||||
if (number&0xFFFFFFFFFFFF == 0xFFFFFFFFFFFF) && sizeof.Signed(number>>48) <= 2 {
|
||||
return MoveInvertedWideImmediate(destination, uint16((^number)>>48), 3), true
|
||||
return MoveInvertedNumber(destination, uint16((^number)>>48), 3), true
|
||||
}
|
||||
|
||||
code, encodable := MoveBitmaskImmediate(destination, number)
|
||||
code, encodable := MoveBitmaskNumber(destination, number)
|
||||
|
||||
if encodable {
|
||||
return code, true
|
||||
}
|
||||
|
||||
if (number&0xFFFFFFFF == 0xFFFFFFFF) && sizeof.Signed(number>>32) <= 2 {
|
||||
return MoveInvertedWideImmediate(destination, uint16((^number)>>32), 2), true
|
||||
return MoveInvertedNumber(destination, uint16((^number)>>32), 2), true
|
||||
}
|
||||
|
||||
if (number&0xFFFF == 0xFFFF) && sizeof.Signed(number>>16) <= 2 {
|
||||
return MoveInvertedWideImmediate(destination, uint16((^number)>>16), 1), true
|
||||
return MoveInvertedNumber(destination, uint16((^number)>>16), 1), true
|
||||
}
|
||||
|
||||
return 0, false
|
||||
@ -77,13 +77,13 @@ func MoveRegisterRegister(destination cpu.Register, source cpu.Register) uint32
|
||||
return OrRegisterRegister(destination, ZR, source)
|
||||
}
|
||||
|
||||
// MoveBitmaskImmediate moves a bitmask immediate value to a register.
|
||||
func MoveBitmaskImmediate(destination cpu.Register, number int) (uint32, bool) {
|
||||
// MoveBitmaskNumber moves a bitmask immediate value to a register.
|
||||
func MoveBitmaskNumber(destination cpu.Register, number int) (uint32, bool) {
|
||||
return OrRegisterNumber(destination, ZR, number)
|
||||
}
|
||||
|
||||
// MoveInvertedWideImmediate moves an inverted 16-bit immediate value to a register.
|
||||
func MoveInvertedWideImmediate(destination cpu.Register, number uint16, shift uint32) uint32 {
|
||||
// MoveInvertedNumber moves an inverted 16-bit immediate value to a register.
|
||||
func MoveInvertedNumber(destination cpu.Register, number uint16, shift uint32) uint32 {
|
||||
return 0b100100101<<23 | shift<<21 | regImm(destination, number)
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,7 @@ func TestMoveRegisterNumber(t *testing.T) {
|
||||
Number uint64
|
||||
Code []byte
|
||||
}{
|
||||
{arm.X0, 0, []byte{0x00, 0x00, 0x80, 0xD2}},
|
||||
{arm.X0, 0xCAFEBABE, []byte{0xC0, 0x57, 0x97, 0xD2, 0xC0, 0x5F, 0xB9, 0xF2}},
|
||||
{arm.X0, 0xDEADC0DE, []byte{0xC0, 0x1B, 0x98, 0xD2, 0xA0, 0xD5, 0xBB, 0xF2}},
|
||||
}
|
||||
@ -51,8 +52,9 @@ func TestMoveRegisterNumberSI(t *testing.T) {
|
||||
Code uint32
|
||||
}{
|
||||
// MOVZ
|
||||
{arm.X0, 0, 0xD2800000},
|
||||
{arm.X0, 1, 0xD2800020},
|
||||
{arm.X0, 0x0, 0xD2800000},
|
||||
{arm.X0, 0x1, 0xD2800020},
|
||||
{arm.X0, 0x1000, 0xD2820000},
|
||||
|
||||
// MOV (bitmask immediate)
|
||||
{arm.X0, 0x1FFFF, 0xB24043E0},
|
||||
|
@ -14,7 +14,22 @@ func SubRegisterRegister(destination cpu.Register, source cpu.Register, operand
|
||||
|
||||
// subRegisterNumber subtracts the register and optionally updates the condition flags based on the result.
|
||||
func subRegisterNumber(destination cpu.Register, source cpu.Register, number int, flags uint32) uint32 {
|
||||
return flags<<29 | 0b110100010<<23 | reg2Imm(destination, source, number)
|
||||
shift := uint32(0)
|
||||
|
||||
if number > mask12 {
|
||||
if number&mask12 != 0 {
|
||||
panic("number can't be encoded")
|
||||
}
|
||||
|
||||
shift = 1
|
||||
number >>= 12
|
||||
|
||||
if number > mask12 {
|
||||
panic("number can't be encoded")
|
||||
}
|
||||
}
|
||||
|
||||
return flags<<29 | 0b110100010<<23 | shift<<22 | reg2Imm(destination, source, number)
|
||||
}
|
||||
|
||||
// subRegisterRegister subtracts the registers and optionally updates the condition flags based on the result.
|
||||
|
@ -16,6 +16,7 @@ func TestSubRegisterNumber(t *testing.T) {
|
||||
Code uint32
|
||||
}{
|
||||
{arm.X0, arm.X0, 1, 0xD1000400},
|
||||
{arm.X0, arm.X0, 0x1000, 0xD1400400},
|
||||
{arm.SP, arm.SP, 16, 0xD10043FF},
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user