Home | History | Annotate | Download | only in avr32
      1 /* -----------------------------------------------------------------------
      2    sysv.S - Copyright (c) 2009  Bradley Smith <brad (at) brad-smith.co.uk>
      3 
      4    AVR32 Foreign Function Interface
      5 
      6    Permission is hereby granted, free of charge, to any person obtaining
      7    a copy of this software and associated documentation files (the
      8    ``Software''), to deal in the Software without restriction, including
      9    without limitation the rights to use, copy, modify, merge, publish,
     10    distribute, sublicense, and/or sell copies of the Software, and to
     11    permit persons to whom the Software is furnished to do so, subject to
     12    the following conditions:
     13 
     14    The above copyright notice and this permission notice shall be included
     15    in all copies or substantial portions of the Software.
     16 
     17    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
     18    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     19    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     20    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
     21    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     22    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     23    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     24    --------------------------------------------------------------------- */
     25 
     26 #define LIBFFI_ASM
     27 #include <fficonfig.h>
     28 #include <ffi.h>
     29 
     30     /* r12:  ffi_prep_args
     31      * r11:  &ecif
     32      * r10:  size
     33      * r9:   cif->flags
     34      * r8:   ecif.rvalue
     35      * sp+0: cif->rstruct_flag
     36      * sp+4: fn */
     37 
     38     .text
     39     .align  1
     40     .globl  ffi_call_SYSV
     41     .type   ffi_call_SYSV, @function
     42 ffi_call_SYSV:
     43     stm     --sp, r0,r1,lr
     44     stm     --sp, r8-r12
     45     mov     r0, sp
     46 
     47     /* Make room for all of the new args. */
     48     sub     sp, r10
     49     /* Pad to make way for potential skipped registers */
     50     sub     sp, 20
     51 
     52     /* Call ffi_prep_args(stack, &ecif). */
     53     /* r11 already set */
     54     mov     r1, r12
     55     mov     r12, sp
     56     icall   r1
     57 
     58     /* Save new argument size */
     59     mov     r1, r12
     60 
     61     /* Move first 5 parameters in registers. */
     62     ldm     sp++, r8-r12
     63 
     64     /* call (fn) (...). */
     65     ld.w    r1, r0[36]
     66     icall   r1
     67 
     68     /* Remove the space we pushed for the args. */
     69     mov     sp, r0
     70 
     71     /* Load r1 with the rstruct flag. */
     72     ld.w    r1, sp[32]
     73 
     74     /* Load r9 with the return type code. */
     75     ld.w    r9, sp[12]
     76 
     77     /* Load r8 with the return value pointer. */
     78     ld.w    r8, sp[16]
     79 
     80     /* If the return value pointer is NULL, assume no return value. */
     81     cp.w    r8, 0
     82     breq    .Lend
     83 
     84     /* Check if return type is actually a struct */
     85     cp.w    r1, 0
     86     breq    1f
     87 
     88     /* Return 8bit */
     89     cp.w    r9, FFI_TYPE_UINT8
     90     breq    .Lstore8
     91 
     92     /* Return 16bit */
     93     cp.w    r9, FFI_TYPE_UINT16
     94     breq    .Lstore16
     95 
     96 1:
     97     /* Return 32bit */
     98     cp.w    r9, FFI_TYPE_UINT32
     99     breq    .Lstore32
    100     cp.w    r9, FFI_TYPE_UINT16
    101     breq    .Lstore32
    102     cp.w    r9, FFI_TYPE_UINT8
    103     breq    .Lstore32
    104 
    105     /* Return 64bit */
    106     cp.w    r9, FFI_TYPE_UINT64
    107     breq    .Lstore64
    108 
    109     /* Didn't match anything */
    110     bral    .Lend
    111 
    112 .Lstore64:
    113     st.w    r8[0], r11
    114     st.w    r8[4], r10
    115     bral    .Lend
    116 
    117 .Lstore32:
    118     st.w    r8[0], r12
    119     bral    .Lend
    120 
    121 .Lstore16:
    122     st.h    r8[0], r12
    123     bral    .Lend
    124 
    125 .Lstore8:
    126     st.b    r8[0], r12
    127     bral    .Lend
    128 
    129 .Lend:
    130     sub     sp, -20
    131     ldm     sp++, r0,r1,pc
    132 
    133     .size   ffi_call_SYSV, . - ffi_call_SYSV
    134 
    135 
    136     /* r12:  __ctx
    137      * r11:  __rstruct_flag
    138      * r10:  __inner */
    139 
    140     .align  1
    141     .globl  ffi_closure_SYSV
    142     .type   ffi_closure_SYSV, @function
    143 ffi_closure_SYSV:
    144     stm     --sp, r0,lr
    145     mov     r0, r11
    146     mov     r8, r10
    147     sub     r10, sp, -8
    148     sub     sp, 12
    149     st.w    sp[8], sp
    150     sub     r11, sp, -8
    151     icall   r8
    152 
    153     /* Check if return type is actually a struct */
    154     cp.w    r0, 0
    155     breq    1f
    156 
    157     /* Return 8bit */
    158     cp.w    r12, FFI_TYPE_UINT8
    159     breq    .Lget8
    160 
    161     /* Return 16bit */
    162     cp.w    r12, FFI_TYPE_UINT16
    163     breq    .Lget16
    164 
    165 1:
    166     /* Return 32bit */
    167     cp.w    r12, FFI_TYPE_UINT32
    168     breq    .Lget32
    169     cp.w    r12, FFI_TYPE_UINT16
    170     breq    .Lget32
    171     cp.w    r12, FFI_TYPE_UINT8
    172     breq    .Lget32
    173 
    174     /* Return 64bit */
    175     cp.w    r12, FFI_TYPE_UINT64
    176     breq    .Lget64
    177 
    178     /* Didn't match anything */
    179     bral    .Lclend
    180 
    181 .Lget64:
    182     ld.w    r11, sp[0]
    183     ld.w    r10, sp[4]
    184     bral    .Lclend
    185 
    186 .Lget32:
    187     ld.w    r12, sp[0]
    188     bral    .Lclend
    189 
    190 .Lget16:
    191     ld.uh   r12, sp[0]
    192     bral    .Lclend
    193 
    194 .Lget8:
    195     ld.ub   r12, sp[0]
    196     bral    .Lclend
    197 
    198 .Lclend:
    199     sub     sp, -12
    200     ldm     sp++, r0,lr
    201     sub     sp, -20
    202     mov     pc, lr
    203 
    204     .size   ffi_closure_SYSV, . - ffi_closure_SYSV
    205 
    206 #if defined __ELF__ && defined __linux__
    207     .section    .note.GNU-stack,"",@progbits
    208 #endif
    209