Avoid passing a name to mono_register_jit_icall () which is later freed.
[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     - See exceptions-amd64.c for docs.                      */
432 /*                                                                  */
433 /*------------------------------------------------------------------*/
434
435 gboolean
436 mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, 
437                                                          MonoJitInfo *ji, MonoContext *ctx, 
438                                                          MonoContext *new_ctx, MonoLMF **lmf, 
439                                                          StackFrameInfo *frame)
440 {
441         gpointer ip = (gpointer) MONO_CONTEXT_GET_IP (ctx);
442         MonoS390StackFrame *sframe;
443
444         memset (frame, 0, sizeof (StackFrameInfo));
445         frame->ji = ji;
446         frame->managed = FALSE;
447
448         *new_ctx = *ctx;
449
450         if (ji != NULL) {
451                 gint64 address;
452
453                 frame->type = FRAME_TYPE_MANAGED;
454
455                 if (!ji->method->wrapper_type || ji->method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD)
456                         frame->managed = TRUE;
457
458                 if (*lmf && (MONO_CONTEXT_GET_SP (ctx) >= (gpointer)(*lmf)->ebp)) {
459                         /* remove any unused lmf */
460                         *lmf = (*lmf)->previous_lmf;
461                 }
462
463                 address = (char *)ip - (char *)ji->code_start;
464
465                 sframe = (MonoS390StackFrame *) MONO_CONTEXT_GET_SP (ctx);
466                 MONO_CONTEXT_SET_BP (new_ctx, sframe->prev);
467                 sframe = (MonoS390StackFrame *) sframe->prev;
468                 MONO_CONTEXT_SET_IP (new_ctx, (guint8*)sframe->return_address - 2);
469                 memcpy (&new_ctx->uc_mcontext.gregs[6], sframe->regs, (8*sizeof(gint64)));
470                 return TRUE;
471
472         } else if (*lmf) {
473                 if (!(*lmf)->method)
474                         return FALSE;
475
476                 ji = mini_jit_info_table_find (domain, (gpointer)(*lmf)->eip, NULL);
477                 if (!ji) {
478                         // FIXME: This can happen with multiple appdomains (bug #444383)
479                         return FALSE;
480                 }
481
482                 frame->ji = ji;
483                 frame->type = FRAME_TYPE_MANAGED_TO_NATIVE;
484
485                 memcpy(new_ctx->uc_mcontext.gregs, (*lmf)->gregs, sizeof((*lmf)->gregs));
486                 memcpy(new_ctx->uc_mcontext.fpregs.fprs, (*lmf)->fregs, sizeof((*lmf)->fregs));
487
488                 MONO_CONTEXT_SET_BP (new_ctx, (*lmf)->ebp);
489                 MONO_CONTEXT_SET_IP (new_ctx, (*lmf)->eip - 2);
490                 *lmf = (*lmf)->previous_lmf;
491
492                 return TRUE;
493         }
494
495         return FALSE;
496 }
497
498 /*========================= End of Function ========================*/
499
500 /*------------------------------------------------------------------*/
501 /*                                                                  */
502 /* Name         - mono_arch_handle_exception                        */
503 /*                                                                  */
504 /* Function     - Handle an exception raised by the JIT code.       */
505 /*                                                                  */
506 /* Parameters   - ctx       - Saved processor state                 */
507 /*                obj       - The exception object                  */
508 /*                test_only - Only test if the exception is caught, */
509 /*                            but don't call handlers               */
510 /*                                                                  */
511 /*------------------------------------------------------------------*/
512
513 gboolean
514 mono_arch_handle_exception (void *uc, gpointer obj, gboolean test_only)
515 {
516         return mono_handle_exception (uc, obj, mono_arch_ip_from_context(uc), test_only);
517 }
518
519 /*========================= End of Function ========================*/
520
521 /*------------------------------------------------------------------*/
522 /*                                                                  */
523 /* Name         - mono_arch_sigctx_to_monoctx.                      */
524 /*                                                                  */
525 /* Function     - Called from the signal handler to convert signal  */
526 /*                context to MonoContext.                           */
527 /*                                                                  */
528 /*------------------------------------------------------------------*/
529
530 void
531 mono_arch_sigctx_to_monoctx (void *ctx, MonoContext *mctx)
532 {
533         memcpy (mctx, ctx, sizeof(MonoContext));
534 }
535
536 /*========================= End of Function ========================*/
537
538 /*------------------------------------------------------------------*/
539 /*                                                                  */
540 /* Name         - mono_arch_monoctx_to_sigctx.                      */
541 /*                                                                  */
542 /* Function     - Convert MonoContext structure to signal context.  */
543 /*                                                                  */
544 /*------------------------------------------------------------------*/
545
546 void
547 mono_arch_monoctx_to_sigctx (MonoContext *mctx, void *ctx)
548 {
549         memcpy (ctx, mctx, sizeof(MonoContext));
550 }
551
552 /*========================= End of Function ========================*/
553
554 /*------------------------------------------------------------------*/
555 /*                                                                  */
556 /* Name         - mono_arch_ip_from_context                         */
557 /*                                                                  */
558 /* Function     - Return the instruction pointer from the context.  */
559 /*                                                                  */
560 /* Parameters   - sigctx    - Saved processor state                 */
561 /*                                                                  */
562 /*------------------------------------------------------------------*/
563
564 gpointer
565 mono_arch_ip_from_context (void *sigctx)
566 {
567         return ((gpointer) MONO_CONTEXT_GET_IP(((MonoContext *) sigctx)));
568 }
569
570
571 /*========================= End of Function ========================*/
572
573 /*------------------------------------------------------------------*/
574 /*                                                                  */
575 /* Name         - mono_arch_get_restore_context                    */
576 /*                                                                  */
577 /* Function     - Return the address of the routine that will rest- */
578 /*                ore the context.                                  */
579 /*                                                                  */
580 /*------------------------------------------------------------------*/
581
582 gpointer
583 mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot)
584 {
585         g_assert (!aot);
586         if (info)
587                 *info = NULL;
588
589         return setcontext;
590 }
591
592 /*========================= End of Function ========================*/
593
594 /*------------------------------------------------------------------*/
595 /*                                                                  */
596 /* Name         - mono_arch_is_int_overflow                         */
597 /*                                                                  */
598 /* Function     - Inspect the code that raised the SIGFPE signal    */
599 /*                to see if the DivideByZero or Arithmetic exception*/
600 /*                should be raised.                                 */
601 /*                                                                  */
602 /*------------------------------------------------------------------*/
603
604 gboolean
605 mono_arch_is_int_overflow (void *uc, void *info)
606 {
607         MonoContext *ctx;
608         guint8      *code;
609         guint64     *operand;
610         gboolean    arithExc = TRUE;
611         gint        regNo,
612                     idxNo,
613                     offset;
614
615         ctx  = (MonoContext *) uc;
616         code =  (guint8 *) ((siginfo_t *)info)->si_addr;
617         /*----------------------------------------------------------*/
618         /* Divide operations are the only ones that will give the   */
619         /* divide by zero exception so just check for these ops.    */
620         /*----------------------------------------------------------*/
621         switch (code[0]) {
622                 case 0x1d :             /* Divide Register          */
623                         regNo = code[1] & 0x0f; 
624                         if (ctx->uc_mcontext.gregs[regNo] == 0)
625                                 arithExc = FALSE;
626                 break;
627                 case 0x5d :             /* Divide                   */
628                         regNo   = (code[2] & 0xf0 >> 8);        
629                         idxNo   = (code[1] & 0x0f);
630                         offset  = *((guint16 *) code+2) & 0x0fff;
631                         operand = (guint64*)(ctx->uc_mcontext.gregs[regNo] + offset);
632                         if (idxNo != 0)
633                                 operand += ctx->uc_mcontext.gregs[idxNo];
634                         if (*operand == 0)
635                                 arithExc = FALSE; 
636                 break;
637                 case 0xb9 :             /* DL[GR] or DS[GR]         */
638                         if ((code[1] == 0x97) || (code[1] == 0x87) ||
639                             (code[1] == 0x0d) || (code[1] == 0x1d)) {
640                                 regNo = (code[3] & 0x0f);
641                                 if (ctx->uc_mcontext.gregs[regNo] == 0)
642                                         arithExc = FALSE;
643                         }
644                 break;
645                 case 0xe3 :             /* DL[G] | DS[G]            */
646                         if ((code[5] == 0x97) || (code[5] == 0x87) ||
647                             (code[5] == 0x0d) || (code[5] == 0x1d)) {
648                                 regNo   = (code[2] & 0xf0 >> 8);        
649                                 idxNo   = (code[1] & 0x0f);
650                                 offset  = (code[2] & 0x0f << 8) + 
651                                           code[3] + (code[4] << 12);
652                                 operand = (guint64*)(ctx->uc_mcontext.gregs[regNo] + offset);
653                                 if (idxNo != 0)
654                                         operand += ctx->uc_mcontext.gregs[idxNo];
655                                 if (*operand == 0)
656                                         arithExc = FALSE; 
657                         }
658                 break;
659                 default:
660                         arithExc = TRUE;
661         }
662         ctx->uc_mcontext.psw.addr = (guint64)code;
663         return (arithExc);
664 }
665
666 /*========================= End of Function ========================*/