[project @ 1999-01-18 09:20:08 by sof]
[ghc-hetmet.git] / ghc / rts / callfun.S
1 /* --------------------------------------------------------------------------
2  * Assembly code to call C and Haskell functions 
3  *
4  * Copyright (c) 1994-1998.
5  *
6  * $RCSfile: callfun.S,v $
7  * $Revision: 1.2 $
8  * $Date: 1998/12/15 13:08:03 $
9  * ------------------------------------------------------------------------*/
10         
11 #include "config.h"
12 #include "options.h"    
13         
14 #ifdef INTERPRETER
15         .file "callfun.S"
16
17 /* No longer needed - I finally figured out how to use __builtin_apply  */
18 #if 0 && i386_TARGET_ARCH
19
20 #if 0   
21   void ccall( CFunDescriptor* d, void* fun )
22   {
23       void *rs=alloca(d->result_size);
24       void *as=alloca(d->arg_size);
25       unmarshall(d->arg_tys,as);
26       rs = fun(as)              ; 
27       marshall(d->result_tys,rs);
28   }
29
30   On entry, we have:    
31     ret   =  0(%esp)
32     d     =  4(%esp)
33     fun   =  8(%esp)    
34           
35   We assume that %ebp is a callee saves register
36   and that %ecx is not used to return the result.
37   If %ecx is a callee saves register (I think it is), the code
38   can be optimised slightly - but I doubt its worth it. 
39 #endif
40 .globl ccall
41 ccall:
42         pushl %ebp           /* Save stack frame pointer       */
43         pushl %ecx           /* Save callee-saves register     */
44                 
45         leal  8(%esp), %ebp  /* ebp = frame pointer            */
46         movl  4(%ebp), %ecx  /* ecx = d;                       */
47         subl 12(%ecx), %esp  /* rs  = alloca(d->result_size);  */
48         subl  4(%ecx), %esp  /* as  = alloca(d->arg_size);     */
49
50         /* Marshall arguments off STG stack */  
51         pushl %esp
52         pushl 0(%ecx)
53         call  unmarshall
54         addl  $8,%esp        /* unmarshall(d->arg_tys,as);     */
55
56         /* Call function */
57         movl  8(%ebp), %ecx 
58         call  *%ecx          /* rs = fun(as);                  */
59
60         movl  4(%ebp), %ecx  /* ecx = d;                       */
61         addl  4(%ecx), %esp  /* free(as)                       */
62
63
64         /* Save result in rs - assume one or zero results for now */
65         movl  8(%ecx), %ecx  /* ecx = d->result_tys            */
66
67         cmpl  $0,(%ecx)      /* '\0' = no result               */
68         je    .args_saved
69
70         cmpl  $70,(%ecx)     /* 'F' = float result             */
71         jne   .not_float
72         flds  (%esp)         /* *rs = (float)f1                */
73         jmp   .args_saved
74
75 .not_float:
76         cmpl  $68,(%ecx)     /* 'D' = double result            */
77         jne   .not_double
78         fldl  (%esp)         /* *rs = (double)f1               */
79         jmp   .args_saved
80
81 .not_double:    
82         movl  %eax,(%esp)    /* *rs = eax                      */
83         /* fall through to .args_saved */
84
85         /* Marshall results back onto STG stack */
86 .args_saved:
87         pushl %esp                                             
88         movl  4(%ebp), %ecx  /* ecx = d;                       */
89         pushl 8(%ecx)                                          
90         call  marshall                                         
91         addl  $8,%esp        /* marshall(d->result_tys,rs);    */
92
93         
94         movl  4(%ebp), %ecx  /* ecx = d;                       */
95         addl  12(%ecx), %esp /* free(rs)                       */
96
97         popl %ecx            /* Restore callee-saves register  */
98         popl %ebp            /* restore stack frame pointer    */
99         ret                  
100         
101 #if 0
102 /* When we call a Fun, we push the arguments on the stack, push a return
103  * address and execute the instruction "call callFun_entry" which brings us
104  * here with a return address on top of the stack, a pointer to
105  * the FunDescriptor under that and the arguments under that.
106  * We swap the top arguments so that when we jmp to callFunDesc, the stack
107  * will look as though we executed "callFunDesc(fDescriptor,arg1,arg2,...)"
108  */
109         
110         /* function call/return - standard entry point
111          * we'll have one of these for each calling convention
112          * all of which jump to callFunDesc when done
113          */     
114         .globl callFun_entry
115         .type  callFun_entry,@function
116 callFun_entry:  
117         popl  %eax   /* FunDescriptor  */
118         popl  %edx   /* Return address */
119         pushl %eax
120         pushl %edx
121         jmp   callFunDesc
122
123         /* generic function call/return */
124 callFunDesc:
125         subl  $8,%esp        /* int/double res1;  */
126         pushl %esp           /* &res1             */
127         leal  20(%esp),%ecx  /* &arg1             */
128         pushl %ecx 
129         pushl 20(%esp)       /* fun               */
130         call  call_H         /* returns result type in %eax */
131         addl  $20,%esp
132
133         testl %eax,%eax      /* '\0' = no result */
134         jne   .L1
135         ret
136 .L1:
137         cmpl  $70,%eax       /* 'F' = float result */
138         jne   .L2
139         flds  -8(%esp)
140         ret
141 .L2:
142         cmpl  $68,%eax       /* 'D' = double result */
143         jne   .L3
144         fldl  -8(%esp)
145         ret
146 .L3:
147         movl  -8(%esp),%eax  /* return r          */
148         ret
149
150
151 /* Some useful instructions - for later use:            
152  *      fstpl (%ebx)  store a double
153  *      fstps (%ebx)  store a float
154  *
155  *      fldl (%esi)   load a double (ready for return)
156  *      flds (%esi)   load a float (ready for return)
157  */
158 #endif /* 0 */
159         
160 #endif /* i386_TARGET_ARCH */
161         
162 #endif /* INTERPRETER */