Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 1 | /* ----------------------------------------------------------------------- |
Christian Heimes | 7864476 | 2008-03-04 23:39:23 +0000 | [diff] [blame] | 2 | sysv.S - Copyright (c) 1998 Geoffrey Keating |
| 3 | Copyright (C) 2007 Free Software Foundation, Inc |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 4 | |
| 5 | PowerPC Assembly glue. |
| 6 | |
| 7 | Permission is hereby granted, free of charge, to any person obtaining |
| 8 | a copy of this software and associated documentation files (the |
| 9 | ``Software''), to deal in the Software without restriction, including |
| 10 | without limitation the rights to use, copy, modify, merge, publish, |
| 11 | distribute, sublicense, and/or sell copies of the Software, and to |
| 12 | permit persons to whom the Software is furnished to do so, subject to |
| 13 | the following conditions: |
| 14 | |
| 15 | The above copyright notice and this permission notice shall be included |
| 16 | in all copies or substantial portions of the Software. |
| 17 | |
Christian Heimes | 7864476 | 2008-03-04 23:39:23 +0000 | [diff] [blame] | 18 | THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, |
| 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| 20 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
| 22 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
| 23 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| 25 | DEALINGS IN THE SOFTWARE. |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 26 | ----------------------------------------------------------------------- */ |
| 27 | |
| 28 | #define LIBFFI_ASM |
| 29 | #include <fficonfig.h> |
| 30 | #include <ffi.h> |
| 31 | #include <powerpc/asm.h> |
| 32 | |
| 33 | #ifndef __powerpc64__ |
| 34 | .globl ffi_prep_args_SYSV |
| 35 | ENTRY(ffi_call_SYSV) |
| 36 | .LFB1: |
| 37 | /* Save the old stack pointer as AP. */ |
| 38 | mr %r8,%r1 |
| 39 | |
| 40 | .LCFI0: |
| 41 | /* Allocate the stack space we need. */ |
| 42 | stwux %r1,%r1,%r4 |
| 43 | /* Save registers we use. */ |
| 44 | mflr %r9 |
| 45 | stw %r28,-16(%r8) |
| 46 | .LCFI1: |
| 47 | stw %r29,-12(%r8) |
| 48 | .LCFI2: |
| 49 | stw %r30, -8(%r8) |
| 50 | .LCFI3: |
| 51 | stw %r31, -4(%r8) |
| 52 | .LCFI4: |
| 53 | stw %r9, 4(%r8) |
| 54 | .LCFI5: |
| 55 | |
| 56 | /* Save arguments over call... */ |
| 57 | mr %r31,%r5 /* flags, */ |
| 58 | mr %r30,%r6 /* rvalue, */ |
| 59 | mr %r29,%r7 /* function address, */ |
| 60 | mr %r28,%r8 /* our AP. */ |
| 61 | .LCFI6: |
| 62 | |
| 63 | /* Call ffi_prep_args_SYSV. */ |
| 64 | mr %r4,%r1 |
| 65 | bl ffi_prep_args_SYSV@local |
| 66 | |
| 67 | /* Now do the call. */ |
| 68 | /* Set up cr1 with bits 4-7 of the flags. */ |
| 69 | mtcrf 0x40,%r31 |
| 70 | /* Get the address to call into CTR. */ |
| 71 | mtctr %r29 |
| 72 | /* Load all those argument registers. */ |
| 73 | lwz %r3,-16-(8*4)(%r28) |
| 74 | lwz %r4,-16-(7*4)(%r28) |
| 75 | lwz %r5,-16-(6*4)(%r28) |
| 76 | lwz %r6,-16-(5*4)(%r28) |
| 77 | bf- 5,1f |
| 78 | nop |
| 79 | lwz %r7,-16-(4*4)(%r28) |
| 80 | lwz %r8,-16-(3*4)(%r28) |
| 81 | lwz %r9,-16-(2*4)(%r28) |
| 82 | lwz %r10,-16-(1*4)(%r28) |
| 83 | nop |
| 84 | 1: |
| 85 | |
| 86 | /* Load all the FP registers. */ |
| 87 | bf- 6,2f |
| 88 | lfd %f1,-16-(8*4)-(8*8)(%r28) |
| 89 | lfd %f2,-16-(8*4)-(7*8)(%r28) |
| 90 | lfd %f3,-16-(8*4)-(6*8)(%r28) |
| 91 | lfd %f4,-16-(8*4)-(5*8)(%r28) |
| 92 | nop |
| 93 | lfd %f5,-16-(8*4)-(4*8)(%r28) |
| 94 | lfd %f6,-16-(8*4)-(3*8)(%r28) |
| 95 | lfd %f7,-16-(8*4)-(2*8)(%r28) |
| 96 | lfd %f8,-16-(8*4)-(1*8)(%r28) |
| 97 | 2: |
| 98 | |
| 99 | /* Make the call. */ |
| 100 | bctrl |
| 101 | |
| 102 | /* Now, deal with the return value. */ |
Christian Heimes | 7864476 | 2008-03-04 23:39:23 +0000 | [diff] [blame] | 103 | mtcrf 0x01,%r31 /* cr7 */ |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 104 | bt- 31,L(small_struct_return_value) |
| 105 | bt- 30,L(done_return_value) |
| 106 | bt- 29,L(fp_return_value) |
| 107 | stw %r3,0(%r30) |
| 108 | bf+ 28,L(done_return_value) |
| 109 | stw %r4,4(%r30) |
Christian Heimes | 7864476 | 2008-03-04 23:39:23 +0000 | [diff] [blame] | 110 | mtcrf 0x02,%r31 /* cr6 */ |
| 111 | bf 27,L(done_return_value) |
| 112 | stw %r5,8(%r30) |
| 113 | stw %r6,12(%r30) |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 114 | /* Fall through... */ |
| 115 | |
| 116 | L(done_return_value): |
| 117 | /* Restore the registers we used and return. */ |
| 118 | lwz %r9, 4(%r28) |
| 119 | lwz %r31, -4(%r28) |
| 120 | mtlr %r9 |
| 121 | lwz %r30, -8(%r28) |
| 122 | lwz %r29,-12(%r28) |
| 123 | lwz %r28,-16(%r28) |
| 124 | lwz %r1,0(%r1) |
| 125 | blr |
| 126 | |
| 127 | L(fp_return_value): |
| 128 | bf 28,L(float_return_value) |
| 129 | stfd %f1,0(%r30) |
Christian Heimes | 7864476 | 2008-03-04 23:39:23 +0000 | [diff] [blame] | 130 | mtcrf 0x02,%r31 /* cr6 */ |
| 131 | bf 27,L(done_return_value) |
| 132 | stfd %f2,8(%r30) |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 133 | b L(done_return_value) |
| 134 | L(float_return_value): |
| 135 | stfs %f1,0(%r30) |
| 136 | b L(done_return_value) |
| 137 | |
| 138 | L(small_struct_return_value): |
Matthias Klose | a834975 | 2010-03-15 13:25:28 +0000 | [diff] [blame] | 139 | extrwi %r6,%r31,2,19 /* number of bytes padding = shift/8 */ |
| 140 | mtcrf 0x02,%r31 /* copy flags to cr[24:27] (cr6) */ |
| 141 | extrwi %r5,%r31,5,19 /* r5 <- number of bits of padding */ |
| 142 | subfic %r6,%r6,4 /* r6 <- number of useful bytes in r3 */ |
| 143 | bf- 25,L(done_return_value) /* struct in r3 ? if not, done. */ |
| 144 | /* smst_one_register: */ |
| 145 | slw %r3,%r3,%r5 /* Left-justify value in r3 */ |
| 146 | mtxer %r6 /* move byte count to XER ... */ |
| 147 | stswx %r3,0,%r30 /* ... and store that many bytes */ |
| 148 | bf+ 26,L(done_return_value) /* struct in r3:r4 ? */ |
| 149 | add %r6,%r6,%r30 /* adjust pointer */ |
| 150 | stswi %r4,%r6,4 /* store last four bytes */ |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 151 | b L(done_return_value) |
| 152 | |
| 153 | .LFE1: |
| 154 | END(ffi_call_SYSV) |
| 155 | |
| 156 | .section ".eh_frame",EH_FRAME_FLAGS,@progbits |
| 157 | .Lframe1: |
| 158 | .4byte .LECIE1-.LSCIE1 /* Length of Common Information Entry */ |
| 159 | .LSCIE1: |
| 160 | .4byte 0x0 /* CIE Identifier Tag */ |
| 161 | .byte 0x1 /* CIE Version */ |
| 162 | #if defined _RELOCATABLE || defined __PIC__ |
| 163 | .ascii "zR\0" /* CIE Augmentation */ |
| 164 | #else |
| 165 | .ascii "\0" /* CIE Augmentation */ |
| 166 | #endif |
| 167 | .uleb128 0x1 /* CIE Code Alignment Factor */ |
| 168 | .sleb128 -4 /* CIE Data Alignment Factor */ |
| 169 | .byte 0x41 /* CIE RA Column */ |
| 170 | #if defined _RELOCATABLE || defined __PIC__ |
| 171 | .uleb128 0x1 /* Augmentation size */ |
| 172 | .byte 0x1b /* FDE Encoding (pcrel sdata4) */ |
| 173 | #endif |
| 174 | .byte 0xc /* DW_CFA_def_cfa */ |
| 175 | .uleb128 0x1 |
| 176 | .uleb128 0x0 |
| 177 | .align 2 |
| 178 | .LECIE1: |
| 179 | .LSFDE1: |
| 180 | .4byte .LEFDE1-.LASFDE1 /* FDE Length */ |
| 181 | .LASFDE1: |
| 182 | .4byte .LASFDE1-.Lframe1 /* FDE CIE offset */ |
| 183 | #if defined _RELOCATABLE || defined __PIC__ |
| 184 | .4byte .LFB1-. /* FDE initial location */ |
| 185 | #else |
| 186 | .4byte .LFB1 /* FDE initial location */ |
| 187 | #endif |
| 188 | .4byte .LFE1-.LFB1 /* FDE address range */ |
| 189 | #if defined _RELOCATABLE || defined __PIC__ |
| 190 | .uleb128 0x0 /* Augmentation size */ |
| 191 | #endif |
| 192 | .byte 0x4 /* DW_CFA_advance_loc4 */ |
| 193 | .4byte .LCFI0-.LFB1 |
| 194 | .byte 0xd /* DW_CFA_def_cfa_register */ |
| 195 | .uleb128 0x08 |
| 196 | .byte 0x4 /* DW_CFA_advance_loc4 */ |
| 197 | .4byte .LCFI5-.LCFI0 |
| 198 | .byte 0x11 /* DW_CFA_offset_extended_sf */ |
| 199 | .uleb128 0x41 |
| 200 | .sleb128 -1 |
| 201 | .byte 0x9f /* DW_CFA_offset, column 0x1f */ |
| 202 | .uleb128 0x1 |
| 203 | .byte 0x9e /* DW_CFA_offset, column 0x1e */ |
| 204 | .uleb128 0x2 |
| 205 | .byte 0x9d /* DW_CFA_offset, column 0x1d */ |
| 206 | .uleb128 0x3 |
| 207 | .byte 0x9c /* DW_CFA_offset, column 0x1c */ |
| 208 | .uleb128 0x4 |
| 209 | .byte 0x4 /* DW_CFA_advance_loc4 */ |
| 210 | .4byte .LCFI6-.LCFI5 |
| 211 | .byte 0xd /* DW_CFA_def_cfa_register */ |
| 212 | .uleb128 0x1c |
| 213 | .align 2 |
| 214 | .LEFDE1: |
| 215 | #endif |
Christian Heimes | 7864476 | 2008-03-04 23:39:23 +0000 | [diff] [blame] | 216 | |
| 217 | #if defined __ELF__ && defined __linux__ |
| 218 | .section .note.GNU-stack,"",@progbits |
| 219 | #endif |