* test-9.il: New test, test instaniating a class
[mono.git] / mono / arch / alpha / tramp.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Create trampolines to invoke arbitrary functions.
4  * 
5  * Copyright (C) Ximian Inc.
6  *
7  * Authors: Laramie Leavitt (lar@leavitt.us)
8  *
9  *
10  */
11
12 /* A typical Alpha stack frame looks like this */
13 /*
14 fun:                         // called from outside the module.
15         ldgp gp,0(pv)        // load the global pointer
16 fun..ng:                     // called from inside the module.
17         lda sp, -SIZE( sp )  // grow the stack downwards.
18
19         stq ra, 0(sp)        // save the return address.
20
21         stq s0, 8(sp)        // callee-saved registers.
22         stq s1, 16(sp)       // ...
23
24         // Move the arguments to the argument registers...
25         
26         mov addr, pv         // Load the callee address
27         jsr  ra, (pv)        // call the method.
28         ldgp gp, 0(ra)       // restore gp
29
30         // return value is in v0
31         
32         ldq ra, 0(sp)        // free stack frame
33         ldq s0, 8(sp)        // restore callee-saved registers.
34         ldq s1, 16(sp)       
35         ldq sp, 32(sp)       // restore stack pointer
36
37         ret zero, (ra), 1    // return.
38
39 // assuming that the procedure is in a0.
40 #define emit_prologue( p )  \
41         alpha_ldah( p, alpha_gp, alpha_pv, 0 );      \
42         alpha_lda( p, alpha_sp, alpha_sp, -32 );   \
43         alpha_lda( p, alpha_gp, alpha_gp, 0 );      \
44         alpha_stq( p, alpha_ra, alpha_sp, 0 );      \
45         alpha_stq( p, alpha_fp, alpha_sp, 8 );      \
46         alpha_mov( p, alpha_sp, alpha_fp )
47
48 #define emit_move_a0_to_pv( p ) \
49         alpha_mov( p, alpha_a0, alpha_pv )
50
51 #define emit_call( p ) \
52         alpha_jsr( p, alpha_ra, alpha_pv, 0 );    \
53         alpha_ldah( p, alpha_gp, alpha_ra, 0 );   \
54         alpha_lda( p, alpha_gp, alpha_gp, 0 );    \
55
56 #define emit_epilogue( p ) \
57         alpha_mov( p, alpha_fp, alpha_sp ); \
58         alpha_ldq( p, alpha_ra, alpha_sp, 0 ); \
59         alpha_ldq( p, alpha_fp, alpha_sp, 8 ); \
60         alpha_lda( p, alpha_sp, alpha_sp, 32 ); \
61         alpha_ret( p, alpha_ra )
62
63 */
64 /*****************************************************/
65
66 #include "config.h"
67 #include <stdlib.h>
68 #include <string.h>
69
70 #include "alpha-codegen.h"
71
72 #include "mono/metadata/class.h"
73 #include "mono/metadata/tabledefs.h"
74 #include "mono/interpreter/interp.h"
75 #include "mono/metadata/appdomain.h"
76 #include "mono/metadata/debug-helpers.h"
77
78 #define AXP_GENERAL_REGS     6
79 #define AXP_MIN_STACK_SIZE   32
80
81 #define PROLOG_INS           6
82 #define CALL_INS             3
83 #define EPILOG_INS           5
84
85 /*****************************************************/
86
87 typedef struct {
88         guint i_regs;
89         guint f_regs;
90         guint stack_size;
91         guint code_size;
92 } size_data;    
93
94
95 static char*
96 sig_to_name (MonoMethodSignature *sig, const char *prefix)
97 {
98     /* from sparc.c.  this should be global */
99
100         int i;
101         char *result;
102         GString *res = g_string_new ("");
103
104         if (prefix) {
105                 g_string_append (res, prefix);
106                 g_string_append_c (res, '_');
107         }
108
109         mono_type_get_desc (res, sig->ret, TRUE);
110
111         for (i = 0; i < sig->param_count; ++i) {
112                 g_string_append_c (res, '_');
113                 mono_type_get_desc (res, sig->params [i], TRUE);
114         }
115         result = res->str;
116         g_string_free (res, FALSE);
117         return result;
118 }
119
120
121 static void inline
122 add_general ( size_data *sz, gboolean simple)
123 {
124     // we don't really know yet, so just put something in here.
125     if ( sz->i_regs >= AXP_GENERAL_REGS) 
126     {
127         sz->stack_size += 8;
128     }
129
130     // ...and it probably doesn't matter if our code size is a
131     // little large...
132
133     sz->code_size += 12;
134     sz->i_regs ++;
135 }
136
137 static void
138 calculate_sizes (MonoMethodSignature *sig, 
139                  size_data *sz, 
140                  gboolean string_ctor)
141 {
142         guint i, size;
143         guint32 simpletype, align;
144
145         sz->i_regs     = 0;
146         sz->f_regs     = 0;
147         sz->stack_size = AXP_MIN_STACK_SIZE;
148         sz->code_size  = 4 * (PROLOG_INS + CALL_INS + EPILOG_INS);
149
150         if (sig->hasthis) {
151                 add_general (&gr, sz, TRUE);
152         }
153
154         for (i = 0; i < sig->param_count; ++i) {
155                 switch (sig->ret->type) {
156                 case MONO_TYPE_VOID:
157                         break;
158                 case MONO_TYPE_BOOLEAN:
159                 case MONO_TYPE_I1:
160                 case MONO_TYPE_U1:
161                 case MONO_TYPE_I2:
162                 case MONO_TYPE_U2:
163                 case MONO_TYPE_CHAR:
164                 case MONO_TYPE_I4:
165                 case MONO_TYPE_U4:
166                 case MONO_TYPE_I:
167                 case MONO_TYPE_U:
168                 case MONO_TYPE_CLASS:
169                 case MONO_TYPE_OBJECT:
170                 case MONO_TYPE_R4:
171                 case MONO_TYPE_R8:
172                 case MONO_TYPE_SZARRAY:
173                 case MONO_TYPE_ARRAY:
174                 case MONO_TYPE_STRING:
175                 case MONO_TYPE_I8:
176                         add_general (&gr, sz, TRUE);
177                         break;
178                 case MONO_TYPE_VALUETYPE:
179                 default:
180                         g_error ("Can't handle as return value 0x%x", sig->ret->type);
181                 }
182         }
183
184         /* align stack size to 8 */
185         sz->stack_size = (sz->stack_size + 8) & ~8;
186         sz->local_size = (sz->local_size + 8) & ~8;
187 }
188
189 /*                                                                  */
190 /*                void func (void (*callme)(), void *retval,        */
191 /*                           void *this_obj, stackval *arguments);  */
192 static inline guint8 *
193 emit_prolog (guint8 *p, MonoMethodSignature *sig, size_data *sz)
194 {
195         guint stack_size;
196
197         stack_size = sz->stack_size;
198
199         /* function prolog */
200         alpha_ldah( p, alpha_gp, alpha_pv, 0 );      
201         alpha_lda( p, alpha_sp, alpha_sp, -stack_size );   
202         alpha_lda( p, alpha_gp, alpha_gp, 0  );
203
204         /* save ra, fp */
205         alpha_stq( p, alpha_ra, alpha_sp, 0  );
206         alpha_stq( p, alpha_fp, alpha_sp, 8  );
207
208         /* store the return parameter */
209         alpha_stq( p, alpha_a0, alpha_sp, 16 ); 
210         alpha_stq( p, alpha_a1, alpha_sp, 24 ); 
211
212         /* load fp into sp */
213         alpha_mov( p, alpha_sp, alpha_fp )
214
215         return p;
216 }
217
218 static inline guint8 *
219 emit_epilog (guint8 *p, MonoMethodSignature *sig, size_data *sz)
220 {
221         alpha_mov( p, alpha_fp, alpha_sp ); 
222
223         /* restore fp, ra, sp */
224         alpha_ldq( p, alpha_ra, alpha_sp, 0 ); 
225         alpha_ldq( p, alpha_fp, alpha_sp, 8 ); 
226         alpha_lda( p, alpha_sp, alpha_sp, 32 ); 
227         
228         /* return */
229         alpha_ret( p, alpha_ra );
230 }
231
232 static inline guint8 *
233 emit_call( guint8 *p, MonoMethodSignature *sig, size_data *sz )
234 {
235         /* move a0 into pv, ready to call */
236         alpha_mov( p, alpha_a0, alpha_pv );
237         
238         /* call arg */
239         alpha_jsr( p, alpha_ra, alpha_pv, 0 );
240
241         /* reload the gp */
242         alpha_ldah( p, alpha_gp, alpha_ra, 0 );   
243         alpha_lda( p, alpha_gp, alpha_gp, 0 );    
244 }
245
246
247 MonoPIFunc
248 mono_create_trampoline (MonoMethodSignature *sig, gboolean string_ctor)
249 {
250         g_error ("Unsupported arch");
251         return NULL;
252 }
253
254 void *
255 mono_create_method_pointer (MonoMethod *method)
256 {
257         g_error ("Unsupported arch");
258         return NULL;
259 }
260