Lloyd Pique | 457ba79 | 2015-10-27 14:32:21 -0700 | [diff] [blame] | 1 | /* ----------------------------------------------------------------------- |
| 2 | sysv.S - Copyright (c) 2012 Alexandre K. I. de Mendonca <alexandre.keunecke@gmail.com>, |
| 3 | Paulo Pizarro <paulo.pizarro@gmail.com> |
| 4 | |
| 5 | Blackfin 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, |
| 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 | .text |
| 33 | .align 4 |
| 34 | |
| 35 | /* |
| 36 | There is a "feature" in the bfin toolchain that it puts a _ before function names |
| 37 | that's why the function here it's called _ffi_call_SYSV and not ffi_call_SYSV |
| 38 | */ |
| 39 | .global _ffi_call_SYSV; |
| 40 | .type _ffi_call_SYSV, STT_FUNC; |
| 41 | .func ffi_call_SYSV |
| 42 | |
| 43 | /* |
| 44 | cif->bytes = R0 (fp+8) |
| 45 | &ecif = R1 (fp+12) |
| 46 | ffi_prep_args = R2 (fp+16) |
| 47 | ret_type = stack (fp+20) |
| 48 | ecif.rvalue = stack (fp+24) |
| 49 | fn = stack (fp+28) |
| 50 | got (fp+32) |
| 51 | |
| 52 | There is room for improvement here (we can use temporary registers |
| 53 | instead of saving the values in the memory) |
| 54 | REGS: |
| 55 | P5 => Stack pointer (function arguments) |
| 56 | R5 => cif->bytes |
| 57 | R4 => ret->type |
| 58 | |
| 59 | FP-20 = P3 |
| 60 | FP-16 = SP (parameters area) |
| 61 | FP-12 = SP (temp) |
| 62 | FP-08 = function return part 1 [R0] |
| 63 | FP-04 = function return part 2 [R1] |
| 64 | */ |
| 65 | |
| 66 | _ffi_call_SYSV: |
| 67 | .prologue: |
| 68 | LINK 20; |
| 69 | [FP-20] = P3; |
| 70 | [FP+8] = R0; |
| 71 | [FP+12] = R1; |
| 72 | [FP+16] = R2; |
| 73 | |
| 74 | .allocate_stack: |
| 75 | //alocate cif->bytes into the stack |
| 76 | R1 = [FP+8]; |
| 77 | R0 = SP; |
| 78 | R0 = R0 - R1; |
| 79 | R1 = 4; |
| 80 | R0 = R0 - R1; |
| 81 | [FP-12] = SP; |
| 82 | SP = R0; |
| 83 | [FP-16] = SP; |
| 84 | |
| 85 | .call_prep_args: |
| 86 | //get the addr of prep_args |
| 87 | P0 = [P3 + _ffi_prep_args@FUNCDESC_GOT17M4]; |
| 88 | P1 = [P0]; |
| 89 | P3 = [P0+4]; |
| 90 | R0 = [FP-16];//SP (parameter area) |
| 91 | R1 = [FP+12];//ecif |
| 92 | call (P1); |
| 93 | |
| 94 | .call_user_function: |
| 95 | //ajust SP so as to allow the user function access the parameters on the stack |
| 96 | SP = [FP-16]; //point to function parameters |
| 97 | R0 = [SP]; |
| 98 | R1 = [SP+4]; |
| 99 | R2 = [SP+8]; |
| 100 | //load user function address |
| 101 | P0 = FP; |
| 102 | P0 +=28; |
| 103 | P1 = [P0]; |
| 104 | P1 = [P1]; |
| 105 | P3 = [P0+4]; |
| 106 | /* |
| 107 | For functions returning aggregate values (struct) occupying more than 8 bytes, |
| 108 | the caller allocates the return value object on the stack and the address |
| 109 | of this object is passed to the callee as a hidden argument in register P0. |
| 110 | */ |
| 111 | P0 = [FP+24]; |
| 112 | |
| 113 | call (P1); |
| 114 | SP = [FP-12]; |
| 115 | .compute_return: |
| 116 | P2 = [FP-20]; |
| 117 | [FP-8] = R0; |
| 118 | [FP-4] = R1; |
| 119 | |
| 120 | R0 = [FP+20]; |
| 121 | R1 = R0 << 2; |
| 122 | |
| 123 | R0 = [P2+.rettable@GOT17M4]; |
| 124 | R0 = R1 + R0; |
| 125 | P2 = R0; |
| 126 | R1 = [P2]; |
| 127 | |
| 128 | P2 = [FP+-20]; |
| 129 | R0 = [P2+.rettable@GOT17M4]; |
| 130 | R0 = R1 + R0; |
| 131 | P2 = R0; |
| 132 | R0 = [FP-8]; |
| 133 | R1 = [FP-4]; |
| 134 | jump (P2); |
| 135 | |
| 136 | /* |
| 137 | #define FFIBFIN_RET_VOID 0 |
| 138 | #define FFIBFIN_RET_BYTE 1 |
| 139 | #define FFIBFIN_RET_HALFWORD 2 |
| 140 | #define FFIBFIN_RET_INT64 3 |
| 141 | #define FFIBFIN_RET_INT32 4 |
| 142 | */ |
| 143 | .align 4 |
| 144 | .align 4 |
| 145 | .rettable: |
| 146 | .dd .epilogue - .rettable |
| 147 | .dd .rbyte - .rettable; |
| 148 | .dd .rhalfword - .rettable; |
| 149 | .dd .rint64 - .rettable; |
| 150 | .dd .rint32 - .rettable; |
| 151 | |
| 152 | .rbyte: |
| 153 | P0 = [FP+24]; |
| 154 | R0 = R0.B (Z); |
| 155 | [P0] = R0; |
| 156 | JUMP .epilogue |
| 157 | .rhalfword: |
| 158 | P0 = [FP+24]; |
| 159 | R0 = R0.L; |
| 160 | [P0] = R0; |
| 161 | JUMP .epilogue |
| 162 | .rint64: |
| 163 | P0 = [FP+24];// &rvalue |
| 164 | [P0] = R0; |
| 165 | [P0+4] = R1; |
| 166 | JUMP .epilogue |
| 167 | .rint32: |
| 168 | P0 = [FP+24]; |
| 169 | [P0] = R0; |
| 170 | .epilogue: |
| 171 | R0 = [FP+8]; |
| 172 | R1 = [FP+12]; |
| 173 | R2 = [FP+16]; |
| 174 | P3 = [FP-20]; |
| 175 | UNLINK; |
| 176 | RTS; |
| 177 | |
| 178 | .size _ffi_call_SYSV,.-_ffi_call_SYSV; |
| 179 | .endfunc |