1 /* ----------------------------------------------------------------------- 2 sysv.S - Copyright (c) 2004 Simon Posnjak 3 Copyright (c) 2005 Axis Communications AB 4 5 CRIS Foreign Function Interface 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, EXPRESS 19 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 IN NO EVENT SHALL SIMON POSNJAK BE LIABLE FOR ANY CLAIM, DAMAGES OR 22 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 23 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 OTHER DEALINGS IN THE SOFTWARE. 25 ----------------------------------------------------------------------- */ 26 27 #define LIBFFI_ASM 28 #include <ffi.h> 29 #define CONCAT(x,y) x ## y 30 #define XCONCAT(x,y) CONCAT (x, y) 31 #define L(x) XCONCAT (__USER_LABEL_PREFIX__, x) 32 33 .text 34 35 ;; OK, when we get called we should have this (according to 36 ;; AXIS ETRAX 100LX Programmer's Manual chapter 6.3). 37 ;; 38 ;; R10: ffi_prep_args (func. pointer) 39 ;; R11: &ecif 40 ;; R12: cif->bytes 41 ;; R13: fig->flags 42 ;; sp+0: ecif.rvalue 43 ;; sp+4: fn (function pointer to the function that we need to call) 44 45 .globl L(ffi_call_SYSV) 46 .type L(ffi_call_SYSV),@function 47 .hidden L(ffi_call_SYSV) 48 49 L(ffi_call_SYSV): 50 ;; Save the regs to the stack. 51 push $srp 52 ;; Used for stack pointer saving. 53 push $r6 54 ;; Used for function address pointer. 55 push $r7 56 ;; Used for stack pointer saving. 57 push $r8 58 ;; We save fig->flags to stack we will need them after we 59 ;; call The Function. 60 push $r13 61 62 ;; Saving current stack pointer. 63 move.d $sp,$r8 64 move.d $sp,$r6 65 66 ;; Move address of ffi_prep_args to r13. 67 move.d $r10,$r13 68 69 ;; Make room on the stack for the args of fn. 70 sub.d $r12,$sp 71 72 ;; Function void ffi_prep_args(char *stack, extended_cif *ecif) parameters are: 73 ;; r10 <-- stack pointer 74 ;; r11 <-- &ecif (already there) 75 move.d $sp,$r10 76 77 ;; Call the function. 78 jsr $r13 79 80 ;; Save the size of the structures which are passed on stack. 81 move.d $r10,$r7 82 83 ;; Move first four args in to r10..r13. 84 move.d [$sp+0],$r10 85 move.d [$sp+4],$r11 86 move.d [$sp+8],$r12 87 move.d [$sp+12],$r13 88 89 ;; Adjust the stack and check if any parameters are given on stack. 90 addq 16,$sp 91 sub.d $r7,$r6 92 cmp.d $sp,$r6 93 94 bpl go_on 95 nop 96 97 go_on_no_params_on_stack: 98 move.d $r6,$sp 99 100 go_on: 101 ;; Discover if we need to put rval address in to r9. 102 move.d [$r8+0],$r7 103 cmpq FFI_TYPE_STRUCT,$r7 104 bne call_now 105 nop 106 107 ;; Move rval address to $r9. 108 move.d [$r8+20],$r9 109 110 call_now: 111 ;; Move address of The Function in to r7. 112 move.d [$r8+24],$r7 113 114 ;; Call The Function. 115 jsr $r7 116 117 ;; Reset stack. 118 move.d $r8,$sp 119 120 ;; Load rval type (fig->flags) in to r13. 121 pop $r13 122 123 ;; Detect rval type. 124 cmpq FFI_TYPE_VOID,$r13 125 beq epilogue 126 127 cmpq FFI_TYPE_STRUCT,$r13 128 beq epilogue 129 130 cmpq FFI_TYPE_DOUBLE,$r13 131 beq return_double_or_longlong 132 133 cmpq FFI_TYPE_UINT64,$r13 134 beq return_double_or_longlong 135 136 cmpq FFI_TYPE_SINT64,$r13 137 beq return_double_or_longlong 138 nop 139 140 ;; Just return the 32 bit value. 141 ba return 142 nop 143 144 return_double_or_longlong: 145 ;; Load half of the rval to r10 and the other half to r11. 146 move.d [$sp+16],$r13 147 move.d $r10,[$r13] 148 addq 4,$r13 149 move.d $r11,[$r13] 150 ba epilogue 151 nop 152 153 return: 154 ;; Load the rval to r10. 155 move.d [$sp+16],$r13 156 move.d $r10,[$r13] 157 158 epilogue: 159 pop $r8 160 pop $r7 161 pop $r6 162 Jump [$sp+] 163 164 .size ffi_call_SYSV,.-ffi_call_SYSV 165 166 /* Save R10..R13 into an array, somewhat like varargs. Copy the next 167 argument too, to simplify handling of any straddling parameter. 168 Save R9 and SP after those. Jump to function handling the rest. 169 Since this is a template, copied and the main function filled in by 170 the user. */ 171 172 .globl L(ffi_cris_trampoline_template) 173 .type L(ffi_cris_trampoline_template),@function 174 .hidden L(ffi_cris_trampoline_template) 175 176 L(ffi_cris_trampoline_template): 177 0: 178 /* The value we get for "PC" is right after the prefix instruction, 179 two bytes from the beginning, i.e. 0b+2. */ 180 move.d $r10,[$pc+2f-(0b+2)] 181 move.d $pc,$r10 182 1: 183 addq 2f-1b+4,$r10 184 move.d $r11,[$r10+] 185 move.d $r12,[$r10+] 186 move.d $r13,[$r10+] 187 move.d [$sp],$r11 188 move.d $r11,[$r10+] 189 move.d $r9,[$r10+] 190 move.d $sp,[$r10+] 191 subq FFI_CRIS_TRAMPOLINE_DATA_PART_SIZE,$r10 192 move.d 0,$r11 193 3: 194 jump 0 195 2: 196 .size ffi_cris_trampoline_template,.-0b 197 198 /* This macro create a constant usable as "extern const int \name" in 199 C from within libffi, when \name has no prefix decoration. */ 200 201 .macro const name,value 202 .globl \name 203 .type \name,@object 204 .hidden \name 205 \name: 206 .dword \value 207 .size \name,4 208 .endm 209 210 /* Constants for offsets within the trampoline. We could do this with 211 just symbols, avoiding memory contents and memory accesses, but the 212 C usage code would look a bit stranger. */ 213 214 const L(ffi_cris_trampoline_fn_offset),2b-4-0b 215 const L(ffi_cris_trampoline_closure_offset),3b-4-0b 216