1*1fd5a2e1SPrashanth Swaminathan/* Low-level libffi support for Altera Nios II. 2*1fd5a2e1SPrashanth Swaminathan 3*1fd5a2e1SPrashanth Swaminathan Copyright (c) 2013 Mentor Graphics. 4*1fd5a2e1SPrashanth Swaminathan 5*1fd5a2e1SPrashanth Swaminathan Permission is hereby granted, free of charge, to any person obtaining 6*1fd5a2e1SPrashanth Swaminathan a copy of this software and associated documentation files (the 7*1fd5a2e1SPrashanth Swaminathan ``Software''), to deal in the Software without restriction, including 8*1fd5a2e1SPrashanth Swaminathan without limitation the rights to use, copy, modify, merge, publish, 9*1fd5a2e1SPrashanth Swaminathan distribute, sublicense, and/or sell copies of the Software, and to 10*1fd5a2e1SPrashanth Swaminathan permit persons to whom the Software is furnished to do so, subject to 11*1fd5a2e1SPrashanth Swaminathan the following conditions: 12*1fd5a2e1SPrashanth Swaminathan 13*1fd5a2e1SPrashanth Swaminathan The above copyright notice and this permission notice shall be 14*1fd5a2e1SPrashanth Swaminathan included in all copies or substantial portions of the Software. 15*1fd5a2e1SPrashanth Swaminathan 16*1fd5a2e1SPrashanth Swaminathan THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 17*1fd5a2e1SPrashanth Swaminathan EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18*1fd5a2e1SPrashanth Swaminathan MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19*1fd5a2e1SPrashanth Swaminathan IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20*1fd5a2e1SPrashanth Swaminathan CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21*1fd5a2e1SPrashanth Swaminathan TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22*1fd5a2e1SPrashanth Swaminathan SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 23*1fd5a2e1SPrashanth Swaminathan 24*1fd5a2e1SPrashanth Swaminathan/* This function is declared on the C side as 25*1fd5a2e1SPrashanth Swaminathan 26*1fd5a2e1SPrashanth Swaminathan extern UINT64 ffi_call_sysv (void (*arghook) (char *, extended_cif *), 27*1fd5a2e1SPrashanth Swaminathan extended_cif *ecif, 28*1fd5a2e1SPrashanth Swaminathan unsigned nbytes, 29*1fd5a2e1SPrashanth Swaminathan void (*fn) (void)); 30*1fd5a2e1SPrashanth Swaminathan 31*1fd5a2e1SPrashanth Swaminathan On input, the arguments appear as 32*1fd5a2e1SPrashanth Swaminathan r4 = arghook 33*1fd5a2e1SPrashanth Swaminathan r5 = ecif 34*1fd5a2e1SPrashanth Swaminathan r6 = nbytes 35*1fd5a2e1SPrashanth Swaminathan r7 = fn 36*1fd5a2e1SPrashanth Swaminathan*/ 37*1fd5a2e1SPrashanth Swaminathan 38*1fd5a2e1SPrashanth Swaminathan .section .text 39*1fd5a2e1SPrashanth Swaminathan .align 2 40*1fd5a2e1SPrashanth Swaminathan .global ffi_call_sysv 41*1fd5a2e1SPrashanth Swaminathan .type ffi_call_sysv, @function 42*1fd5a2e1SPrashanth Swaminathan 43*1fd5a2e1SPrashanth Swaminathanffi_call_sysv: 44*1fd5a2e1SPrashanth Swaminathan .cfi_startproc 45*1fd5a2e1SPrashanth Swaminathan 46*1fd5a2e1SPrashanth Swaminathan /* Create the stack frame, saving r16 so we can use it locally. */ 47*1fd5a2e1SPrashanth Swaminathan addi sp, sp, -12 48*1fd5a2e1SPrashanth Swaminathan .cfi_def_cfa_offset 12 49*1fd5a2e1SPrashanth Swaminathan stw ra, 8(sp) 50*1fd5a2e1SPrashanth Swaminathan stw fp, 4(sp) 51*1fd5a2e1SPrashanth Swaminathan stw r16, 0(sp) 52*1fd5a2e1SPrashanth Swaminathan .cfi_offset 31, -4 53*1fd5a2e1SPrashanth Swaminathan .cfi_offset 28, -8 54*1fd5a2e1SPrashanth Swaminathan .cfi_offset 16, -12 55*1fd5a2e1SPrashanth Swaminathan mov fp, sp 56*1fd5a2e1SPrashanth Swaminathan .cfi_def_cfa_register 28 57*1fd5a2e1SPrashanth Swaminathan mov r16, r7 58*1fd5a2e1SPrashanth Swaminathan 59*1fd5a2e1SPrashanth Swaminathan /* Adjust the stack pointer to create the argument buffer 60*1fd5a2e1SPrashanth Swaminathan nbytes long. */ 61*1fd5a2e1SPrashanth Swaminathan sub sp, sp, r6 62*1fd5a2e1SPrashanth Swaminathan 63*1fd5a2e1SPrashanth Swaminathan /* Call the arghook function. */ 64*1fd5a2e1SPrashanth Swaminathan mov r2, r4 /* fn */ 65*1fd5a2e1SPrashanth Swaminathan mov r4, sp /* argbuffer */ 66*1fd5a2e1SPrashanth Swaminathan callr r2 /* r5 already contains ecif */ 67*1fd5a2e1SPrashanth Swaminathan 68*1fd5a2e1SPrashanth Swaminathan /* Pop off the first 16 bytes of the argument buffer on the stack, 69*1fd5a2e1SPrashanth Swaminathan transferring the contents to the argument registers. */ 70*1fd5a2e1SPrashanth Swaminathan ldw r4, 0(sp) 71*1fd5a2e1SPrashanth Swaminathan ldw r5, 4(sp) 72*1fd5a2e1SPrashanth Swaminathan ldw r6, 8(sp) 73*1fd5a2e1SPrashanth Swaminathan ldw r7, 12(sp) 74*1fd5a2e1SPrashanth Swaminathan addi sp, sp, 16 75*1fd5a2e1SPrashanth Swaminathan 76*1fd5a2e1SPrashanth Swaminathan /* Call the user function, which leaves its result in r2 and r3. */ 77*1fd5a2e1SPrashanth Swaminathan callr r16 78*1fd5a2e1SPrashanth Swaminathan 79*1fd5a2e1SPrashanth Swaminathan /* Pop off the stack frame. */ 80*1fd5a2e1SPrashanth Swaminathan mov sp, fp 81*1fd5a2e1SPrashanth Swaminathan ldw ra, 8(sp) 82*1fd5a2e1SPrashanth Swaminathan ldw fp, 4(sp) 83*1fd5a2e1SPrashanth Swaminathan ldw r16, 0(sp) 84*1fd5a2e1SPrashanth Swaminathan addi sp, sp, 12 85*1fd5a2e1SPrashanth Swaminathan ret 86*1fd5a2e1SPrashanth Swaminathan .cfi_endproc 87*1fd5a2e1SPrashanth Swaminathan .size ffi_call_sysv, .-ffi_call_sysv 88*1fd5a2e1SPrashanth Swaminathan 89*1fd5a2e1SPrashanth Swaminathan 90*1fd5a2e1SPrashanth Swaminathan/* Closure trampolines jump here after putting the C helper address 91*1fd5a2e1SPrashanth Swaminathan in r9 and the closure pointer in r10. The user-supplied arguments 92*1fd5a2e1SPrashanth Swaminathan to the closure are in the normal places, in r4-r7 and on the 93*1fd5a2e1SPrashanth Swaminathan stack. Push the register arguments on the stack too and then call the 94*1fd5a2e1SPrashanth Swaminathan C helper function to deal with them. */ 95*1fd5a2e1SPrashanth Swaminathan 96*1fd5a2e1SPrashanth Swaminathan .section .text 97*1fd5a2e1SPrashanth Swaminathan .align 2 98*1fd5a2e1SPrashanth Swaminathan .global ffi_closure_sysv 99*1fd5a2e1SPrashanth Swaminathan .type ffi_closure_sysv, @function 100*1fd5a2e1SPrashanth Swaminathan 101*1fd5a2e1SPrashanth Swaminathanffi_closure_sysv: 102*1fd5a2e1SPrashanth Swaminathan .cfi_startproc 103*1fd5a2e1SPrashanth Swaminathan 104*1fd5a2e1SPrashanth Swaminathan /* Create the stack frame, pushing the register args on the stack 105*1fd5a2e1SPrashanth Swaminathan just below the stack args. This is the same trick illustrated 106*1fd5a2e1SPrashanth Swaminathan in Figure 7-3 in the Nios II Processor Reference Handbook, used 107*1fd5a2e1SPrashanth Swaminathan for variable arguments and structures passed by value. */ 108*1fd5a2e1SPrashanth Swaminathan addi sp, sp, -20 109*1fd5a2e1SPrashanth Swaminathan .cfi_def_cfa_offset 20 110*1fd5a2e1SPrashanth Swaminathan stw ra, 0(sp) 111*1fd5a2e1SPrashanth Swaminathan .cfi_offset 31, -20 112*1fd5a2e1SPrashanth Swaminathan stw r4, 4(sp) 113*1fd5a2e1SPrashanth Swaminathan .cfi_offset 4, -16 114*1fd5a2e1SPrashanth Swaminathan stw r5, 8(sp) 115*1fd5a2e1SPrashanth Swaminathan .cfi_offset 5, -12 116*1fd5a2e1SPrashanth Swaminathan stw r6, 12(sp) 117*1fd5a2e1SPrashanth Swaminathan .cfi_offset 6, -8 118*1fd5a2e1SPrashanth Swaminathan stw r7, 16(sp) 119*1fd5a2e1SPrashanth Swaminathan .cfi_offset 7, -4 120*1fd5a2e1SPrashanth Swaminathan 121*1fd5a2e1SPrashanth Swaminathan /* Call the helper. 122*1fd5a2e1SPrashanth Swaminathan r4 = pointer to arguments on stack 123*1fd5a2e1SPrashanth Swaminathan r5 = closure pointer (loaded in r10 by the trampoline) 124*1fd5a2e1SPrashanth Swaminathan r9 = address of helper function (loaded by trampoline) */ 125*1fd5a2e1SPrashanth Swaminathan addi r4, sp, 4 126*1fd5a2e1SPrashanth Swaminathan mov r5, r10 127*1fd5a2e1SPrashanth Swaminathan callr r9 128*1fd5a2e1SPrashanth Swaminathan 129*1fd5a2e1SPrashanth Swaminathan /* Pop the stack and return. */ 130*1fd5a2e1SPrashanth Swaminathan ldw ra, 0(sp) 131*1fd5a2e1SPrashanth Swaminathan addi sp, sp, 20 132*1fd5a2e1SPrashanth Swaminathan .cfi_def_cfa_offset -20 133*1fd5a2e1SPrashanth Swaminathan ret 134*1fd5a2e1SPrashanth Swaminathan .cfi_endproc 135*1fd5a2e1SPrashanth Swaminathan .size ffi_closure_sysv, .-ffi_closure_sysv 136*1fd5a2e1SPrashanth Swaminathan 137