Home | History | Annotate | Download | only in powerpc
      1 /* -----------------------------------------------------------------------
      2    sysv.S - Copyright (c) 1998 Geoffrey Keating
      3    Copyright (C) 2007 Free Software Foundation, Inc
      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 
     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 #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 #ifndef __NO_FPRS__
     87 	/* Load all the FP registers.  */
     88 	bf-	6,2f
     89 	lfd	%f1,-16-(8*4)-(8*8)(%r28)
     90 	lfd	%f2,-16-(8*4)-(7*8)(%r28)
     91 	lfd	%f3,-16-(8*4)-(6*8)(%r28)
     92 	lfd	%f4,-16-(8*4)-(5*8)(%r28)
     93 	nop
     94 	lfd	%f5,-16-(8*4)-(4*8)(%r28)
     95 	lfd	%f6,-16-(8*4)-(3*8)(%r28)
     96 	lfd	%f7,-16-(8*4)-(2*8)(%r28)
     97 	lfd	%f8,-16-(8*4)-(1*8)(%r28)
     98 #endif
     99 2:
    100 
    101 	/* Make the call.  */
    102 	bctrl
    103 
    104 	/* Now, deal with the return value.  */
    105 	mtcrf	0x01,%r31 /* cr7  */
    106 	bt-	31,L(small_struct_return_value)
    107 	bt-	30,L(done_return_value)
    108 #ifndef __NO_FPRS__
    109 	bt-	29,L(fp_return_value)
    110 #endif
    111 	stw	%r3,0(%r30)
    112 	bf+	28,L(done_return_value)
    113 	stw	%r4,4(%r30)
    114 	mtcrf	0x02,%r31 /* cr6  */
    115 	bf	27,L(done_return_value)
    116 	stw     %r5,8(%r30)
    117 	stw	%r6,12(%r30)
    118 	/* Fall through...  */
    119 
    120 L(done_return_value):
    121 	/* Restore the registers we used and return.  */
    122 	lwz	%r9,   4(%r28)
    123 	lwz	%r31, -4(%r28)
    124 	mtlr	%r9
    125 	lwz	%r30, -8(%r28)
    126 	lwz	%r29,-12(%r28)
    127 	lwz	%r28,-16(%r28)
    128 	lwz	%r1,0(%r1)
    129 	blr
    130 
    131 #ifndef __NO_FPRS__
    132 L(fp_return_value):
    133 	bf	28,L(float_return_value)
    134 	stfd	%f1,0(%r30)
    135 	mtcrf   0x02,%r31 /* cr6  */
    136 	bf	27,L(done_return_value)
    137 	stfd	%f2,8(%r30)
    138 	b	L(done_return_value)
    139 L(float_return_value):
    140 	stfs	%f1,0(%r30)
    141 	b	L(done_return_value)
    142 #endif
    143 
    144 L(small_struct_return_value):
    145 	/*
    146 	 * The C code always allocates a properly-aligned 8-byte bounce
    147 	 * buffer to make this assembly code very simple.  Just write out
    148 	 * r3 and r4 to the buffer to allow the C code to handle the rest.
    149 	 */
    150 	stw %r3, 0(%r30)
    151 	stw %r4, 4(%r30)
    152 	b L(done_return_value)
    153 
    154 .LFE1:
    155 END(ffi_call_SYSV)
    156 
    157       .section	".eh_frame",EH_FRAME_FLAGS,@progbits
    158 .Lframe1:
    159       .4byte    .LECIE1-.LSCIE1  /*  Length of Common Information Entry */
    160 .LSCIE1:
    161       .4byte    0x0      /*  CIE Identifier Tag */
    162       .byte     0x1      /*  CIE Version */
    163 #if defined _RELOCATABLE || defined __PIC__
    164       .ascii	"zR\0"   /*  CIE Augmentation */
    165 #else
    166       .ascii	"\0"	 /*  CIE Augmentation */
    167 #endif
    168       .uleb128  0x1      /*  CIE Code Alignment Factor */
    169       .sleb128  -4	 /*  CIE Data Alignment Factor */
    170       .byte     0x41     /*  CIE RA Column */
    171 #if defined _RELOCATABLE || defined __PIC__
    172       .uleb128  0x1      /*  Augmentation size */
    173       .byte	0x1b	 /*  FDE Encoding (pcrel sdata4) */
    174 #endif
    175       .byte     0xc      /*  DW_CFA_def_cfa */
    176       .uleb128  0x1
    177       .uleb128  0x0
    178       .align 2
    179 .LECIE1:
    180 .LSFDE1:
    181       .4byte    .LEFDE1-.LASFDE1         /*  FDE Length */
    182 .LASFDE1:
    183       .4byte    .LASFDE1-.Lframe1         /*  FDE CIE offset */
    184 #if defined _RELOCATABLE || defined __PIC__
    185       .4byte    .LFB1-.  /*  FDE initial location */
    186 #else
    187       .4byte    .LFB1    /*  FDE initial location */
    188 #endif
    189       .4byte    .LFE1-.LFB1      /*  FDE address range */
    190 #if defined _RELOCATABLE || defined __PIC__
    191       .uleb128  0x0	 /*  Augmentation size */
    192 #endif
    193       .byte     0x4      /*  DW_CFA_advance_loc4 */
    194       .4byte    .LCFI0-.LFB1
    195       .byte     0xd      /*  DW_CFA_def_cfa_register */
    196       .uleb128  0x08
    197       .byte     0x4      /*  DW_CFA_advance_loc4 */
    198       .4byte    .LCFI5-.LCFI0
    199       .byte     0x11     /*  DW_CFA_offset_extended_sf */
    200       .uleb128  0x41
    201       .sleb128  -1
    202       .byte     0x9f     /*  DW_CFA_offset, column 0x1f */
    203       .uleb128  0x1
    204       .byte     0x9e     /*  DW_CFA_offset, column 0x1e */
    205       .uleb128  0x2
    206       .byte     0x9d     /*  DW_CFA_offset, column 0x1d */
    207       .uleb128  0x3
    208       .byte     0x9c     /*  DW_CFA_offset, column 0x1c */
    209       .uleb128  0x4
    210       .byte     0x4      /*  DW_CFA_advance_loc4 */
    211       .4byte    .LCFI6-.LCFI5
    212       .byte     0xd      /*  DW_CFA_def_cfa_register */
    213       .uleb128  0x1c
    214       .align 2
    215 .LEFDE1:
    216 
    217 #if defined __ELF__ && defined __linux__
    218 	.section	.note.GNU-stack,"",@progbits
    219 #endif
    220 #endif
    221