aboutsummaryrefslogtreecommitdiff
path: root/libffi/src
diff options
context:
space:
mode:
authorWim Lewis <wiml@hhhh.org>2009-06-16 17:55:39 +0000
committerAndreas Tobler <andreast@gcc.gnu.org>2009-06-16 19:55:39 +0200
commit6975f17fe7593bccab74d0404f8f3abe53e69c68 (patch)
treed45c3919a861936258fab6cda27c873f7c0a187d /libffi/src
parent7bbcc28642a8821ad5a5281ac914d49184a8af21 (diff)
downloadgcc-6975f17fe7593bccab74d0404f8f3abe53e69c68.zip
gcc-6975f17fe7593bccab74d0404f8f3abe53e69c68.tar.gz
gcc-6975f17fe7593bccab74d0404f8f3abe53e69c68.tar.bz2
ffi.c: Avoid clobbering cr3 and cr4, which are supposed to be callee-saved.
2009-06-16 Wim Lewis <wiml@hhhh.org> * src/powerpc/ffi.c: Avoid clobbering cr3 and cr4, which are supposed to be callee-saved. * src/powerpc/sysv.S (small_struct_return_value): Fix overrun of return buffer for odd-size structs. From-SVN: r148543
Diffstat (limited to 'libffi/src')
-rw-r--r--libffi/src/powerpc/ffi.c13
-rw-r--r--libffi/src/powerpc/sysv.S35
2 files changed, 19 insertions, 29 deletions
diff --git a/libffi/src/powerpc/ffi.c b/libffi/src/powerpc/ffi.c
index a0426f4..fbbfbe2 100644
--- a/libffi/src/powerpc/ffi.c
+++ b/libffi/src/powerpc/ffi.c
@@ -43,11 +43,12 @@ enum {
FLAG_RETURNS_64BITS = 1 << (31-28),
FLAG_RETURNS_128BITS = 1 << (31-27), /* cr6 */
-
- FLAG_SYSV_SMST_R4 = 1 << (31-16), /* cr4, use r4 for FFI_SYSV 8 byte
+ FLAG_SYSV_SMST_R4 = 1 << (31-26), /* use r4 for FFI_SYSV 8 byte
structs. */
- FLAG_SYSV_SMST_R3 = 1 << (31-15), /* cr3, use r3 for FFI_SYSV 4 byte
+ FLAG_SYSV_SMST_R3 = 1 << (31-25), /* use r3 for FFI_SYSV 4 byte
structs. */
+ /* Bits (31-24) through (31-19) store shift value for SMST */
+
FLAG_ARG_NEEDS_COPY = 1 << (31- 7),
FLAG_FP_ARGUMENTS = 1 << (31- 6), /* cr1.eq; specified by ABI */
FLAG_4_GPR_ARGUMENTS = 1 << (31- 5),
@@ -685,14 +686,14 @@ ffi_prep_cif_machdep (ffi_cif *cif)
if (size <= 4)
{
flags |= FLAG_SYSV_SMST_R3;
- flags |= 8 * (4 - size) << 4;
+ flags |= 8 * (4 - size) << 8;
break;
}
/* These structs are returned in r3 and r4. See above. */
if (size <= 8)
{
- flags |= FLAG_SYSV_SMST_R4;
- flags |= 8 * (8 - size) << 4;
+ flags |= FLAG_SYSV_SMST_R3 | FLAG_SYSV_SMST_R4;
+ flags |= 8 * (8 - size) << 8;
break;
}
}
diff --git a/libffi/src/powerpc/sysv.S b/libffi/src/powerpc/sysv.S
index c06311f..96ea22b 100644
--- a/libffi/src/powerpc/sysv.S
+++ b/libffi/src/powerpc/sysv.S
@@ -136,29 +136,18 @@ L(float_return_value):
b L(done_return_value)
L(small_struct_return_value):
- mtcrf 0x10,%r31 /* cr3 */
- bt- 15,L(smst_one_register)
- mtcrf 0x08,%r31 /* cr4 */
- bt- 16,L(smst_two_register)
- b L(done_return_value)
-
-L(smst_one_register):
- rlwinm %r5,%r31,5+23,32-5,31 /* Extract the value to shift. */
- slw %r3,%r3,%r5
- stw %r3,0(%r30)
- b L(done_return_value)
-L(smst_two_register):
- rlwinm %r5,%r31,5+23,32-5,31 /* Extract the value to shift. */
- cmpwi %r5,0
- subfic %r9,%r5,32
- slw %r29,%r3,%r5
- srw %r9,%r4,%r9
- beq- L(smst_8byte)
- or %r3,%r9,%r29
- slw %r4,%r4,%r5
-L(smst_8byte):
- stw %r3,0(%r30)
- stw %r4,4(%r30)
+ extrwi %r6,%r31,2,19 /* number of bytes padding = shift/8 */
+ mtcrf 0x02,%r31 /* copy flags to cr[24:27] (cr6) */
+ extrwi %r5,%r31,5,19 /* r5 <- number of bits of padding */
+ subfic %r6,%r6,4 /* r6 <- number of useful bytes in r3 */
+ bf- 25,L(done_return_value) /* struct in r3 ? if not, done. */
+/* smst_one_register: */
+ slw %r3,%r3,%r5 /* Left-justify value in r3 */
+ mtxer %r6 /* move byte count to XER ... */
+ stswx %r3,0,%r30 /* ... and store that many bytes */
+ bf+ 26,L(done_return_value) /* struct in r3:r4 ? */
+ add %r6,%r6,%r30 /* adjust pointer */
+ stswi %r4,%r6,4 /* store last four bytes */
b L(done_return_value)
.LFE1: