Implemented more move instructions on arm64
This commit is contained in:
@ -2,6 +2,7 @@ package arm
|
||||
|
||||
import (
|
||||
"git.urbach.dev/cli/q/src/cpu"
|
||||
"git.urbach.dev/cli/q/src/sizeof"
|
||||
)
|
||||
|
||||
// MoveRegisterRegister copies a register to another register.
|
||||
@ -13,18 +14,45 @@ func MoveRegisterRegister(destination cpu.Register, source cpu.Register) uint32
|
||||
return OrRegisterRegister(destination, ZR, source)
|
||||
}
|
||||
|
||||
// MoveRegisterNumber moves an integer into the given register.
|
||||
func MoveRegisterNumber(destination cpu.Register, number int) uint32 {
|
||||
// MoveRegisterNumber moves a number into the given register.
|
||||
func MoveRegisterNumber(destination cpu.Register, number int) (uint32, bool) {
|
||||
if number < 0 {
|
||||
return MoveInvertedWideImmediate(destination, ^number)
|
||||
return MoveInvertedWideImmediate(destination, ^number, 0), true
|
||||
}
|
||||
|
||||
return MoveZero(destination, 0, uint16(number))
|
||||
if sizeof.Signed(number) <= 2 {
|
||||
return MoveZero(destination, 0, uint16(number)), true
|
||||
}
|
||||
|
||||
if (number&0xFFFFFFFFFFFF == 0xFFFFFFFFFFFF) && sizeof.Signed(number>>48) <= 2 {
|
||||
return MoveInvertedWideImmediate(destination, (^number)>>48, 3), true
|
||||
}
|
||||
|
||||
code, encodable := MoveBitmaskImmediate(destination, number)
|
||||
|
||||
if encodable {
|
||||
return code, true
|
||||
}
|
||||
|
||||
if (number&0xFFFFFFFF == 0xFFFFFFFF) && sizeof.Signed(number>>32) <= 2 {
|
||||
return MoveInvertedWideImmediate(destination, (^number)>>32, 2), true
|
||||
}
|
||||
|
||||
if (number&0xFFFF == 0xFFFF) && sizeof.Signed(number>>16) <= 2 {
|
||||
return MoveInvertedWideImmediate(destination, (^number)>>16, 1), true
|
||||
}
|
||||
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// MoveBitmaskImmediate moves a bitmask immediate value to a register.
|
||||
func MoveBitmaskImmediate(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 int) uint32 {
|
||||
return 0b100100101<<23 | regImm(destination, number)
|
||||
func MoveInvertedWideImmediate(destination cpu.Register, number int, shift uint32) uint32 {
|
||||
return 0b100100101<<23 | shift<<21 | regImm(destination, number)
|
||||
}
|
||||
|
||||
// MoveKeep moves a 16-bit integer into the given register and keeps all other bits.
|
||||
|
@ -33,15 +33,36 @@ func TestMoveRegisterNumber(t *testing.T) {
|
||||
Number int
|
||||
Code uint32
|
||||
}{
|
||||
// MOVZ
|
||||
{arm.X0, 0, 0xD2800000},
|
||||
{arm.X0, 1, 0xD2800020},
|
||||
|
||||
// MOV (bitmask immediate)
|
||||
{arm.X0, 0x1FFFF, 0xB24043E0},
|
||||
{arm.X0, 0x7FFFFFFF, 0xB2407BE0},
|
||||
{arm.X0, 0xFFFFFFFF, 0xB2407FE0},
|
||||
|
||||
// MOV (inverted wide immediate)
|
||||
{arm.X0, -1, 0x92800000},
|
||||
{arm.X0, 0x7FFFFFFFFFFFFFFF, 0x92F00000},
|
||||
{arm.X0, 0x2FFFFFFFF, 0x92DFFFA0}, // not encodable in the GNU assembler
|
||||
{arm.X0, 0x2FFFF, 0x92BFFFA0}, // not encodable in the GNU assembler
|
||||
|
||||
// Not encodable
|
||||
{arm.X0, 0xCAFEBABE, 0},
|
||||
{arm.X0, 0xDEADC0DE, 0},
|
||||
}
|
||||
|
||||
for _, pattern := range usagePatterns {
|
||||
t.Logf("mov %s, %d", pattern.Register, pattern.Number)
|
||||
code := arm.MoveRegisterNumber(pattern.Register, pattern.Number)
|
||||
assert.DeepEqual(t, code, pattern.Code)
|
||||
code, encodable := arm.MoveRegisterNumber(pattern.Register, pattern.Number)
|
||||
|
||||
if pattern.Code != 0 {
|
||||
assert.True(t, encodable)
|
||||
assert.DeepEqual(t, code, pattern.Code)
|
||||
} else {
|
||||
assert.False(t, encodable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,6 @@ import (
|
||||
|
||||
func TestARM(t *testing.T) {
|
||||
assert.DeepEqual(t, arm.Call(0), 0x94000000)
|
||||
assert.DeepEqual(t, arm.MoveRegisterNumber(arm.X0, 42), arm.MoveZero(arm.X0, 0, 42))
|
||||
assert.DeepEqual(t, arm.Nop(), 0xD503201F)
|
||||
assert.DeepEqual(t, arm.Return(), 0xD65F03C0)
|
||||
assert.DeepEqual(t, arm.Syscall(), 0xD4000001)
|
||||
|
@ -76,8 +76,9 @@ func (c *compiler) compileARM(x asm.Instruction) {
|
||||
operands := c.assembler.Param.MemoryNumber[x.Index]
|
||||
|
||||
if operands.Address.OffsetRegister < 0 {
|
||||
c.append(arm.MoveRegisterNumber(arm.X0, operands.Number))
|
||||
c.append(arm.StoreRegister(arm.X0, operands.Address.Base, int(operands.Address.Offset), operands.Address.Length))
|
||||
tmp := arm.X28
|
||||
c.moveRegisterNumberARM(tmp, operands.Number)
|
||||
c.append(arm.StoreRegister(tmp, operands.Address.Base, int(operands.Address.Offset), operands.Address.Length))
|
||||
} else {
|
||||
panic("not implemented")
|
||||
}
|
||||
@ -109,7 +110,7 @@ func (c *compiler) compileARM(x asm.Instruction) {
|
||||
c.append(code)
|
||||
} else {
|
||||
tmp := arm.X28
|
||||
c.append(arm.MoveRegisterNumber(tmp, operand.Number))
|
||||
c.moveRegisterNumberARM(tmp, operand.Number)
|
||||
c.append(arm.AndRegisterRegister(operand.Register, operand.Register, tmp))
|
||||
}
|
||||
case asm.TypeRegisterRegister:
|
||||
@ -127,7 +128,7 @@ func (c *compiler) compileARM(x asm.Instruction) {
|
||||
c.append(code)
|
||||
} else {
|
||||
tmp := arm.X28
|
||||
c.append(arm.MoveRegisterNumber(tmp, operand.Number))
|
||||
c.moveRegisterNumberARM(tmp, operand.Number)
|
||||
c.append(arm.OrRegisterRegister(operand.Register, operand.Register, tmp))
|
||||
}
|
||||
case asm.TypeRegisterRegister:
|
||||
@ -145,7 +146,7 @@ func (c *compiler) compileARM(x asm.Instruction) {
|
||||
c.append(code)
|
||||
} else {
|
||||
tmp := arm.X28
|
||||
c.append(arm.MoveRegisterNumber(tmp, operand.Number))
|
||||
c.moveRegisterNumberARM(tmp, operand.Number)
|
||||
c.append(arm.XorRegisterRegister(operand.Register, operand.Register, tmp))
|
||||
}
|
||||
case asm.TypeRegisterRegister:
|
||||
@ -200,7 +201,7 @@ func (c *compiler) compileARM(x asm.Instruction) {
|
||||
case asm.TypeRegisterNumber:
|
||||
operand := c.assembler.Param.RegisterNumber[x.Index]
|
||||
tmp := arm.X28
|
||||
c.append(arm.MoveRegisterNumber(tmp, operand.Number))
|
||||
c.moveRegisterNumberARM(tmp, operand.Number)
|
||||
c.append(arm.MulRegisterRegister(operand.Register, operand.Register, tmp))
|
||||
}
|
||||
|
||||
@ -226,7 +227,7 @@ func (c *compiler) compileARM(x asm.Instruction) {
|
||||
|
||||
case asm.TypeRegisterNumber:
|
||||
operands := c.assembler.Param.RegisterNumber[x.Index]
|
||||
c.append(arm.MoveRegisterNumber(operands.Register, operands.Number))
|
||||
c.moveRegisterNumberARM(operands.Register, operands.Number)
|
||||
|
||||
case asm.TypeRegisterLabel:
|
||||
operands := c.assembler.Param.RegisterLabel[x.Index]
|
||||
|
16
src/asmc/movARM.go
Normal file
16
src/asmc/movARM.go
Normal file
@ -0,0 +1,16 @@
|
||||
package asmc
|
||||
|
||||
import (
|
||||
"git.urbach.dev/cli/q/src/arm"
|
||||
"git.urbach.dev/cli/q/src/cpu"
|
||||
)
|
||||
|
||||
func (c *compiler) moveRegisterNumberARM(register cpu.Register, number int) {
|
||||
code, encodable := arm.MoveRegisterNumber(register, number)
|
||||
|
||||
if encodable {
|
||||
c.append(code)
|
||||
} else {
|
||||
panic("not implemented") // movz movk
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user