aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.4.3/libffi/src/cris/sysv.S
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.4.3/libffi/src/cris/sysv.S')
-rw-r--r--gcc-4.4.3/libffi/src/cris/sysv.S215
1 files changed, 215 insertions, 0 deletions
diff --git a/gcc-4.4.3/libffi/src/cris/sysv.S b/gcc-4.4.3/libffi/src/cris/sysv.S
new file mode 100644
index 000000000..79abaee4d
--- /dev/null
+++ b/gcc-4.4.3/libffi/src/cris/sysv.S
@@ -0,0 +1,215 @@
+/* -----------------------------------------------------------------------
+ sysv.S - Copyright (c) 2004 Simon Posnjak
+ Copyright (c) 2005 Axis Communications AB
+
+ CRIS Foreign Function Interface
+
+ 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 SIMON POSNJAK 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.
+ ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM
+#include <ffi.h>
+#define CONCAT(x,y) x ## y
+#define XCONCAT(x,y) CONCAT (x, y)
+#define L(x) XCONCAT (__USER_LABEL_PREFIX__, x)
+
+ .text
+
+ ;; OK, when we get called we should have this (according to
+ ;; AXIS ETRAX 100LX Programmer's Manual chapter 6.3).
+ ;;
+ ;; R10: ffi_prep_args (func. pointer)
+ ;; R11: &ecif
+ ;; R12: cif->bytes
+ ;; R13: fig->flags
+ ;; sp+0: ecif.rvalue
+ ;; sp+4: fn (function pointer to the function that we need to call)
+
+ .globl L(ffi_call_SYSV)
+ .type L(ffi_call_SYSV),@function
+ .hidden L(ffi_call_SYSV)
+
+L(ffi_call_SYSV):
+ ;; Save the regs to the stack.
+ push $srp
+ ;; Used for stack pointer saving.
+ push $r6
+ ;; Used for function address pointer.
+ push $r7
+ ;; Used for stack pointer saving.
+ push $r8
+ ;; We save fig->flags to stack we will need them after we
+ ;; call The Function.
+ push $r13
+
+ ;; Saving current stack pointer.
+ move.d $sp,$r8
+ move.d $sp,$r6
+
+ ;; Move address of ffi_prep_args to r13.
+ move.d $r10,$r13
+
+ ;; Make room on the stack for the args of fn.
+ sub.d $r12,$sp
+
+ ;; Function void ffi_prep_args(char *stack, extended_cif *ecif) parameters are:
+ ;; r10 <-- stack pointer
+ ;; r11 <-- &ecif (already there)
+ move.d $sp,$r10
+
+ ;; Call the function.
+ jsr $r13
+
+ ;; Save the size of the structures which are passed on stack.
+ move.d $r10,$r7
+
+ ;; Move first four args in to r10..r13.
+ move.d [$sp+0],$r10
+ move.d [$sp+4],$r11
+ move.d [$sp+8],$r12
+ move.d [$sp+12],$r13
+
+ ;; Adjust the stack and check if any parameters are given on stack.
+ addq 16,$sp
+ sub.d $r7,$r6
+ cmp.d $sp,$r6
+
+ bpl go_on
+ nop
+
+go_on_no_params_on_stack:
+ move.d $r6,$sp
+
+go_on:
+ ;; Discover if we need to put rval address in to r9.
+ move.d [$r8+0],$r7
+ cmpq FFI_TYPE_STRUCT,$r7
+ bne call_now
+ nop
+
+ ;; Move rval address to $r9.
+ move.d [$r8+20],$r9
+
+call_now:
+ ;; Move address of The Function in to r7.
+ move.d [$r8+24],$r7
+
+ ;; Call The Function.
+ jsr $r7
+
+ ;; Reset stack.
+ move.d $r8,$sp
+
+ ;; Load rval type (fig->flags) in to r13.
+ pop $r13
+
+ ;; Detect rval type.
+ cmpq FFI_TYPE_VOID,$r13
+ beq epilogue
+
+ cmpq FFI_TYPE_STRUCT,$r13
+ beq epilogue
+
+ cmpq FFI_TYPE_DOUBLE,$r13
+ beq return_double_or_longlong
+
+ cmpq FFI_TYPE_UINT64,$r13
+ beq return_double_or_longlong
+
+ cmpq FFI_TYPE_SINT64,$r13
+ beq return_double_or_longlong
+ nop
+
+ ;; Just return the 32 bit value.
+ ba return
+ nop
+
+return_double_or_longlong:
+ ;; Load half of the rval to r10 and the other half to r11.
+ move.d [$sp+16],$r13
+ move.d $r10,[$r13]
+ addq 4,$r13
+ move.d $r11,[$r13]
+ ba epilogue
+ nop
+
+return:
+ ;; Load the rval to r10.
+ move.d [$sp+16],$r13
+ move.d $r10,[$r13]
+
+epilogue:
+ pop $r8
+ pop $r7
+ pop $r6
+ Jump [$sp+]
+
+ .size ffi_call_SYSV,.-ffi_call_SYSV
+
+/* Save R10..R13 into an array, somewhat like varargs. Copy the next
+ argument too, to simplify handling of any straddling parameter.
+ Save R9 and SP after those. Jump to function handling the rest.
+ Since this is a template, copied and the main function filled in by
+ the user. */
+
+ .globl L(ffi_cris_trampoline_template)
+ .type L(ffi_cris_trampoline_template),@function
+ .hidden L(ffi_cris_trampoline_template)
+
+L(ffi_cris_trampoline_template):
+0:
+ /* The value we get for "PC" is right after the prefix instruction,
+ two bytes from the beginning, i.e. 0b+2. */
+ move.d $r10,[$pc+2f-(0b+2)]
+ move.d $pc,$r10
+1:
+ addq 2f-1b+4,$r10
+ move.d $r11,[$r10+]
+ move.d $r12,[$r10+]
+ move.d $r13,[$r10+]
+ move.d [$sp],$r11
+ move.d $r11,[$r10+]
+ move.d $r9,[$r10+]
+ move.d $sp,[$r10+]
+ subq FFI_CRIS_TRAMPOLINE_DATA_PART_SIZE,$r10
+ move.d 0,$r11
+3:
+ jump 0
+2:
+ .size ffi_cris_trampoline_template,.-0b
+
+/* This macro create a constant usable as "extern const int \name" in
+ C from within libffi, when \name has no prefix decoration. */
+
+ .macro const name,value
+ .globl \name
+ .type \name,@object
+ .hidden \name
+\name:
+ .dword \value
+ .size \name,4
+ .endm
+
+/* Constants for offsets within the trampoline. We could do this with
+ just symbols, avoiding memory contents and memory accesses, but the
+ C usage code would look a bit stranger. */
+
+ const L(ffi_cris_trampoline_fn_offset),2b-4-0b
+ const L(ffi_cris_trampoline_closure_offset),3b-4-0b