From 6975f17fe7593bccab74d0404f8f3abe53e69c68 Mon Sep 17 00:00:00 2001 From: Wim Lewis Date: Tue, 16 Jun 2009 17:55:39 +0000 Subject: [PATCH] ffi.c: Avoid clobbering cr3 and cr4, which are supposed to be callee-saved. 2009-06-16 Wim Lewis * 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 --- libffi/ChangeLog | 7 +++++++ libffi/src/powerpc/ffi.c | 15 ++++++++------- libffi/src/powerpc/sysv.S | 35 ++++++++++++----------------------- 3 files changed, 27 insertions(+), 30 deletions(-) diff --git a/libffi/ChangeLog b/libffi/ChangeLog index 1d8e7e763bd..b08b72720cc 100644 --- a/libffi/ChangeLog +++ b/libffi/ChangeLog @@ -1,3 +1,10 @@ +2009-06-16 Wim Lewis + + * 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. + 2009-06-16 Andreas Tobler PR libffi/40444 diff --git a/libffi/src/powerpc/ffi.c b/libffi/src/powerpc/ffi.c index a0426f46750..fbbfbe2e2ea 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-26), /* use r4 for FFI_SYSV 8 byte + structs. */ + 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_SYSV_SMST_R4 = 1 << (31-16), /* cr4, use r4 for FFI_SYSV 8 byte - structs. */ - FLAG_SYSV_SMST_R3 = 1 << (31-15), /* cr3, use r3 for FFI_SYSV 4 byte - structs. */ 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 c06311fd591..96ea22b0b40 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: