From d887d645f763aa39e6f31382a11eb53b6beb9c36 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Wed, 21 Nov 2018 17:06:56 +0100 Subject: [PATCH] arm: implement SVCall The SVCall function call is lowered to an inline "svc" instruction. The first parameter *must* be a constant number. --- compiler/compiler.go | 30 ++++++++++++++++++++++++++++++ src/device/arm/arm.go | 12 ++++++++++++ 2 files changed, 42 insertions(+) diff --git a/compiler/compiler.go b/compiler/compiler.go index bb6ffbbf0..1a56c98c1 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 5ff7d0747..6fed5dc89 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