1 /* ----------------------------------------------------------------------- 2 sysv.h - Copyright (c) 2003 Jakub Jelinek <jakub (at) redhat.com> 3 Copyright (c) 2008 Red Hat, Inc. 4 5 PowerPC64 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 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. 26 ----------------------------------------------------------------------- */ 27 28 #define LIBFFI_ASM 29 #include <fficonfig.h> 30 #include <ffi.h> 31 32 #ifdef POWERPC64 33 .hidden ffi_call_LINUX64 34 .globl ffi_call_LINUX64 35 # if _CALL_ELF == 2 36 .text 37 ffi_call_LINUX64: 38 addis %r2, %r12, .TOC.-ffi_call_LINUX64@ha 39 addi %r2, %r2, .TOC.-ffi_call_LINUX64@l 40 .localentry ffi_call_LINUX64, . - ffi_call_LINUX64 41 # else 42 .section ".opd","aw" 43 .align 3 44 ffi_call_LINUX64: 45 # ifdef _CALL_LINUX 46 .quad .L.ffi_call_LINUX64,.TOC.@tocbase,0 47 .type ffi_call_LINUX64,@function 48 .text 49 .L.ffi_call_LINUX64: 50 # else 51 .hidden .ffi_call_LINUX64 52 .globl .ffi_call_LINUX64 53 .quad .ffi_call_LINUX64,.TOC.@tocbase,0 54 .size ffi_call_LINUX64,24 55 .type .ffi_call_LINUX64,@function 56 .text 57 .ffi_call_LINUX64: 58 # endif 59 # endif 60 .LFB1: 61 mflr %r0 62 std %r28, -32(%r1) 63 std %r29, -24(%r1) 64 std %r30, -16(%r1) 65 std %r31, -8(%r1) 66 std %r0, 16(%r1) 67 68 mr %r28, %r1 /* our AP. */ 69 .LCFI0: 70 stdux %r1, %r1, %r4 71 mr %r31, %r5 /* flags, */ 72 mr %r30, %r6 /* rvalue, */ 73 mr %r29, %r7 /* function address. */ 74 /* Save toc pointer, not for the ffi_prep_args64 call, but for the later 75 bctrl function call. */ 76 # if _CALL_ELF == 2 77 std %r2, 24(%r1) 78 # else 79 std %r2, 40(%r1) 80 # endif 81 82 /* Call ffi_prep_args64. */ 83 mr %r4, %r1 84 # if defined _CALL_LINUX || _CALL_ELF == 2 85 bl ffi_prep_args64 86 # else 87 bl .ffi_prep_args64 88 # endif 89 90 # if _CALL_ELF == 2 91 mr %r12, %r29 92 # else 93 ld %r12, 0(%r29) 94 ld %r2, 8(%r29) 95 ld %r11, 16(%r29) 96 # endif 97 /* Now do the call. */ 98 /* Set up cr1 with bits 4-7 of the flags. */ 99 mtcrf 0x40, %r31 100 101 /* Get the address to call into CTR. */ 102 mtctr %r12 103 /* Load all those argument registers. */ 104 ld %r3, -32-(8*8)(%r28) 105 ld %r4, -32-(7*8)(%r28) 106 ld %r5, -32-(6*8)(%r28) 107 ld %r6, -32-(5*8)(%r28) 108 bf- 5, 1f 109 ld %r7, -32-(4*8)(%r28) 110 ld %r8, -32-(3*8)(%r28) 111 ld %r9, -32-(2*8)(%r28) 112 ld %r10, -32-(1*8)(%r28) 113 1: 114 115 /* Load all the FP registers. */ 116 bf- 6, 2f 117 lfd %f1, -32-(21*8)(%r28) 118 lfd %f2, -32-(20*8)(%r28) 119 lfd %f3, -32-(19*8)(%r28) 120 lfd %f4, -32-(18*8)(%r28) 121 lfd %f5, -32-(17*8)(%r28) 122 lfd %f6, -32-(16*8)(%r28) 123 lfd %f7, -32-(15*8)(%r28) 124 lfd %f8, -32-(14*8)(%r28) 125 lfd %f9, -32-(13*8)(%r28) 126 lfd %f10, -32-(12*8)(%r28) 127 lfd %f11, -32-(11*8)(%r28) 128 lfd %f12, -32-(10*8)(%r28) 129 lfd %f13, -32-(9*8)(%r28) 130 2: 131 132 /* Make the call. */ 133 bctrl 134 135 /* This must follow the call immediately, the unwinder 136 uses this to find out if r2 has been saved or not. */ 137 # if _CALL_ELF == 2 138 ld %r2, 24(%r1) 139 # else 140 ld %r2, 40(%r1) 141 # endif 142 143 /* Now, deal with the return value. */ 144 mtcrf 0x01, %r31 145 bt 31, .Lstruct_return_value 146 bt 30, .Ldone_return_value 147 bt 29, .Lfp_return_value 148 std %r3, 0(%r30) 149 /* Fall through... */ 150 151 .Ldone_return_value: 152 /* Restore the registers we used and return. */ 153 mr %r1, %r28 154 ld %r0, 16(%r28) 155 ld %r28, -32(%r28) 156 mtlr %r0 157 ld %r29, -24(%r1) 158 ld %r30, -16(%r1) 159 ld %r31, -8(%r1) 160 blr 161 162 .Lfp_return_value: 163 bf 28, .Lfloat_return_value 164 stfd %f1, 0(%r30) 165 mtcrf 0x02, %r31 /* cr6 */ 166 bf 27, .Ldone_return_value 167 stfd %f2, 8(%r30) 168 b .Ldone_return_value 169 .Lfloat_return_value: 170 stfs %f1, 0(%r30) 171 b .Ldone_return_value 172 173 .Lstruct_return_value: 174 bf 29, .Lsmall_struct 175 bf 28, .Lfloat_homog_return_value 176 stfd %f1, 0(%r30) 177 stfd %f2, 8(%r30) 178 stfd %f3, 16(%r30) 179 stfd %f4, 24(%r30) 180 stfd %f5, 32(%r30) 181 stfd %f6, 40(%r30) 182 stfd %f7, 48(%r30) 183 stfd %f8, 56(%r30) 184 b .Ldone_return_value 185 186 .Lfloat_homog_return_value: 187 stfs %f1, 0(%r30) 188 stfs %f2, 4(%r30) 189 stfs %f3, 8(%r30) 190 stfs %f4, 12(%r30) 191 stfs %f5, 16(%r30) 192 stfs %f6, 20(%r30) 193 stfs %f7, 24(%r30) 194 stfs %f8, 28(%r30) 195 b .Ldone_return_value 196 197 .Lsmall_struct: 198 std %r3, 0(%r30) 199 std %r4, 8(%r30) 200 b .Ldone_return_value 201 202 .LFE1: 203 .long 0 204 .byte 0,12,0,1,128,4,0,0 205 # if _CALL_ELF == 2 206 .size ffi_call_LINUX64,.-ffi_call_LINUX64 207 # else 208 # ifdef _CALL_LINUX 209 .size ffi_call_LINUX64,.-.L.ffi_call_LINUX64 210 # else 211 .size .ffi_call_LINUX64,.-.ffi_call_LINUX64 212 # endif 213 # endif 214 215 .section .eh_frame,EH_FRAME_FLAGS,@progbits 216 .Lframe1: 217 .4byte .LECIE1-.LSCIE1 # Length of Common Information Entry 218 .LSCIE1: 219 .4byte 0x0 # CIE Identifier Tag 220 .byte 0x1 # CIE Version 221 .ascii "zR\0" # CIE Augmentation 222 .uleb128 0x1 # CIE Code Alignment Factor 223 .sleb128 -8 # CIE Data Alignment Factor 224 .byte 0x41 # CIE RA Column 225 .uleb128 0x1 # Augmentation size 226 .byte 0x14 # FDE Encoding (pcrel udata8) 227 .byte 0xc # DW_CFA_def_cfa 228 .uleb128 0x1 229 .uleb128 0x0 230 .align 3 231 .LECIE1: 232 .LSFDE1: 233 .4byte .LEFDE1-.LASFDE1 # FDE Length 234 .LASFDE1: 235 .4byte .LASFDE1-.Lframe1 # FDE CIE offset 236 .8byte .LFB1-. # FDE initial location 237 .8byte .LFE1-.LFB1 # FDE address range 238 .uleb128 0x0 # Augmentation size 239 .byte 0x2 # DW_CFA_advance_loc1 240 .byte .LCFI0-.LFB1 241 .byte 0xd # DW_CFA_def_cfa_register 242 .uleb128 0x1c 243 .byte 0x11 # DW_CFA_offset_extended_sf 244 .uleb128 0x41 245 .sleb128 -2 246 .byte 0x9f # DW_CFA_offset, column 0x1f 247 .uleb128 0x1 248 .byte 0x9e # DW_CFA_offset, column 0x1e 249 .uleb128 0x2 250 .byte 0x9d # DW_CFA_offset, column 0x1d 251 .uleb128 0x3 252 .byte 0x9c # DW_CFA_offset, column 0x1c 253 .uleb128 0x4 254 .align 3 255 .LEFDE1: 256 257 # if (defined __ELF__ && defined __linux__) || _CALL_ELF == 2 258 .section .note.GNU-stack,"",@progbits 259 # endif 260 #endif 261