rubinius/rubinius

View on GitHub
build/libraries/libffi/src/nios2/sysv.S

Summary

Maintainability
Test Coverage
/* Low-level libffi support for Altera Nios II.

   Copyright (c) 2013 Mentor Graphics.

   Permission is hereby granted, free of charge, to any person obtaining
   a copy of this software and associated documentation files (the
   ``Software''), to deal in the Software without restriction, including
   without limitation the rights to use, copy, modify, merge, publish,
   distribute, sublicense, and/or sell copies of the Software, and to
   permit persons to whom the Software is furnished to do so, subject to
   the following conditions:
   
   The above copyright notice and this permission notice shall be
   included in all copies or substantial portions of the Software.
   
   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
   IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
   CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
   TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
   SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */

/* This function is declared on the C side as 

   extern UINT64 ffi_call_sysv (void (*arghook) (char *, extended_cif *),
                      extended_cif *ecif,
                unsigned nbytes, 
                void (*fn) (void));
    
   On input, the arguments appear as
    r4 = arghook
    r5 = ecif
    r6 = nbytes
    r7 = fn
*/

    .section    .text
    .align    2
    .global    ffi_call_sysv
    .type    ffi_call_sysv, @function

ffi_call_sysv:
    .cfi_startproc

    /* Create the stack frame, saving r16 so we can use it locally.  */
    addi    sp, sp, -12
    .cfi_def_cfa_offset 12
    stw    ra, 8(sp)
    stw    fp, 4(sp)
    stw    r16, 0(sp)
    .cfi_offset 31, -4
    .cfi_offset 28, -8
    .cfi_offset 16, -12
    mov    fp, sp
    .cfi_def_cfa_register 28
    mov    r16, r7

    /* Adjust the stack pointer to create the argument buffer
       nbytes long.  */
    sub    sp, sp, r6

    /* Call the arghook function.  */
    mov    r2, r4        /* fn */
    mov    r4, sp        /* argbuffer */
    callr    r2        /* r5 already contains ecif */

    /* Pop off the first 16 bytes of the argument buffer on the stack,
       transferring the contents to the argument registers.  */
    ldw    r4, 0(sp)
    ldw    r5, 4(sp)
    ldw    r6, 8(sp)
    ldw    r7, 12(sp)
    addi    sp, sp, 16

    /* Call the user function, which leaves its result in r2 and r3.  */
    callr    r16

    /* Pop off the stack frame.  */
    mov    sp, fp
    ldw    ra, 8(sp)
    ldw    fp, 4(sp)
    ldw    r16, 0(sp)
    addi    sp, sp, 12
    ret
    .cfi_endproc
    .size    ffi_call_sysv, .-ffi_call_sysv


/* Closure trampolines jump here after putting the C helper address
   in r9 and the closure pointer in r10.  The user-supplied arguments
   to the closure are in the normal places, in r4-r7 and on the
   stack.  Push the register arguments on the stack too and then call the
   C helper function to deal with them.  */
   
    .section    .text
    .align    2
    .global    ffi_closure_sysv
    .type    ffi_closure_sysv, @function

ffi_closure_sysv:
    .cfi_startproc

    /* Create the stack frame, pushing the register args on the stack
       just below the stack args.  This is the same trick illustrated
       in Figure 7-3 in the Nios II Processor Reference Handbook, used
       for variable arguments and structures passed by value.  */
    addi    sp, sp, -20
    .cfi_def_cfa_offset 20
    stw    ra, 0(sp)
    .cfi_offset 31, -20
    stw    r4, 4(sp)
    .cfi_offset 4, -16
    stw    r5, 8(sp)
    .cfi_offset 5, -12
    stw    r6, 12(sp)
    .cfi_offset 6, -8
    stw    r7, 16(sp)
    .cfi_offset 7, -4

    /* Call the helper.
       r4 = pointer to arguments on stack
       r5 = closure pointer (loaded in r10 by the trampoline)
       r9 = address of helper function (loaded by trampoline) */
    addi    r4, sp, 4
    mov    r5, r10
    callr    r9
    
    /* Pop the stack and return.  */
    ldw    ra, 0(sp)
    addi    sp, sp, 20
    .cfi_def_cfa_offset -20
    ret
    .cfi_endproc
    .size    ffi_closure_sysv, .-ffi_closure_sysv