runtime: load sp and pc inside tinygo_longjmp
This is a small change to make it easier to support architectures that need to restore more than just the sp and pc registers. In particular, it is needed for the AVR architecture that needs to restore the frame pointer (Y register).
Этот коммит содержится в:
родитель
c119721e3b
коммит
49e22fe678
7 изменённых файлов: 24 добавлений и 19 удалений
|
@ -28,6 +28,7 @@ tinygo_scanCurrentStack:
|
||||||
tinygo_longjmp:
|
tinygo_longjmp:
|
||||||
// Note: the code we jump to assumes eax is set to a non-zero value if we
|
// Note: the code we jump to assumes eax is set to a non-zero value if we
|
||||||
// jump from here.
|
// jump from here.
|
||||||
movl 8(%esp), %eax // jumpPC (stash in volatile register)
|
movl 4(%esp), %eax
|
||||||
movl 4(%esp), %esp // jumpSP
|
movl 0(%eax), %esp // jumpSP
|
||||||
|
movl 4(%eax), %eax // jumpPC (stash in volatile register)
|
||||||
jmpl *%eax
|
jmpl *%eax
|
||||||
|
|
|
@ -37,11 +37,11 @@ tinygo_longjmp:
|
||||||
.global _tinygo_longjmp
|
.global _tinygo_longjmp
|
||||||
_tinygo_longjmp:
|
_tinygo_longjmp:
|
||||||
#endif
|
#endif
|
||||||
// Note: the code we jump to assumes rax is non-zero so we have to load it
|
// Note: the code we jump to assumes rax is set to a non-zero value if we
|
||||||
// with some value here.
|
// jump from here, so we use rax as the temporary value for jumpPC.
|
||||||
movq $1, %rax
|
movq 0(%rdi), %rsp // jumpSP
|
||||||
movq %rdi, %rsp // jumpSP
|
movq 8(%rdi), %rax // jumpPC
|
||||||
jmpq *%rsi // jumpPC
|
jmpq *%rax
|
||||||
|
|
||||||
|
|
||||||
#ifdef __MACH__ // Darwin
|
#ifdef __MACH__ // Darwin
|
||||||
|
|
|
@ -24,8 +24,8 @@ tinygo_scanCurrentStack:
|
||||||
.section .text.tinygo_longjmp,"ax"
|
.section .text.tinygo_longjmp,"ax"
|
||||||
.global tinygo_longjmp
|
.global tinygo_longjmp
|
||||||
tinygo_longjmp:
|
tinygo_longjmp:
|
||||||
// Note: the code we jump to assumes rax is non-zero so we have to load it
|
// Note: the code we jump to assumes rax is set to a non-zero value if we
|
||||||
// with some value here.
|
// jump from here, so we use rax as the temporary value for jumpPC.
|
||||||
movq $1, %rax
|
movq 0(%rcx), %rsp // jumpSP
|
||||||
movq %rcx, %rsp // jumpSP
|
movq 8(%rcx), %rax // jumpPC
|
||||||
jmpq *%rdx // jumpPC
|
jmpq *%rax
|
||||||
|
|
|
@ -40,6 +40,8 @@ tinygo_longjmp:
|
||||||
.cfi_startproc
|
.cfi_startproc
|
||||||
// Note: the code we jump to assumes r0 is set to a non-zero value if we
|
// Note: the code we jump to assumes r0 is set to a non-zero value if we
|
||||||
// jump from here (which is conveniently already the case).
|
// jump from here (which is conveniently already the case).
|
||||||
|
|
||||||
|
ldm r0, {r0, r1}
|
||||||
mov sp, r0 // jumpSP
|
mov sp, r0 // jumpSP
|
||||||
mov pc, r1 // jumpPC
|
mov pc, r1 // jumpPC
|
||||||
.cfi_endproc
|
.cfi_endproc
|
||||||
|
|
|
@ -43,5 +43,6 @@ tinygo_longjmp:
|
||||||
#endif
|
#endif
|
||||||
// Note: the code we jump to assumes x0 is set to a non-zero value if we
|
// Note: the code we jump to assumes x0 is set to a non-zero value if we
|
||||||
// jump from here (which is conveniently already the case).
|
// jump from here (which is conveniently already the case).
|
||||||
mov sp, x0 // jumpSP
|
ldp x1, x2, [x0] // jumpSP, jumpPC
|
||||||
br x1 // jumpPC
|
mov sp, x1
|
||||||
|
br x2
|
||||||
|
|
|
@ -46,6 +46,7 @@ tinygo_scanCurrentStack:
|
||||||
.global tinygo_longjmp
|
.global tinygo_longjmp
|
||||||
tinygo_longjmp:
|
tinygo_longjmp:
|
||||||
// Note: the code we jump to assumes a0 is non-zero, which is already the
|
// Note: the code we jump to assumes a0 is non-zero, which is already the
|
||||||
// case because that's jumpSP (the stack pointer).
|
// case because that's the defer frame pointer.
|
||||||
mv sp, a0 // jumpSP
|
lw sp, 0(a0) // jumpSP
|
||||||
jr a1 // jumpPC
|
lw a1, REGSIZE(a0) // jumpPC
|
||||||
|
jr a1
|
||||||
|
|
|
@ -13,7 +13,7 @@ func trap()
|
||||||
// Inline assembly stub. It is essentially C longjmp but modified a bit for the
|
// Inline assembly stub. It is essentially C longjmp but modified a bit for the
|
||||||
// purposes of TinyGo. It restores the stack pointer and jumps to the given pc.
|
// purposes of TinyGo. It restores the stack pointer and jumps to the given pc.
|
||||||
//export tinygo_longjmp
|
//export tinygo_longjmp
|
||||||
func tinygo_longjmp(sp, pc unsafe.Pointer)
|
func tinygo_longjmp(frame *task.DeferFrame)
|
||||||
|
|
||||||
// Compiler intrinsic.
|
// Compiler intrinsic.
|
||||||
// Returns whether recover is supported on the current architecture.
|
// Returns whether recover is supported on the current architecture.
|
||||||
|
@ -26,7 +26,7 @@ func _panic(message interface{}) {
|
||||||
if frame != nil {
|
if frame != nil {
|
||||||
frame.PanicValue = message
|
frame.PanicValue = message
|
||||||
frame.Panicking = true
|
frame.Panicking = true
|
||||||
tinygo_longjmp(frame.JumpSP, frame.JumpPC)
|
tinygo_longjmp(frame)
|
||||||
// unreachable
|
// unreachable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче