4 * Function - Exception support for S/390.
6 * Name - Neale Ferguson (Neale.Ferguson@SoftwareAG-usa.com)
10 * Derivation - From exceptions-x86 & exceptions-ppc
11 * Paolo Molaro (lupus@ximian.com)
12 * Dietmar Maurer (dietmar@ximian.com)
14 * Copyright - 2001 Ximian, Inc.
15 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
19 /*------------------------------------------------------------------*/
21 /*------------------------------------------------------------------*/
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)))
28 #define S390_THROWSTACK_ACCPRM S390_MINIMAL_STACK_SIZE // 160
29 #define S390_THROWSTACK_FPCPRM (S390_THROWSTACK_ACCPRM+sizeof(gpointer)) // 168
30 #define S390_THROWSTACK_RETHROW (S390_THROWSTACK_FPCPRM+sizeof(gulong)) // 170
31 #define S390_THROWSTACK_PRESERVE_IPS (S390_THROWSTACK_RETHROW+sizeof(gulong)) // 178
32 #define S390_THROWSTACK_INTREGS (S390_THROWSTACK_PRESERVE_IPS+sizeof(gulong)) // 180
33 #define S390_THROWSTACK_FLTREGS (S390_THROWSTACK_INTREGS+(16*sizeof(gulong))) // 308
34 #define S390_THROWSTACK_ACCREGS (S390_THROWSTACK_FLTREGS+(16*sizeof(gdouble))) // 430
35 #define S390_THROWSTACK_SIZE (S390_THROWSTACK_ACCREGS+(16*sizeof(gint32))) // 494
39 #define setup_context(ctx)
41 /*========================= End of Defines =========================*/
43 /*------------------------------------------------------------------*/
45 /*------------------------------------------------------------------*/
53 #include <mono/arch/s390x/s390x-codegen.h>
54 #include <mono/metadata/appdomain.h>
55 #include <mono/metadata/tabledefs.h>
56 #include <mono/metadata/threads.h>
57 #include <mono/metadata/debug-helpers.h>
58 #include <mono/metadata/exception.h>
59 #include <mono/metadata/mono-debug.h>
62 #include "mini-s390x.h"
63 #include "support-s390x.h"
64 #include "mini-runtime.h"
65 #include "aot-runtime.h"
67 /*========================= End of Includes ========================*/
69 /*------------------------------------------------------------------*/
70 /* P r o t o t y p e s */
71 /*------------------------------------------------------------------*/
73 static void throw_exception (MonoObject
*, unsigned long, unsigned long,
74 host_mgreg_t
*, gdouble
*, gint32
*, guint
, gboolean
, gboolean
);
75 static gpointer
mono_arch_get_throw_exception_generic (int, MonoTrampInfo
**,
76 int, gboolean
, gboolean
, gboolean
);
77 static void handle_signal_exception (gpointer
);
79 /*========================= End of Prototypes ======================*/
81 /*------------------------------------------------------------------*/
82 /* G l o b a l V a r i a b l e s */
83 /*------------------------------------------------------------------*/
90 /*====================== End of Global Variables ===================*/
92 /*------------------------------------------------------------------*/
94 /* Name - mono_arch_get_call_filter */
96 /* Function - Return a pointer to a method which calls an */
97 /* exception filter. We also use this function to */
98 /* call finally handlers (we pass NULL as @exc */
99 /* object in this case). */
101 /*------------------------------------------------------------------*/
104 mono_arch_get_call_filter (MonoTrampInfo
**info
, gboolean aot
)
106 static guint8
*start
;
107 static int inited
= 0;
109 int alloc_size
, pos
, i
;
110 GSList
*unwind_ops
= NULL
;
111 MonoJumpInfo
*ji
= NULL
;
119 /* call_filter (MonoContext *ctx, unsigned long eip, gpointer exc) */
120 code
= start
= mono_global_codeman_reserve (512);
122 s390_stmg (code
, s390_r6
, s390_r14
, STK_BASE
, S390_REG_SAVE_OFFSET
);
123 s390_lgr (code
, s390_r14
, STK_BASE
);
124 alloc_size
= S390_ALIGN(S390_CALLFILTER_SIZE
, S390_STACK_ALIGNMENT
);
125 s390_aghi (code
, STK_BASE
, -alloc_size
);
126 s390_stg (code
, s390_r14
, 0, STK_BASE
, 0);
128 /*------------------------------------------------------*/
129 /* save general registers on stack */
130 /*------------------------------------------------------*/
131 s390_stmg (code
, s390_r0
, STK_BASE
, STK_BASE
, S390_CALLFILTER_INTREGS
);
133 /*------------------------------------------------------*/
134 /* save floating point registers on stack */
135 /*------------------------------------------------------*/
136 pos
= S390_CALLFILTER_FLTREGS
;
137 for (i
= 0; i
< 16; ++i
) {
138 s390_std (code
, i
, 0, STK_BASE
, pos
);
139 pos
+= sizeof (gdouble
);
142 /*------------------------------------------------------*/
143 /* save access registers on stack */
144 /*------------------------------------------------------*/
145 s390_stam (code
, s390_a0
, s390_a15
, STK_BASE
, S390_CALLFILTER_ACCREGS
);
147 /*------------------------------------------------------*/
149 /*------------------------------------------------------*/
150 s390_lgr (code
, s390_r13
, s390_r2
);
152 /*------------------------------------------------------*/
153 /* Get A(Handler Entry Point) */
154 /*------------------------------------------------------*/
155 s390_lgr (code
, s390_r0
, s390_r3
);
157 /*------------------------------------------------------*/
158 /* Set parameter register with Exception */
159 /*------------------------------------------------------*/
160 s390_lgr (code
, s390_r2
, s390_r4
);
162 /*------------------------------------------------------*/
163 /* Load all registers with values from the context */
164 /*------------------------------------------------------*/
165 s390_lmg (code
, s390_r3
, s390_r12
, s390_r13
,
166 G_STRUCT_OFFSET(MonoContext
, uc_mcontext
.gregs
[3]));
167 pos
= G_STRUCT_OFFSET(MonoContext
, uc_mcontext
.fpregs
.fprs
[0]);
168 for (i
= 0; i
< 16; ++i
) {
169 s390_ld (code
, i
, 0, s390_r13
, pos
);
170 pos
+= sizeof(gdouble
);
174 /*------------------------------------------------------*/
175 /* We need to preserve current SP before calling filter */
176 /* with SP from the context */
177 /*------------------------------------------------------*/
178 s390_lgr (code
, s390_r14
, STK_BASE
);
179 s390_lg (code
, STK_BASE
, 0, s390_r13
,
180 G_STRUCT_OFFSET(MonoContext
, uc_mcontext
.gregs
[15]));
181 s390_lgr (code
, s390_r13
, s390_r14
);
184 /*------------------------------------------------------*/
186 /*------------------------------------------------------*/
187 s390_lgr (code
, s390_r1
, s390_r0
);
188 s390_basr (code
, s390_r14
, s390_r1
);
190 /*------------------------------------------------------*/
191 /* Save return value */
192 /*------------------------------------------------------*/
193 s390_lgr (code
, s390_r14
, s390_r2
);
196 /*------------------------------------------------------*/
197 /* Reload our stack register with value saved in context*/
198 /*------------------------------------------------------*/
199 s390_lgr (code
, STK_BASE
, s390_r13
);
202 /*------------------------------------------------------*/
203 /* Restore all the regs from the stack */
204 /*------------------------------------------------------*/
205 s390_lmg (code
, s390_r0
, s390_r13
, STK_BASE
, S390_CALLFILTER_INTREGS
);
206 pos
= S390_CALLFILTER_FLTREGS
;
207 for (i
= 0; i
< 16; ++i
) {
208 s390_ld (code
, i
, 0, STK_BASE
, pos
);
209 pos
+= sizeof (gdouble
);
212 s390_lgr (code
, s390_r2
, s390_r14
);
213 s390_lam (code
, s390_a0
, s390_a15
, STK_BASE
, S390_CALLFILTER_ACCREGS
);
214 s390_aghi (code
, s390_r15
, alloc_size
);
215 s390_lmg (code
, s390_r6
, s390_r14
, STK_BASE
, S390_REG_SAVE_OFFSET
);
216 s390_br (code
, s390_r14
);
218 g_assert ((code
- start
) < SZ_THROW
);
220 mono_arch_flush_icache(start
, code
- start
);
221 MONO_PROFILER_RAISE (jit_code_buffer
, (start
, code
- start
, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING
, NULL
));
224 *info
= mono_tramp_info_create ("call_filter",
225 start
, code
- start
, ji
,
231 /*========================= End of Function ========================*/
233 /*------------------------------------------------------------------*/
235 /* Name - throw_exception. */
237 /* Function - Raise an exception based on the parameters passed.*/
239 /*------------------------------------------------------------------*/
242 throw_exception (MonoObject
*exc
, unsigned long ip
, unsigned long sp
,
243 host_mgreg_t
*int_regs
, gdouble
*fp_regs
, gint32
*acc_regs
,
244 guint fpc
, gboolean rethrow
, gboolean preserve_ips
)
250 memset(&ctx
, 0, sizeof(ctx
));
254 /* adjust eip so that it point into the call instruction */
257 for (iReg
= 0; iReg
< 16; iReg
++) {
258 ctx
.uc_mcontext
.gregs
[iReg
] = int_regs
[iReg
];
259 ctx
.uc_mcontext
.fpregs
.fprs
[iReg
].d
= fp_regs
[iReg
];
260 ctx
.uc_mcontext
.aregs
[iReg
] = acc_regs
[iReg
];
263 ctx
.uc_mcontext
.fpregs
.fpc
= fpc
;
265 MONO_CONTEXT_SET_BP (&ctx
, sp
);
266 MONO_CONTEXT_SET_IP (&ctx
, ip
);
268 if (mono_object_isinst_checked (exc
, mono_defaults
.exception_class
, error
)) {
269 MonoException
*mono_ex
= (MonoException
*)exc
;
271 mono_ex
->stack_trace
= NULL
;
272 mono_ex
->trace_ips
= NULL
;
273 } else if (preserve_ips
) {
274 mono_ex
->caught_in_unmanaged
= TRUE
;
277 mono_error_assert_ok (error
);
278 // mono_arch_handle_exception (&ctx, exc, FALSE);
279 mono_handle_exception (&ctx
, exc
);
280 mono_restore_context(&ctx
);
282 g_assert_not_reached ();
285 /*========================= End of Function ========================*/
287 /*------------------------------------------------------------------*/
289 /* Name - get_throw_exception_generic */
291 /* Function - Return a function pointer which can be used to */
292 /* raise exceptions. The returned function has the */
293 /* following signature: */
294 /* void (*func) (MonoException *exc); or, */
295 /* void (*func) (char *exc_name); */
297 /*------------------------------------------------------------------*/
300 mono_arch_get_throw_exception_generic (int size
, MonoTrampInfo
**info
, int corlib
,
301 gboolean rethrow
, gboolean aot
, gboolean preserve_ips
)
303 guint8
*code
, *start
;
304 int alloc_size
, pos
, i
;
305 MonoJumpInfo
*ji
= NULL
;
306 GSList
*unwind_ops
= NULL
;
308 code
= start
= mono_global_codeman_reserve(size
);
310 s390_stmg (code
, s390_r6
, s390_r14
, STK_BASE
, S390_REG_SAVE_OFFSET
);
311 alloc_size
= S390_ALIGN(S390_THROWSTACK_SIZE
, S390_STACK_ALIGNMENT
);
312 s390_lgr (code
, s390_r14
, STK_BASE
);
313 s390_aghi (code
, STK_BASE
, -alloc_size
);
314 s390_stg (code
, s390_r14
, 0, STK_BASE
, 0);
315 s390_lgr (code
, s390_r3
, s390_r2
);
317 S390_SET (code
, s390_r1
, (guint8
*)mono_exception_from_token
);
318 S390_SET (code
, s390_r2
, (guint8
*)m_class_get_image (mono_defaults
.exception_class
));
319 s390_basr (code
, s390_r14
, s390_r1
);
322 /*------------------------------------------------------*/
323 /* save the general registers on the stack */
324 /*------------------------------------------------------*/
325 s390_stmg (code
, s390_r0
, s390_r13
, STK_BASE
, S390_THROWSTACK_INTREGS
);
327 s390_lgr (code
, s390_r1
, STK_BASE
);
328 s390_aghi (code
, s390_r1
, alloc_size
);
329 /*------------------------------------------------------*/
330 /* save the return address in the parameter register */
331 /*------------------------------------------------------*/
332 s390_lg (code
, s390_r3
, 0, s390_r1
, S390_RET_ADDR_OFFSET
);
334 /*------------------------------------------------------*/
335 /* save the floating point registers */
336 /*------------------------------------------------------*/
337 pos
= S390_THROWSTACK_FLTREGS
;
338 for (i
= 0; i
< 16; ++i
) {
339 s390_std (code
, i
, 0, STK_BASE
, pos
);
340 pos
+= sizeof (gdouble
);
342 /*------------------------------------------------------*/
343 /* save the access registers */
344 /*------------------------------------------------------*/
345 s390_stam (code
, s390_r0
, s390_r15
, STK_BASE
, S390_THROWSTACK_ACCREGS
);
347 /*------------------------------------------------------*/
348 /* call throw_exception (tkn, ip, sp, gr, fr, ar, re) */
349 /* - r2 already contains *exc */
350 /*------------------------------------------------------*/
351 s390_lgr (code
, s390_r4
, s390_r1
); /* caller sp */
353 /*------------------------------------------------------*/
354 /* pointer to the saved int regs */
355 /*------------------------------------------------------*/
356 s390_la (code
, s390_r5
, 0, STK_BASE
, S390_THROWSTACK_INTREGS
);
357 s390_la (code
, s390_r6
, 0, STK_BASE
, S390_THROWSTACK_FLTREGS
);
358 s390_la (code
, s390_r7
, 0, STK_BASE
, S390_THROWSTACK_ACCREGS
);
359 s390_stg (code
, s390_r7
, 0, STK_BASE
, S390_THROWSTACK_ACCPRM
);
360 s390_stfpc(code
, STK_BASE
, S390_THROWSTACK_FPCPRM
+4);
361 S390_SET (code
, s390_r1
, (guint8
*)throw_exception
);
362 s390_lghi (code
, s390_r7
, rethrow
);
363 s390_stg (code
, s390_r7
, 0, STK_BASE
, S390_THROWSTACK_RETHROW
);
364 s390_lghi (code
, s390_r7
, preserve_ips
);
365 s390_stg (code
, s390_r7
, 0, STK_BASE
, S390_THROWSTACK_PRESERVE_IPS
);
366 s390_basr (code
, s390_r14
, s390_r1
);
367 /* we should never reach this breakpoint */
369 g_assert ((code
- start
) < size
);
371 mono_arch_flush_icache (start
, code
- start
);
372 MONO_PROFILER_RAISE (jit_code_buffer
, (start
, code
- start
, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING
, NULL
));
375 *info
= mono_tramp_info_create (corlib
? "throw_corlib_exception"
376 : (rethrow
? "rethrow_exception"
377 : (preserve_ips
? "rethrow_preserve_exception"
378 : "throw_exception")),
379 start
, code
- start
, ji
, unwind_ops
);
384 /*========================= End of Function ========================*/
386 /*------------------------------------------------------------------*/
388 /* Name - arch_get_throw_exception */
390 /* Function - Return a function pointer which can be used to */
391 /* raise exceptions. The returned function has the */
392 /* following signature: */
393 /* void (*func) (MonoException *exc); */
395 /*------------------------------------------------------------------*/
398 mono_arch_get_throw_exception (MonoTrampInfo
**info
, gboolean aot
)
404 return (mono_arch_get_throw_exception_generic (SZ_THROW
, info
, FALSE
, FALSE
, aot
, FALSE
));
407 /*========================= End of Function ========================*/
409 /*------------------------------------------------------------------*/
411 /* Name - arch_get_rethrow_preserve_exception */
413 /* Function - Return a function pointer which can be used to */
414 /* raise exceptions. This preserves the stored ips. */
415 /* The returned function has the */
416 /* following signature: */
417 /* void (*func) (MonoException *exc); */
419 /*------------------------------------------------------------------*/
422 mono_arch_get_rethrow_preserve_exception (MonoTrampInfo
**info
, gboolean aot
)
428 return (mono_arch_get_throw_exception_generic (SZ_THROW
, info
, FALSE
, TRUE
, aot
, TRUE
));
431 /*========================= End of Function ========================*/
433 /*------------------------------------------------------------------*/
435 /* Name - arch_get_rethrow_exception */
437 /* Function - Return a function pointer which can be used to */
438 /* raise exceptions. The returned function has the */
439 /* following signature: */
440 /* void (*func) (MonoException *exc); */
442 /*------------------------------------------------------------------*/
445 mono_arch_get_rethrow_exception (MonoTrampInfo
**info
, gboolean aot
)
451 return (mono_arch_get_throw_exception_generic (SZ_THROW
, info
, FALSE
, TRUE
, aot
, FALSE
));
454 /*========================= End of Function ========================*/
456 /*------------------------------------------------------------------*/
458 /* Name - arch_get_corlib_exception */
460 /* Function - Return a function pointer which can be used to */
461 /* raise corlib exceptions. The return function has */
462 /* the following signature: */
463 /* void (*func) (guint32 token, guint32 offset) */
465 /*------------------------------------------------------------------*/
468 mono_arch_get_throw_corlib_exception (MonoTrampInfo
**info
, gboolean aot
)
474 return (mono_arch_get_throw_exception_generic (SZ_THROW
, info
, TRUE
, FALSE
, aot
, FALSE
));
477 /*========================= End of Function ========================*/
479 /*------------------------------------------------------------------*/
481 /* Name - mono_arch_unwind_frame */
483 /* Function - See exceptions-amd64.c for docs. */
485 /*------------------------------------------------------------------*/
488 mono_arch_unwind_frame (MonoDomain
*domain
, MonoJitTlsData
*jit_tls
,
489 MonoJitInfo
*ji
, MonoContext
*ctx
,
490 MonoContext
*new_ctx
, MonoLMF
**lmf
,
491 host_mgreg_t
**save_locations
,
492 StackFrameInfo
*frame
)
494 gpointer ip
= (gpointer
) MONO_CONTEXT_GET_IP (ctx
);
496 memset (frame
, 0, sizeof (StackFrameInfo
));
504 guint32 unwind_info_len
;
506 host_mgreg_t regs
[16];
508 if (ji
->is_trampoline
)
509 frame
->type
= FRAME_TYPE_TRAMPOLINE
;
511 frame
->type
= FRAME_TYPE_MANAGED
;
513 unwind_info
= mono_jinfo_get_unwind_info (ji
, &unwind_info_len
);
515 address
= (char *)ip
- (char *)ji
->code_start
;
517 memcpy(®s
, &ctx
->uc_mcontext
.gregs
, sizeof(regs
));
518 gboolean success
= mono_unwind_frame (unwind_info
, unwind_info_len
, ji
->code_start
,
519 (guint8
*) ji
->code_start
+ ji
->code_size
,
520 ip
, NULL
, regs
, 16, save_locations
,
521 MONO_MAX_IREGS
, &cfa
);
526 memcpy (&new_ctx
->uc_mcontext
.gregs
, ®s
, sizeof(regs
));
527 MONO_CONTEXT_SET_IP(new_ctx
, regs
[14] - 2);
528 MONO_CONTEXT_SET_BP(new_ctx
, cfa
);
533 ji
= mini_jit_info_table_find (domain
, (gpointer
)(*lmf
)->eip
, NULL
);
538 frame
->method
= (*lmf
)->method
;
542 frame
->type
= FRAME_TYPE_MANAGED_TO_NATIVE
;
544 memcpy(new_ctx
->uc_mcontext
.gregs
, (*lmf
)->gregs
, sizeof((*lmf
)->gregs
));
545 memcpy(new_ctx
->uc_mcontext
.fpregs
.fprs
, (*lmf
)->fregs
, sizeof((*lmf
)->fregs
));
546 MONO_CONTEXT_SET_BP (new_ctx
, (*lmf
)->ebp
);
547 MONO_CONTEXT_SET_IP (new_ctx
, (*lmf
)->eip
- 2);
548 *lmf
= (*lmf
)->previous_lmf
;
556 /*========================= End of Function ========================*/
558 /*------------------------------------------------------------------*/
560 /* Name - handle_signal_exception */
562 /* Function - Handle an exception raised by the JIT code. */
564 /* Parameters - obj - The exception object */
566 /*------------------------------------------------------------------*/
569 handle_signal_exception (gpointer obj
)
571 MonoJitTlsData
*jit_tls
= mono_tls_get_jit_tls ();
574 memcpy (&ctx
, &jit_tls
->ex_ctx
, sizeof (MonoContext
));
575 mono_handle_exception (&ctx
, obj
);
576 mono_restore_context (&ctx
);
579 /*========================= End of Function ========================*/
581 /*------------------------------------------------------------------*/
583 /* Name - mono_arch_handle_exception */
585 /* Function - Handle an exception raised by the JIT code. */
587 /* Parameters - ctx - Saved processor state */
588 /* obj - The exception object */
590 /*------------------------------------------------------------------*/
593 mono_arch_handle_exception (void *sigctx
, gpointer obj
)
598 * Handling the exception in the signal handler is problematic, since the original
599 * signal is disabled, and we could run arbitrary code though the debugger. So
600 * resume into the normal stack and do most work there if possible.
602 MonoJitTlsData
*jit_tls
= mono_tls_get_jit_tls ();
604 /* Pass the ctx parameter in TLS */
605 mono_sigctx_to_monoctx (sigctx
, &jit_tls
->ex_ctx
);
607 mctx
= jit_tls
->ex_ctx
;
608 mono_arch_setup_async_callback (&mctx
, handle_signal_exception
, obj
);
609 mono_monoctx_to_sigctx (&mctx
, sigctx
);
614 /*========================= End of Function ========================*/
616 /*------------------------------------------------------------------*/
618 /* Name - mono_arch_setup_async_callback */
620 /* Function - Establish the async callback. */
622 /* Parameters - ctx - Context */
623 /* async_cb - Callback routine address */
624 /* user_data - Data to be passed to callback */
626 /*------------------------------------------------------------------*/
629 mono_arch_setup_async_callback (MonoContext
*ctx
, void (*async_cb
)(void *fun
), gpointer user_data
)
631 uintptr_t sp
= (uintptr_t) MONO_CONTEXT_GET_SP(ctx
);
633 ctx
->uc_mcontext
.gregs
[2] = (gsize
)user_data
;
635 sp
-= S390_MINIMAL_STACK_SIZE
;
636 *(unsigned long *)sp
= MONO_CONTEXT_GET_SP(ctx
);
637 MONO_CONTEXT_SET_BP(ctx
, sp
);
638 MONO_CONTEXT_SET_IP(ctx
, (gsize
)async_cb
);
641 /*========================= End of Function ========================*/
643 /*------------------------------------------------------------------*/
645 /* Name - mono_arch_ip_from_context */
647 /* Function - Return the instruction pointer from the context. */
649 /* Parameters - sigctx - Saved processor state */
651 /*------------------------------------------------------------------*/
654 mono_arch_ip_from_context (void *sigctx
)
656 return ((gpointer
) MONO_CONTEXT_GET_IP(((MonoContext
*) sigctx
)));
660 /*========================= End of Function ========================*/
662 /*------------------------------------------------------------------*/
664 /* Name - mono_arch_get_restore_context */
666 /* Function - Return the address of the routine that will rest- */
667 /* ore the context. */
669 /*------------------------------------------------------------------*/
672 mono_arch_get_restore_context (MonoTrampInfo
**info
, gboolean aot
)
681 /*========================= End of Function ========================*/
683 /*------------------------------------------------------------------*/
685 /* Name - mono_arch_is_int_overflow */
687 /* Function - Inspect the code that raised the SIGFPE signal */
688 /* to see if the DivideByZero or Arithmetic exception*/
689 /* should be raised. */
691 /*------------------------------------------------------------------*/
694 mono_arch_is_int_overflow (void *uc
, void *info
)
699 gboolean arithExc
= TRUE
;
704 ctx
= (MonoContext
*) uc
;
705 code
= (guint8
*) ((siginfo_t
*)info
)->si_addr
;
706 /*----------------------------------------------------------*/
707 /* Divide operations are the only ones that will give the */
708 /* divide by zero exception so just check for these ops. */
709 /*----------------------------------------------------------*/
711 case 0x1d : /* Divide Register */
712 regNo
= code
[1] & 0x0f;
713 if (ctx
->uc_mcontext
.gregs
[regNo
] == 0)
716 case 0x5d : /* Divide */
717 regNo
= (code
[2] & 0xf0 >> 8);
718 idxNo
= (code
[1] & 0x0f);
719 offset
= *((guint16
*) code
+2) & 0x0fff;
720 operand
= (guint64
*)(ctx
->uc_mcontext
.gregs
[regNo
] + offset
);
722 operand
+= ctx
->uc_mcontext
.gregs
[idxNo
];
726 case 0xb9 : /* DL[GR] or DS[GR] */
727 if ((code
[1] == 0x97) || (code
[1] == 0x87) ||
728 (code
[1] == 0x0d) || (code
[1] == 0x1d)) {
729 regNo
= (code
[3] & 0x0f);
730 if (ctx
->uc_mcontext
.gregs
[regNo
] == 0)
734 case 0xe3 : /* DL[G] | DS[G] */
735 if ((code
[5] == 0x97) || (code
[5] == 0x87) ||
736 (code
[5] == 0x0d) || (code
[5] == 0x1d)) {
737 regNo
= (code
[2] & 0xf0 >> 8);
738 idxNo
= (code
[1] & 0x0f);
739 offset
= (code
[2] & 0x0f << 8) +
740 code
[3] + (code
[4] << 12);
741 operand
= (guint64
*)(ctx
->uc_mcontext
.gregs
[regNo
] + offset
);
743 operand
+= ctx
->uc_mcontext
.gregs
[idxNo
];
751 ctx
->uc_mcontext
.psw
.addr
= (guint64
)code
;
755 /*========================= End of Function ========================*/