diff --git a/compiler/compiler.go b/compiler/compiler.go index bb6ffbbf..1a56c98c 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -1972,6 +1972,36 @@ func (c *Compiler) parseCall(frame *Frame, instr *ssa.CallCommon, parentHandle l 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" { asmString := constant.StringVal(instr.Args[0].(*ssa.Const).Value) registers := map[string]llvm.Value{} diff --git a/src/device/arm/arm.go b/src/device/arm/arm.go index 5ff7d074..6fed5dc8 100644 --- a/src/device/arm/arm.go +++ b/src/device/arm/arm.go @@ -54,6 +54,18 @@ func AsmFull(asm string, regs map[string]interface{}) // must be a processor register, reachable with the "mov" instruction. 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 type RegValue uint32