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