summaryrefslogtreecommitdiffstats
path: root/newlib/libc/machine/m32c/setjmp.S
diff options
context:
space:
mode:
Diffstat (limited to 'newlib/libc/machine/m32c/setjmp.S')
-rw-r--r--newlib/libc/machine/m32c/setjmp.S133
1 files changed, 133 insertions, 0 deletions
diff --git a/newlib/libc/machine/m32c/setjmp.S b/newlib/libc/machine/m32c/setjmp.S
new file mode 100644
index 000000000..96cd0f20d
--- /dev/null
+++ b/newlib/libc/machine/m32c/setjmp.S
@@ -0,0 +1,133 @@
+/*
+
+Copyright (c) 2005 Red Hat Incorporated.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ The name of Red Hat Incorporated may not be used to endorse
+ or promote products derived from this software without specific
+ prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL RED HAT INCORPORATED BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#if defined(__r8c_cpu__) || defined(__m16c_cpu__)
+#define A16 1
+#endif
+
+/* We implement setjmp/longjmp much like the way gcc implements
+ exceptions - we create new stack frames, then switch to them and
+ return. Thus, the two setjmp's below each push all the relevent
+ registers, then copy the whole frame into the buffer (first $sp is
+ moved, then smovf copies the frame itself), and the two longjmps
+ restore $sp, copy the frame back into place, and issue the same
+ return as the setjmp would have used.
+
+ Since the sizes of registers differs between the 16 and 24 bit
+ models, we provide separate implementations for each rather than
+ trying to parameterize them.
+
+ Jump buffer sizes: 21 bytes for 16 bit, 34 bytes for 24 bit.
+*/
+
+ .text
+
+#ifdef A16 /* 16 bit versions */
+
+ .global _setjmp
+_setjmp:
+ enter #0
+ pushm r1,r2,r3,a0,a1,sb,fb
+
+; At this point, the stack looks like this:
+; ... [pc:3] [oldfb:2] <fb> [r1:2] [r2:2] [r3:2] [a0:2] [a1:2] [sb:2] [fb:2] <sp> */
+
+ mov.w r1,a1 ; a1 is the destination of smovf
+ mov.b #0,r1h
+ stc sp,a0 ; r1h:a0 is the source of smovf
+ mov.w a0,[a1]
+ add.w #2,a1
+ mov.w #19,r3 ; plus two for sp later
+ smovf.b
+
+ ; Return 0 to caller.
+ mov.w #0,r0
+ popm r1,r2,r3,a0,a1,sb,fb
+ exitd
+
+ .global _longjmp
+_longjmp:
+ enter #0
+ mov.w r1,a0 ; pointer to jump buf
+ mov.w r2,r0 ; setjmp's "new" return value
+
+ mov.b #0,r1h ; r1h: a0 is the source, now jmpbuf
+ mov.w [a0],a1 ; dest is new stack
+ ldc a1,sp
+ add.w #2,a0
+ mov.w #19,r3
+ smovf.b
+
+ ;; now return to our caller with this newly restored frame
+ popm r1,r2,r3,a0,a1,sb,fb
+ exitd
+
+#else /* 24 bit versions */
+
+ .global _setjmp
+_setjmp:
+ enter #0
+ pushm r1,r2,r3,a0,a1,sb,fb
+
+; At this point, the stack looks like this:
+; ... [jbuf:4] [pc:4] [oldfb:4] <fb> [r1:2] [r2:2] [r3:2] [a0:4] [a1:4] [sb:4] [fb:4] <sp> */
+
+ mov.l 8[fb],a1 ; a1 is the destination of smovf
+ stc sp,a0 ; r1h:a0 is the source of smovf
+ mov.l a0,[a1]
+ add.l #4,a1
+ mov.w #30,r3 ; plus two for sp later
+ smovf.b
+
+ ; Return 0 to caller.
+ mov.w #0,r0
+ popm r1,r2,r3,a0,a1,sb,fb
+ exitd
+
+ .global _longjmp
+_longjmp:
+ enter #0
+; ... [rv:2] [jbuf:4] [pc:4] [oldfb:4] <fb>
+ mov.l 8[fb],a0 ; pointer to jump buf
+ mov.w 12[fb],r0 ; setjmp's "new" return value
+
+ mov.l [a0],a1 ; dest is new stack
+ ldc a1,sp
+ add.l #4,a0
+ mov.w #30,r3
+ smovf.b
+
+ ;; now return to our caller with this newly restored frame
+ popm r1,r2,r3,a0,a1,sb,fb
+ exitd
+#endif
+