mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-06 12:03:41 +00:00
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:
committed by
Ron Evans
parent
159f0051bb
commit
9af535bf98
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -5,6 +5,8 @@ package runtime
|
||||
|
||||
import "device/riscv"
|
||||
|
||||
const deferExtraRegs = 0
|
||||
|
||||
func getCurrentStackPointer() uintptr {
|
||||
return uintptr(stacksave())
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user