arm: implement SVCall
The SVCall function call is lowered to an inline "svc" instruction. The first parameter *must* be a constant number.
Этот коммит содержится в:
родитель
ce0ad1daa2
коммит
d887d645f7
2 изменённых файлов: 42 добавлений и 0 удалений
|
@ -1972,6 +1972,36 @@ func (c *Compiler) parseCall(frame *Frame, instr *ssa.CallCommon, parentHandle l
|
||||||
return c.builder.CreateCall(target, nil, ""), nil
|
return c.builder.CreateCall(target, nil, ""), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(fn.RelString(nil), "device/arm.SVCall") {
|
||||||
|
// Magic function: inline this call as a SVC instruction.
|
||||||
|
num, _ := constant.Uint64Val(instr.Args[0].(*ssa.Const).Value)
|
||||||
|
args := []llvm.Value{}
|
||||||
|
argTypes := []llvm.Type{}
|
||||||
|
asm := "svc #" + strconv.FormatUint(num, 10)
|
||||||
|
constraints := "={r0}"
|
||||||
|
for i, arg := range instr.Args[1:] {
|
||||||
|
arg = arg.(*ssa.MakeInterface).X
|
||||||
|
if i == 0 {
|
||||||
|
constraints += ",0"
|
||||||
|
} else {
|
||||||
|
constraints += ",{r" + strconv.Itoa(i) + "}"
|
||||||
|
}
|
||||||
|
llvmValue, err := c.parseExpr(frame, arg)
|
||||||
|
if err != nil {
|
||||||
|
return llvm.Value{}, err
|
||||||
|
}
|
||||||
|
args = append(args, llvmValue)
|
||||||
|
argTypes = append(argTypes, llvmValue.Type())
|
||||||
|
}
|
||||||
|
// Implement the ARM calling convention by marking r1-r3 as
|
||||||
|
// clobbered. r0 is used as an output register so doesn't have to be
|
||||||
|
// marked as clobbered.
|
||||||
|
constraints += ",~{r1},~{r2},~{r3}"
|
||||||
|
fnType := llvm.FunctionType(c.uintptrType, argTypes, false)
|
||||||
|
target := llvm.InlineAsm(fnType, asm, constraints, true, false, 0)
|
||||||
|
return c.builder.CreateCall(target, args, ""), nil
|
||||||
|
}
|
||||||
|
|
||||||
if fn.RelString(nil) == "device/arm.AsmFull" || fn.RelString(nil) == "device/avr.AsmFull" {
|
if fn.RelString(nil) == "device/arm.AsmFull" || fn.RelString(nil) == "device/avr.AsmFull" {
|
||||||
asmString := constant.StringVal(instr.Args[0].(*ssa.Const).Value)
|
asmString := constant.StringVal(instr.Args[0].(*ssa.Const).Value)
|
||||||
registers := map[string]llvm.Value{}
|
registers := map[string]llvm.Value{}
|
||||||
|
|
|
@ -54,6 +54,18 @@ func AsmFull(asm string, regs map[string]interface{})
|
||||||
// must be a processor register, reachable with the "mov" instruction.
|
// must be a processor register, reachable with the "mov" instruction.
|
||||||
func ReadRegister(name string) uintptr
|
func ReadRegister(name string) uintptr
|
||||||
|
|
||||||
|
// Run the following system call (SVCall) with 1 argument.
|
||||||
|
func SVCall1(num uintptr, a1 interface{}) uintptr
|
||||||
|
|
||||||
|
// Run the following system call (SVCall) with 2 arguments.
|
||||||
|
func SVCall2(num uintptr, a1, a2 interface{}) uintptr
|
||||||
|
|
||||||
|
// Run the following system call (SVCall) with 3 arguments.
|
||||||
|
func SVCall3(num uintptr, a1, a2, a3 interface{}) uintptr
|
||||||
|
|
||||||
|
// Run the following system call (SVCall) with 4 arguments.
|
||||||
|
func SVCall4(num uintptr, a1, a2, a3, a4 interface{}) uintptr
|
||||||
|
|
||||||
//go:volatile
|
//go:volatile
|
||||||
type RegValue uint32
|
type RegValue uint32
|
||||||
|
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче