113 lines
2.7 KiB
Go
113 lines
2.7 KiB
Go
package asmc
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"fmt"
|
|
"math"
|
|
"strings"
|
|
|
|
"git.urbach.dev/cli/q/src/arm"
|
|
"git.urbach.dev/cli/q/src/asm"
|
|
)
|
|
|
|
func (c *compiler) compileARM(x asm.Instruction) {
|
|
switch x.Mnemonic {
|
|
case asm.CALL:
|
|
switch x.Type {
|
|
case asm.TypeLabel:
|
|
label := c.assembler.Param.Label[x.Index]
|
|
position := Address(len(c.code))
|
|
c.append(arm.Call(0))
|
|
|
|
pointer := &pointer{
|
|
Position: position,
|
|
OpSize: 0,
|
|
Size: 4,
|
|
}
|
|
|
|
pointer.Resolve = func() Address {
|
|
destination, exists := c.codeLabels[label.Name]
|
|
|
|
if !exists {
|
|
panic(fmt.Sprintf("unknown jump label %s", label.Name))
|
|
}
|
|
|
|
distance := (destination - position) / 4
|
|
return arm.Call(distance)
|
|
}
|
|
|
|
c.codePointers = append(c.codePointers, pointer)
|
|
}
|
|
|
|
case asm.LABEL:
|
|
label := c.assembler.Param.Label[x.Index]
|
|
c.codeLabels[label.Name] = Address(len(c.code))
|
|
c.append(arm.StorePair(arm.FP, arm.LR, arm.SP, -16))
|
|
c.append(arm.MoveRegisterRegister(arm.FP, arm.SP))
|
|
|
|
case asm.LOAD:
|
|
switch x.Type {
|
|
case asm.TypeMemoryRegister:
|
|
operands := c.assembler.Param.MemoryRegister[x.Index]
|
|
|
|
if operands.Address.OffsetRegister == math.MaxUint8 {
|
|
c.append(arm.LoadRegister(operands.Register, operands.Address.Base, int16(operands.Address.Offset), operands.Address.Length))
|
|
} else {
|
|
// TODO: LoadDynamicRegister
|
|
panic("not implemented")
|
|
}
|
|
}
|
|
|
|
case asm.MOVE:
|
|
switch x.Type {
|
|
case asm.TypeRegisterRegister:
|
|
operands := c.assembler.Param.RegisterRegister[x.Index]
|
|
c.append(arm.MoveRegisterRegister(operands.Destination, operands.Source))
|
|
|
|
case asm.TypeRegisterNumber:
|
|
operands := c.assembler.Param.RegisterNumber[x.Index]
|
|
c.append(arm.MoveRegisterNumber(operands.Register, operands.Number))
|
|
|
|
case asm.TypeRegisterLabel:
|
|
operands := c.assembler.Param.RegisterLabel[x.Index]
|
|
position := Address(len(c.code))
|
|
c.append(arm.LoadAddress(operands.Register, 0))
|
|
|
|
if strings.HasPrefix(operands.Label, "data ") {
|
|
c.dataPointers = append(c.dataPointers, &pointer{
|
|
Position: position,
|
|
OpSize: 0,
|
|
Size: 4,
|
|
Resolve: func() Address {
|
|
destination, exists := c.dataLabels[operands.Label]
|
|
|
|
if !exists {
|
|
panic("unknown label")
|
|
}
|
|
|
|
destination += c.dataStart - c.codeStart
|
|
distance := destination - position + 8
|
|
return arm.LoadAddress(operands.Register, int(distance))
|
|
},
|
|
})
|
|
} else {
|
|
panic("not implemented")
|
|
}
|
|
}
|
|
|
|
case asm.RETURN:
|
|
c.append(arm.LoadPair(arm.FP, arm.LR, arm.SP, 16))
|
|
c.append(arm.Return())
|
|
|
|
case asm.SYSCALL:
|
|
c.append(arm.Syscall())
|
|
|
|
default:
|
|
panic("unknown mnemonic: " + x.Mnemonic.String())
|
|
}
|
|
}
|
|
|
|
func (c *compiler) append(code uint32) {
|
|
c.code = binary.LittleEndian.AppendUint32(c.code, code)
|
|
}
|