source: trunk/libs/newlib/src/newlib/libc/machine/mips/setjmp.S @ 444

Last change on this file since 444 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 3.9 KB
Line 
1/* This is a simple version of setjmp and longjmp for MIPS 32 and 64.
2
3   Ian Lance Taylor, Cygnus Support, 13 May 1993.  */
4
5#ifdef __mips16
6/* This file contains 32 bit assembly code.  */
7        .set nomips16
8#endif
9
10#define GPR_LAYOUT              \
11        GPR_OFFSET ($16, 0);    \
12        GPR_OFFSET ($17, 1);    \
13        GPR_OFFSET ($18, 2);    \
14        GPR_OFFSET ($19, 3);    \
15        GPR_OFFSET ($20, 4);    \
16        GPR_OFFSET ($21, 5);    \
17        GPR_OFFSET ($22, 6);    \
18        GPR_OFFSET ($23, 7);    \
19        GPR_OFFSET ($29, 8);    \
20        GPR_OFFSET ($30, 9);    \
21        GPR_OFFSET ($31, 10)
22
23#define NUM_GPRS_SAVED 11
24
25#ifdef __mips_hard_float
26#if _MIPS_SIM == _ABIN32
27#define FPR_LAYOUT              \
28        FPR_OFFSET ($f20, 0);   \
29        FPR_OFFSET ($f22, 1);   \
30        FPR_OFFSET ($f24, 2);   \
31        FPR_OFFSET ($f26, 3);   \
32        FPR_OFFSET ($f28, 4);   \
33        FPR_OFFSET ($f30, 5);
34#elif _MIPS_SIM == _ABI64
35#define FPR_LAYOUT              \
36        FPR_OFFSET ($f24, 0);   \
37        FPR_OFFSET ($f25, 1);   \
38        FPR_OFFSET ($f26, 2);   \
39        FPR_OFFSET ($f27, 3);   \
40        FPR_OFFSET ($f28, 4);   \
41        FPR_OFFSET ($f29, 5);   \
42        FPR_OFFSET ($f30, 6);   \
43        FPR_OFFSET ($f31, 7);
44#elif __mips_fpr == 0 || __mips_fpr == 64
45
46/* This deals with the o32 FPXX and FP64 cases.  Here we must use
47   SDC1 and LDC1 to access the FPRs.  These instructions require
48   8-byte aligned addresses.
49   Unfortunately, the MIPS jmp_buf only guarantees 4-byte alignment
50   and this cannot be increased without breaking compatibility with
51   pre-existing objects built against newlib.  There are 11 GPRS
52   saved in the jmp_buf so a buffer that happens to be 8-byte aligned
53   ends up leaving the FPR slots 4-byte aligned and an (only) 4-byte
54   aligned buffer leads to the FPR slots being 8-byte aligned!
55   
56   To resolve this, we move the location of $31 to the last slot
57   in the jmp_buf when the overall buffer is 8-byte aligned.  $31
58   is simply loaded/stored twice to avoid adding complexity to the
59   GPR_LAYOUT macro above as well as FPR_LAYOUT.
60
61   The location of the last slot is index 22 which is calculated
62   from there being 11 GPRs saved and then 12 FPRs saved so the
63   index of the last FPR is 11+11.
64   
65   The base of the jmp_buf is modified in $4 to allow the
66   FPR_OFFSET macros to just use the usual constant slot numbers
67   regardless of whether the realignment happened or not.  */
68
69#define FPR_LAYOUT              \
70        and $8, $4, 4;          \
71        bne $8, $0, 1f;         \
72        GPR_OFFSET ($31, 22);   \
73        addiu $4, $4, -4;       \
741:                              \
75        FPR_OFFSET ($f20, 0);   \
76        FPR_OFFSET ($f22, 2);   \
77        FPR_OFFSET ($f24, 4);   \
78        FPR_OFFSET ($f26, 6);   \
79        FPR_OFFSET ($f28, 8);   \
80        FPR_OFFSET ($f30, 10);
81#else /* Assuming _MIPS_SIM == _ABIO32 */
82#define FPR_LAYOUT              \
83        FPR_OFFSET ($f20, 0);   \
84        FPR_OFFSET ($f21, 1);   \
85        FPR_OFFSET ($f22, 2);   \
86        FPR_OFFSET ($f23, 3);   \
87        FPR_OFFSET ($f24, 4);   \
88        FPR_OFFSET ($f25, 5);   \
89        FPR_OFFSET ($f26, 6);   \
90        FPR_OFFSET ($f27, 7);   \
91        FPR_OFFSET ($f28, 8);   \
92        FPR_OFFSET ($f29, 9);   \
93        FPR_OFFSET ($f30, 10);  \
94        FPR_OFFSET ($f31, 11);
95#endif
96#else
97#define FPR_LAYOUT
98#endif
99       
100#ifdef __mips64
101#define BYTES_PER_WORD 8
102#define LOAD_GPR ld
103#define LOAD_FPR ldc1
104#define STORE_GPR sd
105#define STORE_FPR sdc1
106#else
107#define LOAD_GPR lw
108#define STORE_GPR sw
109#define BYTES_PER_WORD 4
110#if __mips_fpr == 0 || __mips_fpr == 64
111#define LOAD_FPR ldc1
112#define STORE_FPR sdc1
113#else
114#define LOAD_FPR lwc1
115#define STORE_FPR swc1
116#endif
117#endif
118
119#define GPOFF(INDEX) (INDEX * BYTES_PER_WORD)
120#define FPOFF(INDEX) ((INDEX + NUM_GPRS_SAVED) * BYTES_PER_WORD)
121
122/* int setjmp (jmp_buf);  */
123        .globl  setjmp
124        .ent    setjmp
125setjmp:
126        .frame  $sp,0,$31
127
128#define GPR_OFFSET(REG, INDEX) STORE_GPR REG,GPOFF(INDEX)($4)
129#define FPR_OFFSET(REG, INDEX) STORE_FPR REG,FPOFF(INDEX)($4)
130        GPR_LAYOUT
131        FPR_LAYOUT
132#undef GPR_OFFSET
133#undef FPR_OFFSET
134
135        move    $2,$0
136        j       $31
137
138        .end    setjmp
139
140/* volatile void longjmp (jmp_buf, int);  */
141        .globl  longjmp
142        .ent    longjmp
143longjmp:
144        .frame  $sp,0,$31
145
146#define GPR_OFFSET(REG, INDEX) LOAD_GPR REG,GPOFF(INDEX)($4)
147#define FPR_OFFSET(REG, INDEX) LOAD_FPR REG,FPOFF(INDEX)($4)
148        GPR_LAYOUT
149        FPR_LAYOUT
150#undef GPR_OFFSET
151#undef FPR_OFFSET
152
153        bne     $5,$0,1f
154        li      $5,1
1551:
156        move    $2,$5
157        j       $31
158
159        .end longjmp
Note: See TracBrowser for help on using the repository browser.