我在 MMIX 中编写了 setjmp 和 longjmp 的实现(假设没有名称修改)。我也是手工组装的。
有没有人能发现的错误?
// Memory stack pointer is stored in $254.
// jmp_buf is rO, next address after setjmp call, memory stack pointer,
// frame pointer, then possibly other data (for sigsetjmp/siglongjmp).
// rG is preserved over a longjmp call
// (not that it should change over one, anyway)
setjmp IS @
GET $1,rO // FE01000A
STOU $1,$0,0 // AF010000
GET $1,rJ // FE010004
STOU $1,$0,8 // AF010008
STOU $254,$0,16 // AFFE0010
STOU $253,$0,24 // AFFD0018
SETL $0,0 // E3000000
POP 1,0 // F8010000
longjmp IS @
LDOU $254,$0,0 // 8FFE0000
SAVE $255,0 // FAFF0000
GET $1,rG // FE000013
// why 15? We save 13 special registers, two local registers,
// and the number 2, as well as any global registers.
// That's 256-rG + 16, and we add only 15 because $255 is the address
// of the saved rGA.
SETL $0,271 // E300010F
SUBU $1,$1,$0 // 26010100
SLU $1,$1,3 // 39000003
// now $255 is topmost saved register, $255+$1 is bottommost such,
// $254 is rO after.
SUBU $0,$254,$1 // 2600FE01
LDOU $2,$255,$1 // 8E02FF01
STOU $2,$0,$1 // AE020001
INCL $1,8 // E7010008
PBNZ $1,@-12 // 5B01FFFD
OR $255,$0,0 // C1FF0000
UNSAVE 0,$255 // FB0000FF
// now we have restored rO, but not other stuff
LDOU $253,$0,24 // 8FFD0018
LDOU $254,$0,16 // 8FFE0010
LDOU $0,$0,8 // 8F000008
PUT rJ,$0 // F6040000
OR $0,$1,0 // C1000100
POP 1,0 // F8010000
寄存器堆栈是这里的难点。SAVE
和包容之间的一切UNSAVE
本质上只是“rO
正确设置”;之后,完全不需要时间来修复其他寄存器并返回。
如果您有任何其他问题,我很乐意解释我对该代码的每个 tetra 的原因。