rubinius/rubinius

View on GitHub
build/libraries/libffi/src/vax/elfbsd.S

Summary

Maintainability
Test Coverage
/*
 * Copyright (c) 2013 Miodrag Vallat.  <miod@openbsd.org>
 *
 * 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.
 */

/*
 * vax Foreign Function Interface
 */

#define LIBFFI_ASM    
#include <fficonfig.h>
#include <ffi.h>

    .text

/*
 * void *                    %r0
 * ffi_call_elfbsd(extended_cif *ecif,        4(%ap)
 *           unsigned bytes,        8(%ap)
 *           unsigned flags,        12(%ap)
 *           void *rvalue,        16(%ap)
 *           void (*fn)());        20(%ap)
 */
    .globl    ffi_call_elfbsd
    .type    ffi_call_elfbsd,@function
    .align    2
ffi_call_elfbsd:
    .word    0x00c        # save R2 and R3

    # Allocate stack space for the args
    subl2    8(%ap), %sp

    # Call ffi_prep_args
    pushl    %sp
    pushl    4(%ap)
    calls    $2, ffi_prep_args

    # Get function pointer
    movl    20(%ap), %r1

    # Build a CALLS frame
    ashl    $-2, 8(%ap), %r0
    pushl    %r0        # argument stack usage
    movl    %sp, %r0    # future %ap
    # saved registers
    bbc    $11, 0(%r1), 1f
    pushl    %r11
1:    bbc    $10, 0(%r1), 1f
    pushl    %r10
1:    bbc    $9, 0(%r1), 1f
    pushl    %r9
1:    bbc    $8, 0(%r1), 1f
    pushl    %r8
1:    bbc    $7, 0(%r1), 1f
    pushl    %r7
1:    bbc    $6, 0(%r1), 1f
    pushl    %r6
1:    bbc    $5, 0(%r1), 1f
    pushl    %r5
1:    bbc    $4, 0(%r1), 1f
    pushl    %r4
1:    bbc    $3, 0(%r1), 1f
    pushl    %r3
1:    bbc    $2, 0(%r1), 1f
    pushl    %r2
1:    
    pushal    9f
    pushl    %fp
    pushl    %ap
    movl    16(%ap), %r3    # struct return address, if needed
    movl    %r0, %ap
    movzwl    4(%fp), %r0    # previous PSW, without the saved registers mask
    bisl2    $0x20000000, %r0 # calls frame
    movzwl    0(%r1), %r2
    bicw2    $0xf003, %r2    # only keep R11-R2
    ashl    $16, %r2, %r2
    bisl2    %r2, %r0    # saved register mask of the called function
    pushl    %r0    
    pushl    $0
    movl    %sp, %fp

    # Invoke the function
    pushal    2(%r1)        # skip procedure entry mask
    movl    %r3, %r1
    bicpsw    $0x000f
    rsb

9:
    # Copy return value if necessary
    tstl    16(%ap)
    jeql    9f
    movl    16(%ap), %r2

    bbc    $0, 12(%ap), 1f    # CIF_FLAGS_CHAR
    movb    %r0, 0(%r2)
    brb    9f
1:
    bbc    $1, 12(%ap), 1f    # CIF_FLAGS_SHORT
    movw    %r0, 0(%r2)
    brb    9f
1:
    bbc    $2, 12(%ap), 1f    # CIF_FLAGS_INT
    movl    %r0, 0(%r2)
    brb    9f
1:
    bbc    $3, 12(%ap), 1f    # CIF_FLAGS_DINT
    movq    %r0, 0(%r2)
    brb    9f
1:
    movl    %r1, %r0    # might have been a struct
    #brb    9f

9:
    ret

/*
 * ffi_closure_elfbsd(void);
 * invoked with    %r0: ffi_closure *closure
 */
    .globl    ffi_closure_elfbsd
    .type    ffi_closure_elfbsd, @function
    .align    2
ffi_closure_elfbsd:
    .word    0

    # Allocate room on stack for return value
    subl2    $8, %sp

    # Invoke the closure function
    pushal    4(%ap)        # calling stack
    pushal    4(%sp)        # return value
    pushl    %r0        # closure
    calls    $3, ffi_closure_elfbsd_inner

    # Copy return value if necessary
    bitb    $1, %r0        # CIF_FLAGS_CHAR
    beql    1f
    movb    0(%sp), %r0
    brb    9f
1:
    bitb    $2, %r0        # CIF_FLAGS_SHORT
    beql    1f
    movw    0(%sp), %r0
    brb    9f
1:
    bitb    $4, %r0        # CIF_FLAGS_INT
    beql    1f
    movl    0(%sp), %r0
    brb    9f
1:
    bitb    $8, %r0        # CIF_FLAGS_DINT
    beql    1f
    movq    0(%sp), %r0
    #brb    9f
1:

9:
    ret

/*
 * ffi_closure_struct_elfbsd(void);
 * invoked with    %r0: ffi_closure *closure
 *        %r1: struct return address
 */
    .globl    ffi_closure_struct_elfbsd
    .type    ffi_closure_struct_elfbsd, @function
    .align    2
ffi_closure_struct_elfbsd:
    .word    0

    # Invoke the closure function
    pushal    4(%ap)        # calling stack
    pushl    %r1        # return value
    pushl    %r0        # closure
    calls    $3, ffi_closure_elfbsd_inner

    ret