Added ABI definitions
All checks were successful
/ test (push) Successful in 15s

This commit is contained in:
Eduard Urbach 2025-07-05 11:33:53 +02:00
parent 7d2eb95c83
commit 6d15ff3a35
Signed by: akyoto
GPG key ID: 49226B848C78F6C8
9 changed files with 116 additions and 43 deletions

View file

@ -41,10 +41,37 @@ const (
ZR = SP // Zero register uses the same numerical value as SP
)
var CPU = cpu.CPU{
Call: []cpu.Register{X0, X1, X2, X3, X4, X5, X6},
Syscall: []cpu.Register{X8, X0, X1, X2, X3, X4, X5},
ExternCall: []cpu.Register{X0, X1, X2, X3, X4, X5, X6, X7},
ExternCallVolatile: []cpu.Register{X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17},
Return: []cpu.Register{X0, X1, X2},
}
var (
LinuxCPU = cpu.CPU{
Call: cpu.ABI{
In: []cpu.Register{X0, X1, X2, X3, X4, X5, X6},
Out: []cpu.Register{X0, X1, X2},
Volatile: []cpu.Register{X0, X1, X2, X3, X4, X5, X6},
},
ExternCall: cpu.ABI{
In: []cpu.Register{X0, X1, X2, X3, X4, X5, X6, X7},
Out: []cpu.Register{X0, X1},
Volatile: []cpu.Register{X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17},
},
Syscall: cpu.ABI{
In: []cpu.Register{X8, X0, X1, X2, X3, X4, X5},
Out: []cpu.Register{X0},
Volatile: []cpu.Register{X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17},
},
}
MacCPU = cpu.CPU{
Call: LinuxCPU.Call,
ExternCall: LinuxCPU.ExternCall,
Syscall: cpu.ABI{
In: []cpu.Register{X16, X0, X1, X2, X3, X4, X5, X6, X7},
Out: LinuxCPU.Syscall.Out,
Volatile: LinuxCPU.Syscall.Volatile,
},
}
WindowsCPU = cpu.CPU{
Call: LinuxCPU.Call,
ExternCall: LinuxCPU.ExternCall,
}
)

8
src/cpu/ABI.go Normal file
View file

@ -0,0 +1,8 @@
package cpu
// ABI is the Application Binary Interface which defines the registers used in function calls.
type ABI struct {
In []Register
Out []Register
Volatile []Register
}

View file

@ -2,9 +2,7 @@ package cpu
// CPU represents the processor.
type CPU struct {
Call []Register
Syscall []Register
ExternCall []Register
ExternCallVolatile []Register
Return []Register
Call ABI
ExternCall ABI
Syscall ABI
}

View file

@ -72,9 +72,23 @@ func (s *scanner) scanFunction(file *fs.File, tokens token.List, i int) (int, er
switch s.build.Arch {
case build.ARM:
function.CPU = &arm.CPU
switch s.build.OS {
case build.Linux:
function.CPU = &arm.LinuxCPU
case build.Mac:
function.CPU = &arm.MacCPU
case build.Windows:
function.CPU = &arm.WindowsCPU
}
case build.X86:
function.CPU = &x86.CPU
switch s.build.OS {
case build.Linux:
function.CPU = &x86.LinuxCPU
case build.Mac:
function.CPU = &x86.MacCPU
case build.Windows:
function.CPU = &x86.WindowsCPU
}
}
function.Body = tokens[bodyStart:i]

View file

@ -29,32 +29,32 @@ func (f *Compiler) CreateSteps(ir ssa.IR) []Step {
if isStruct {
for _, field := range structure.Arguments {
f.ValueToStep[field].Hint(f.CPU.Call[offset+r])
f.ValueToStep[field].Hint(f.CPU.Call.In[offset+r])
offset++
}
offset--
} else {
f.ValueToStep[param].Hint(f.CPU.Call[offset+r])
f.ValueToStep[param].Hint(f.CPU.Call.In[offset+r])
}
}
case *ssa.CallExtern:
for r, param := range instr.Arguments[1:] {
f.ValueToStep[param].Hint(f.CPU.ExternCall[r])
f.ValueToStep[param].Hint(f.CPU.ExternCall.In[r])
}
case *ssa.Parameter:
f.ValueToStep[instr].Register = f.CPU.Call[instr.Index]
f.ValueToStep[instr].Register = f.CPU.Call.In[instr.Index]
case *ssa.Return:
for r, param := range instr.Arguments {
f.ValueToStep[param].Hint(f.CPU.Return[r])
f.ValueToStep[param].Hint(f.CPU.Call.Out[r])
}
case *ssa.Syscall:
for r, param := range slices.Backward(instr.Arguments) {
f.ValueToStep[param].Hint(f.CPU.Syscall[r])
f.ValueToStep[param].Hint(f.CPU.Syscall.In[r])
}
}
@ -89,7 +89,7 @@ func (f *Compiler) CreateSteps(ir ssa.IR) []Step {
liveParam, isParam := live.Value.(*ssa.Parameter)
if isParam {
oldRegister = f.CPU.Call[liveParam.Index]
oldRegister = f.CPU.Call.In[liveParam.Index]
}
for _, existing := range step.Live[:liveIndex] {

View file

@ -35,9 +35,9 @@ func (f *Compiler) Exec(step *Step) {
if isStruct {
for _, field := range structure.Arguments {
if f.ValueToStep[field].Register != f.CPU.Call[offset+i] {
if f.ValueToStep[field].Register != f.CPU.Call.In[offset+i] {
f.Assembler.Append(&asm.MoveRegisterRegister{
Destination: f.CPU.Call[offset+i],
Destination: f.CPU.Call.In[offset+i],
Source: f.ValueToStep[field].Register,
})
}
@ -47,9 +47,9 @@ func (f *Compiler) Exec(step *Step) {
offset--
} else {
if f.ValueToStep[arg].Register != f.CPU.Call[offset+i] {
if f.ValueToStep[arg].Register != f.CPU.Call.In[offset+i] {
f.Assembler.Append(&asm.MoveRegisterRegister{
Destination: f.CPU.Call[offset+i],
Destination: f.CPU.Call.In[offset+i],
Source: f.ValueToStep[arg].Register,
})
}
@ -59,22 +59,22 @@ func (f *Compiler) Exec(step *Step) {
fn := instr.Arguments[0].(*ssa.Function)
f.Assembler.Append(&asm.Call{Label: fn.UniqueName})
if step.Register == -1 || step.Register == f.CPU.Return[0] {
if step.Register == -1 || step.Register == f.CPU.Call.Out[0] {
return
}
f.Assembler.Append(&asm.MoveRegisterRegister{
Destination: step.Register,
Source: f.CPU.Return[0],
Source: f.CPU.Call.Out[0],
})
case *ssa.CallExtern:
args := instr.Arguments[1:]
for i, arg := range args {
if f.ValueToStep[arg].Register != f.CPU.ExternCall[i] {
if f.ValueToStep[arg].Register != f.CPU.ExternCall.In[i] {
f.Assembler.Append(&asm.MoveRegisterRegister{
Destination: f.CPU.ExternCall[i],
Destination: f.CPU.ExternCall.In[i],
Source: f.ValueToStep[arg].Register,
})
}
@ -86,13 +86,13 @@ func (f *Compiler) Exec(step *Step) {
function := fn.UniqueName[dot+1:]
f.Assembler.Append(&asm.CallExtern{Library: library, Function: function})
if step.Register == -1 || step.Register == f.CPU.Return[0] {
if step.Register == -1 || step.Register == f.CPU.ExternCall.Out[0] {
return
}
f.Assembler.Append(&asm.MoveRegisterRegister{
Destination: step.Register,
Source: f.CPU.Return[0],
Source: f.CPU.ExternCall.Out[0],
})
case *ssa.Int:
@ -102,7 +102,7 @@ func (f *Compiler) Exec(step *Step) {
})
case *ssa.Parameter:
source := f.CPU.Call[instr.Index]
source := f.CPU.Call.In[instr.Index]
if step.Register == -1 || step.Register == source {
return
@ -129,9 +129,9 @@ func (f *Compiler) Exec(step *Step) {
case *ssa.Syscall:
for i, arg := range instr.Arguments {
if f.ValueToStep[arg].Register != f.CPU.Syscall[i] {
if f.ValueToStep[arg].Register != f.CPU.Syscall.In[i] {
f.Assembler.Append(&asm.MoveRegisterRegister{
Destination: f.CPU.Syscall[i],
Destination: f.CPU.Syscall.In[i],
Source: f.ValueToStep[arg].Register,
})
}
@ -139,13 +139,13 @@ func (f *Compiler) Exec(step *Step) {
f.Assembler.Append(&asm.Syscall{})
if step.Register == -1 || step.Register == f.CPU.Return[0] {
if step.Register == -1 || step.Register == f.CPU.Syscall.Out[0] {
return
}
f.Assembler.Append(&asm.MoveRegisterRegister{
Destination: step.Register,
Source: f.CPU.Return[0],
Source: f.CPU.Syscall.Out[0],
})
}
}

View file

@ -21,10 +21,33 @@ const (
R15
)
var CPU = cpu.CPU{
Call: []cpu.Register{R0, R7, R6, R2, R10, R8, R9},
Syscall: []cpu.Register{R0, R7, R6, R2, R10, R8, R9},
ExternCall: []cpu.Register{R1, R2, R8, R9},
ExternCallVolatile: []cpu.Register{R0, R1, R2, R8, R9, R10, R11},
Return: []cpu.Register{R0, R7, R6},
}
var (
LinuxCPU = cpu.CPU{
Call: cpu.ABI{
In: []cpu.Register{R0, R7, R6, R2, R10, R8, R9},
Out: []cpu.Register{R0, R7, R6},
Volatile: []cpu.Register{R0, R1, R2, R6, R7, R8, R9, R10, R11},
},
ExternCall: cpu.ABI{
In: []cpu.Register{R7, R6, R2, R1, R8, R9},
Out: []cpu.Register{R0, R2},
Volatile: []cpu.Register{R0, R1, R2, R6, R7, R8, R9, R10, R11},
},
Syscall: cpu.ABI{
In: []cpu.Register{R0, R7, R6, R2, R10, R8, R9},
Out: []cpu.Register{R0},
Volatile: []cpu.Register{R0, R7, R6},
},
}
MacCPU = LinuxCPU
WindowsCPU = cpu.CPU{
Call: LinuxCPU.Call,
ExternCall: cpu.ABI{
In: []cpu.Register{R1, R2, R8, R9},
Out: []cpu.Register{R0},
Volatile: []cpu.Register{R0, R1, R2, R8, R9, R10, R11},
},
}
)