summaryrefslogtreecommitdiffstats
path: root/newlib/libc/machine/mep/setjmp.S
diff options
context:
space:
mode:
Diffstat (limited to 'newlib/libc/machine/mep/setjmp.S')
-rw-r--r--newlib/libc/machine/mep/setjmp.S118
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