269 lines
7.1 KiB
ArmAsm
269 lines
7.1 KiB
ArmAsm
/* This is a simple version of setjmp and longjmp for the PowerPC.
|
|
Ian Lance Taylor, Cygnus Support, 9 Feb 1994.
|
|
Modified by Jeff Johnston, Red Hat Inc. 2 Oct 2001. */
|
|
|
|
#include "ppc-asm.h"
|
|
|
|
FUNC_START(setjmp)
|
|
#ifdef __ALTIVEC__
|
|
addi 3,3,15 # align Altivec to 16 byte boundary
|
|
rlwinm 3,3,0,0,27
|
|
#else
|
|
addi 3,3,7 # align to 8 byte boundary
|
|
rlwinm 3,3,0,0,28
|
|
#endif
|
|
#if __SPE__
|
|
/* If we are E500, then save 64-bit registers. */
|
|
evstdd 1,0(3) # offset 0
|
|
evstdd 2,8(3) # offset 8
|
|
evstdd 13,16(3) # offset 16
|
|
evstdd 14,24(3) # offset 24
|
|
evstdd 15,32(3) # offset 32
|
|
evstdd 16,40(3) # offset 40
|
|
evstdd 17,48(3) # offset 48
|
|
evstdd 18,56(3) # offset 56
|
|
evstdd 19,64(3) # offset 64
|
|
evstdd 20,72(3) # offset 72
|
|
evstdd 21,80(3) # offset 80
|
|
evstdd 22,88(3) # offset 88
|
|
evstdd 23,96(3) # offset 96
|
|
evstdd 24,104(3) # offset 104
|
|
evstdd 25,112(3) # offset 112
|
|
evstdd 26,120(3) # offset 120
|
|
evstdd 27,128(3) # offset 128
|
|
evstdd 28,136(3) # offset 136
|
|
evstdd 29,144(3) # offset 144
|
|
evstdd 30,152(3) # offset 152
|
|
evstdd 31,160(3) # offset 160
|
|
|
|
/* Add 164 to r3 to account for the amount of data we just
|
|
stored. Note that we are not adding 168 because the next
|
|
store instruction uses an offset of 4. */
|
|
addi 3,3,164
|
|
#else
|
|
stw 1,0(3) # offset 0
|
|
stwu 2,4(3) # offset 4
|
|
stwu 13,4(3) # offset 8
|
|
stwu 14,4(3) # offset 12
|
|
stwu 15,4(3) # offset 16
|
|
stwu 16,4(3) # offset 20
|
|
stwu 17,4(3) # offset 24
|
|
stwu 18,4(3) # offset 28
|
|
stwu 19,4(3) # offset 32
|
|
stwu 20,4(3) # offset 36
|
|
stwu 21,4(3) # offset 40
|
|
stwu 22,4(3) # offset 44
|
|
stwu 23,4(3) # offset 48
|
|
stwu 24,4(3) # offset 52
|
|
stwu 25,4(3) # offset 56
|
|
stwu 26,4(3) # offset 60
|
|
stwu 27,4(3) # offset 64
|
|
stwu 28,4(3) # offset 68
|
|
stwu 29,4(3) # offset 72
|
|
stwu 30,4(3) # offset 76
|
|
stwu 31,4(3) # offset 80
|
|
#endif
|
|
|
|
/* From this point on until the end of this function, add 84
|
|
to the offset shown if __SPE__. This difference comes from
|
|
the fact that we save 21 64-bit registers instead of 21
|
|
32-bit registers above. */
|
|
mflr 4
|
|
stwu 4,4(3) # offset 84
|
|
mfcr 4
|
|
stwu 4,4(3) # offset 88
|
|
# one word pad to get floating point aligned on 8 byte boundary
|
|
|
|
/* Check whether we need to save FPRs. Checking __NO_FPRS__
|
|
on its own would be enough for GCC 4.1 and above, but older
|
|
compilers only define _SOFT_FLOAT, so check both. */
|
|
#if !defined (__NO_FPRS__) && !defined (_SOFT_FLOAT)
|
|
stfdu 14,8(3) # offset 96
|
|
stfdu 15,8(3) # offset 104
|
|
stfdu 16,8(3) # offset 112
|
|
stfdu 17,8(3) # offset 120
|
|
stfdu 18,8(3) # offset 128
|
|
stfdu 19,8(3) # offset 136
|
|
stfdu 20,8(3) # offset 144
|
|
stfdu 21,8(3) # offset 152
|
|
stfdu 22,8(3) # offset 160
|
|
stfdu 23,8(3) # offset 168
|
|
stfdu 24,8(3) # offset 176
|
|
stfdu 25,8(3) # offset 184
|
|
stfdu 26,8(3) # offset 192
|
|
stfdu 27,8(3) # offset 200
|
|
stfdu 28,8(3) # offset 208
|
|
stfdu 29,8(3) # offset 216
|
|
stfdu 30,8(3) # offset 224
|
|
stfdu 31,8(3) # offset 232
|
|
#endif
|
|
|
|
/* This requires a total of 21 * 4 + 18 * 8 + 4 + 4 + 4
|
|
bytes == 60 * 4 bytes == 240 bytes. */
|
|
|
|
#ifdef __ALTIVEC__
|
|
/* save Altivec vrsave and vr20-vr31 registers */
|
|
mfspr 4,256 # vrsave register
|
|
stwu 4,16(3) # offset 248
|
|
addi 3,3,8
|
|
stvx 20,0,3 # offset 256
|
|
addi 3,3,16
|
|
stvx 21,0,3 # offset 272
|
|
addi 3,3,16
|
|
stvx 22,0,3 # offset 288
|
|
addi 3,3,16
|
|
stvx 23,0,3 # offset 304
|
|
addi 3,3,16
|
|
stvx 24,0,3 # offset 320
|
|
addi 3,3,16
|
|
stvx 25,0,3 # offset 336
|
|
addi 3,3,16
|
|
stvx 26,0,3 # offset 352
|
|
addi 3,3,16
|
|
stvx 27,0,3 # offset 368
|
|
addi 3,3,16
|
|
stvx 28,0,3 # offset 384
|
|
addi 3,3,16
|
|
stvx 29,0,3 # offset 400
|
|
addi 3,3,16
|
|
stvx 30,0,3 # offset 416
|
|
addi 3,3,16
|
|
stvx 31,0,3 # offset 432
|
|
|
|
/* This requires a total of 240 + 8 + 8 + 12 * 16 == 448 bytes. */
|
|
#endif
|
|
li 3,0
|
|
blr
|
|
FUNC_END(setjmp)
|
|
|
|
|
|
FUNC_START(longjmp)
|
|
#ifdef __ALTIVEC__
|
|
addi 3,3,15 # align Altivec to 16 byte boundary
|
|
rlwinm 3,3,0,0,27
|
|
#else
|
|
addi 3,3,7 # align to 8 byte boundary
|
|
rlwinm 3,3,0,0,28
|
|
#endif
|
|
#if __SPE__
|
|
/* If we are E500, then restore 64-bit registers. */
|
|
evldd 1,0(3) # offset 0
|
|
evldd 2,8(3) # offset 8
|
|
evldd 13,16(3) # offset 16
|
|
evldd 14,24(3) # offset 24
|
|
evldd 15,32(3) # offset 32
|
|
evldd 16,40(3) # offset 40
|
|
evldd 17,48(3) # offset 48
|
|
evldd 18,56(3) # offset 56
|
|
evldd 19,64(3) # offset 64
|
|
evldd 20,72(3) # offset 72
|
|
evldd 21,80(3) # offset 80
|
|
evldd 22,88(3) # offset 88
|
|
evldd 23,96(3) # offset 96
|
|
evldd 24,104(3) # offset 104
|
|
evldd 25,112(3) # offset 112
|
|
evldd 26,120(3) # offset 120
|
|
evldd 27,128(3) # offset 128
|
|
evldd 28,136(3) # offset 136
|
|
evldd 29,144(3) # offset 144
|
|
evldd 30,152(3) # offset 152
|
|
evldd 31,160(3) # offset 160
|
|
|
|
/* Add 164 to r3 to account for the amount of data we just
|
|
loaded. Note that we are not adding 168 because the next
|
|
load instruction uses an offset of 4. */
|
|
addi 3,3,164
|
|
#else
|
|
lwz 1,0(3) # offset 0
|
|
lwzu 2,4(3) # offset 4
|
|
lwzu 13,4(3) # offset 8
|
|
lwzu 14,4(3) # offset 12
|
|
lwzu 15,4(3) # offset 16
|
|
lwzu 16,4(3) # offset 20
|
|
lwzu 17,4(3) # offset 24
|
|
lwzu 18,4(3) # offset 28
|
|
lwzu 19,4(3) # offset 32
|
|
lwzu 20,4(3) # offset 36
|
|
lwzu 21,4(3) # offset 40
|
|
lwzu 22,4(3) # offset 44
|
|
lwzu 23,4(3) # offset 48
|
|
lwzu 24,4(3) # offset 52
|
|
lwzu 25,4(3) # offset 56
|
|
lwzu 26,4(3) # offset 60
|
|
lwzu 27,4(3) # offset 64
|
|
lwzu 28,4(3) # offset 68
|
|
lwzu 29,4(3) # offset 72
|
|
lwzu 30,4(3) # offset 76
|
|
lwzu 31,4(3) # offset 80
|
|
#endif
|
|
/* From this point on until the end of this function, add 84
|
|
to the offset shown if __SPE__. This difference comes from
|
|
the fact that we restore 21 64-bit registers instead of 21
|
|
32-bit registers above. */
|
|
lwzu 5,4(3) # offset 84
|
|
mtlr 5
|
|
lwzu 5,4(3) # offset 88
|
|
mtcrf 255,5
|
|
# one word pad to get floating point aligned on 8 byte boundary
|
|
|
|
/* Check whether we need to restore FPRs. Checking
|
|
__NO_FPRS__ on its own would be enough for GCC 4.1 and
|
|
above, but older compilers only define _SOFT_FLOAT, so
|
|
check both. */
|
|
#if !defined (__NO_FPRS__) && !defined (_SOFT_FLOAT)
|
|
lfdu 14,8(3) # offset 96
|
|
lfdu 15,8(3) # offset 104
|
|
lfdu 16,8(3) # offset 112
|
|
lfdu 17,8(3) # offset 120
|
|
lfdu 18,8(3) # offset 128
|
|
lfdu 19,8(3) # offset 136
|
|
lfdu 20,8(3) # offset 144
|
|
lfdu 21,8(3) # offset 152
|
|
lfdu 22,8(3) # offset 160
|
|
lfdu 23,8(3) # offset 168
|
|
lfdu 24,8(3) # offset 176
|
|
lfdu 25,8(3) # offset 184
|
|
lfdu 26,8(3) # offset 192
|
|
lfdu 27,8(3) # offset 200
|
|
lfdu 28,8(3) # offset 208
|
|
lfdu 29,8(3) # offset 216
|
|
lfdu 30,8(3) # offset 224
|
|
lfdu 31,8(3) # offset 232
|
|
#endif
|
|
|
|
#ifdef __ALTIVEC__
|
|
/* restore Altivec vrsave and v20-v31 registers */
|
|
lwzu 5,16(3) # offset 248
|
|
mtspr 256,5 # vrsave
|
|
addi 3,3,8
|
|
lvx 20,0,3 # offset 256
|
|
addi 3,3,16
|
|
lvx 21,0,3 # offset 272
|
|
addi 3,3,16
|
|
lvx 22,0,3 # offset 288
|
|
addi 3,3,16
|
|
lvx 23,0,3 # offset 304
|
|
addi 3,3,16
|
|
lvx 24,0,3 # offset 320
|
|
addi 3,3,16
|
|
lvx 25,0,3 # offset 336
|
|
addi 3,3,16
|
|
lvx 26,0,3 # offset 352
|
|
addi 3,3,16
|
|
lvx 27,0,3 # offset 368
|
|
addi 3,3,16
|
|
lvx 28,0,3 # offset 384
|
|
addi 3,3,16
|
|
lvx 29,0,3 # offset 400
|
|
addi 3,3,16
|
|
lvx 30,0,3 # offset 416
|
|
addi 3,3,16
|
|
lvx 31,0,3 # offset 432
|
|
#endif
|
|
|
|
mr. 3,4
|
|
bclr+ 4,2
|
|
li 3,1
|
|
blr
|
|
FUNC_END(longjmp)
|