diff options
Diffstat (limited to 'newlib/libc/machine/mep/setjmp.S')
-rw-r--r-- | newlib/libc/machine/mep/setjmp.S | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/newlib/libc/machine/mep/setjmp.S b/newlib/libc/machine/mep/setjmp.S new file mode 100644 index 000000000..3b39bcf8c --- /dev/null +++ b/newlib/libc/machine/mep/setjmp.S @@ -0,0 +1,118 @@ +# +# Setjmp/longjmp for MeP +# +# DJ Delorie, Red Hat Inc. +# +# 19 32-bit words in the jmpbuf: +# $0 +# $1 +# ... +# $15 +# $pc +# $hi +# $lo +# +# Note that $0 is saved but not restored. It can't be restored +# as it's the return value of setjmp, but we save it in case +# some application wants to see it in the jmp_buf. Ideally, +# we should not need to save anything that is call-clobbered, +# but you never know what the user is going to tell gcc with -f +# options. + + .noregerr + .text + + .globl setjmp + .type setjmp,@function + +setjmp: + + # $1 is the address of the buffer. We return 0 in $0. + + sw $0, ($1) + sw $1, 4($1) + sw $2, 8($1) + sw $3, 12($1) + sw $4, 16($1) + sw $5, 20($1) + sw $6, 24($1) + sw $7, 28($1) + sw $8, 32($1) + sw $9, 36($1) + sw $10, 40($1) + sw $11, 44($1) + sw $12, 48($1) + sw $13, 52($1) + sw $14, 56($1) + sw $15, 60($1) + + ldc $0, $lp + sw $0, 64($1) + ldc $0, $opt + sra $0, 24 + and3 $0, $0, 3 + beqz $0, sj_skip_hilo + ldc $0, $hi + sw $0, 68($1) + ldc $0, $lo + sw $0, 72($1) +sj_skip_hilo: + + mov $0, 0 + ret + + .globl longjmp + .type longjmp,@function + +longjmp: + + # $1 is the address of the buffer. $2 is the value setjmp + # returns. We do not faithfully restore $0 or $lp, because + # the act of calling setjmp clobbered those anyway. + + bnez $2, rv_not_zero + mov $2, 1 +rv_not_zero: + + # We restore $sp first so we can save the return value there, + # otherwise we'd need to have another unrestored register. + lw $15, 60($1) + add3 $sp, $sp, -4 + sw $2, ($sp) + + # Now restore the general registers. + lw $2, 8($1) + lw $3, 12($1) + lw $4, 16($1) + lw $5, 20($1) + lw $6, 24($1) + lw $7, 28($1) + lw $8, 32($1) + lw $9, 36($1) + lw $10, 40($1) + lw $11, 44($1) + lw $12, 48($1) + lw $13, 52($1) + lw $14, 56($1) + + # We restore $pc's value to $lp so that we can just ret later. + lw $0, 64($1) + stc $0, $lp + ldc $0, $opt + sra $0, 24 + and3 $0, $0, 3 + beqz $0, lj_skip_hilo + lw $0, 68($1) + stc $0, $hi + lw $0, 72($1) + stc $0, $lo +lj_skip_hilo: + + # Restore $1 + lw $1, 8($1) + + # Get the return value off the stack, and restore the stack. + lw $0, ($sp) + add3 $sp, $sp, 4 + + ret |