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.
|
// 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 {
|
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.
|
// 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
|
Code uint32
|
||||||
}{
|
}{
|
||||||
{arm.X0, arm.X0, 1, 0x91000400},
|
{arm.X0, arm.X0, 1, 0x91000400},
|
||||||
|
{arm.X0, arm.X0, 0x1000, 0x91400400},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, pattern := range usagePatterns {
|
for _, pattern := range usagePatterns {
|
||||||
|
@ -14,8 +14,10 @@ func TestCompareRegisterNumber(t *testing.T) {
|
|||||||
Number int
|
Number int
|
||||||
Code uint32
|
Code uint32
|
||||||
}{
|
}{
|
||||||
|
{arm.X0, 0, 0xF100001F},
|
||||||
{arm.X0, 1, 0xF100041F},
|
{arm.X0, 1, 0xF100041F},
|
||||||
{arm.X0, -1, 0xB100041F},
|
{arm.X0, -1, 0xB100041F},
|
||||||
|
{arm.X0, 0x1000, 0xF140041F},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, pattern := range usagePatterns {
|
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) {
|
func MoveRegisterNumberSI(destination cpu.Register, number int) (uint32, bool) {
|
||||||
if sizeof.Signed(number) <= 2 {
|
if sizeof.Signed(number) <= 2 {
|
||||||
if number < 0 {
|
if number < 0 {
|
||||||
return MoveInvertedWideImmediate(destination, uint16(^number), 0), true
|
return MoveInvertedNumber(destination, uint16(^number), 0), true
|
||||||
}
|
}
|
||||||
|
|
||||||
return MoveZero(destination, 0, uint16(number)), true
|
return MoveZero(destination, 0, uint16(number)), true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (number&0xFFFFFFFFFFFF == 0xFFFFFFFFFFFF) && sizeof.Signed(number>>48) <= 2 {
|
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 {
|
if encodable {
|
||||||
return code, true
|
return code, true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (number&0xFFFFFFFF == 0xFFFFFFFF) && sizeof.Signed(number>>32) <= 2 {
|
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 {
|
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
|
return 0, false
|
||||||
@ -77,13 +77,13 @@ func MoveRegisterRegister(destination cpu.Register, source cpu.Register) uint32
|
|||||||
return OrRegisterRegister(destination, ZR, source)
|
return OrRegisterRegister(destination, ZR, source)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MoveBitmaskImmediate moves a bitmask immediate value to a register.
|
// MoveBitmaskNumber moves a bitmask immediate value to a register.
|
||||||
func MoveBitmaskImmediate(destination cpu.Register, number int) (uint32, bool) {
|
func MoveBitmaskNumber(destination cpu.Register, number int) (uint32, bool) {
|
||||||
return OrRegisterNumber(destination, ZR, number)
|
return OrRegisterNumber(destination, ZR, number)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MoveInvertedWideImmediate moves an inverted 16-bit immediate value to a register.
|
// MoveInvertedNumber moves an inverted 16-bit immediate value to a register.
|
||||||
func MoveInvertedWideImmediate(destination cpu.Register, number uint16, shift uint32) uint32 {
|
func MoveInvertedNumber(destination cpu.Register, number uint16, shift uint32) uint32 {
|
||||||
return 0b100100101<<23 | shift<<21 | regImm(destination, number)
|
return 0b100100101<<23 | shift<<21 | regImm(destination, number)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ func TestMoveRegisterNumber(t *testing.T) {
|
|||||||
Number uint64
|
Number uint64
|
||||||
Code []byte
|
Code []byte
|
||||||
}{
|
}{
|
||||||
|
{arm.X0, 0, []byte{0x00, 0x00, 0x80, 0xD2}},
|
||||||
{arm.X0, 0xCAFEBABE, []byte{0xC0, 0x57, 0x97, 0xD2, 0xC0, 0x5F, 0xB9, 0xF2}},
|
{arm.X0, 0xCAFEBABE, []byte{0xC0, 0x57, 0x97, 0xD2, 0xC0, 0x5F, 0xB9, 0xF2}},
|
||||||
{arm.X0, 0xDEADC0DE, []byte{0xC0, 0x1B, 0x98, 0xD2, 0xA0, 0xD5, 0xBB, 0xF2}},
|
{arm.X0, 0xDEADC0DE, []byte{0xC0, 0x1B, 0x98, 0xD2, 0xA0, 0xD5, 0xBB, 0xF2}},
|
||||||
}
|
}
|
||||||
@ -51,8 +52,9 @@ func TestMoveRegisterNumberSI(t *testing.T) {
|
|||||||
Code uint32
|
Code uint32
|
||||||
}{
|
}{
|
||||||
// MOVZ
|
// MOVZ
|
||||||
{arm.X0, 0, 0xD2800000},
|
{arm.X0, 0x0, 0xD2800000},
|
||||||
{arm.X0, 1, 0xD2800020},
|
{arm.X0, 0x1, 0xD2800020},
|
||||||
|
{arm.X0, 0x1000, 0xD2820000},
|
||||||
|
|
||||||
// MOV (bitmask immediate)
|
// MOV (bitmask immediate)
|
||||||
{arm.X0, 0x1FFFF, 0xB24043E0},
|
{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.
|
// 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 {
|
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.
|
// 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
|
Code uint32
|
||||||
}{
|
}{
|
||||||
{arm.X0, arm.X0, 1, 0xD1000400},
|
{arm.X0, arm.X0, 1, 0xD1000400},
|
||||||
|
{arm.X0, arm.X0, 0x1000, 0xD1400400},
|
||||||
{arm.SP, arm.SP, 16, 0xD10043FF},
|
{arm.SP, arm.SP, 16, 0xD10043FF},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user