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