ImageButtonTest.cs added new tests for 2.0 and new resource NoEventValidation.aspx
[mono.git] / mono / mini / exceptions-alpha.c
1 /*------------------------------------------------------------------*/
2 /*                                                                  */
3 /* Name        - exceptions-alpha.c                                 */
4 /*                                                                  */
5 /* Function    - Exception support for Alpha.                       */
6 /*                                                                  */
7 /* Name        - Sergey Tikhonov (tsv@solvo.ru)                     */
8 /*                                                                  */
9 /* Date        - January, 2006                                      */
10 /*                                                                  */
11 /* Derivation  - From exceptions-amd64 & exceptions-ia64            */
12 /*               Paolo Molaro (lupus@ximian.com)                    */
13 /*               Dietmar Maurer (dietmar@ximian.com)                */
14 /*               Zoltan Varga (vargaz@gmail.com)                    */
15 /*                                                                  */
16 /*                                                                  */
17 /*------------------------------------------------------------------*/
18
19 /*------------------------------------------------------------------*/
20 /*                 D e f i n e s                                    */
21 /*------------------------------------------------------------------*/
22 #define NOT_IMPLEMENTED(x) \
23         g_error ("FIXME: %s is not yet implemented.", x);
24
25 #define ALPHA_DEBUG(x) \
26   if (mini_alpha_verbose_level) \
27     g_debug ("ALPHA_DEBUG: %s is called.", x);
28
29 #define ALPHA_PRINT if (mini_alpha_verbose_level)
30
31 #define SZ_THROW     384
32
33 extern int mini_alpha_verbose_level;
34
35 /*========================= End of Defines =========================*/
36
37
38 /*------------------------------------------------------------------*/
39 /*                 I n c l u d e s                                  */
40 /*------------------------------------------------------------------*/
41
42 #include <config.h>
43 #include <glib.h>
44 #include <signal.h>
45 #include <string.h>
46 #include <ucontext.h>
47
48 #include <mono/arch/alpha/alpha-codegen.h>
49 #include <mono/metadata/appdomain.h>
50 #include <mono/metadata/tabledefs.h>
51 #include <mono/metadata/threads.h>
52 #include <mono/metadata/debug-helpers.h>
53 #include <mono/metadata/exception.h>
54 #include <mono/metadata/mono-debug.h>
55
56 #include "mini.h"
57 #include "mini-alpha.h"
58
59 /*========================= End of Includes ========================*/
60
61 /*------------------------------------------------------------------*/
62 /*                                                                  */
63 /* Name         - mono_arch_get_call_filter                         */
64 /*                                                                  */
65 /* Function     - Return a pointer to a method which calls an       */
66 /*                exception filter. We also use this function to    */
67 /*                call finally handlers (we pass NULL as @exc       */
68 /*                object in this case).                             */
69 /*                                                                  */
70 /*------------------------------------------------------------------*/
71
72 gpointer
73 mono_arch_get_call_filter (void)
74 {
75   static gboolean inited = FALSE;
76   static unsigned int *start_code;
77   unsigned int *code;
78
79   ALPHA_DEBUG("mono_arch_get_call_filter");
80
81   if (inited)
82     return start_code;
83
84   start_code = code = mono_global_codeman_reserve (128 * 4);
85
86   /* call_filter (MonoContext *ctx, unsigned long eip) */
87   code = start_code;
88
89   alpha_ldah( code, alpha_gp, alpha_pv, 0 );
90   alpha_lda( code, alpha_gp, alpha_gp, 0 );     // ldgp gp, 0(pv)
91
92   /* store call convention parameters on stack */
93   alpha_lda(code, alpha_sp, alpha_sp, -(8*25)); // Save 22 regs + RA, FP
94   alpha_stq(code, alpha_ra, alpha_sp, 0);
95   alpha_stq(code, alpha_fp, alpha_sp, 8);
96
97   /* set the frame pointer */
98   alpha_mov1( code, alpha_sp, alpha_fp );
99
100   /* Save registers */
101   alpha_stq(code, alpha_r1, alpha_fp, (16+(8*0)));
102   alpha_stq(code, alpha_r2, alpha_fp, (16+(8*1)));
103   alpha_stq(code, alpha_r3, alpha_fp, (16+(8*2)));
104   alpha_stq(code, alpha_r4, alpha_fp, (16+(8*3)));
105   alpha_stq(code, alpha_r5, alpha_fp, (16+(8*4)));
106   alpha_stq(code, alpha_r6, alpha_fp, (16+(8*5)));
107   alpha_stq(code, alpha_r7, alpha_fp, (16+(8*6)));
108   alpha_stq(code, alpha_r8, alpha_fp, (16+(8*7)));
109   alpha_stq(code, alpha_r9, alpha_fp, (16+(8*8)));
110   alpha_stq(code, alpha_r10, alpha_fp, (16+(8*9)));
111   alpha_stq(code, alpha_r11, alpha_fp, (16+(8*10)));
112   alpha_stq(code, alpha_r12, alpha_fp, (16+(8*11)));
113   alpha_stq(code, alpha_r13, alpha_fp, (16+(8*12)));
114   alpha_stq(code, alpha_r14, alpha_fp, (16+(8*13)));
115   alpha_stq(code, alpha_r22, alpha_fp, (16+(8*14)));
116   alpha_stq(code, alpha_r23, alpha_fp, (16+(8*15)));
117   alpha_stq(code, alpha_r24, alpha_fp, (16+(8*16)));
118   alpha_stq(code, alpha_r25, alpha_fp, (16+(8*17)));
119   alpha_stq(code, alpha_r26, alpha_fp, (16+(8*18)));
120   alpha_stq(code, alpha_r27, alpha_fp, (16+(8*19)));
121   alpha_stq(code, alpha_r28, alpha_fp, (16+(8*20)));
122   alpha_stq(code, alpha_r29, alpha_fp, (16+(8*21)));
123
124   /* Load regs from ctx */
125
126   alpha_ldq(code, alpha_r1, alpha_a0,
127             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r1]));
128   alpha_ldq(code, alpha_r2, alpha_a0,
129             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r2]));
130   alpha_ldq(code, alpha_r3, alpha_a0,
131             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r3]));
132   alpha_ldq(code, alpha_r4, alpha_a0,
133             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r4]));
134   alpha_ldq(code, alpha_r5, alpha_a0,
135             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r5]));
136   alpha_ldq(code, alpha_r6, alpha_a0,
137             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r6]));
138   alpha_ldq(code, alpha_r7, alpha_a0,
139             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r7]));
140   alpha_ldq(code, alpha_r8, alpha_a0,
141             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r8]));
142   alpha_ldq(code, alpha_r9, alpha_a0,
143             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r9]));
144   alpha_ldq(code, alpha_r10, alpha_a0,
145             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r10]));
146   alpha_ldq(code, alpha_r11, alpha_a0,
147             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r11]));
148   alpha_ldq(code, alpha_r12, alpha_a0,
149             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r12]));
150   alpha_ldq(code, alpha_r13, alpha_a0,
151             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r13]));
152   alpha_ldq(code, alpha_r14, alpha_a0,
153             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r14]));
154   alpha_ldq(code, alpha_r15, alpha_a0,
155             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r15]));
156   alpha_ldq(code, alpha_r22, alpha_a0,
157             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r22]));
158   alpha_ldq(code, alpha_r23, alpha_a0,
159             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r23]));
160   alpha_ldq(code, alpha_r24, alpha_a0,
161             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r24]));
162   alpha_ldq(code, alpha_r25, alpha_a0,
163             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r25]));
164   alpha_ldq(code, alpha_r26, alpha_a0,
165             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r26]));
166   alpha_ldq(code, alpha_r27, alpha_a0,
167             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r27]));
168   alpha_ldq(code, alpha_r28, alpha_a0,
169             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r28]));
170   alpha_ldq(code, alpha_r29, alpha_a0,
171             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r29]));
172
173   alpha_mov1(code, alpha_a1, alpha_pv);
174
175   /* call the handler */
176   alpha_jsr(code, alpha_ra, alpha_pv, 0);
177
178   /* restore saved regs */
179   alpha_ldq(code, alpha_r1, alpha_sp, (16+(8*0)));
180   alpha_ldq(code, alpha_r2, alpha_sp, (16+(8*1)));
181   alpha_ldq(code, alpha_r3, alpha_sp, (16+(8*2)));
182   alpha_ldq(code, alpha_r4, alpha_sp, (16+(8*3)));
183   alpha_ldq(code, alpha_r5, alpha_sp, (16+(8*4)));
184   alpha_ldq(code, alpha_r6, alpha_sp, (16+(8*5)));
185   alpha_ldq(code, alpha_r7, alpha_sp, (16+(8*6)));
186   alpha_ldq(code, alpha_r8, alpha_sp, (16+(8*7)));
187   alpha_ldq(code, alpha_r9, alpha_sp, (16+(8*8)));
188   alpha_ldq(code, alpha_r10, alpha_sp, (16+(8*9)));
189   alpha_ldq(code, alpha_r11, alpha_sp, (16+(8*10)));
190   alpha_ldq(code, alpha_r12, alpha_sp, (16+(8*11)));
191   alpha_ldq(code, alpha_r13, alpha_sp, (16+(8*12)));
192   alpha_ldq(code, alpha_r14, alpha_sp, (16+(8*13)));
193   alpha_ldq(code, alpha_r22, alpha_sp, (16+(8*14)));
194   alpha_ldq(code, alpha_r23, alpha_sp, (16+(8*15)));
195   alpha_ldq(code, alpha_r24, alpha_sp, (16+(8*16)));
196   alpha_ldq(code, alpha_r25, alpha_sp, (16+(8*17)));
197   alpha_ldq(code, alpha_r26, alpha_sp, (16+(8*18)));
198   alpha_ldq(code, alpha_r27, alpha_sp, (16+(8*19)));
199   alpha_ldq(code, alpha_r28, alpha_sp, (16+(8*20)));
200   alpha_ldq(code, alpha_r29, alpha_sp, (16+(8*21)));
201
202   alpha_ldq(code, alpha_ra, alpha_sp, 0);
203   alpha_ldq(code, alpha_fp, alpha_sp, 8);
204   alpha_lda(code, alpha_sp, alpha_sp, (8*25)); // Save 22 regs + RA, FP
205   
206   alpha_ret(code, alpha_ra, 1);
207
208   inited = TRUE;
209
210   g_assert (( ((char *)code) - (char *)start_code) < 128 * 4);
211
212   return start_code;
213 }
214
215 /*========================= End of Function ========================*/
216
217 /*------------------------------------------------------------------*/
218 /*                                                                  */
219 /* Name         - arch_get_throw_exception                          */
220 /*                                                                  */
221 /* Function     - Return a function pointer which can be used to    */
222 /*                raise exceptions. The returned function has the   */
223 /*                following signature:                              */
224 /*                void (*func) (MonoException *exc);                */
225 /*                                                                  */
226 /*------------------------------------------------------------------*/
227
228 static void throw_exception(MonoException *exc, unsigned long RA,
229                             unsigned long *SP, unsigned long rethrow)
230 {
231   static void (*restore_context) (MonoContext *);
232   MonoContext ctx;
233   unsigned long *LSP = SP - 24;
234
235   //g_print("ALPHA: throw_exception - Exc: %p, RA: %0lX, SP: %p\n",
236   //      exc, RA, SP);
237
238   if (!restore_context)
239     restore_context = mono_arch_get_restore_context ();
240
241   // Save stored regs into context
242   ctx.uc_mcontext.sc_regs[alpha_r0] = LSP[0];
243   ctx.uc_mcontext.sc_regs[alpha_r1] = LSP[1];
244   ctx.uc_mcontext.sc_regs[alpha_r2] = LSP[2];
245   ctx.uc_mcontext.sc_regs[alpha_r3] = LSP[3];
246   ctx.uc_mcontext.sc_regs[alpha_r4] = LSP[4];
247   ctx.uc_mcontext.sc_regs[alpha_r5] = LSP[5];
248   ctx.uc_mcontext.sc_regs[alpha_r6] = LSP[6];
249   ctx.uc_mcontext.sc_regs[alpha_r7] = LSP[7];
250   ctx.uc_mcontext.sc_regs[alpha_r8] = LSP[8];
251   ctx.uc_mcontext.sc_regs[alpha_r9] = LSP[9];
252   ctx.uc_mcontext.sc_regs[alpha_r10] = LSP[10];
253   ctx.uc_mcontext.sc_regs[alpha_r11] = LSP[11];
254   ctx.uc_mcontext.sc_regs[alpha_r12] = LSP[12];
255   ctx.uc_mcontext.sc_regs[alpha_r13] = LSP[13];
256   ctx.uc_mcontext.sc_regs[alpha_r14] = LSP[14];
257   ctx.uc_mcontext.sc_regs[alpha_r15] = LSP[15];
258   ctx.uc_mcontext.sc_regs[alpha_r22] = LSP[16];
259   ctx.uc_mcontext.sc_regs[alpha_r23] = LSP[17];
260   ctx.uc_mcontext.sc_regs[alpha_r24] = LSP[18];
261   ctx.uc_mcontext.sc_regs[alpha_r25] = LSP[19];
262   ctx.uc_mcontext.sc_regs[alpha_r26] = LSP[20];
263   ctx.uc_mcontext.sc_regs[alpha_r27] = LSP[21];
264   ctx.uc_mcontext.sc_regs[alpha_r28] = LSP[22];
265   ctx.uc_mcontext.sc_regs[alpha_r29] = LSP[23];
266
267   ctx.uc_mcontext.sc_regs[alpha_r30] = (unsigned long)SP;
268   ctx.uc_mcontext.sc_pc = RA;
269
270   if (mono_object_isinst (exc, mono_defaults.exception_class))
271     {
272       MonoException *mono_ex = (MonoException*)exc;
273       if (!rethrow)
274         mono_ex->stack_trace = NULL;
275     }
276
277   mono_handle_exception (&ctx, exc, (gpointer)RA, FALSE);
278
279   restore_context(&ctx);
280
281   g_assert_not_reached ();
282 }
283
284 /*
285 ** This trampoline code is called from the code as action on
286 ** throw opcode. It should save all necessary regs somethere and
287 ** call the C function to do the rest.
288 ** For Alpha trampoline code should allocate space on stack and 
289 **  save all registers into it. Then call "throw_exception"
290 **  function with "exc" info and saved registers. The "throw_exception"
291 **  should handle the rest. The "throw_exception" has signature
292 **  void (*throw_exception)(MonoException *, long PC, long SP)
293 ** The stack layout is:
294 ** R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14,
295 ** R15, R22, R23, R24, R25, R26, R27, R28, R29
296 **
297 **
298 */
299
300 static gpointer
301 get_throw_trampoline (gboolean rethrow)
302 {
303   guint8 *start_code;
304   unsigned int *code;
305
306   start_code = mono_global_codeman_reserve (46*4);
307
308   code = (unsigned int *)start_code;
309
310   /* Exception is in a0 already */
311   alpha_mov1(code, alpha_ra, alpha_a1);  // Return address
312   alpha_mov1(code, alpha_sp, alpha_a2);  // Stack pointer
313
314   if (rethrow)
315     alpha_lda(code, alpha_a3, alpha_zero, 1);
316   else
317     alpha_mov1(code, alpha_zero, alpha_a3);
318
319   alpha_lda(code, alpha_sp, alpha_sp, -(24*8)); // Allocate stack for regs
320
321   alpha_stq(code, alpha_r0, alpha_sp, 0*8);
322   alpha_stq(code, alpha_r1, alpha_sp, 1*8);
323   alpha_stq(code, alpha_r2, alpha_sp, 2*8);
324   alpha_stq(code, alpha_r3, alpha_sp, 3*8);
325   alpha_stq(code, alpha_r4, alpha_sp, 4*8);
326   alpha_stq(code, alpha_r5, alpha_sp, 5*8);
327   alpha_stq(code, alpha_r6, alpha_sp, 6*8);
328   alpha_stq(code, alpha_r7, alpha_sp, 7*8);
329   alpha_stq(code, alpha_r8, alpha_sp, 8*8);
330   alpha_stq(code, alpha_r9, alpha_sp, 9*8);
331   alpha_stq(code, alpha_r10, alpha_sp, 10*8);
332   alpha_stq(code, alpha_r11, alpha_sp, 11*8);
333   alpha_stq(code, alpha_r12, alpha_sp, 12*8);
334   alpha_stq(code, alpha_r13, alpha_sp, 13*8);
335   alpha_stq(code, alpha_r14, alpha_sp, 14*8);
336   alpha_stq(code, alpha_r15, alpha_sp, 15*8);
337   alpha_stq(code, alpha_r22, alpha_sp, 16*8);
338   alpha_stq(code, alpha_r23, alpha_sp, 17*8);
339   alpha_stq(code, alpha_r24, alpha_sp, 18*8);
340   alpha_stq(code, alpha_r25, alpha_sp, 19*8);
341   alpha_stq(code, alpha_r26, alpha_sp, 20*8);
342   alpha_stq(code, alpha_r27, alpha_sp, 21*8);
343   alpha_stq(code, alpha_r28, alpha_sp, 22*8);
344   alpha_stq(code, alpha_r29, alpha_sp, 23*8);
345
346   alpha_mov1(code, alpha_zero, alpha_pv);
347   alpha_lda(code, alpha_r1, alpha_zero,
348             ((unsigned long)throw_exception)&0xFFFF);
349   alpha_lda(code, alpha_r2, alpha_zero,
350             (((unsigned long)throw_exception) >> 16)&0xFFFF);
351   alpha_lda(code, alpha_r3, alpha_zero,
352             (((unsigned long)throw_exception) >> 32)&0xFFFF);
353   alpha_lda(code, alpha_r4, alpha_zero,
354             (((unsigned long)throw_exception) >> 48)&0xFFFF);
355   alpha_zapnot_(code, alpha_r1, 0x3, alpha_r1);
356   alpha_bis(code, alpha_r1, alpha_pv, alpha_pv);
357
358   alpha_zapnot_(code, alpha_r2, 0x3, alpha_r2);
359   alpha_sll_(code, alpha_r2, 16, alpha_r2);
360   alpha_bis(code, alpha_r2, alpha_pv, alpha_pv);
361
362   alpha_zapnot_(code, alpha_r3, 0x3, alpha_r3);
363   alpha_sll_(code, alpha_r3, 32, alpha_r3);
364   alpha_bis(code, alpha_r3, alpha_pv, alpha_pv);
365
366   alpha_zapnot_(code, alpha_r4, 0x3, alpha_r4);
367   alpha_sll_(code, alpha_r4, 48, alpha_r4);
368   alpha_bis(code, alpha_r4, alpha_pv, alpha_pv); // pv - handle_exception addr
369
370   alpha_jmp(code, alpha_zero, alpha_pv, 0);
371
372   // alpha_break(code);
373
374   g_assert (( ((char *)code) - (char *)start_code) < 46 * 4);
375
376   return start_code;
377 }
378
379 /**
380  * mono_arch_get_throw_exception:
381  *
382  * Returns a function pointer which can be used to raise
383  * exceptions. The returned function has the following
384  * signature: void (*func) (MonoException *exc);
385  *
386  */
387 gpointer
388 mono_arch_get_throw_exception (void)
389 {
390   static guint8* start;
391   static gboolean inited = FALSE;
392
393   ALPHA_DEBUG("mono_arch_get_throw_exception");
394
395   if (inited)
396     return start;
397
398   start = get_throw_trampoline (FALSE);
399
400   inited = TRUE;
401
402   return start;
403 }
404 /*========================= End of Function ========================*/
405
406
407 /**
408  * mono_arch_get_throw_corlib_exception:
409  *
410  * Returns a function pointer which can be used to raise
411  * corlib exceptions. The returned function has the following
412  * signature: void (*func) (guint32 ex_token, guint32 offset);
413  * Here, offset is the offset which needs to be substracted from the caller IP
414  * to get the IP of the throw. Passing the offset has the advantage that it
415  * needs no relocations in the caller.
416  */
417 gpointer
418 mono_arch_get_throw_corlib_exception (void)
419 {
420   static guint8* start;
421   static gboolean inited = FALSE;
422   unsigned int *code;
423   guint64 throw_ex;
424
425   ALPHA_DEBUG("mono_arch_get_throw_corlib_exception");
426
427   if (inited)
428     return start;
429
430   start = mono_global_codeman_reserve (512);
431
432   code = (unsigned int *)start;
433   // Logic
434   // Expect exception token as parameter
435   // call mono_exception_from_token(void *, uint32 token)
436   // Get result and call "throw_ex" (got from mono_arch_get_throw_exception)
437   // Throw exception
438
439   // The trampoline code will be called with PV set
440   //  so expect correct ABI handling
441
442   //alpha_ldah(code, alpha_gp, alpha_pv, 0);
443   //alpha_lda(code, alpha_gp, alpha_gp, 0);
444   alpha_lda(code, alpha_sp, alpha_sp, -(8*4));
445
446   // Save caller GP
447   alpha_stq(code, alpha_gp, alpha_sp, 24);
448
449   /* store call convention parameters on stack */
450   alpha_stq( code, alpha_ra, alpha_sp, 0 ); // ra
451   alpha_stq( code, alpha_fp, alpha_sp, 8 ); // fp
452
453   /* set the frame pointer */
454   alpha_mov1(code, alpha_sp, alpha_fp );
455
456   // Store throw_ip offset
457   alpha_stq(code, alpha_a1, alpha_fp, 16);
458
459   // Prepare to call "mono_exception_from_token (MonoImage *image, guint32 token)"
460   // Move token to a1 reg
461   alpha_mov1(code, alpha_a0, alpha_a1);
462
463   alpha_mov1(code, alpha_zero, alpha_a0);
464   alpha_lda(code, alpha_r1, alpha_zero,
465             ((unsigned long)mono_defaults.exception_class->image)&0xFFFF);
466   alpha_lda(code, alpha_r2, alpha_zero,
467             (((unsigned long)mono_defaults.exception_class->image) >> 16)&0xFFFF);
468   alpha_lda(code, alpha_r3, alpha_zero,
469             (((unsigned long)mono_defaults.exception_class->image) >> 32)&0xFFFF);
470   alpha_lda(code, alpha_r4, alpha_zero,
471             (((unsigned long)mono_defaults.exception_class->image) >> 48)&0xFFFF);
472   alpha_zapnot_(code, alpha_r1, 0x3, alpha_r1);
473   alpha_bis(code, alpha_r1, alpha_a0, alpha_a0);
474
475   alpha_zapnot_(code, alpha_r2, 0x3, alpha_r2);
476   alpha_sll_(code, alpha_r2, 16, alpha_r2);
477   alpha_bis(code, alpha_r2, alpha_a0, alpha_a0);
478
479   alpha_zapnot_(code, alpha_r3, 0x3, alpha_r3);
480   alpha_sll_(code, alpha_r3, 32, alpha_r3);
481   alpha_bis(code, alpha_r3, alpha_a0, alpha_a0);
482
483   alpha_zapnot_(code, alpha_r4, 0x3, alpha_r4);
484   alpha_sll_(code, alpha_r4, 48, alpha_r4);
485   alpha_bis(code, alpha_r4, alpha_a0, alpha_a0); // a0 - mono_defaults.exception_class->image
486
487   alpha_mov1(code, alpha_zero, alpha_pv);
488   alpha_lda(code, alpha_r1, alpha_zero,
489             ((unsigned long)mono_exception_from_token)&0xFFFF);
490   alpha_lda(code, alpha_r2, alpha_zero,
491             (((unsigned long)mono_exception_from_token) >> 16)&0xFFFF);
492   alpha_lda(code, alpha_r3, alpha_zero,
493             (((unsigned long)mono_exception_from_token) >> 32)&0xFFFF);
494   alpha_lda(code, alpha_r4, alpha_zero,
495             (((unsigned long)mono_exception_from_token) >> 48)&0xFFFF);
496   alpha_zapnot_(code, alpha_r1, 0x3, alpha_r1);
497   alpha_bis(code, alpha_r1, alpha_pv, alpha_pv);
498
499   alpha_zapnot_(code, alpha_r2, 0x3, alpha_r2);
500   alpha_sll_(code, alpha_r2, 16, alpha_r2);
501   alpha_bis(code, alpha_r2, alpha_pv, alpha_pv);
502
503   alpha_zapnot_(code, alpha_r3, 0x3, alpha_r3);
504   alpha_sll_(code, alpha_r3, 32, alpha_r3);
505   alpha_bis(code, alpha_r3, alpha_pv, alpha_pv);
506
507   alpha_zapnot_(code, alpha_r4, 0x3, alpha_r4);
508   alpha_sll_(code, alpha_r4, 48, alpha_r4);
509   alpha_bis(code, alpha_r4, alpha_pv, alpha_pv); // pv - mono_exception_from_token addr
510
511   alpha_jsr(code, alpha_ra, alpha_pv, 0);
512
513   // R0 holds pointer to initialised exception object
514
515   throw_ex = (guint64)mono_arch_get_throw_exception ();
516
517   alpha_mov1(code, alpha_r0, alpha_a0);
518
519   // Calc return address
520   alpha_mov1(code, alpha_fp, alpha_sp);
521   alpha_ldq(code, alpha_ra, alpha_sp, 0);
522   alpha_ldq(code, alpha_fp, alpha_sp, 8);
523   alpha_ldq(code, alpha_a1, alpha_sp, 16);
524   alpha_addq(code, alpha_ra, alpha_a1, alpha_ra);
525   alpha_ldq(code, alpha_gp, alpha_sp, 24);
526
527   // Modify stack to point to exception caller
528   alpha_lda(code, alpha_sp, alpha_sp, (8*4));
529
530   alpha_mov1(code, alpha_zero, alpha_pv);
531   alpha_lda(code, alpha_r1, alpha_zero,
532             ((unsigned long)throw_ex)&0xFFFF);
533   alpha_lda(code, alpha_r2, alpha_zero,
534             (((unsigned long)throw_ex) >> 16)&0xFFFF);
535   alpha_lda(code, alpha_r3, alpha_zero,
536             (((unsigned long)throw_ex) >> 32)&0xFFFF);
537   alpha_lda(code, alpha_r4, alpha_zero,
538             (((unsigned long)throw_ex) >> 48)&0xFFFF);
539   alpha_zapnot_(code, alpha_r1, 0x3, alpha_r1);
540   alpha_bis(code, alpha_r1, alpha_pv, alpha_pv);
541
542   alpha_zapnot_(code, alpha_r2, 0x3, alpha_r2);
543   alpha_sll_(code, alpha_r2, 16, alpha_r2);
544   alpha_bis(code, alpha_r2, alpha_pv, alpha_pv);
545
546   alpha_zapnot_(code, alpha_r3, 0x3, alpha_r3);
547   alpha_sll_(code, alpha_r3, 32, alpha_r3);
548   alpha_bis(code, alpha_r3, alpha_pv, alpha_pv);
549
550   alpha_zapnot_(code, alpha_r4, 0x3, alpha_r4);
551   alpha_sll_(code, alpha_r4, 48, alpha_r4);
552   alpha_bis(code, alpha_r4, alpha_pv, alpha_pv); // pv - handle_exception addr
553
554   alpha_jmp(code, alpha_zero, alpha_pv, 0);
555
556   g_assert (((char *)code - (char *)start) < 512);
557
558   inited = TRUE;
559
560   return start;
561 }
562
563 /*------------------------------------------------------------------*/
564 /*                                                                  */
565 /* Name         - mono_arch_handle_exception                        */
566 /*                                                                  */
567 /* Function     - Handle an exception raised by the JIT code.       */
568 /*                                                                  */
569 /* Parameters   - ctx       - Saved processor state                 */
570 /*                obj       - The exception object                  */
571 /*                test_only - Only test if the exception is caught, */
572 /*                            but don't call handlers               */
573 /*                                                                  */
574 /*------------------------------------------------------------------*/
575
576 gboolean
577 mono_arch_handle_exception (void *uc, gpointer obj, gboolean test_only)
578 {
579   ALPHA_DEBUG("mono_arch_handle_exception");
580
581   return mono_handle_exception (uc, obj, mono_arch_ip_from_context(uc),
582                                 test_only);
583 }
584
585 /*========================= End of Function ========================*/
586
587 /*------------------------------------------------------------------*/
588 /*                                                                  */
589 /* Name         - mono_arch_get_restore_context                     */
590 /*                                                                  */
591 /* Function     - Return the address of the routine that will rest- */
592 /*                ore the context.                                  */
593 /*                                                                  */
594 /*------------------------------------------------------------------*/
595
596 gpointer
597 mono_arch_get_restore_context ()
598 {
599   static guint8 *start_code = NULL;
600   static gboolean inited = FALSE;
601   unsigned int *code;
602
603   ALPHA_DEBUG("mono_arch_get_restore_context");
604
605   if (inited)
606     return start_code;
607
608   /* restore_contect (MonoContext *ctx) */
609
610   start_code = mono_global_codeman_reserve (30*4);
611
612   code = (unsigned int *)start_code;
613
614   alpha_ldq(code, alpha_r0, alpha_a0,
615             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r0]));
616   alpha_ldq(code, alpha_r1, alpha_a0,
617             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r1]));
618   alpha_ldq(code, alpha_r2, alpha_a0,
619             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r2]));
620   alpha_ldq(code, alpha_r3, alpha_a0,
621             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r3]));
622   alpha_ldq(code, alpha_r4, alpha_a0,
623             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r4]));
624   alpha_ldq(code, alpha_r5, alpha_a0,
625             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r5]));
626   alpha_ldq(code, alpha_r6, alpha_a0,
627             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r6]));
628   alpha_ldq(code, alpha_r7, alpha_a0,
629             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r7]));
630   alpha_ldq(code, alpha_r8, alpha_a0,
631             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r8]));
632   alpha_ldq(code, alpha_r9, alpha_a0,
633             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r9]));
634   alpha_ldq(code, alpha_r10, alpha_a0,
635             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r10]));
636   alpha_ldq(code, alpha_r11, alpha_a0,
637             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r11]));
638   alpha_ldq(code, alpha_r12, alpha_a0,
639             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r12]));
640   alpha_ldq(code, alpha_r13, alpha_a0,
641             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r13]));
642   alpha_ldq(code, alpha_r14, alpha_a0,
643             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r14]));
644   alpha_ldq(code, alpha_r15, alpha_a0,
645             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r15]));
646   alpha_ldq(code, alpha_r22, alpha_a0,
647             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r22]));
648   alpha_ldq(code, alpha_r23, alpha_a0,
649             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r23]));
650   alpha_ldq(code, alpha_r24, alpha_a0,
651             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r24]));
652   alpha_ldq(code, alpha_r25, alpha_a0,
653             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r25]));
654   alpha_ldq(code, alpha_r26, alpha_a0,
655             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r26]));
656   alpha_ldq(code, alpha_r27, alpha_a0,
657             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r27]));
658   alpha_ldq(code, alpha_r28, alpha_a0,
659             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r28]));
660   alpha_ldq(code, alpha_r29, alpha_a0,
661             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r29]));
662   alpha_ldq(code, alpha_r30, alpha_a0,
663             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_regs[alpha_r30]));
664
665   alpha_ldq(code, alpha_ra, alpha_a0,
666             G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_pc));
667
668   alpha_ret(code, alpha_ra, 1);
669
670   inited = TRUE;
671
672   return start_code;
673 }
674
675 /*========================= End of Function ========================*/
676
677 /*------------------------------------------------------------------*/
678 /*                                                                  */
679 /* Name         - mono_arch_ip_from_context                         */
680 /*                                                                  */
681 /* Function     - Return the instruction pointer from the context.  */
682 /*                                                                  */
683 /* Parameters   - sigctx    - Saved processor state                 */
684 /*                                                                  */
685 /*------------------------------------------------------------------*/
686
687 gpointer
688 mono_arch_ip_from_context (void *sigctx)
689 {
690   gpointer ip;
691   ALPHA_DEBUG("mono_arch_ip_from_context");
692
693   ip = (gpointer) MONO_CONTEXT_GET_IP(((MonoContext *) sigctx));
694
695   printf("ip_from_context = %p\n", ip);
696
697   return ip;
698 }
699
700
701 /*========================= End of Function ========================*/
702
703 /*------------------------------------------------------------------*/
704 /*                                                                  */
705 /* Name         - arch_get_rethrow_exception                        */
706 /*                                                                  */
707 /* Function     - Return a function pointer which can be used to    */
708 /*                raise exceptions. The returned function has the   */
709 /*                following signature:                              */
710 /*                void (*func) (MonoException *exc);                */
711 /*                                                                  */
712 /*------------------------------------------------------------------*/
713
714 gpointer
715 mono_arch_get_rethrow_exception (void)
716 {
717   static guint8 *start;
718   static int inited = 0;
719
720   ALPHA_DEBUG("mono_arch_get_rethrow_exception");
721
722   if (inited)
723     return start;
724
725   start = get_throw_trampoline (TRUE);
726
727   inited = 1;
728
729   return start;
730 }
731
732 /*========================= End of Function ========================*/
733
734 /*------------------------------------------------------------------*/
735 /*                                                                  */
736 /* Name         - arch_get_throw_exception_by_name                  */
737 /*                                                                  */
738 /* Function     - Return a function pointer which can be used to    */
739 /*                raise corlib exceptions. The return function has  */
740 /*                the following signature:                          */
741 /*                void (*func) (char *exc_name);                    */
742 /*                                                                  */
743 /*------------------------------------------------------------------*/
744
745 gpointer
746 mono_arch_get_throw_exception_by_name (void)
747 {
748   static guint8 *start;
749   static int inited = 0;
750   unsigned int *code;
751   
752   if (inited)
753     return start;
754
755   start = mono_global_codeman_reserve (SZ_THROW);
756   //        get_throw_exception_generic (start, SZ_THROW, TRUE, FALSE);
757   inited = 1;
758
759   code = (unsigned int *)start;
760
761   alpha_call_pal(code, 0x80);
762
763   return start;
764 }
765 /*========================= End of Function ========================*/
766
767 /*------------------------------------------------------------------*/
768 /*                                                                  */
769 /* Name         - mono_arch_find_jit_info                           */
770 /*                                                                  */
771 /* Function     - This function is used to gather informatoin from  */
772 /*                @ctx. It returns the MonoJitInfo of the corres-   */
773 /*                ponding function, unwinds one stack frame and     */
774 /*                stores the resulting context into @new_ctx. It    */
775 /*                also stores a string describing the stack location*/
776 /*                into @trace (if not NULL), and modifies the @lmf  */
777 /*                if necessary. @native_offset returns the IP off-  */
778 /*                set from the start of the function or -1 if that  */
779 /*                information is not available.                     */
780 /*                                                                  */
781 /*------------------------------------------------------------------*/
782
783 MonoJitInfo *
784 mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls,
785                          MonoJitInfo *res, MonoJitInfo *prev_ji,
786                          MonoContext *ctx,
787                          MonoContext *new_ctx, char **trace, MonoLMF **lmf,
788                          int *native_offset, gboolean *managed)
789 {
790   MonoJitInfo *ji;
791   int i;
792   gpointer ip = MONO_CONTEXT_GET_IP (ctx);
793
794   ALPHA_DEBUG("mono_arch_find_jit_info");
795
796   /* Avoid costly table lookup during stack overflow */
797   if (prev_ji &&
798       (ip > prev_ji->code_start &&
799        ((guint8*)ip < ((guint8*)prev_ji->code_start) + prev_ji->code_size)))
800     ji = prev_ji;
801   else
802     ji = mono_jit_info_table_find (domain, ip);
803
804   if (managed)
805     *managed = FALSE;
806
807   if (ji != NULL)
808     {
809       int offset;
810       gboolean omit_fp = 0; //(ji->used_regs & (1 << 31)) > 0;
811
812       *new_ctx = *ctx;
813
814       if (managed)
815         if (!ji->method->wrapper_type)
816           *managed = TRUE;
817
818       /*
819        * Some managed methods like pinvoke wrappers might have save_lmf set.
820        * In this case, register save/restore code is not generated by the
821        * JIT, so we have to restore callee saved registers from the lmf.
822        */
823
824       if (ji->method->save_lmf)
825         {
826           /*
827            * We only need to do this if the exception was raised in managed
828            * code, since otherwise the lmf was already popped of the stack.
829            */
830           if (*lmf && ((*lmf) != jit_tls->first_lmf) &&
831               (MONO_CONTEXT_GET_SP (ctx) >= (gpointer)(*lmf)->rsp))
832             {
833               new_ctx->uc_mcontext.sc_regs[alpha_fp] = (*lmf)->ebp;
834               new_ctx->uc_mcontext.sc_regs[alpha_sp] = (*lmf)->rsp;
835               new_ctx->uc_mcontext.sc_regs[alpha_gp] = (*lmf)->rgp;
836
837               /*
838               new_ctx->rbp = (*lmf)->ebp;
839               new_ctx->rbx = (*lmf)->rbx;
840               new_ctx->rsp = (*lmf)->rsp;
841               new_ctx->r12 = (*lmf)->r12;
842               new_ctx->r13 = (*lmf)->r13;
843               new_ctx->r14 = (*lmf)->r14;
844               new_ctx->r15 = (*lmf)->r15;
845               */
846             }
847         }
848       else
849         {
850           offset = omit_fp ? 0 : 2;
851
852           /* restore caller saved registers */
853           for (i = 0; i < MONO_MAX_IREGS; i++)
854             if (ALPHA_IS_CALLEE_SAVED_REG(i) &&
855                 (ji->used_regs & (1 << i)))
856               {
857
858                 guint64 reg;
859 #if 0
860                 if (omit_fp)
861                   {
862                     reg = *((guint64*)ctx->rsp + offset);
863                     offset++;
864                   }
865                 else
866                   {
867                     //reg = *((guint64 *)ctx->SC_EBP + offset);
868                     //offset--;
869                   }
870
871                 switch (i)
872                   {
873                   case AMD64_RBX:
874                     new_ctx->rbx = reg;
875                     break;
876                   case AMD64_R12:
877                     new_ctx->r12 = reg;
878                     break;
879                   case AMD64_R13:
880                     new_ctx->r13 = reg;
881                     break;
882                   case AMD64_R14:
883                     new_ctx->r14 = reg;
884                     break;
885                   case AMD64_R15:
886                     new_ctx->r15 = reg;
887                     break;
888                   case AMD64_RBP:
889                     new_ctx->rbp = reg;
890                     break;
891                   default:
892                     g_assert_not_reached ();
893                   }
894 #endif
895               }
896         }
897
898       if (*lmf && ((*lmf) != jit_tls->first_lmf) &&
899           (MONO_CONTEXT_GET_SP (ctx) >= (gpointer)(*lmf)->rsp)) {
900         /* remove any unused lmf */
901         *lmf = (*lmf)->previous_lmf;
902       }
903
904 #if 0
905       if (omit_fp)
906         {
907           /* Pop frame */
908           new_ctx->rsp += (ji->used_regs >> 16) & (0x7fff);
909           new_ctx->SC_EIP = *((guint64 *)new_ctx->rsp) - 1;
910           /* Pop return address */
911           new_ctx->rsp += 8;
912         }
913       else
914 #endif
915         {
916
917           /* Pop FP and the RA */
918           /* Some how we should find size of frame. One way:
919            read 3rd instruction (alpha_lda(alpha_sp, alpha_sp, -stack_size ))
920            and extract "stack_size" from there
921            read 4th and 5th insts to get offsets to saved RA & FP
922           */
923           unsigned int *code = (unsigned int *)ji->code_start;
924           short stack_size = -((short)(code[2] & 0xFFFF));
925           short ra_off = code[3] & 0xFFFF;
926           short fp_off = code[4] & 0xFFFF;
927
928           /* Restore stack - value of FP reg + stack_size */
929           new_ctx->uc_mcontext.sc_regs[alpha_sp] =
930             ctx->uc_mcontext.sc_regs[alpha_r15] + stack_size;
931
932           /* we substract 1, so that the IP points into the call instruction */
933           /* restore PC - @FP + 0 */
934           new_ctx->uc_mcontext.sc_pc = 
935             *((guint64 *)(ctx->uc_mcontext.sc_regs[alpha_r15] + ra_off));
936           
937           /* Restore FP reg - @FP + 8 */
938           new_ctx->uc_mcontext.sc_regs[alpha_r15] = 
939             *((guint64 *)(ctx->uc_mcontext.sc_regs[alpha_r15] + fp_off));
940
941           /* Restore GP - read two insts that restore GP from sc_pc and */
942           /* do the same. Use sc_pc as RA */
943           code = (unsigned int *)new_ctx->uc_mcontext.sc_pc;
944           if ((code[0] & 0xFFFF0000) == 0x27ba0000 &&   // ldah    gp,high_off(ra)
945               (code[1] & 0xFFFF0000) == 0x23bd0000)     // lda     gp,low_off(gp)
946             {
947               short high_off = (short)(code[0] & 0xFFFF);
948               short low_off = (short)(code[1] & 0xFFFF);
949
950               long rgp = new_ctx->uc_mcontext.sc_pc +
951                 (65536 * high_off) + low_off;
952
953               new_ctx->uc_mcontext.sc_regs[alpha_gp] = rgp;
954             }
955         }
956
957 #if 0
958       /* Pop arguments off the stack */
959       // No poping args off stack on Alpha
960       // We use fixed place
961       {
962         MonoJitArgumentInfo *arg_info =
963           g_newa (MonoJitArgumentInfo,
964                   mono_method_signature (ji->method)->param_count + 1);
965
966         guint32 stack_to_pop =
967           mono_arch_get_argument_info (mono_method_signature (ji->method),
968                                        mono_method_signature (ji->method)->param_count,
969                                        arg_info);
970         new_ctx->uc_mcontext.sc_regs[alpha_sp] += stack_to_pop;
971       }
972 #endif
973       return ji;
974     }
975   else if (*lmf)
976     {
977       // Unwind based on LMF info
978       if (!(*lmf)->method)
979         return (gpointer)-1;
980
981       if ((ji = mono_jit_info_table_find (domain, (gpointer)(*lmf)->eip))) {
982       } else {
983         memset (res, 0, sizeof (MonoJitInfo));
984         res->method = (*lmf)->method;
985       }
986
987       new_ctx->uc_mcontext.sc_regs[alpha_fp] = (*lmf)->ebp;
988       new_ctx->uc_mcontext.sc_regs[alpha_sp] = (*lmf)->rsp;
989       new_ctx->uc_mcontext.sc_regs[alpha_gp] = (*lmf)->rgp;
990       new_ctx->uc_mcontext.sc_pc = (*lmf)->eip;
991
992       *lmf = (*lmf)->previous_lmf;
993
994       return ji ? ji : res;
995     }
996
997   return NULL;
998 }
999
1000 /*========================= End of Function ========================*/
1001
1002