Enabled arm64 encoding
This commit is contained in:
8
lib/core/core_linux_arm.q
Normal file
8
lib/core/core_linux_arm.q
Normal file
@ -0,0 +1,8 @@
|
||||
init() {
|
||||
main.main()
|
||||
exit()
|
||||
}
|
||||
|
||||
exit() {
|
||||
syscall(93, 0)
|
||||
}
|
@ -6,5 +6,10 @@ import "encoding/binary"
|
||||
// The offset starts from the address of this instruction and is encoded as "imm26" times 4.
|
||||
// This instruction is also known as BL (branch with link).
|
||||
func Call(code []byte, offset uint32) []byte {
|
||||
return binary.LittleEndian.AppendUint32(code, uint32(0b100101<<26)|offset)
|
||||
return binary.LittleEndian.AppendUint32(code, EncodeCall(offset))
|
||||
}
|
||||
|
||||
// EncodeCall returns the raw encoding of a call with the given offset.
|
||||
func EncodeCall(offset uint32) uint32 {
|
||||
return uint32(0b100101<<26) | offset
|
||||
}
|
||||
|
@ -39,8 +39,8 @@ const (
|
||||
|
||||
var (
|
||||
GeneralRegisters = []cpu.Register{X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28}
|
||||
InputRegisters = SyscallInputRegisters
|
||||
OutputRegisters = SyscallInputRegisters
|
||||
InputRegisters = []cpu.Register{X0, X1, X2, X3, X4, X5}
|
||||
OutputRegisters = InputRegisters
|
||||
SyscallInputRegisters = []cpu.Register{X8, X0, X1, X2, X3, X4, X5}
|
||||
SyscallOutputRegisters = []cpu.Register{X0, X1}
|
||||
WindowsInputRegisters = []cpu.Register{X0, X1, X2, X3, X4, X5, X6, X7}
|
||||
|
@ -1,23 +1,54 @@
|
||||
package asmc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"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.MOVE:
|
||||
// switch operands := x.Data.(type) {
|
||||
// case *asm.RegisterNumber:
|
||||
// c.code = arm.MoveRegisterNumber(c.code, operands.Register, operands.Number)
|
||||
// }
|
||||
case asm.CALL:
|
||||
switch data := x.Data.(type) {
|
||||
case *asm.Label:
|
||||
position := len(c.code)
|
||||
c.code = arm.Call(c.code, 0)
|
||||
|
||||
// case asm.RETURN:
|
||||
// c.code = arm.Return(c.code)
|
||||
pointer := &pointer{
|
||||
Position: Address(position),
|
||||
OpSize: 0,
|
||||
Size: 4,
|
||||
}
|
||||
|
||||
// case asm.SYSCALL:
|
||||
// c.code = arm.Syscall(c.code)
|
||||
pointer.Resolve = func() Address {
|
||||
destination, exists := c.codeLabels[data.Name]
|
||||
|
||||
if !exists {
|
||||
panic(fmt.Sprintf("unknown jump label %s", data.Name))
|
||||
}
|
||||
|
||||
distance := (destination - pointer.Position) / 4
|
||||
return arm.EncodeCall(distance)
|
||||
}
|
||||
|
||||
c.codePointers = append(c.codePointers, pointer)
|
||||
}
|
||||
|
||||
case asm.LABEL:
|
||||
c.codeLabels[x.Data.(*asm.Label).Name] = Address(len(c.code))
|
||||
|
||||
case asm.MOVE:
|
||||
switch operands := x.Data.(type) {
|
||||
case *asm.RegisterNumber:
|
||||
c.code = arm.MoveRegisterNumber(c.code, operands.Register, operands.Number)
|
||||
}
|
||||
|
||||
case asm.RETURN:
|
||||
c.code = arm.Return(c.code)
|
||||
|
||||
case asm.SYSCALL:
|
||||
c.code = arm.Syscall(c.code)
|
||||
|
||||
default:
|
||||
c.code = arm.Nop(c.code)
|
||||
|
@ -1,7 +1,7 @@
|
||||
package asmc
|
||||
|
||||
// Address represents a memory address.
|
||||
type Address = int32
|
||||
type Address = uint32
|
||||
|
||||
// pointer stores a relative memory address that we can later turn into an absolute one.
|
||||
// Position: The machine code offset where the address was inserted.
|
||||
|
@ -16,7 +16,7 @@ restart:
|
||||
for i, pointer := range c.codePointers {
|
||||
address := pointer.Resolve()
|
||||
|
||||
if sizeof.Signed(address) > int(pointer.Size) {
|
||||
if sizeof.Signed(int32(address)) > int(pointer.Size) {
|
||||
left := c.code[:pointer.Position-Address(pointer.OpSize)]
|
||||
right := c.code[pointer.Position+Address(pointer.Size):]
|
||||
size := pointer.Size + pointer.OpSize
|
||||
|
@ -7,10 +7,10 @@ import (
|
||||
|
||||
// Finalize returns the final raw data slice and a map of labels with their respective indices.
|
||||
// It will try to reuse existing data whenever possible.
|
||||
func (data Data) Finalize() ([]byte, map[string]int32) {
|
||||
func (data Data) Finalize() ([]byte, map[string]uint32) {
|
||||
var (
|
||||
keys = make([]string, 0, len(data))
|
||||
positions = make(map[string]int32, len(data))
|
||||
positions = make(map[string]uint32, len(data))
|
||||
capacity = 0
|
||||
)
|
||||
|
||||
@ -30,9 +30,9 @@ func (data Data) Finalize() ([]byte, map[string]int32) {
|
||||
position := bytes.Index(final, raw)
|
||||
|
||||
if position != -1 {
|
||||
positions[key] = int32(position)
|
||||
positions[key] = uint32(position)
|
||||
} else {
|
||||
positions[key] = int32(len(final))
|
||||
positions[key] = uint32(len(final))
|
||||
final = append(final, raw...)
|
||||
}
|
||||
}
|
||||
|
@ -21,20 +21,50 @@ func (s *Scanner) queueDirectory(directory string, pkg string) {
|
||||
return
|
||||
}
|
||||
|
||||
if strings.HasSuffix(name, "_linux.q") && config.TargetOS != config.Linux {
|
||||
return
|
||||
}
|
||||
tmp := name[:len(name)-2]
|
||||
|
||||
if strings.HasSuffix(name, "_mac.q") && config.TargetOS != config.Mac {
|
||||
return
|
||||
}
|
||||
for {
|
||||
underscore := strings.LastIndexByte(tmp, '_')
|
||||
|
||||
if strings.HasSuffix(name, "_unix.q") && config.TargetOS != config.Linux && config.TargetOS != config.Mac {
|
||||
return
|
||||
}
|
||||
if underscore == -1 {
|
||||
break
|
||||
}
|
||||
|
||||
if strings.HasSuffix(name, "_windows.q") && config.TargetOS != config.Windows {
|
||||
return
|
||||
condition := tmp[underscore+1:]
|
||||
|
||||
switch condition {
|
||||
case "linux":
|
||||
if config.TargetOS != config.Linux {
|
||||
return
|
||||
}
|
||||
|
||||
case "mac":
|
||||
if config.TargetOS != config.Mac {
|
||||
return
|
||||
}
|
||||
|
||||
case "unix":
|
||||
if config.TargetOS != config.Linux && config.TargetOS != config.Mac {
|
||||
return
|
||||
}
|
||||
|
||||
case "windows":
|
||||
if config.TargetOS != config.Windows {
|
||||
return
|
||||
}
|
||||
|
||||
case "x86":
|
||||
if config.TargetArch != config.X86 {
|
||||
return
|
||||
}
|
||||
|
||||
case "arm":
|
||||
if config.TargetArch != config.ARM {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
tmp = tmp[:underscore]
|
||||
}
|
||||
|
||||
fullPath := filepath.Join(directory, name)
|
||||
|
Reference in New Issue
Block a user