1 /*------------------------------------------------------------------*/
3 /* Name - exceptions-alpha.c */
5 /* Function - Exception support for Alpha. */
7 /* Name - Sergey Tikhonov (tsv@solvo.ru) */
9 /* Date - January, 2006 */
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) */
17 /*------------------------------------------------------------------*/
19 /*------------------------------------------------------------------*/
21 /*------------------------------------------------------------------*/
22 #define NOT_IMPLEMENTED(x) \
23 g_error ("FIXME: %s is not yet implemented.", x);
25 #define ALPHA_DEBUG(x) \
26 if (mini_alpha_verbose_level) \
27 g_debug ("ALPHA_DEBUG: %s is called.", x);
29 #define ALPHA_PRINT if (mini_alpha_verbose_level)
33 extern int mini_alpha_verbose_level;
35 /*========================= End of Defines =========================*/
38 /*------------------------------------------------------------------*/
40 /*------------------------------------------------------------------*/
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>
57 #include "mini-alpha.h"
59 /*========================= End of Includes ========================*/
61 /*------------------------------------------------------------------*/
63 /* Name - mono_arch_get_call_filter */
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). */
70 /*------------------------------------------------------------------*/
73 mono_arch_get_call_filter (void)
75 static gboolean inited = FALSE;
76 static unsigned int *start_code;
79 ALPHA_DEBUG("mono_arch_get_call_filter");
84 start_code = code = mono_global_codeman_reserve (128 * 4);
86 /* call_filter (MonoContext *ctx, unsigned long eip) */
89 alpha_ldah( code, alpha_gp, alpha_pv, 0 );
90 alpha_lda( code, alpha_gp, alpha_gp, 0 ); // ldgp gp, 0(pv)
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);
97 /* set the frame pointer */
98 alpha_mov1( code, alpha_sp, alpha_fp );
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)));
124 /* Load regs from ctx */
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]));
173 alpha_mov1(code, alpha_a1, alpha_pv);
175 /* call the handler */
176 alpha_jsr(code, alpha_ra, alpha_pv, 0);
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)));
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
206 alpha_ret(code, alpha_ra, 1);
210 g_assert (( ((char *)code) - (char *)start_code) < 128 * 4);
215 /*========================= End of Function ========================*/
217 /*------------------------------------------------------------------*/
219 /* Name - arch_get_throw_exception */
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); */
226 /*------------------------------------------------------------------*/
228 static void throw_exception(MonoException *exc, unsigned long RA,
229 unsigned long *SP, unsigned long rethrow)
231 static void (*restore_context) (MonoContext *);
233 unsigned long *LSP = SP - 24;
235 //g_print("ALPHA: throw_exception - Exc: %p, RA: %0lX, SP: %p\n",
238 if (!restore_context)
239 restore_context = mono_arch_get_restore_context ();
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];
267 ctx.uc_mcontext.sc_regs[alpha_r30] = (unsigned long)SP;
268 ctx.uc_mcontext.sc_pc = RA;
270 if (mono_object_isinst (exc, mono_defaults.exception_class))
272 MonoException *mono_ex = (MonoException*)exc;
274 mono_ex->stack_trace = NULL;
277 mono_handle_exception (&ctx, exc, (gpointer)RA, FALSE);
279 restore_context(&ctx);
281 g_assert_not_reached ();
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
301 get_throw_trampoline (gboolean rethrow)
306 start_code = mono_global_codeman_reserve (46*4);
308 code = (unsigned int *)start_code;
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
315 alpha_lda(code, alpha_a3, alpha_zero, 1);
317 alpha_mov1(code, alpha_zero, alpha_a3);
319 alpha_lda(code, alpha_sp, alpha_sp, -(24*8)); // Allocate stack for regs
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);
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);
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);
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);
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
370 alpha_jmp(code, alpha_zero, alpha_pv, 0);
372 // alpha_break(code);
374 g_assert (( ((char *)code) - (char *)start_code) < 46 * 4);
380 * mono_arch_get_throw_exception:
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);
388 mono_arch_get_throw_exception (void)
390 static guint8* start;
391 static gboolean inited = FALSE;
393 ALPHA_DEBUG("mono_arch_get_throw_exception");
398 start = get_throw_trampoline (FALSE);
404 /*========================= End of Function ========================*/
408 * mono_arch_get_throw_corlib_exception:
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.
418 mono_arch_get_throw_corlib_exception (void)
420 static guint8* start;
421 static gboolean inited = FALSE;
425 ALPHA_DEBUG("mono_arch_get_throw_corlib_exception");
430 start = mono_global_codeman_reserve (512);
432 code = (unsigned int *)start;
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)
439 // The trampoline code will be called with PV set
440 // so expect correct ABI handling
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));
447 alpha_stq(code, alpha_gp, alpha_sp, 24);
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
453 /* set the frame pointer */
454 alpha_mov1(code, alpha_sp, alpha_fp );
456 // Store throw_ip offset
457 alpha_stq(code, alpha_a1, alpha_fp, 16);
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);
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);
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);
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);
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
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);
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);
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);
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
511 alpha_jsr(code, alpha_ra, alpha_pv, 0);
513 // R0 holds pointer to initialised exception object
515 throw_ex = (guint64)mono_arch_get_throw_exception ();
517 alpha_mov1(code, alpha_r0, alpha_a0);
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);
527 // Modify stack to point to exception caller
528 alpha_lda(code, alpha_sp, alpha_sp, (8*4));
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);
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);
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);
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
554 alpha_jmp(code, alpha_zero, alpha_pv, 0);
556 g_assert (((char *)code - (char *)start) < 512);
563 /*------------------------------------------------------------------*/
565 /* Name - mono_arch_handle_exception */
567 /* Function - Handle an exception raised by the JIT code. */
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 */
574 /*------------------------------------------------------------------*/
577 mono_arch_handle_exception (void *uc, gpointer obj, gboolean test_only)
579 ALPHA_DEBUG("mono_arch_handle_exception");
581 return mono_handle_exception (uc, obj, mono_arch_ip_from_context(uc),
585 /*========================= End of Function ========================*/
587 /*------------------------------------------------------------------*/
589 /* Name - mono_arch_get_restore_context */
591 /* Function - Return the address of the routine that will rest- */
592 /* ore the context. */
594 /*------------------------------------------------------------------*/
597 mono_arch_get_restore_context ()
599 static guint8 *start_code = NULL;
600 static gboolean inited = FALSE;
603 ALPHA_DEBUG("mono_arch_get_restore_context");
608 /* restore_contect (MonoContext *ctx) */
610 start_code = mono_global_codeman_reserve (30*4);
612 code = (unsigned int *)start_code;
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]));
665 alpha_ldq(code, alpha_ra, alpha_a0,
666 G_STRUCT_OFFSET(MonoContext, uc_mcontext.sc_pc));
668 alpha_ret(code, alpha_ra, 1);
675 /*========================= End of Function ========================*/
677 /*------------------------------------------------------------------*/
679 /* Name - mono_arch_ip_from_context */
681 /* Function - Return the instruction pointer from the context. */
683 /* Parameters - sigctx - Saved processor state */
685 /*------------------------------------------------------------------*/
688 mono_arch_ip_from_context (void *sigctx)
691 ALPHA_DEBUG("mono_arch_ip_from_context");
693 ip = (gpointer) MONO_CONTEXT_GET_IP(((MonoContext *) sigctx));
695 printf("ip_from_context = %p\n", ip);
701 /*========================= End of Function ========================*/
703 /*------------------------------------------------------------------*/
705 /* Name - arch_get_rethrow_exception */
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); */
712 /*------------------------------------------------------------------*/
715 mono_arch_get_rethrow_exception (void)
717 static guint8 *start;
718 static int inited = 0;
720 ALPHA_DEBUG("mono_arch_get_rethrow_exception");
725 start = get_throw_trampoline (TRUE);
732 /*========================= End of Function ========================*/
734 /*------------------------------------------------------------------*/
736 /* Name - arch_get_throw_exception_by_name */
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); */
743 /*------------------------------------------------------------------*/
746 mono_arch_get_throw_exception_by_name (void)
748 static guint8 *start;
749 static int inited = 0;
755 start = mono_global_codeman_reserve (SZ_THROW);
756 // get_throw_exception_generic (start, SZ_THROW, TRUE, FALSE);
759 code = (unsigned int *)start;
761 alpha_call_pal(code, 0x80);
765 /*========================= End of Function ========================*/
767 /*------------------------------------------------------------------*/
769 /* Name - mono_arch_find_jit_info */
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. */
781 /*------------------------------------------------------------------*/
784 mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls,
785 MonoJitInfo *res, MonoJitInfo *prev_ji,
787 MonoContext *new_ctx, char **trace, MonoLMF **lmf,
788 int *native_offset, gboolean *managed)
792 gpointer ip = MONO_CONTEXT_GET_IP (ctx);
794 ALPHA_DEBUG("mono_arch_find_jit_info");
796 /* Avoid costly table lookup during stack overflow */
798 (ip > prev_ji->code_start &&
799 ((guint8*)ip < ((guint8*)prev_ji->code_start) + prev_ji->code_size)))
802 ji = mono_jit_info_table_find (domain, ip);
810 gboolean omit_fp = 0; //(ji->used_regs & (1 << 31)) > 0;
815 if (!ji->method->wrapper_type)
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.
824 if (ji->method->save_lmf)
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.
830 if (*lmf && ((*lmf) != jit_tls->first_lmf) &&
831 (MONO_CONTEXT_GET_SP (ctx) >= (gpointer)(*lmf)->rsp))
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;
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;
850 offset = omit_fp ? 0 : 2;
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)))
862 reg = *((guint64*)ctx->rsp + offset);
867 //reg = *((guint64 *)ctx->SC_EBP + offset);
892 g_assert_not_reached ();
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;
908 new_ctx->rsp += (ji->used_regs >> 16) & (0x7fff);
909 new_ctx->SC_EIP = *((guint64 *)new_ctx->rsp) - 1;
910 /* Pop return address */
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
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;
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;
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));
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));
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)
947 short high_off = (short)(code[0] & 0xFFFF);
948 short low_off = (short)(code[1] & 0xFFFF);
950 long rgp = new_ctx->uc_mcontext.sc_pc +
951 (65536 * high_off) + low_off;
953 new_ctx->uc_mcontext.sc_regs[alpha_gp] = rgp;
958 /* Pop arguments off the stack */
959 // No poping args off stack on Alpha
960 // We use fixed place
962 MonoJitArgumentInfo *arg_info =
963 g_newa (MonoJitArgumentInfo,
964 mono_method_signature (ji->method)->param_count + 1);
966 guint32 stack_to_pop =
967 mono_arch_get_argument_info (mono_method_signature (ji->method),
968 mono_method_signature (ji->method)->param_count,
970 new_ctx->uc_mcontext.sc_regs[alpha_sp] += stack_to_pop;
977 // Unwind based on LMF info
981 if ((ji = mono_jit_info_table_find (domain, (gpointer)(*lmf)->eip))) {
983 memset (res, 0, sizeof (MonoJitInfo));
984 res->method = (*lmf)->method;
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;
992 *lmf = (*lmf)->previous_lmf;
994 return ji ? ji : res;
1000 /*========================= End of Function ========================*/