Transition s390/mips/ia64 to use mono_arch_find_jit_info_ext.
[mono.git] / mono / mini / exceptions-s390x.c
1 /*------------------------------------------------------------------*/
2 /*                                                                  */
3 /* Name        - exceptions-s390.c                                  */
4 /*                                                                  */
5 /* Function    - Exception support for S/390.                       */
6 /*                                                                  */
7 /* Name        - Neale Ferguson (Neale.Ferguson@SoftwareAG-usa.com) */
8 /*                                                                  */
9 /* Date        - January, 2004                                      */
10 /*                                                                  */
11 /* Derivation  - From exceptions-x86 & exceptions-ppc               */
12 /*               Paolo Molaro (lupus@ximian.com)                    */
13 /*               Dietmar Maurer (dietmar@ximian.com)                */
14 /*                                                                  */
15 /* Copyright   - 2001 Ximian, Inc.                                  */
16 /*                                                                  */
17 /*------------------------------------------------------------------*/
18
19 /*------------------------------------------------------------------*/
20 /*                 D e f i n e s                                    */
21 /*------------------------------------------------------------------*/
22
23 #define S390_CALLFILTER_INTREGS         S390_MINIMAL_STACK_SIZE
24 #define S390_CALLFILTER_FLTREGS         (S390_CALLFILTER_INTREGS+(16*sizeof(gulong)))
25 #define S390_CALLFILTER_ACCREGS         (S390_CALLFILTER_FLTREGS+(16*sizeof(gdouble)))
26 #define S390_CALLFILTER_SIZE            (S390_CALLFILTER_ACCREGS+(16*sizeof(gint32)))
27
28 #define S390_THROWSTACK_ACCPRM          S390_MINIMAL_STACK_SIZE
29 #define S390_THROWSTACK_FPCPRM          (S390_THROWSTACK_ACCPRM+sizeof(gpointer))
30 #define S390_THROWSTACK_RETHROW         (S390_THROWSTACK_FPCPRM+sizeof(gulong))
31 #define S390_THROWSTACK_INTREGS         (S390_THROWSTACK_RETHROW+sizeof(gboolean))
32 #define S390_THROWSTACK_FLTREGS         (S390_THROWSTACK_INTREGS+(16*sizeof(gulong)))
33 #define S390_THROWSTACK_ACCREGS         (S390_THROWSTACK_FLTREGS+(16*sizeof(gdouble)))
34 #define S390_THROWSTACK_SIZE            (S390_THROWSTACK_ACCREGS+(16*sizeof(gint32)))
35
36 #define SZ_THROW        384
37
38 /*========================= End of Defines =========================*/
39
40 /*------------------------------------------------------------------*/
41 /*                 I n c l u d e s                                  */
42 /*------------------------------------------------------------------*/
43
44 #include <config.h>
45 #include <glib.h>
46 #include <signal.h>
47 #include <string.h>
48 #include <ucontext.h>
49
50 #include <mono/arch/s390x/s390x-codegen.h>
51 #include <mono/metadata/appdomain.h>
52 #include <mono/metadata/tabledefs.h>
53 #include <mono/metadata/threads.h>
54 #include <mono/metadata/debug-helpers.h>
55 #include <mono/metadata/exception.h>
56 #include <mono/metadata/mono-debug.h>
57
58 #include "mini.h"
59 #include "mini-s390x.h"
60
61 /*========================= End of Includes ========================*/
62
63 /*------------------------------------------------------------------*/
64 /*                   P r o t o t y p e s                            */
65 /*------------------------------------------------------------------*/
66
67 gboolean mono_arch_handle_exception (void     *ctx,
68                                      gpointer obj, 
69                                      gboolean test_only);
70
71 /*========================= End of Prototypes ======================*/
72
73 /*------------------------------------------------------------------*/
74 /*                 G l o b a l   V a r i a b l e s                  */
75 /*------------------------------------------------------------------*/
76
77 typedef enum {
78         by_none,
79         by_token
80 } throwType;
81
82 /*====================== End of Global Variables ===================*/
83
84 /*------------------------------------------------------------------*/
85 /*                                                                  */
86 /* Name         - mono_arch_has_unwind_info                         */
87 /*                                                                  */
88 /* Function     - Tests if a function has a DWARF exception table   */
89 /*                that is able to restore all caller saved registers*/
90 /*                                                                  */
91 /*------------------------------------------------------------------*/
92
93 gboolean
94 mono_arch_has_unwind_info (gconstpointer addr)
95 {
96         return FALSE;
97 }
98
99 /*========================= End of Function ========================*/
100
101 /*------------------------------------------------------------------*/
102 /*                                                                  */
103 /* Name         - mono_arch_get_call_filter                         */
104 /*                                                                  */
105 /* Function     - Return a pointer to a method which calls an       */
106 /*                exception filter. We also use this function to    */
107 /*                call finally handlers (we pass NULL as @exc       */
108 /*                object in this case).                             */
109 /*                                                                  */
110 /*------------------------------------------------------------------*/
111
112 gpointer
113 mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
114 {
115         static guint8 *start;
116         static int inited = 0;
117         guint8 *code;
118         int alloc_size, pos, i;
119
120         g_assert (!aot);
121         if (info)
122                 *info = NULL;
123
124         if (inited)
125                 return start;
126
127         inited = 1;
128         /* call_filter (MonoContext *ctx, unsigned long eip, gpointer exc) */
129         code = start = mono_global_codeman_reserve (512);
130
131         s390_stmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
132         s390_lgr  (code, s390_r14, STK_BASE);
133         alloc_size = S390_ALIGN(S390_CALLFILTER_SIZE, S390_STACK_ALIGNMENT);
134         s390_aghi (code, STK_BASE, -alloc_size);
135         s390_stg  (code, s390_r14, 0, STK_BASE, 0);
136
137         /*------------------------------------------------------*/
138         /* save general registers on stack                      */
139         /*------------------------------------------------------*/
140         s390_stmg (code, s390_r0, STK_BASE, STK_BASE, S390_CALLFILTER_INTREGS);
141
142         /*------------------------------------------------------*/
143         /* save floating point registers on stack               */
144         /*------------------------------------------------------*/
145         pos = S390_CALLFILTER_FLTREGS;
146         for (i = 0; i < 16; ++i) {
147                 s390_std (code, i, 0, STK_BASE, pos);
148                 pos += sizeof (gdouble);
149         }
150
151         /*------------------------------------------------------*/
152         /* save access registers on stack                       */
153         /*------------------------------------------------------*/
154         s390_stam (code, s390_a0, s390_a15, STK_BASE, S390_CALLFILTER_ACCREGS);
155
156         /*------------------------------------------------------*/
157         /* Get A(Context)                                       */
158         /*------------------------------------------------------*/
159         s390_lgr  (code, s390_r13, s390_r2);
160
161         /*------------------------------------------------------*/
162         /* Get A(Handler Entry Point)                           */
163         /*------------------------------------------------------*/
164         s390_lgr  (code, s390_r0, s390_r3);
165
166         /*------------------------------------------------------*/
167         /* Set parameter register with Exception                */
168         /*------------------------------------------------------*/
169         s390_lgr  (code, s390_r2, s390_r4);
170
171         /*------------------------------------------------------*/
172         /* Load all registers with values from the context      */
173         /*------------------------------------------------------*/
174         s390_lmg  (code, s390_r3, s390_r12, s390_r13, 
175                    G_STRUCT_OFFSET(MonoContext, uc_mcontext.gregs[3]));
176         pos = G_STRUCT_OFFSET(MonoContext, uc_mcontext.fpregs.fprs[0]);
177         for (i = 0; i < 16; ++i) {
178                 s390_ld  (code, i, 0, s390_r13, pos);
179                 pos += sizeof(gdouble);
180         }
181         
182         /*------------------------------------------------------*/
183         /* Go call filter                                       */
184         /*------------------------------------------------------*/
185         s390_lgr  (code, s390_r1, s390_r0);
186         s390_basr (code, s390_r14, s390_r1);
187
188         /*------------------------------------------------------*/
189         /* Save return value                                    */
190         /*------------------------------------------------------*/
191         s390_lgr  (code, s390_r14, s390_r2);
192
193         /*------------------------------------------------------*/
194         /* Restore all the regs from the stack                  */
195         /*------------------------------------------------------*/
196         s390_lmg  (code, s390_r0, s390_r13, STK_BASE, S390_CALLFILTER_INTREGS);
197         pos = S390_CALLFILTER_FLTREGS;
198         for (i = 0; i < 16; ++i) {
199                 s390_ld (code, i, 0, STK_BASE, pos);
200                 pos += sizeof (gdouble);
201         }
202
203         s390_lgr  (code, s390_r2, s390_r14);
204         s390_lam  (code, s390_a0, s390_a15, STK_BASE, S390_CALLFILTER_ACCREGS);
205         s390_aghi (code, s390_r15, alloc_size);
206         s390_lmg  (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
207         s390_br   (code, s390_r14);
208
209         g_assert ((code - start) < SZ_THROW); 
210         return start;
211 }
212
213 /*========================= End of Function ========================*/
214
215 /*------------------------------------------------------------------*/
216 /*                                                                  */
217 /* Name         - throw_exception.                                  */
218 /*                                                                  */
219 /* Function     - Raise an exception based on the parameters passed.*/
220 /*                                                                  */
221 /*------------------------------------------------------------------*/
222
223 static void
224 throw_exception (MonoObject *exc, unsigned long ip, unsigned long sp, 
225                  gulong *int_regs, gdouble *fp_regs, gint32 *acc_regs, 
226                  guint fpc, gboolean rethrow)
227 {
228         MonoContext ctx;
229         int iReg;
230         static void (*restore_context) (MonoContext *);
231
232         if (!restore_context)
233                 restore_context = mono_get_restore_context();
234         
235         memset(&ctx, 0, sizeof(ctx));
236
237         getcontext(&ctx);
238
239         /* adjust eip so that it point into the call instruction */
240         ip -= 2;
241
242         for (iReg = 0; iReg < 16; iReg++) {
243                 ctx.uc_mcontext.gregs[iReg]         = int_regs[iReg];
244                 ctx.uc_mcontext.fpregs.fprs[iReg].d = fp_regs[iReg];
245                 ctx.uc_mcontext.aregs[iReg]         = acc_regs[iReg];
246         }
247
248         ctx.uc_mcontext.fpregs.fpc = fpc;
249
250         MONO_CONTEXT_SET_BP (&ctx, sp);
251         MONO_CONTEXT_SET_IP (&ctx, ip);
252         
253         if (mono_object_isinst (exc, mono_defaults.exception_class)) {
254                 MonoException *mono_ex = (MonoException*)exc;
255                 if (!rethrow)
256                         mono_ex->stack_trace = NULL;
257         }
258         mono_arch_handle_exception (&ctx, exc, FALSE);
259         restore_context(&ctx);
260
261         g_assert_not_reached ();
262 }
263
264 /*========================= End of Function ========================*/
265
266 /*------------------------------------------------------------------*/
267 /*                                                                  */
268 /* Name         - get_throw_exception_generic                       */
269 /*                                                                  */
270 /* Function     - Return a function pointer which can be used to    */
271 /*                raise exceptions. The returned function has the   */
272 /*                following signature:                              */
273 /*                void (*func) (MonoException *exc); or,            */
274 /*                void (*func) (char *exc_name);                    */
275 /*                                                                  */
276 /*------------------------------------------------------------------*/
277
278 static gpointer 
279 mono_arch_get_throw_exception_generic (int size, MonoTrampInfo **info, 
280                                 int corlib, gboolean rethrow, gboolean aot)
281 {
282         guint8 *code, *start;
283         int alloc_size, pos, i;
284
285         code = start = mono_global_codeman_reserve(size);
286
287         s390_stmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
288         alloc_size = S390_ALIGN(S390_THROWSTACK_SIZE, S390_STACK_ALIGNMENT);
289         s390_lgr  (code, s390_r14, STK_BASE);
290         s390_aghi (code, STK_BASE, -alloc_size);
291         s390_stg  (code, s390_r14, 0, STK_BASE, 0);
292         s390_lgr  (code, s390_r3, s390_r2);
293         if (corlib) {
294                 s390_basr (code, s390_r13, 0);
295                 s390_j    (code, 10);
296                 s390_llong(code, mono_defaults.exception_class->image);
297                 s390_llong(code, mono_exception_from_token);
298                 s390_lg   (code, s390_r2, 0, s390_r13, 4);
299                 s390_lg   (code, s390_r1, 0, s390_r13, 12);
300                 s390_basr (code, s390_r14, s390_r1);
301         }
302
303         /*------------------------------------------------------*/
304         /* save the general registers on the stack              */
305         /*------------------------------------------------------*/
306         s390_stmg (code, s390_r0, s390_r13, STK_BASE, S390_THROWSTACK_INTREGS);
307
308         s390_lgr  (code, s390_r1, STK_BASE);
309         s390_aghi (code, s390_r1, alloc_size);
310         /*------------------------------------------------------*/
311         /* save the return address in the parameter register    */
312         /*------------------------------------------------------*/
313         s390_lg   (code, s390_r3, 0, s390_r1, S390_RET_ADDR_OFFSET);
314
315         /*------------------------------------------------------*/
316         /* save the floating point registers                    */
317         /*------------------------------------------------------*/
318         pos = S390_THROWSTACK_FLTREGS;
319         for (i = 0; i < 16; ++i) {
320                 s390_std (code, i, 0, STK_BASE, pos);
321                 pos += sizeof (gdouble);
322         }
323         /*------------------------------------------------------*/
324         /* save the access registers                            */
325         /*------------------------------------------------------*/
326         s390_stam (code, s390_r0, s390_r15, STK_BASE, S390_THROWSTACK_ACCREGS);
327
328         /*------------------------------------------------------*/
329         /* call throw_exception (tkn, ip, sp, gr, fr, ar, re)   */
330         /* - r2 already contains *exc                           */
331         /*------------------------------------------------------*/
332         s390_lgr  (code, s390_r4, s390_r1);        /* caller sp */
333
334         /*------------------------------------------------------*/
335         /* pointer to the saved int regs                        */
336         /*------------------------------------------------------*/
337         s390_la   (code, s390_r5, 0, STK_BASE, S390_THROWSTACK_INTREGS);
338         s390_la   (code, s390_r6, 0, STK_BASE, S390_THROWSTACK_FLTREGS);
339         s390_la   (code, s390_r7, 0, STK_BASE, S390_THROWSTACK_ACCREGS);
340         s390_stg  (code, s390_r7, 0, STK_BASE, S390_THROWSTACK_ACCPRM);
341         s390_stfpc(code, STK_BASE, S390_THROWSTACK_FPCPRM+4);
342         s390_lghi (code, s390_r7, rethrow);
343         s390_stg  (code, s390_r7, 0, STK_BASE, S390_THROWSTACK_RETHROW);
344         s390_basr (code, s390_r13, 0);
345         s390_j    (code, 6);
346         s390_llong(code, throw_exception);
347         s390_lg   (code, s390_r1, 0, s390_r13, 4);
348         s390_basr (code, s390_r14, s390_r1);
349         /* we should never reach this breakpoint */
350         s390_break (code);
351         g_assert ((code - start) < size);
352         return start;
353 }
354
355 /*========================= End of Function ========================*/
356
357 /*------------------------------------------------------------------*/
358 /*                                                                  */
359 /* Name         - arch_get_throw_exception                          */
360 /*                                                                  */
361 /* Function     - Return a function pointer which can be used to    */
362 /*                raise exceptions. The returned function has the   */
363 /*                following signature:                              */
364 /*                void (*func) (MonoException *exc);                */
365 /*                                                                  */
366 /*------------------------------------------------------------------*/
367
368 gpointer
369 mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot)
370 {
371
372         g_assert (!aot);
373         if (info)
374                 *info = NULL;
375
376         return (mono_arch_get_throw_exception_generic (SZ_THROW, info, FALSE, FALSE, aot));
377 }
378
379 /*========================= End of Function ========================*/
380
381 /*------------------------------------------------------------------*/
382 /*                                                                  */
383 /* Name         - arch_get_rethrow_exception                        */
384 /*                                                                  */
385 /* Function     - Return a function pointer which can be used to    */
386 /*                raise exceptions. The returned function has the   */
387 /*                following signature:                              */
388 /*                void (*func) (MonoException *exc);                */
389 /*                                                                  */
390 /*------------------------------------------------------------------*/
391
392 gpointer 
393 mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot)
394 {
395         g_assert (!aot);
396         if (info)
397                 *info = NULL;
398
399         return (mono_arch_get_throw_exception_generic (SZ_THROW, info, FALSE, FALSE, aot));
400 }
401
402 /*========================= End of Function ========================*/
403
404 /*------------------------------------------------------------------*/
405 /*                                                                  */
406 /* Name         - arch_get_corlib_exception                         */
407 /*                                                                  */
408 /* Function     - Return a function pointer which can be used to    */
409 /*                raise corlib exceptions. The return function has  */
410 /*                the following signature:                          */
411 /*                void (*func) (guint32 token, guint32 offset)      */
412 /*                                                                  */
413 /*------------------------------------------------------------------*/
414
415 gpointer
416 mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot)
417 {
418         g_assert (!aot);
419         if (info)
420                 *info = NULL;
421
422         return (mono_arch_get_throw_exception_generic (SZ_THROW, info, TRUE, FALSE, aot));
423 }       
424
425 /*========================= End of Function ========================*/
426
427 /*------------------------------------------------------------------*/
428 /*                                                                  */
429 /* Name         - mono_arch_find_jit_info                           */
430 /*                                                                  */
431 /* Function     - This function is used to gather information from  */
432 /*                @ctx. It returns the MonoJitInfo of the corres-   */
433 /*                ponding function, unwinds one stack frame and     */
434 /*                stores the resulting context into @new_ctx. It    */
435 /*                also stores a string describing the stack location*/
436 /*                into @trace (if not NULL), and modifies the @lmf  */
437 /*                if necessary. @native_offset returns the IP off-  */
438 /*                set from the start of the function or -1 if that  */
439 /*                information is not available.                     */
440 /*                                                                  */
441 /*------------------------------------------------------------------*/
442
443 gboolean
444 mono_arch_find_jit_info_ext (MonoDomain *domain, MonoJitTlsData *jit_tls, 
445                                                          MonoJitInfo *ji, MonoContext *ctx, 
446                                                          MonoContext *new_ctx, MonoLMF **lmf, 
447                                                          StackFrameInfo *frame)
448 {
449         gpointer ip = (gpointer) MONO_CONTEXT_GET_IP (ctx);
450         MonoS390StackFrame *sframe;
451
452         memset (frame, 0, sizeof (StackFrameInfo));
453         frame->ji = ji;
454         frame->managed = FALSE;
455
456         *new_ctx = *ctx;
457
458         if (ji != NULL) {
459                 gint64 address;
460
461                 frame->type = FRAME_TYPE_MANAGED;
462
463                 if (!ji->method->wrapper_type || ji->method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD)
464                         frame->managed = TRUE;
465
466                 if (*lmf && (MONO_CONTEXT_GET_SP (ctx) >= (gpointer)(*lmf)->ebp)) {
467                         /* remove any unused lmf */
468                         *lmf = (*lmf)->previous_lmf;
469                 }
470
471                 address = (char *)ip - (char *)ji->code_start;
472
473                 sframe = (MonoS390StackFrame *) MONO_CONTEXT_GET_SP (ctx);
474                 MONO_CONTEXT_SET_BP (new_ctx, sframe->prev);
475                 sframe = (MonoS390StackFrame *) sframe->prev;
476                 MONO_CONTEXT_SET_IP (new_ctx, sframe->return_address);
477                 memcpy (&new_ctx->uc_mcontext.gregs[6], sframe->regs, (8*sizeof(gint64)));
478                 return TRUE;
479
480         } else if (*lmf) {
481                 if (!(*lmf)->method)
482                         return FALSE;
483
484                 ji = mini_jit_info_table_find (domain, (gpointer)(*lmf)->eip, NULL);
485                 if (!ji) {
486                         // FIXME: This can happen with multiple appdomains (bug #444383)
487                         return FALSE;
488                 }
489
490                 frame->ji = ji;
491                 frame->type = FRAME_TYPE_MANAGED_TO_NATIVE;
492
493                 memcpy(new_ctx->uc_mcontext.gregs, (*lmf)->gregs, sizeof((*lmf)->gregs));
494                 memcpy(new_ctx->uc_mcontext.fpregs.fprs, (*lmf)->fregs, sizeof((*lmf)->fregs));
495
496                 MONO_CONTEXT_SET_BP (new_ctx, (*lmf)->ebp);
497                 MONO_CONTEXT_SET_IP (new_ctx, (*lmf)->eip);
498                 *lmf = (*lmf)->previous_lmf;
499
500                 return TRUE;
501         }
502
503         return FALSE;
504 }
505
506 /*========================= End of Function ========================*/
507
508 /*------------------------------------------------------------------*/
509 /*                                                                  */
510 /* Name         - mono_arch_handle_exception                        */
511 /*                                                                  */
512 /* Function     - Handle an exception raised by the JIT code.       */
513 /*                                                                  */
514 /* Parameters   - ctx       - Saved processor state                 */
515 /*                obj       - The exception object                  */
516 /*                test_only - Only test if the exception is caught, */
517 /*                            but don't call handlers               */
518 /*                                                                  */
519 /*------------------------------------------------------------------*/
520
521 gboolean
522 mono_arch_handle_exception (void *uc, gpointer obj, gboolean test_only)
523 {
524         return mono_handle_exception (uc, obj, mono_arch_ip_from_context(uc), test_only);
525 }
526
527 /*========================= End of Function ========================*/
528
529 /*------------------------------------------------------------------*/
530 /*                                                                  */
531 /* Name         - mono_arch_sigctx_to_monoctx.                      */
532 /*                                                                  */
533 /* Function     - Called from the signal handler to convert signal  */
534 /*                context to MonoContext.                           */
535 /*                                                                  */
536 /*------------------------------------------------------------------*/
537
538 void
539 mono_arch_sigctx_to_monoctx (void *ctx, MonoContext *mctx)
540 {
541         memcpy (mctx, ctx, sizeof(MonoContext));
542 }
543
544 /*========================= End of Function ========================*/
545
546 /*------------------------------------------------------------------*/
547 /*                                                                  */
548 /* Name         - mono_arch_monoctx_to_sigctx.                      */
549 /*                                                                  */
550 /* Function     - Convert MonoContext structure to signal context.  */
551 /*                                                                  */
552 /*------------------------------------------------------------------*/
553
554 void
555 mono_arch_monoctx_to_sigctx (MonoContext *mctx, void *ctx)
556 {
557         memcpy (ctx, mctx, sizeof(MonoContext));
558 }
559
560 /*========================= End of Function ========================*/
561
562 /*------------------------------------------------------------------*/
563 /*                                                                  */
564 /* Name         - mono_arch_ip_from_context                         */
565 /*                                                                  */
566 /* Function     - Return the instruction pointer from the context.  */
567 /*                                                                  */
568 /* Parameters   - sigctx    - Saved processor state                 */
569 /*                                                                  */
570 /*------------------------------------------------------------------*/
571
572 gpointer
573 mono_arch_ip_from_context (void *sigctx)
574 {
575         return ((gpointer) MONO_CONTEXT_GET_IP(((MonoContext *) sigctx)));
576 }
577
578
579 /*========================= End of Function ========================*/
580
581 /*------------------------------------------------------------------*/
582 /*                                                                  */
583 /* Name         - mono_arch_get_restore_context                    */
584 /*                                                                  */
585 /* Function     - Return the address of the routine that will rest- */
586 /*                ore the context.                                  */
587 /*                                                                  */
588 /*------------------------------------------------------------------*/
589
590 gpointer
591 mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot)
592 {
593         g_assert (!aot);
594         if (info)
595                 *info = NULL;
596
597         return setcontext;
598 }
599
600 /*========================= End of Function ========================*/
601
602 /*------------------------------------------------------------------*/
603 /*                                                                  */
604 /* Name         - mono_arch_is_int_overflow                         */
605 /*                                                                  */
606 /* Function     - Inspect the code that raised the SIGFPE signal    */
607 /*                to see if the DivideByZero or Arithmetic exception*/
608 /*                should be raised.                                 */
609 /*                                                                  */
610 /*------------------------------------------------------------------*/
611
612 gboolean
613 mono_arch_is_int_overflow (void *uc, void *info)
614 {
615         MonoContext *ctx;
616         guint8      *code;
617         guint64     *operand;
618         gboolean    arithExc = TRUE;
619         gint        regNo,
620                     idxNo,
621                     offset;
622
623         ctx  = (MonoContext *) uc;
624         code =  (guint8 *) ((siginfo_t *)info)->si_addr;
625         /*----------------------------------------------------------*/
626         /* Divide operations are the only ones that will give the   */
627         /* divide by zero exception so just check for these ops.    */
628         /*----------------------------------------------------------*/
629         switch (code[0]) {
630                 case 0x1d :             /* Divide Register          */
631                         regNo = code[1] & 0x0f; 
632                         if (ctx->uc_mcontext.gregs[regNo] == 0)
633                                 arithExc = FALSE;
634                 break;
635                 case 0x5d :             /* Divide                   */
636                         regNo   = (code[2] & 0xf0 >> 8);        
637                         idxNo   = (code[1] & 0x0f);
638                         offset  = *((guint16 *) code+2) & 0x0fff;
639                         operand = (guint64*)(ctx->uc_mcontext.gregs[regNo] + offset);
640                         if (idxNo != 0)
641                                 operand += ctx->uc_mcontext.gregs[idxNo];
642                         if (*operand == 0)
643                                 arithExc = FALSE; 
644                 break;
645                 case 0xb9 :             /* DL[GR] or DS[GR]         */
646                         if ((code[1] == 0x97) || (code[1] == 0x87) ||
647                             (code[1] == 0x0d) || (code[1] == 0x1d)) {
648                                 regNo = (code[3] & 0x0f);
649                                 if (ctx->uc_mcontext.gregs[regNo] == 0)
650                                         arithExc = FALSE;
651                         }
652                 break;
653                 case 0xe3 :             /* DL[G] | DS[G]            */
654                         if ((code[5] == 0x97) || (code[5] == 0x87) ||
655                             (code[5] == 0x0d) || (code[5] == 0x1d)) {
656                                 regNo   = (code[2] & 0xf0 >> 8);        
657                                 idxNo   = (code[1] & 0x0f);
658                                 offset  = (code[2] & 0x0f << 8) + 
659                                           code[3] + (code[4] << 12);
660                                 operand = (guint64*)(ctx->uc_mcontext.gregs[regNo] + offset);
661                                 if (idxNo != 0)
662                                         operand += ctx->uc_mcontext.gregs[idxNo];
663                                 if (*operand == 0)
664                                         arithExc = FALSE; 
665                         }
666                 break;
667                 default:
668                         arithExc = TRUE;
669         }
670         ctx->uc_mcontext.psw.addr = (guint64)code;
671         return (arithExc);
672 }
673
674 /*========================= End of Function ========================*/