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