1
#ifndef _avcall_m88k_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 -fno-omit-frame-pointer !!!
15
Foreign function interface for a M88000 with gcc.
17
This calls a C function with an argument list built up using macros
20
M88k Argument Passing Conventions:
22
All arguments, except the non-structs among the first 8 words, are passed
23
on the stack with word alignment. Doubles take two words and force double
24
alignment. Scalars among the first 8 words are passed in registers.
25
Structure args are are passed as true structures embedded in the argument
28
To return a structure, the called function copies the return value to the
29
address supplied in register "r12".
31
Compile this routine with gcc -O (or -O2 -fno-omit-frame-pointer or -g -O)
32
to get the right register variables. For other compilers use the
33
pre-compiled assembler version.
34
----------------------------------------------------------------------*/
35
#include "avcall.h.in"
37
#define RETURN(TYPE,VAL) (*(TYPE*)l->raddr = (TYPE)(VAL))
39
register __avword* sret __asm__("r12"); /* structure return pointer */
42
__builtin_avcall(av_alist* l)
44
register __avword* sp __asm__("r31"); /* C names for registers */
45
/*register __avword iret __asm__("r2"); */
46
register __avword iret2 __asm__("r3");
47
register float fret __asm__("r2");
48
register double dret __asm__("r2");
50
__avword* argframe = (sp -= __AV_ALIST_WORDS); /* make room for argument list */
51
int arglen = l->aptr - l->args;
54
for (i = 0; i < arglen; i++) /* push function args onto stack */
55
argframe[i] = l->args[i];
57
if (l->rtype == __AVstruct) /* pass struct return address */
60
/* call function, pass 8 args in registers */
61
i = (*l->func)(l->args[0], l->args[1], l->args[2], l->args[3],
62
l->args[4], l->args[5], l->args[6], l->args[7]);
64
/* save return value */
65
if (l->rtype == __AVvoid) {
67
if (l->rtype == __AVword) {
70
if (l->rtype == __AVchar) {
73
if (l->rtype == __AVschar) {
74
RETURN(signed char, i);
76
if (l->rtype == __AVuchar) {
77
RETURN(unsigned char, i);
79
if (l->rtype == __AVshort) {
82
if (l->rtype == __AVushort) {
83
RETURN(unsigned short, i);
85
if (l->rtype == __AVint) {
88
if (l->rtype == __AVuint) {
89
RETURN(unsigned int, i);
91
if (l->rtype == __AVlong) {
94
if (l->rtype == __AVulong) {
95
RETURN(unsigned long, i);
97
if (l->rtype == __AVlonglong || l->rtype == __AVulonglong) {
98
((__avword*)l->raddr)[0] = i;
99
((__avword*)l->raddr)[1] = iret2;
101
if (l->rtype == __AVfloat) {
104
if (l->rtype == __AVdouble) {
105
RETURN(double, dret);
107
if (l->rtype == __AVvoidp) {
110
if (l->rtype == __AVstruct) {
111
if (l->flags & __AV_PCC_STRUCT_RETURN) {
112
/* pcc struct return convention: need a *(TYPE*)l->raddr = *(TYPE*)i; */
113
if (l->rsize == sizeof(char)) {
114
RETURN(char, *(char*)i);
116
if (l->rsize == sizeof(short)) {
117
RETURN(short, *(short*)i);
119
if (l->rsize == sizeof(int)) {
120
RETURN(int, *(int*)i);
122
if (l->rsize == sizeof(double)) {
123
((int*)l->raddr)[0] = ((int*)i)[0];
124
((int*)l->raddr)[1] = ((int*)i)[1];
126
int n = (l->rsize + sizeof(__avword)-1)/sizeof(__avword);
128
((__avword*)l->raddr)[n] = ((__avword*)i)[n];
131
/* normal struct return convention */
132
if (l->flags & __AV_SMALL_STRUCT_RETURN) {
133
if (l->rsize == sizeof(char)) {
136
if (l->rsize == sizeof(short)) {
139
if (l->rsize == sizeof(int)) {
145
sp += __AV_ALIST_WORDS;
149
#endif /*_avcall_m88k_c */