1
#ifndef _avcall_arm_c /*-*- C -*-*/
4
Copyright 1993 Bill Triggs, <Bill.Triggs@inrialpes.fr>
5
Copyright 1995-1999 Bruno Haible, <bruno@clisp.org>
7
This is free software distributed under the GNU General Public
8
Licence described in the file COPYING. Contact the author if
9
you don't have this or can't live with it. There is ABSOLUTELY
10
NO WARRANTY, explicit or implied, on this software.
12
/*----------------------------------------------------------------------
13
!!! THIS ROUTINE MUST BE COMPILED gcc -O !!!
15
Foreign function interface for an Acorn Risc Maschine with gcc.
17
This calls a C function with an argument list built up using macros
20
ARM Argument Passing Conventions:
22
All arguments, except the first 4 words, are passed on the stack with
23
word alignment. Doubles take two words. Structure args are passed as
24
true structures embedded in the argument stack. To return a structure,
25
the called function copies the return value to the address supplied
28
Compile this routine with gcc -O (or -O2 or -g -O) to get the right
29
register variables, or use the assembler version.
30
----------------------------------------------------------------------*/
31
#include "avcall.h.in"
33
#define RETURN(TYPE,VAL) (*(TYPE*)l->raddr = (TYPE)(VAL))
36
__builtin_avcall(av_alist* l)
38
register __avword* sp __asm__("r13"); /* C names for registers */
39
/*register __avword iret __asm__("r0"); */
40
register __avword iret2 __asm__("r1");
41
register float fret __asm__("r0"); /* r0 */
42
register double dret __asm__("r0"); /* r0,r1 */
44
__avword space[__AV_ALIST_WORDS]; /* space for callee's stack frame */
45
__avword* argframe = sp; /* stack offset for argument list */
46
int arglen = l->aptr - l->args;
49
for (i = 4; i < arglen; i++) /* push function args onto stack */
50
argframe[i-4] = l->args[i];
52
/* call function, pass 4 args in registers */
53
i = (*l->func)(l->args[0], l->args[1], l->args[2], l->args[3]);
55
/* save return value */
56
if (l->rtype == __AVvoid) {
58
if (l->rtype == __AVword) {
61
if (l->rtype == __AVchar) {
64
if (l->rtype == __AVschar) {
65
RETURN(signed char, i);
67
if (l->rtype == __AVuchar) {
68
RETURN(unsigned char, i);
70
if (l->rtype == __AVshort) {
73
if (l->rtype == __AVushort) {
74
RETURN(unsigned short, i);
76
if (l->rtype == __AVint) {
79
if (l->rtype == __AVuint) {
80
RETURN(unsigned int, i);
82
if (l->rtype == __AVlong) {
85
if (l->rtype == __AVulong) {
86
RETURN(unsigned long, i);
88
if (l->rtype == __AVlonglong || l->rtype == __AVulonglong) {
89
((__avword*)l->raddr)[0] = i;
90
((__avword*)l->raddr)[1] = iret2;
92
if (l->rtype == __AVfloat) {
95
if (l->rtype == __AVdouble) {
98
if (l->rtype == __AVvoidp) {
101
if (l->rtype == __AVstruct) {
102
/* NB: On arm, all structure sizes are divisible by 4. */
103
if (l->flags & __AV_PCC_STRUCT_RETURN) {
104
/* pcc struct return convention: need a *(TYPE*)l->raddr = *(TYPE*)i; */
105
if (l->rsize == sizeof(char)) { /* can't occur */
106
RETURN(char, *(char*)i);
108
if (l->rsize == sizeof(short)) { /* can't occur */
109
RETURN(short, *(short*)i);
111
if (l->rsize == sizeof(int)) {
112
RETURN(int, *(int*)i);
114
if (l->rsize == sizeof(double)) {
115
((int*)l->raddr)[0] = ((int*)i)[0];
116
((int*)l->raddr)[1] = ((int*)i)[1];
118
int n = (l->rsize+3)/4;
120
((__avword*)l->raddr)[n] = ((__avword*)i)[n];
123
/* normal struct return convention */
124
if (l->flags & __AV_REGISTER_STRUCT_RETURN) {
125
if (l->rsize == sizeof(char)) { /* can't occur */
128
if (l->rsize == sizeof(short)) { /* can't occur */
131
if (l->rsize == sizeof(int)) {
134
if (l->rsize == 2*sizeof(__avword)) {
135
((__avword*)l->raddr)[0] = i;
136
((__avword*)l->raddr)[1] = iret2;
144
#endif /*_avcall_arm_c */