avr: add support for recover()

You can see that it works with the following command:

    tinygo run -target=simavr ./testdata/recover.go

This also gets the following tests to pass again:

    go test -run=Build -target=simavr -v

Adding support for AVR was a bit more compliated because it's also
necessary to save and restore the Y register.
This commit is contained in:
Ayke van Laethem
2022-06-17 16:55:18 +02:00
committed by Ron Evans
parent 159f0051bb
commit 9af535bf98
14 changed files with 75 additions and 9 deletions
+2
View File
@@ -5,6 +5,8 @@ const GOARCH = "386"
// The bitness of the CPU (e.g. 8, 32, 64).
const TargetBits = 32
const deferExtraRegs = 0
// Align on word boundary.
func align(ptr uintptr) uintptr {
return (ptr + 15) &^ 15
+2
View File
@@ -5,6 +5,8 @@ const GOARCH = "amd64"
// The bitness of the CPU (e.g. 8, 32, 64).
const TargetBits = 64
const deferExtraRegs = 0
// Align a pointer.
// Note that some amd64 instructions (like movaps) expect 16-byte aligned
// memory, thus the result must be 16-byte aligned.
+2
View File
@@ -8,6 +8,8 @@ const GOARCH = "arm"
// The bitness of the CPU (e.g. 8, 32, 64).
const TargetBits = 32
const deferExtraRegs = 0
// Align on word boundary.
func align(ptr uintptr) uintptr {
return (ptr + 3) &^ 3
+2
View File
@@ -5,6 +5,8 @@ const GOARCH = "arm64"
// The bitness of the CPU (e.g. 8, 32, 64).
const TargetBits = 64
const deferExtraRegs = 0
// Align on word boundary.
func align(ptr uintptr) uintptr {
return (ptr + 7) &^ 7
+2
View File
@@ -10,6 +10,8 @@ const GOARCH = "arm" // avr pretends to be arm
// The bitness of the CPU (e.g. 8, 32, 64).
const TargetBits = 8
const deferExtraRegs = 1 // the frame pointer (Y register) also needs to be stored
// Align on a word boundary.
func align(ptr uintptr) uintptr {
// No alignment necessary on the AVR.
+2
View File
@@ -12,6 +12,8 @@ const GOARCH = "arm"
// The bitness of the CPU (e.g. 8, 32, 64).
const TargetBits = 32
const deferExtraRegs = 0
// Align on word boundary.
func align(ptr uintptr) uintptr {
return (ptr + 3) &^ 3
+2
View File
@@ -5,6 +5,8 @@ package runtime
import "device/riscv"
const deferExtraRegs = 0
func getCurrentStackPointer() uintptr {
return uintptr(stacksave())
}
+2
View File
@@ -12,6 +12,8 @@ const GOARCH = "wasm"
// The bitness of the CPU (e.g. 8, 32, 64).
const TargetBits = 32
const deferExtraRegs = 0
//go:extern __heap_base
var heapStartSymbol [0]byte
+2
View File
@@ -8,6 +8,8 @@ const GOARCH = "arm" // xtensa pretends to be arm
// The bitness of the CPU (e.g. 8, 32, 64).
const TargetBits = 32
const deferExtraRegs = 0
// Align on a word boundary.
func align(ptr uintptr) uintptr {
return (ptr + 3) &^ 3
+30
View File
@@ -50,3 +50,33 @@ tinygo_scanCurrentStack:
pop r17
pop r28 // Y
pop r29 // Y
.section .text.tinygo_longjmp
.global tinygo_longjmp
tinygo_longjmp:
; Move the *DeferFrame pointer to the X register.
mov r26, r24
mov r27, r25
; Load the stack pointer
ld r24, X+
ld r25, X+
; Switch to the given stack pointer.
in r0, 0x3f ; SREG
cli ; disable interrupts
out 0x3d, r24 ; SPL
out 0x3f, r0 ; re-enable interrupts (with one instruction delay)
out 0x3e, r25 ; SPH
; Load the new PC
ld r30, X+
ld r31, X+
; Load the new Y register
ld r28, X+
ld r29, X+
; Jump to the PC (stored in the Z register)
icall
+6 -5
View File
@@ -25,11 +25,12 @@ func supportsRecover() bool
// The compiler knows about the JumpPC struct offset, so it should not be moved
// without also updating compiler/defer.go.
type deferFrame struct {
JumpSP unsafe.Pointer // stack pointer to return to
JumpPC unsafe.Pointer // pc to return to
Previous *deferFrame // previous recover buffer pointer
Panicking bool // true iff this defer frame is panicking
PanicValue interface{} // panic value, might be nil for panic(nil) for example
JumpSP unsafe.Pointer // stack pointer to return to
JumpPC unsafe.Pointer // pc to return to
ExtraRegs [deferExtraRegs]unsafe.Pointer // extra registers (depending on the architecture)
Previous *deferFrame // previous recover buffer pointer
Panicking bool // true iff this defer frame is panicking
PanicValue interface{} // panic value, might be nil for panic(nil) for example
}
// Builtin function panic(msg), used as a compiler intrinsic.