1 /*------------------------------------------------------------------*/
3 /* Name - mini-s390.c */
5 /* Function - S/390 backend for the Mono code generator. */
7 /* Name - Neale Ferguson (Neale.Ferguson@SoftwareAG-usa.com) */
9 /* Date - January, 2004 */
11 /* Derivation - From mini-x86 & mini-ppc by - */
12 /* Paolo Molaro (lupus@ximian.com) */
13 /* Dietmar Maurer (dietmar@ximian.com) */
15 /*------------------------------------------------------------------*/
17 /*------------------------------------------------------------------*/
19 /*------------------------------------------------------------------*/
21 #define MAX_ARCH_DELEGATE_PARAMS 7
23 #define EMIT_COND_BRANCH(ins,cond) \
25 if (ins->inst_true_bb->native_offset) { \
27 displace = ((cfg->native_code + \
28 ins->inst_true_bb->native_offset) - code) / 2; \
29 if (s390_is_imm16(displace)) { \
30 s390_brc (code, cond, displace); \
32 s390_jcl (code, cond, displace); \
35 mono_add_patch_info (cfg, code - cfg->native_code, \
36 MONO_PATCH_INFO_BB, ins->inst_true_bb); \
37 s390_jcl (code, cond, 0); \
41 #define EMIT_UNCOND_BRANCH(ins) \
43 if (ins->inst_target_bb->native_offset) { \
45 displace = ((cfg->native_code + \
46 ins->inst_target_bb->native_offset) - code) / 2; \
47 if (s390_is_imm16(displace)) { \
48 s390_brc (code, S390_CC_UN, displace); \
50 s390_jcl (code, S390_CC_UN, displace); \
53 mono_add_patch_info (cfg, code - cfg->native_code, \
54 MONO_PATCH_INFO_BB, ins->inst_target_bb); \
55 s390_jcl (code, S390_CC_UN, 0); \
59 #define EMIT_COND_SYSTEM_EXCEPTION(cond,exc_name) \
61 mono_add_patch_info (cfg, code - cfg->native_code, \
62 MONO_PATCH_INFO_EXC, exc_name); \
63 s390_jcl (code, cond, 0); \
66 #define CHECK_SRCDST_COM \
67 if (ins->dreg == ins->sreg2) { \
71 if (ins->dreg != ins->sreg1) { \
72 s390_lgr (code, ins->dreg, ins->sreg1); \
76 #define CHECK_SRCDST_NCOM \
77 if (ins->dreg == ins->sreg2) { \
79 s390_lgr (code, s390_r13, ins->sreg2); \
83 if (ins->dreg != ins->sreg1) { \
84 s390_lgr (code, ins->dreg, ins->sreg1); \
87 #define CHECK_SRCDST_COM_I \
88 if (ins->dreg == ins->sreg2) { \
92 if (ins->dreg != ins->sreg1) { \
93 s390_lgfr (code, ins->dreg, ins->sreg1); \
97 #define CHECK_SRCDST_NCOM_I \
98 if (ins->dreg == ins->sreg2) { \
100 s390_lgfr (code, s390_r13, ins->sreg2); \
104 if (ins->dreg != ins->sreg1) { \
105 s390_lgfr (code, ins->dreg, ins->sreg1); \
108 #define CHECK_SRCDST_COM_F \
109 if (ins->dreg == ins->sreg2) { \
113 if (ins->dreg != ins->sreg1) { \
114 s390_ldr (code, ins->dreg, ins->sreg1); \
118 #define CHECK_SRCDST_NCOM_F \
119 if (ins->dreg == ins->sreg2) { \
121 s390_ldr (code, s390_r13, ins->sreg2); \
125 if (ins->dreg != ins->sreg1) { \
126 s390_ldr (code, ins->dreg, ins->sreg1); \
129 #define MONO_EMIT_NEW_MOVE(cfg,dest,offset,src,imm,size) do { \
132 MONO_INST_NEW (cfg, inst, OP_NOP); \
135 inst->inst_offset = offset; \
137 inst->inst_imm = imm; \
139 if (s390_is_uimm12(offset)) { \
141 inst->inst_offset = offset; \
143 dReg = mono_alloc_preg (cfg); \
144 MONO_EMIT_NEW_BIALU_IMM(cfg, OP_ADD_IMM, \
145 dReg, dest, offset); \
147 inst->inst_offset = 0; \
149 if (s390_is_uimm12(imm)) { \
151 inst->inst_imm = imm; \
153 sReg = mono_alloc_preg (cfg); \
154 MONO_EMIT_NEW_BIALU_IMM(cfg, OP_ADD_IMM, \
156 inst->sreg1 = sReg; \
157 inst->inst_imm = 0; \
160 inst->opcode = OP_S390_MOVE; \
161 inst->backend.size = size; \
162 MONO_ADD_INS (cfg->cbb, inst); \
165 #define MONO_OUTPUT_VTR(cfg, size, dr, sr, so) do { \
166 int reg = mono_alloc_preg (cfg); \
169 MONO_EMIT_NEW_ICONST(cfg, reg, 0); \
172 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU1_MEMBASE, \
176 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU2_MEMBASE, \
180 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI4_MEMBASE, \
184 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI8_MEMBASE, \
188 mono_call_inst_add_outarg_reg(cfg, call, reg, dr, FALSE); \
191 #define MONO_OUTPUT_VTS(cfg, size, dr, dx, sr, so) do { \
195 tmpr = mono_alloc_preg (cfg); \
196 MONO_EMIT_NEW_ICONST(cfg, tmpr, 0); \
197 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
201 tmpr = mono_alloc_preg (cfg); \
202 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU1_MEMBASE, \
204 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
208 tmpr = mono_alloc_preg (cfg); \
209 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU2_MEMBASE, \
211 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
215 tmpr = mono_alloc_preg (cfg); \
216 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI4_MEMBASE, \
218 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
222 MONO_EMIT_NEW_MOVE (cfg, dr, dx, sr, so, size); \
228 #define DEBUG(a) if (cfg->verbose_level > 1) a
232 #define S390_TRACE_STACK_SIZE (5*sizeof(gpointer)+4*sizeof(gdouble))
234 #define BREAKPOINT_SIZE sizeof(breakpoint_t)
235 #define S390X_NOP_SIZE sizeof(RR_Format)
237 #define MAX(a, b) ((a) > (b) ? (a) : (b))
240 * imt trampoline size values
243 #define LOADCON_SIZE 20
247 #define ENABLE_WRONG_METHOD_CHECK 0
249 #define mono_mini_arch_lock() mono_os_mutex_lock (&mini_arch_mutex)
250 #define mono_mini_arch_unlock() mono_os_mutex_unlock (&mini_arch_mutex)
252 /*========================= End of Defines =========================*/
254 /*------------------------------------------------------------------*/
255 /* I n c l u d e s */
256 /*------------------------------------------------------------------*/
260 #include <sys/types.h>
263 #include <mono/metadata/abi-details.h>
264 #include <mono/metadata/appdomain.h>
265 #include <mono/metadata/debug-helpers.h>
266 #include <mono/metadata/profiler-private.h>
267 #include <mono/utils/mono-error.h>
268 #include <mono/utils/mono-error-internals.h>
269 #include <mono/utils/mono-math.h>
270 #include <mono/utils/mono-mmap.h>
271 #include <mono/utils/mono-hwcap.h>
272 #include <mono/utils/mono-threads.h>
274 #include "mini-s390x.h"
275 #include "cpu-s390x.h"
276 #include "support-s390x.h"
277 #include "jit-icalls.h"
282 /*========================= End of Includes ========================*/
284 /*------------------------------------------------------------------*/
285 /* T y p e d e f s */
286 /*------------------------------------------------------------------*/
298 /*------------------------------------------------------------------*/
299 /* Used by the instrument_emit_epilog */
300 /*------------------------------------------------------------------*/
311 typedef struct InstList InstList;
325 RegTypeStructByValInFP,
327 RegTypeStructByAddrOnStack
331 gint32 offset; /* offset from caller's stack */
332 gint32 offparm; /* offset from callee's stack */
333 guint16 vtsize; /* in param area */
336 guint32 size; /* Size of structure used by RegTypeStructByVal */
337 gint32 type; /* Data type of argument */
353 gint64 gr[5]; /* R2-R6 */
354 gdouble fp[3]; /* F0-F2 */
355 } __attribute__ ((packed)) RegParm;
363 } __attribute__ ((packed)) breakpoint_t;
365 /*========================= End of Typedefs ========================*/
367 /*------------------------------------------------------------------*/
368 /* P r o t o t y p e s */
369 /*------------------------------------------------------------------*/
371 static void indent (int);
372 static guint8 * backUpStackPtr(MonoCompile *, guint8 *);
373 static void decodeParm (MonoType *, void *, int);
374 static void enter_method (MonoMethod *, RegParm *, char *);
375 static void leave_method (MonoMethod *, ...);
376 static inline void add_general (guint *, size_data *, ArgInfo *);
377 static inline void add_stackParm (guint *, size_data *, ArgInfo *, gint);
378 static inline void add_float (guint *, size_data *, ArgInfo *);
379 static CallInfo * get_call_info (MonoCompile *, MonoMemPool *, MonoMethodSignature *);
380 static guchar * emit_float_to_int (MonoCompile *, guchar *, int, int, int, gboolean);
381 static guint8 * emit_load_volatile_arguments (guint8 *, MonoCompile *);
382 static __inline__ void emit_unwind_regs(MonoCompile *, guint8 *, int, int, long);
384 /*========================= End of Prototypes ======================*/
386 /*------------------------------------------------------------------*/
387 /* G l o b a l V a r i a b l e s */
388 /*------------------------------------------------------------------*/
390 int mono_exc_esp_offset = 0;
392 __thread int indent_level = 0;
394 static gint appdomain_tls_offset = -1,
396 lmf_addr_tls_offset = -1;
398 pthread_key_t lmf_addr_key;
400 gboolean lmf_addr_key_inited = FALSE;
403 * The code generated for sequence points reads from this location,
404 * which is made read-only when single stepping is enabled.
406 static gpointer ss_trigger_page;
409 * Enabled breakpoints read from this trigger page
411 static gpointer bp_trigger_page;
413 breakpoint_t breakpointCode;
415 static mono_mutex_t mini_arch_mutex;
417 static const char * grNames[] = {
418 "s390_r0", "s390_sp", "s390_r2", "s390_r3", "s390_r4",
419 "s390_r5", "s390_r6", "s390_r7", "s390_r8", "s390_r9",
420 "s390_r10", "s390_r11", "s390_r12", "s390_r13", "s390_r14",
424 static const char * fpNames[] = {
425 "s390_f0", "s390_f1", "s390_f2", "s390_f3", "s390_f4",
426 "s390_f5", "s390_f6", "s390_f7", "s390_f8", "s390_f9",
427 "s390_f10", "s390_f11", "s390_f12", "s390_f13", "s390_f14",
431 static const char * vrNames[] = {
432 "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7",
433 "vr8", "vr9", "vr10", "vr11", "vr12", "vr13", "vr14", "vr15",
434 "vr16", "vr17", "vr18", "vr19", "vr20", "vr21", "vr22", "vr23",
435 "vr24", "vr25", "vr26", "vr27", "vr28", "vr29", "vr30", "vr31"
438 /*====================== End of Global Variables ===================*/
440 /*------------------------------------------------------------------*/
442 /* Name - mono_arch_regname */
444 /* Function - Returns the name of the register specified by */
445 /* the input parameter. */
447 /*------------------------------------------------------------------*/
450 mono_arch_regname (int reg)
452 if (reg >= 0 && reg < 16)
453 return grNames [reg];
458 /*========================= End of Function ========================*/
460 /*------------------------------------------------------------------*/
462 /* Name - mono_arch_fregname */
464 /* Function - Returns the name of the register specified by */
465 /* the input parameter. */
467 /*------------------------------------------------------------------*/
470 mono_arch_fregname (int reg)
472 if (reg >= 0 && reg < 16)
473 return fpNames [reg];
478 /*========================= End of Function ========================*/
480 /*------------------------------------------------------------------*/
482 /* Name - mono_arch_xregname */
484 /* Function - Returns the name of the register specified by */
485 /* the input parameter. */
487 /*------------------------------------------------------------------*/
490 mono_arch_xregname (int reg)
492 if (reg < s390_VR_NREG)
493 return vrNames [reg];
498 /*========================= End of Function ========================*/
500 /*------------------------------------------------------------------*/
502 /* Name - arch_get_argument_info */
504 /* Function - Gathers information on parameters such as size, */
505 /* alignment, and padding. arg_info should be large */
506 /* enough to hold param_count + 1 entries. */
508 /* Parameters - @csig - Method signature */
509 /* @param_count - No. of parameters to consider */
510 /* @arg_info - An array to store the result info */
512 /* Returns - Size of the activation frame */
514 /*------------------------------------------------------------------*/
517 mono_arch_get_argument_info (MonoMethodSignature *csig,
519 MonoJitArgumentInfo *arg_info)
521 int k, frame_size = 0;
522 int size, align, pad;
525 if (MONO_TYPE_ISSTRUCT (csig->ret)) {
526 frame_size += sizeof (gpointer);
530 arg_info [0].offset = offset;
533 frame_size += sizeof (gpointer);
537 arg_info [0].size = frame_size;
539 for (k = 0; k < param_count; k++) {
542 size = mono_type_native_stack_size (csig->params [k], (guint32 *) &align);
544 size = mini_type_stack_size (csig->params [k], &align);
546 frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
547 arg_info [k].pad = pad;
549 arg_info [k + 1].pad = 0;
550 arg_info [k + 1].size = size;
552 arg_info [k + 1].offset = offset;
556 align = MONO_ARCH_FRAME_ALIGNMENT;
557 frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
558 arg_info [k].pad = pad;
563 /*========================= End of Function ========================*/
565 /*------------------------------------------------------------------*/
567 /* Name - emit_unwind_regs. */
569 /* Function - Determines if a value can be returned in one or */
572 /*------------------------------------------------------------------*/
574 static void __inline__
575 emit_unwind_regs(MonoCompile *cfg, guint8 *code, int start, int end, long offset)
579 for (i = start; i < end; i++) {
580 mono_emit_unwind_op_offset (cfg, code, i, offset);
581 mini_gc_set_slot_type_from_cfa (cfg, offset, SLOT_NOREF);
582 offset += sizeof(gulong);
586 /*========================= End of Function ========================*/
588 /*------------------------------------------------------------------*/
590 /* Name - retFitsInReg. */
592 /* Function - Determines if a value can be returned in one or */
595 /*------------------------------------------------------------------*/
597 static inline gboolean
598 retFitsInReg(guint32 size)
613 /*========================= End of Function ========================*/
615 /*------------------------------------------------------------------*/
617 /* Name - backStackPtr. */
619 /* Function - Restore Stack Pointer to previous frame. */
621 /*------------------------------------------------------------------*/
623 static inline guint8 *
624 backUpStackPtr(MonoCompile *cfg, guint8 *code)
626 int stackSize = cfg->stack_usage;
628 if (cfg->frame_reg != STK_BASE)
629 s390_lgr (code, STK_BASE, cfg->frame_reg);
631 if (s390_is_imm16 (stackSize)) {
632 s390_aghi (code, STK_BASE, stackSize);
634 while (stackSize > 32767) {
635 s390_aghi (code, STK_BASE, 32767);
638 s390_aghi (code, STK_BASE, stackSize);
643 /*========================= End of Function ========================*/
645 /*------------------------------------------------------------------*/
649 /* Function - Perform nice indenting to current level */
651 /*------------------------------------------------------------------*/
657 indent_level += diff;
659 printf("%p [%3d] ",(void *)pthread_self(),v);
664 indent_level += diff;
667 /*========================= End of Function ========================*/
669 /*------------------------------------------------------------------*/
671 /* Name - cvtMonoType */
673 /* Function - Convert a mono-type to a string. */
675 /*------------------------------------------------------------------*/
678 cvtMonoType(MonoTypeEnum t)
683 return "MONO_TYPE_END";
685 return "MONO_TYPE_VOID";
686 case MONO_TYPE_BOOLEAN:
687 return "MONO_TYPE_BOOLEAN";
689 return "MONO_TYPE_CHAR";
691 return "MONO_TYPE_I1";
693 return "MONO_TYPE_U1";
695 return "MONO_TYPE_I2";
697 return "MONO_TYPE_U2";
699 return "MONO_TYPE_I4";
701 return "MONO_TYPE_U4";
703 return "MONO_TYPE_I8";
705 return "MONO_TYPE_U8";
707 return "MONO_TYPE_R4";
709 return "MONO_TYPE_R8";
710 case MONO_TYPE_STRING:
711 return "MONO_TYPE_STRING";
713 return "MONO_TYPE_PTR";
714 case MONO_TYPE_BYREF:
715 return "MONO_TYPE_BYREF";
716 case MONO_TYPE_VALUETYPE:
717 return "MONO_TYPE_VALUETYPE";
718 case MONO_TYPE_CLASS:
719 return "MONO_TYPE_CLASS";
721 return "MONO_TYPE_VAR";
722 case MONO_TYPE_ARRAY:
723 return "MONO_TYPE_ARRAY";
724 case MONO_TYPE_GENERICINST:
725 return "MONO_TYPE_GENERICINST";
726 case MONO_TYPE_TYPEDBYREF:
727 return "MONO_TYPE_TYPEDBYREF";
729 return "MONO_TYPE_I";
731 return "MONO_TYPE_U";
732 case MONO_TYPE_FNPTR:
733 return "MONO_TYPE_FNPTR";
734 case MONO_TYPE_OBJECT:
735 return "MONO_TYPE_OBJECT";
736 case MONO_TYPE_SZARRAY:
737 return "MONO_TYPE_SZARRAY";
739 return "MONO_TYPE_MVAR";
740 case MONO_TYPE_CMOD_REQD:
741 return "MONO_TYPE_CMOD_REQD";
742 case MONO_TYPE_CMOD_OPT:
743 return "MONO_TYPE_CMOD_OPT";
744 case MONO_TYPE_INTERNAL:
745 return "MONO_TYPE_INTERNAL";
746 case MONO_TYPE_MODIFIER:
747 return "MONO_TYPE_MODIFIER";
748 case MONO_TYPE_SENTINEL:
749 return "MONO_TYPE_SENTINEL";
750 case MONO_TYPE_PINNED:
751 return "MONO_TYPE_PINNED";
758 /*========================= End of Function ========================*/
760 /*------------------------------------------------------------------*/
762 /* Name - decodeParm */
764 /* Function - Decode a parameter for the trace. */
766 /*------------------------------------------------------------------*/
769 decodeParmString (MonoString *s)
772 char *str = mono_string_to_utf8_checked(s, &error);
773 if (is_ok (&error)) {
774 printf("[STRING:%p:%s], ", s, str);
777 mono_error_cleanup (&error);
778 printf("[STRING:%p:], ", s);
783 decodeParm(MonoType *type, void *curParm, int size)
788 printf("[BYREF:%p], ", *((char **) curParm));
790 simpleType = mini_get_underlying_type(type)->type;
792 switch (simpleType) {
794 printf ("[INTPTR:%p], ", *((int **) curParm));
797 printf ("[UINTPTR:%p], ", *((int **) curParm));
799 case MONO_TYPE_BOOLEAN :
800 printf ("[BOOL:%ld], ", *((gint64 *) curParm));
802 case MONO_TYPE_CHAR :
803 printf ("[CHAR:%c], ", *((int *) curParm));
806 printf ("[INT1:%ld], ", *((gint64 *) curParm));
809 printf ("[INT2:%ld], ", *((gint64 *) curParm));
812 printf ("[INT4:%ld], ", *((gint64 *) curParm));
815 printf ("[UINT1:%lu], ", *((guint64 *) curParm));
818 printf ("[UINT2:%lu], ", *((guint64 *) curParm));
821 printf ("[UINT4:%lu], ", *((guint64 *) curParm));
824 printf ("[UINT8:%lu], ", *((guint64 *) curParm));
826 case MONO_TYPE_STRING : {
827 MonoString *s = *((MonoString **) curParm);
829 g_assert (((MonoObject *) s)->vtable->klass == mono_defaults.string_class);
830 decodeParmString (s);
832 printf("[STRING:null], ");
836 case MONO_TYPE_CLASS :
837 case MONO_TYPE_OBJECT : {
838 MonoObject *obj = *((MonoObject **) curParm);
840 if ((obj) && (obj->vtable)) {
841 printf("[CLASS/OBJ:");
842 klass = obj->vtable->klass;
843 printf("%p [%p] ",obj,curParm);
844 if (klass == mono_defaults.string_class) {
845 decodeParmString ((MonoString *)obj);
846 } else if (klass == mono_defaults.int32_class) {
847 printf("[INT32:%p:%d]",
848 obj, *(gint32 *)((char *)obj + sizeof (MonoObject)));
851 klass->name_space, klass->name, obj);
854 printf("[OBJECT:null], ");
859 printf("[PTR:%p], ", *((gpointer **) (curParm)));
861 case MONO_TYPE_FNPTR :
862 printf("[FNPTR:%p], ", *((gpointer **) (curParm)));
864 case MONO_TYPE_ARRAY :
865 printf("[ARRAY:%p], ", *((gpointer **) (curParm)));
867 case MONO_TYPE_SZARRAY :
868 printf("[SZARRAY:%p], ", *((gpointer **) (curParm)));
871 printf("[INT8:%ld], ", *((gint64 *) (curParm)));
874 printf("[FLOAT4:%g], ", *((float *) (curParm)));
877 printf("[FLOAT8:%g], ", *((double *) (curParm)));
879 case MONO_TYPE_VALUETYPE : {
881 MonoMarshalType *info;
883 if (type->data.klass->enumtype) {
884 simpleType = mono_class_enum_basetype (type->data.klass)->type;
885 printf("{VALUETYPE} - ");
889 info = mono_marshal_load_type_info (type->data.klass);
891 if ((info->native_size == sizeof(float)) &&
892 (info->num_fields == 1) &&
893 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
894 printf("[FLOAT4:%f], ", *((float *) (curParm)));
898 if ((info->native_size == sizeof(double)) &&
899 (info->num_fields == 1) &&
900 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
901 printf("[FLOAT8:%g], ", *((double *) (curParm)));
905 printf("[VALUETYPE:");
906 for (i = 0; i < size; i++)
907 printf("%02x,", *((guint8 *)curParm+i));
911 case MONO_TYPE_TYPEDBYREF: {
913 printf("[TYPEDBYREF:");
914 for (i = 0; i < size; i++)
915 printf("%02x,", *((guint8 *)curParm+i));
920 printf("[%s], ",cvtMonoType(simpleType));
925 /*========================= End of Function ========================*/
927 /*------------------------------------------------------------------*/
929 /* Name - enter_method */
931 /* Function - Perform tracing of the entry to the current */
934 /*------------------------------------------------------------------*/
937 enter_method (MonoMethod *method, RegParm *rParm, char *sp)
939 int i, oParm = 0, iParm = 0;
942 MonoMethodSignature *sig;
949 fname = mono_method_full_name (method, TRUE);
951 printf ("ENTER: %s ", fname);
954 ip = (*(guint64 *) (sp+S390_RET_ADDR_OFFSET));
955 printf ("ip: %p sp: %p - ", (gpointer) ip, sp);
960 sig = mono_method_signature (method);
962 cinfo = get_call_info (NULL, NULL, sig);
964 if (cinfo->struct_ret) {
965 printf ("[STRUCTRET:%p], ", (gpointer) rParm->gr[0]);
970 gpointer *this_arg = (gpointer *) rParm->gr[iParm];
971 obj = (MonoObject *) this_arg;
972 switch(method->klass->this_arg.type) {
973 case MONO_TYPE_VALUETYPE:
975 guint64 *value = (guint64 *) ((uintptr_t)this_arg + sizeof(MonoObject));
976 printf("this:[value:%p:%016lx], ", this_arg, *value);
978 printf ("this:[NULL], ");
980 case MONO_TYPE_STRING:
983 klass = obj->vtable->klass;
984 if (klass == mono_defaults.string_class) {
986 decodeParmString((MonoString *)obj);
988 printf ("this:%p[%s.%s], ",
989 obj, klass->name_space, klass->name);
992 printf("vtable:[NULL], ");
994 printf ("this:[NULL], ");
997 printf("this[%s]: %p, ",cvtMonoType(method->klass->this_arg.type),this_arg);
1002 for (i = 0; i < sig->param_count; ++i) {
1003 ainfo = &cinfo->args[i + oParm];
1004 switch (ainfo->regtype) {
1005 case RegTypeGeneral :
1006 decodeParm(sig->params[i], &(rParm->gr[ainfo->reg-2]), ainfo->size);
1009 decodeParm(sig->params[i], &(rParm->fp[ainfo->reg]), ainfo->size);
1012 decodeParm(sig->params[i], sp+ainfo->offset, ainfo->size);
1014 case RegTypeStructByVal :
1015 if (ainfo->reg != STK_BASE) {
1016 int offset = sizeof(glong) - ainfo->size;
1017 curParm = &(rParm->gr[ainfo->reg-2])+offset;
1020 curParm = sp+ainfo->offset;
1022 if (retFitsInReg (ainfo->vtsize))
1023 decodeParm(sig->params[i],
1027 decodeParm(sig->params[i],
1028 *((char **) curParm),
1031 case RegTypeStructByAddr :
1032 if (ainfo->reg != STK_BASE)
1033 curParm = &(rParm->gr[ainfo->reg-2]);
1035 curParm = sp+ainfo->offset;
1037 decodeParm(sig->params[i],
1038 *((char **) curParm),
1050 /*========================= End of Function ========================*/
1052 /*------------------------------------------------------------------*/
1054 /* Name - leave_method */
1058 /*------------------------------------------------------------------*/
1061 leave_method (MonoMethod *method, ...)
1068 va_start(ap, method);
1070 fname = mono_method_full_name (method, TRUE);
1072 printf ("LEAVE: %s", fname);
1075 type = mono_method_signature (method)->ret;
1078 switch (type->type) {
1079 case MONO_TYPE_VOID:
1081 case MONO_TYPE_BOOLEAN: {
1082 int val = va_arg (ap, int);
1084 printf ("[TRUE:%d]", val);
1090 case MONO_TYPE_CHAR: {
1091 int val = va_arg (ap, int);
1092 printf ("[CHAR:%d]", val);
1095 case MONO_TYPE_I1: {
1096 int val = va_arg (ap, int);
1097 printf ("[INT1:%d]", val);
1100 case MONO_TYPE_U1: {
1101 int val = va_arg (ap, int);
1102 printf ("[UINT1:%d]", val);
1105 case MONO_TYPE_I2: {
1106 int val = va_arg (ap, int);
1107 printf ("[INT2:%d]", val);
1110 case MONO_TYPE_U2: {
1111 int val = va_arg (ap, int);
1112 printf ("[UINT2:%d]", val);
1115 case MONO_TYPE_I4: {
1116 int val = va_arg (ap, int);
1117 printf ("[INT4:%d]", val);
1120 case MONO_TYPE_U4: {
1121 int val = va_arg (ap, int);
1122 printf ("[UINT4:%d]", val);
1126 gint64 val = va_arg (ap, gint64);
1127 printf ("[INT:%ld]", val);
1132 gint64 val = va_arg (ap, gint64);
1133 printf ("[UINT:%lu]", val);
1137 case MONO_TYPE_STRING: {
1138 MonoString *s = va_arg (ap, MonoString *);
1141 g_assert (((MonoObject *)s)->vtable->klass == mono_defaults.string_class);
1142 decodeParmString (s);
1144 printf ("[STRING:null], ");
1147 case MONO_TYPE_CLASS:
1148 case MONO_TYPE_OBJECT: {
1149 MonoObject *o = va_arg (ap, MonoObject *);
1151 if ((o) && (o->vtable)) {
1152 if (o->vtable->klass == mono_defaults.boolean_class) {
1153 printf ("[BOOLEAN:%p:%d]", o, *((guint8 *)o + sizeof (MonoObject)));
1154 } else if (o->vtable->klass == mono_defaults.int32_class) {
1155 printf ("[INT32:%p:%d]", o, *((gint32 *)((char *)o + sizeof (MonoObject))));
1156 } else if (o->vtable->klass == mono_defaults.int64_class) {
1157 printf ("[INT64:%p:%ld]", o, *((gint64 *)((char *)o + sizeof (MonoObject))));
1159 printf ("[%s.%s:%p]", o->vtable->klass->name_space, o->vtable->klass->name, o);
1161 printf ("[OBJECT:%p]", o);
1166 case MONO_TYPE_FNPTR:
1167 case MONO_TYPE_ARRAY:
1168 case MONO_TYPE_SZARRAY: {
1169 gpointer p = va_arg (ap, gpointer);
1170 printf ("[result=%p]", p);
1173 case MONO_TYPE_I8: {
1174 gint64 l = va_arg (ap, gint64);
1175 printf ("[LONG:%ld]", l);
1178 case MONO_TYPE_U8: {
1179 guint64 l = va_arg (ap, guint64);
1180 printf ("[ULONG:%lu]", l);
1183 case MONO_TYPE_R4: {
1184 double f = va_arg (ap, double);
1185 printf ("[FLOAT4:%g]\n", f);
1188 case MONO_TYPE_R8: {
1189 double f = va_arg (ap, double);
1190 printf ("[FLOAT8:%g]\n", f);
1193 case MONO_TYPE_VALUETYPE: {
1194 MonoMarshalType *info;
1195 if (type->data.klass->enumtype) {
1196 type = mono_class_enum_basetype (type->data.klass);
1201 info = mono_marshal_load_type_info (type->data.klass);
1203 if ((info->native_size == sizeof(float)) &&
1204 (info->num_fields == 1) &&
1205 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1206 double f = va_arg (ap, double);
1207 printf("[FLOAT4:%g]\n", (double) f);
1211 if ((info->native_size == sizeof(double)) &&
1212 (info->num_fields == 1) &&
1213 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1214 double f = va_arg (ap, double);
1215 printf("[FLOAT8:%g]\n", f);
1219 size = mono_type_size (type, &align);
1222 guint32 p = va_arg (ap, guint32);
1223 printf ("[%02x]\n",p);
1227 guint32 p = va_arg (ap, guint32);
1228 printf ("[%04x]\n",p);
1232 guint32 p = va_arg (ap, guint32);
1233 printf ("[%08x]\n",p);
1237 guint64 p = va_arg (ap, guint64);
1238 printf ("[%016lx]\n",p);
1242 gpointer p = va_arg (ap, gpointer);
1243 printf ("[VALUETYPE] %p\n",p);
1249 case MONO_TYPE_TYPEDBYREF: {
1250 guint8 *p = va_arg (ap, gpointer);
1252 size = mono_type_size (type, &align);
1259 for (j = 0; p && j < size; j++)
1260 printf ("%02x,", p [j]);
1264 printf ("[TYPEDBYREF]\n");
1268 case MONO_TYPE_GENERICINST: {
1269 printf("[GENERICINST]\n");
1272 case MONO_TYPE_MVAR: {
1276 case MONO_TYPE_CMOD_REQD: {
1277 printf("[CMOD_REQD]\n");
1280 case MONO_TYPE_CMOD_OPT: {
1281 printf("[CMOD_OPT]\n");
1284 case MONO_TYPE_INTERNAL: {
1285 printf("[INTERNAL]\n");
1289 printf ("(unknown return type %x)",
1290 mono_method_signature (method)->ret->type);
1293 ip = ((gint64) __builtin_extract_return_addr (__builtin_return_address (0)));
1294 printf (" ip: %p\n", (gpointer) ip);
1298 /*========================= End of Function ========================*/
1300 /*------------------------------------------------------------------*/
1302 /* Name - mono_arch_cpu_init */
1304 /* Function - Perform CPU specific initialization to execute */
1307 /*------------------------------------------------------------------*/
1310 mono_arch_cpu_init (void)
1314 /*========================= End of Function ========================*/
1316 /*------------------------------------------------------------------*/
1318 /* Name - mono_arch_init. */
1320 /* Function - Initialize architecture specific code. */
1322 /*------------------------------------------------------------------*/
1325 mono_arch_init (void)
1329 mono_set_partial_sharing_supported (FALSE);
1330 mono_os_mutex_init_recursive (&mini_arch_mutex);
1332 ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ, MONO_MEM_ACCOUNT_OTHER);
1333 bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ, MONO_MEM_ACCOUNT_OTHER);
1334 mono_mprotect (bp_trigger_page, mono_pagesize (), 0);
1336 code = (guint8 *) &breakpointCode;
1337 s390_basr(code, s390_r13, 0);
1339 s390_llong(code, 0);
1340 s390_lg(code, s390_r13, 0, s390_r13, 4);
1341 s390_lg(code, s390_r0, 0, s390_r13, 0);
1344 /*========================= End of Function ========================*/
1346 /*------------------------------------------------------------------*/
1348 /* Name - mono_arch_cleanup. */
1350 /* Function - Cleanup architecture specific code . */
1352 /*------------------------------------------------------------------*/
1355 mono_arch_cleanup (void)
1357 if (ss_trigger_page)
1358 mono_vfree (ss_trigger_page, mono_pagesize (), MONO_MEM_ACCOUNT_OTHER);
1359 if (bp_trigger_page)
1360 mono_vfree (bp_trigger_page, mono_pagesize (), MONO_MEM_ACCOUNT_OTHER);
1361 mono_os_mutex_destroy (&mini_arch_mutex);
1364 /*========================= End of Function ========================*/
1366 /*------------------------------------------------------------------*/
1368 /* Name - mono_arch_cpu_optimizations */
1370 /* Function - Returns the optimizations supported on this CPU */
1372 /*------------------------------------------------------------------*/
1375 mono_arch_cpu_optimizations (guint32 *exclude_mask)
1379 /*----------------------------------------------------------*/
1380 /* No s390-specific optimizations yet */
1381 /*----------------------------------------------------------*/
1382 *exclude_mask = MONO_OPT_LINEARS;
1386 /*========================= End of Function ========================*/
1388 /*------------------------------------------------------------------*/
1390 /* Name - mono_arch_get_allocatable_int_vars */
1394 /*------------------------------------------------------------------*/
1397 mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
1402 for (i = 0; i < cfg->num_varinfo; i++) {
1403 MonoInst *ins = cfg->varinfo [i];
1404 MonoMethodVar *vmv = MONO_VARINFO (cfg, i);
1407 if (vmv->range.first_use.abs_pos >= vmv->range.last_use.abs_pos)
1410 if (ins->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) ||
1411 (ins->opcode != OP_LOCAL && ins->opcode != OP_ARG))
1414 /* we can only allocate 32 bit values */
1415 if (mono_is_regsize_var(ins->inst_vtype)) {
1416 g_assert (MONO_VARINFO (cfg, i)->reg == -1);
1417 g_assert (i == vmv->idx);
1418 vars = mono_varlist_insert_sorted (cfg, vars, vmv, FALSE);
1425 /*========================= End of Function ========================*/
1427 /*------------------------------------------------------------------*/
1429 /* Name - mono_arch_global_int_regs */
1431 /* Function - Return a list of usable integer registers. */
1433 /*------------------------------------------------------------------*/
1436 mono_arch_get_global_int_regs (MonoCompile *cfg)
1439 MonoMethodHeader *header;
1442 header = cfg->header;
1443 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
1444 cfg->frame_reg = s390_r11;
1447 /* FIXME: s390_r12 is reserved for bkchain_reg. Only reserve it if needed */
1449 for (i = 8; i < top; ++i) {
1450 if (cfg->frame_reg != i)
1451 regs = g_list_prepend (regs, GUINT_TO_POINTER (i));
1457 /*========================= End of Function ========================*/
1459 /*------------------------------------------------------------------*/
1461 /* Name - mono_arch_flush_icache */
1463 /* Function - Flush the CPU icache. */
1465 /*------------------------------------------------------------------*/
1468 mono_arch_flush_icache (guint8 *code, gint size)
1472 /*========================= End of Function ========================*/
1474 /*------------------------------------------------------------------*/
1476 /* Name - add_general */
1478 /* Function - Determine code and stack size incremements for a */
1481 /*------------------------------------------------------------------*/
1484 add_general (guint *gr, size_data *sz, ArgInfo *ainfo)
1486 if (*gr > S390_LAST_ARG_REG) {
1487 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1488 ainfo->offset = sz->stack_size;
1489 ainfo->reg = STK_BASE;
1490 ainfo->regtype = RegTypeBase;
1491 sz->stack_size += sizeof(long);
1492 sz->local_size += sizeof(long);
1493 sz->offStruct += sizeof(long);
1494 sz->code_size += 12;
1502 /*========================= End of Function ========================*/
1504 /*------------------------------------------------------------------*/
1506 /* Name - add_stackParm */
1508 /* Function - Determine code and stack size incremements for a */
1511 /*------------------------------------------------------------------*/
1514 add_stackParm (guint *gr, size_data *sz, ArgInfo *ainfo, gint size)
1516 if (*gr > S390_LAST_ARG_REG) {
1517 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1518 ainfo->reg = STK_BASE;
1519 ainfo->offset = sz->stack_size;
1520 ainfo->regtype = RegTypeStructByAddrOnStack;
1521 sz->stack_size += sizeof (gpointer);
1522 sz->parm_size += sizeof(gpointer);
1523 sz->offStruct += sizeof(gpointer);
1526 ainfo->offset = sz->stack_size;
1527 ainfo->regtype = RegTypeStructByAddr;
1530 ainfo->offparm = sz->offset;
1531 sz->offset = S390_ALIGN(sz->offset+size, sizeof(long));
1533 ainfo->vtsize = size;
1534 sz->parm_size += size;
1537 /*========================= End of Function ========================*/
1539 /*------------------------------------------------------------------*/
1541 /* Name - add_float */
1543 /* Function - Determine code and stack size incremements for a */
1544 /* float parameter. */
1546 /*------------------------------------------------------------------*/
1549 add_float (guint *fr, size_data *sz, ArgInfo *ainfo)
1551 if ((*fr) <= S390_LAST_FPARG_REG) {
1552 ainfo->regtype = RegTypeFP;
1558 ainfo->offset = sz->stack_size;
1559 ainfo->reg = STK_BASE;
1560 ainfo->regtype = RegTypeBase;
1562 sz->stack_size += sizeof(double);
1563 sz->local_size += sizeof(double);
1564 sz->offStruct += sizeof(double);
1568 /*========================= End of Function ========================*/
1570 /*------------------------------------------------------------------*/
1572 /* Name - get_call_info */
1574 /* Function - Determine the amount of space required for code */
1575 /* and stack. In addition determine starting points */
1576 /* for stack-based parameters, and area for struct- */
1577 /* ures being returned on the stack. */
1579 /*------------------------------------------------------------------*/
1582 get_call_info (MonoCompile *cfg, MonoMemPool *mp, MonoMethodSignature *sig)
1584 guint i, fr, gr, size, pstart;
1585 int nParm = sig->hasthis + sig->param_count;
1587 guint32 simpleType, align;
1588 gboolean is_pinvoke = sig->pinvoke;
1593 cinfo = mono_mempool_alloc0 (mp, sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1595 cinfo = g_malloc0 (sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1600 cinfo->struct_ret = 0;
1604 sz->offStruct = S390_MINIMAL_STACK_SIZE;
1605 sz->stack_size = S390_MINIMAL_STACK_SIZE;
1612 /*----------------------------------------------------------*/
1613 /* We determine the size of the return code/stack in case we*/
1614 /* need to reserve a register to be used to address a stack */
1615 /* area that the callee will use. */
1616 /*----------------------------------------------------------*/
1618 ret_type = mini_get_underlying_type (sig->ret);
1619 simpleType = ret_type->type;
1621 switch (simpleType) {
1622 case MONO_TYPE_BOOLEAN:
1627 case MONO_TYPE_CHAR:
1632 case MONO_TYPE_CLASS:
1633 case MONO_TYPE_OBJECT:
1634 case MONO_TYPE_SZARRAY:
1635 case MONO_TYPE_ARRAY:
1637 case MONO_TYPE_FNPTR:
1638 case MONO_TYPE_STRING:
1639 cinfo->ret.reg = s390_r2;
1644 cinfo->ret.reg = s390_f0;
1649 cinfo->ret.reg = s390_r2;
1652 case MONO_TYPE_GENERICINST:
1653 if (!mono_type_generic_inst_is_valuetype (sig->ret)) {
1654 cinfo->ret.reg = s390_r2;
1659 case MONO_TYPE_VALUETYPE: {
1660 MonoClass *klass = mono_class_from_mono_type (sig->ret);
1661 if (klass->enumtype) {
1662 simpleType = mono_class_enum_basetype (klass)->type;
1665 size = mini_type_stack_size_full (&klass->byval_arg, NULL, sig->pinvoke);
1667 cinfo->struct_ret = 1;
1668 cinfo->ret.size = size;
1669 cinfo->ret.vtsize = size;
1672 case MONO_TYPE_TYPEDBYREF:
1673 size = sizeof (MonoTypedRef);
1674 cinfo->struct_ret = 1;
1675 cinfo->ret.size = size;
1676 cinfo->ret.vtsize = size;
1678 case MONO_TYPE_VOID:
1681 g_error ("Can't handle as return value 0x%x", sig->ret->type);
1687 * To simplify get_this_arg_reg () and LLVM integration, emit the vret arg after
1688 * the first argument, allowing 'this' to be always passed in the first arg reg.
1689 * Also do this if the first argument is a reference type, since virtual calls
1690 * are sometimes made using calli without sig->hasthis set, like in the delegate
1693 if (cinfo->struct_ret && !is_pinvoke &&
1695 (sig->param_count > 0 &&
1696 MONO_TYPE_IS_REFERENCE (mini_get_underlying_type (sig->params [0]))))) {
1698 cinfo->args[nParm].size = sizeof (gpointer);
1699 add_general (&gr, sz, cinfo->args + nParm);
1701 cinfo->args[nParm].size = sizeof (gpointer);
1702 add_general (&gr, sz, &cinfo->args [sig->hasthis + nParm]);
1706 cinfo->vret_arg_index = 1;
1707 cinfo->ret.reg = gr;
1712 cinfo->args[nParm].size = sizeof (gpointer);
1713 add_general (&gr, sz, cinfo->args + nParm);
1717 if (cinfo->struct_ret) {
1718 cinfo->ret.reg = gr;
1723 if ((sig->call_convention == MONO_CALL_VARARG) && (sig->param_count == 0)) {
1724 gr = S390_LAST_ARG_REG + 1;
1725 fr = S390_LAST_FPARG_REG + 1;
1727 /* Emit the signature cookie just before the implicit arguments */
1728 add_general (&gr, sz, &cinfo->sigCookie);
1731 /*----------------------------------------------------------*/
1732 /* We determine the size of the parameter code and stack */
1733 /* requirements by checking the types and sizes of the */
1735 /*----------------------------------------------------------*/
1737 for (i = pstart; i < sig->param_count; ++i) {
1740 /*--------------------------------------------------*/
1741 /* Handle vararg type calls. All args are put on */
1743 /*--------------------------------------------------*/
1744 if ((sig->call_convention == MONO_CALL_VARARG) &&
1745 (i == sig->sentinelpos)) {
1746 gr = S390_LAST_ARG_REG + 1;
1747 fr = S390_LAST_FPARG_REG + 1;
1748 add_general (&gr, sz, &cinfo->sigCookie);
1751 if (sig->params [i]->byref) {
1752 add_general (&gr, sz, cinfo->args+nParm);
1753 cinfo->args[nParm].size = sizeof(gpointer);
1758 ptype = mini_get_underlying_type (sig->params [i]);
1759 simpleType = ptype->type;
1760 cinfo->args[nParm].type = simpleType;
1761 switch (simpleType) {
1762 case MONO_TYPE_BOOLEAN:
1765 cinfo->args[nParm].size = sizeof(char);
1766 add_general (&gr, sz, cinfo->args+nParm);
1771 case MONO_TYPE_CHAR:
1772 cinfo->args[nParm].size = sizeof(short);
1773 add_general (&gr, sz, cinfo->args+nParm);
1778 cinfo->args[nParm].size = sizeof(int);
1779 add_general (&gr, sz, cinfo->args+nParm);
1785 case MONO_TYPE_FNPTR:
1786 case MONO_TYPE_CLASS:
1787 case MONO_TYPE_OBJECT:
1788 case MONO_TYPE_STRING:
1789 case MONO_TYPE_SZARRAY:
1790 case MONO_TYPE_ARRAY:
1791 cinfo->args[nParm].size = sizeof(gpointer);
1792 add_general (&gr, sz, cinfo->args+nParm);
1797 cinfo->args[nParm].size = sizeof(long long);
1798 add_general (&gr, sz, cinfo->args+nParm);
1802 cinfo->args[nParm].size = sizeof(float);
1803 add_float (&fr, sz, cinfo->args+nParm);
1807 cinfo->args[nParm].size = sizeof(double);
1808 add_float (&fr, sz, cinfo->args+nParm);
1811 case MONO_TYPE_GENERICINST:
1812 if (!mono_type_generic_inst_is_valuetype (ptype)) {
1813 cinfo->args[nParm].size = sizeof(gpointer);
1814 add_general (&gr, sz, cinfo->args+nParm);
1819 case MONO_TYPE_VALUETYPE: {
1820 MonoMarshalType *info;
1821 MonoClass *klass = mono_class_from_mono_type (ptype);
1824 size = mono_class_native_size(klass, NULL);
1826 size = mono_class_value_size(klass, NULL);
1828 if (simpleType != MONO_TYPE_GENERICINST) {
1829 info = mono_marshal_load_type_info(klass);
1831 if ((info->native_size == sizeof(float)) &&
1832 (info->num_fields == 1) &&
1833 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1834 cinfo->args[nParm].size = sizeof(float);
1835 add_float(&fr, sz, cinfo->args+nParm);
1840 if ((info->native_size == sizeof(double)) &&
1841 (info->num_fields == 1) &&
1842 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1843 cinfo->args[nParm].size = sizeof(double);
1844 add_float(&fr, sz, cinfo->args+nParm);
1850 cinfo->args[nParm].vtsize = 0;
1851 cinfo->args[nParm].size = 0;
1854 /*----------------------------------*/
1855 /* On S/390, structures of size 1, */
1856 /* 2, 4, and 8 bytes are passed in */
1857 /* (a) register(s). */
1858 /*----------------------------------*/
1864 add_general(&gr, sz, cinfo->args+nParm);
1865 cinfo->args[nParm].size = size;
1866 cinfo->args[nParm].regtype = RegTypeStructByVal;
1868 sz->local_size += sizeof(long);
1871 add_stackParm(&gr, sz, cinfo->args+nParm, size);
1876 case MONO_TYPE_TYPEDBYREF: {
1877 int size = sizeof (MonoTypedRef);
1879 cinfo->args[nParm].vtsize = 0;
1880 cinfo->args[nParm].size = 0;
1883 /*----------------------------------*/
1884 /* On S/390, structures of size 1, */
1885 /* 2, 4, and 8 bytes are passed in */
1886 /* (a) register(s). */
1887 /*----------------------------------*/
1893 add_general(&gr, sz, cinfo->args+nParm);
1894 cinfo->args[nParm].size = size;
1895 cinfo->args[nParm].regtype = RegTypeStructByVal;
1897 sz->local_size += sizeof(long);
1900 add_stackParm(&gr, sz, cinfo->args+nParm, size);
1906 g_error ("Can't trampoline 0x%x", ptype);
1910 /*----------------------------------------------------------*/
1911 /* Handle the case where there are no implicit arguments */
1912 /*----------------------------------------------------------*/
1913 if ((sig->call_convention == MONO_CALL_VARARG) &&
1916 (sig->param_count == sig->sentinelpos)) {
1917 gr = S390_LAST_ARG_REG + 1;
1918 fr = S390_LAST_FPARG_REG + 1;
1919 add_general (&gr, sz, &cinfo->sigCookie);
1922 /*----------------------------------------------------------*/
1923 /* If we are passing a structure back then if it won't be */
1924 /* in a register(s) then we make room at the end of the */
1925 /* parameters that may have been placed on the stack */
1926 /*----------------------------------------------------------*/
1927 if (cinfo->struct_ret) {
1928 cinfo->ret.offset = sz->stack_size;
1929 switch (cinfo->ret.size) {
1937 sz->stack_size += S390_ALIGN(cinfo->ret.size, align);
1942 sz->stack_size = sz->stack_size + sz->local_size + sz->parm_size +
1944 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1949 /*========================= End of Function ========================*/
1951 /*------------------------------------------------------------------*/
1953 /* Name - mono_arch_allocate_vars */
1955 /* Function - Set var information according to the calling */
1956 /* convention for S/390. The local var stuff should */
1957 /* most likely be split in another method. */
1959 /* Parameter - @m - Compile unit. */
1961 /*------------------------------------------------------------------*/
1964 mono_arch_allocate_vars (MonoCompile *cfg)
1966 MonoMethodSignature *sig;
1967 MonoMethodHeader *header;
1970 int iParm, iVar, offset, align, size, curinst;
1971 int frame_reg = STK_BASE;
1974 header = cfg->header;
1976 cfg->flags |= MONO_CFG_HAS_SPILLUP;
1978 /*---------------------------------------------------------*/
1979 /* We use the frame register also for any method that has */
1980 /* filter clauses. This way, when the handlers are called, */
1981 /* the code will reference local variables using the frame */
1982 /* reg instead of the stack pointer: if we had to restore */
1983 /* the stack pointer, we'd corrupt the method frames that */
1984 /* are already on the stack (since filters get called */
1985 /* before stack unwinding happens) when the filter code */
1986 /* would call any method. */
1987 /*---------------------------------------------------------*/
1988 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
1989 frame_reg = s390_r11;
1991 cfg->frame_reg = frame_reg;
1993 cfg->arch.bkchain_reg = -1;
1995 if (frame_reg != STK_BASE)
1996 cfg->used_int_regs |= (1 << frame_reg);
1998 if (cfg->uses_rgctx_reg)
1999 cfg->used_int_regs |= (1 << MONO_ARCH_IMT_REG);
2001 sig = mono_method_signature (cfg->method);
2003 cinfo = get_call_info (cfg, cfg->mempool, sig);
2005 if (!cinfo->struct_ret) {
2006 switch (mini_get_underlying_type (sig->ret)->type) {
2007 case MONO_TYPE_VOID:
2010 cfg->ret->opcode = OP_REGVAR;
2011 cfg->ret->dreg = s390_r2;
2016 /*--------------------------------------------------------------*/
2017 /* local vars are at a positive offset from the stack pointer */
2018 /* also note that if the function uses alloca, we use s390_r11 */
2019 /* to point at the local variables. */
2020 /* add parameter area size for called functions */
2021 /*--------------------------------------------------------------*/
2022 if (cfg->param_area == 0)
2023 offset = S390_MINIMAL_STACK_SIZE;
2025 offset = cfg->param_area;
2027 cfg->sig_cookie = 0;
2029 if (cinfo->struct_ret) {
2030 inst = cfg->vret_addr;
2031 offset = S390_ALIGN(offset, sizeof(gpointer));
2032 inst->inst_offset = offset;
2033 inst->opcode = OP_REGOFFSET;
2034 inst->inst_basereg = frame_reg;
2035 offset += sizeof(gpointer);
2036 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2037 printf ("vret_addr =");
2038 mono_print_ins (cfg->vret_addr);
2043 inst = cfg->args [0];
2044 if (inst->opcode != OP_REGVAR) {
2045 inst->opcode = OP_REGOFFSET;
2046 inst->inst_basereg = frame_reg;
2047 offset = S390_ALIGN(offset, sizeof(gpointer));
2048 inst->inst_offset = offset;
2049 offset += sizeof (gpointer);
2056 eArg = sig->param_count + sArg;
2058 if (sig->call_convention == MONO_CALL_VARARG)
2059 cfg->sig_cookie += S390_MINIMAL_STACK_SIZE;
2061 for (iParm = sArg; iParm < eArg; ++iParm) {
2062 inst = cfg->args [curinst];
2063 if (inst->opcode != OP_REGVAR) {
2064 switch (cinfo->args[iParm].regtype) {
2065 case RegTypeStructByAddr : {
2068 size = sizeof (gpointer);
2070 inst->opcode = OP_REGOFFSET;
2071 inst->inst_basereg = frame_reg;
2072 offset = S390_ALIGN (offset, sizeof (gpointer));
2073 inst->inst_offset = offset;
2075 /* Add a level of indirection */
2076 MONO_INST_NEW (cfg, indir, 0);
2078 inst->opcode = OP_VTARG_ADDR;
2079 inst->inst_left = indir;
2082 case RegTypeStructByAddrOnStack : {
2085 size = sizeof (gpointer);
2087 /* Similar to the == STK_BASE case below */
2088 cfg->arch.bkchain_reg = s390_r12;
2089 cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2091 inst->opcode = OP_REGOFFSET;
2092 inst->dreg = mono_alloc_preg (cfg);
2093 inst->inst_basereg = cfg->arch.bkchain_reg;
2094 inst->inst_offset = cinfo->args [iParm].offset;
2096 /* Add a level of indirection */
2097 MONO_INST_NEW (cfg, indir, 0);
2099 inst->opcode = OP_VTARG_ADDR;
2100 inst->inst_left = indir;
2103 case RegTypeStructByVal :
2104 size = cinfo->args[iParm].size;
2105 offset = S390_ALIGN(offset, size);
2106 inst->opcode = OP_REGOFFSET;
2107 inst->inst_basereg = frame_reg;
2108 inst->inst_offset = offset;
2111 if (cinfo->args [iParm].reg == STK_BASE) {
2113 * These arguments are in the previous frame, so we can't
2114 * compute their offset from the current frame pointer right
2115 * now, since cfg->stack_offset is not yet known, so dedicate a
2116 * register holding the previous frame pointer.
2118 cfg->arch.bkchain_reg = s390_r12;
2119 cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2121 inst->opcode = OP_REGOFFSET;
2122 inst->inst_basereg = cfg->arch.bkchain_reg;
2123 size = (cinfo->args[iParm].size < 8
2124 ? 8 - cinfo->args[iParm].size
2126 inst->inst_offset = cinfo->args [iParm].offset + size;
2127 size = sizeof (long);
2129 inst->opcode = OP_REGOFFSET;
2130 inst->inst_basereg = frame_reg;
2131 size = (cinfo->args[iParm].size < 8
2134 offset = S390_ALIGN(offset, size);
2135 if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
2136 inst->inst_offset = offset;
2138 inst->inst_offset = offset + (8 - size);
2143 if ((sig->call_convention == MONO_CALL_VARARG) &&
2144 (cinfo->args[iParm].regtype != RegTypeGeneral) &&
2145 (iParm < sig->sentinelpos))
2146 cfg->sig_cookie += size;
2147 printf("%s %4d cookine %x\n",__FUNCTION__,__LINE__,cfg->sig_cookie);
2150 offset += MAX(size, 8);
2155 cfg->locals_min_stack_offset = offset;
2157 curinst = cfg->locals_start;
2158 for (iVar = curinst; iVar < cfg->num_varinfo; ++iVar) {
2159 inst = cfg->varinfo [iVar];
2160 if ((inst->flags & MONO_INST_IS_DEAD) ||
2161 (inst->opcode == OP_REGVAR))
2164 /*--------------------------------------------------*/
2165 /* inst->backend.is_pinvoke indicates native sized */
2166 /* value typs this is used by the pinvoke wrappers */
2167 /* when they call functions returning structure */
2168 /*--------------------------------------------------*/
2169 if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype))
2170 size = mono_class_native_size (mono_class_from_mono_type(inst->inst_vtype),
2171 (guint32 *) &align);
2173 size = mono_type_size (inst->inst_vtype, &align);
2175 offset = S390_ALIGN(offset, align);
2176 inst->inst_offset = offset;
2177 inst->opcode = OP_REGOFFSET;
2178 inst->inst_basereg = frame_reg;
2180 DEBUG (g_print("allocating local %d to %ld, size: %d\n",
2181 iVar, inst->inst_offset, size));
2184 cfg->locals_max_stack_offset = offset;
2186 /*------------------------------------------------------*/
2187 /* Allow space for the trace method stack area if needed*/
2188 /*------------------------------------------------------*/
2189 if ((mono_jit_trace_calls != NULL && mono_trace_eval (cfg->method))
2190 || (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE))
2191 offset += S390_TRACE_STACK_SIZE;
2193 /*------------------------------------------------------*/
2194 /* Reserve space to save LMF and caller saved registers */
2195 /*------------------------------------------------------*/
2196 if (cfg->method->save_lmf)
2197 offset += sizeof (MonoLMF);
2199 /*------------------------------------------------------*/
2200 /* align the offset */
2201 /*------------------------------------------------------*/
2202 cfg->stack_offset = S390_ALIGN(offset, S390_STACK_ALIGNMENT);
2204 /*------------------------------------------------------*/
2205 /* Fix offsets for args whose value is in parent frame */
2206 /*------------------------------------------------------*/
2207 for (iParm = sArg; iParm < eArg; ++iParm) {
2208 inst = cfg->args [iParm];
2210 if (inst->opcode == OP_S390_STKARG) {
2211 inst->opcode = OP_REGOFFSET;
2212 inst->inst_offset += cfg->stack_offset;
2217 /*========================= End of Function ========================*/
2219 /*------------------------------------------------------------------*/
2221 /* Name - mono_arch_create_vars */
2223 /*------------------------------------------------------------------*/
2226 mono_arch_create_vars (MonoCompile *cfg)
2228 MonoMethodSignature *sig;
2231 sig = mono_method_signature (cfg->method);
2233 cinfo = get_call_info (cfg, cfg->mempool, sig);
2235 if (cinfo->struct_ret) {
2236 cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG);
2237 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2238 printf ("vret_addr = ");
2239 mono_print_ins (cfg->vret_addr);
2244 /*========================= End of Function ========================*/
2246 /*------------------------------------------------------------------*/
2248 /* Name - add_outarg_reg2. */
2250 /*------------------------------------------------------------------*/
2253 add_outarg_reg2 (MonoCompile *cfg, MonoCallInst *call, ArgStorage storage, int reg, MonoInst *tree)
2258 case RegTypeGeneral:
2259 MONO_INST_NEW (cfg, ins, OP_MOVE);
2260 ins->dreg = mono_alloc_ireg (cfg);
2261 ins->sreg1 = tree->dreg;
2262 MONO_ADD_INS (cfg->cbb, ins);
2263 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, FALSE);
2266 MONO_INST_NEW (cfg, ins, OP_FMOVE);
2267 ins->dreg = mono_alloc_freg (cfg);
2268 ins->sreg1 = tree->dreg;
2269 MONO_ADD_INS (cfg->cbb, ins);
2270 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2273 MONO_INST_NEW (cfg, ins, OP_S390_SETF4RET);
2274 ins->dreg = mono_alloc_freg (cfg);
2275 ins->sreg1 = tree->dreg;
2276 MONO_ADD_INS (cfg->cbb, ins);
2277 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2280 g_assert_not_reached ();
2284 /*========================= End of Function ========================*/
2286 /*------------------------------------------------------------------*/
2288 /* Name - emit_sig_cookie. */
2290 /*------------------------------------------------------------------*/
2293 emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo)
2295 MonoMethodSignature *tmpSig;
2298 cfg->disable_aot = TRUE;
2300 /*----------------------------------------------------------*/
2301 /* mono_ArgIterator_Setup assumes the signature cookie is */
2302 /* passed first and all the arguments which were before it */
2303 /* passed on the stack after the signature. So compensate */
2304 /* by passing a different signature. */
2305 /*----------------------------------------------------------*/
2306 tmpSig = mono_metadata_signature_dup (call->signature);
2307 tmpSig->param_count -= call->signature->sentinelpos;
2308 tmpSig->sentinelpos = 0;
2309 if (tmpSig->param_count > 0)
2310 memcpy (tmpSig->params,
2311 call->signature->params + call->signature->sentinelpos,
2312 tmpSig->param_count * sizeof(MonoType *));
2314 MONO_INST_NEW (cfg, sig_arg, OP_ICONST);
2315 sig_arg->dreg = mono_alloc_ireg (cfg);
2316 sig_arg->inst_p0 = tmpSig;
2317 MONO_ADD_INS (cfg->cbb, sig_arg);
2319 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, STK_BASE,
2320 cinfo->sigCookie.offset, sig_arg->dreg);
2323 /*========================= End of Function ========================*/
2325 /*------------------------------------------------------------------*/
2327 /* Name - mono_arch_emit_call */
2329 /*------------------------------------------------------------------*/
2332 mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
2335 MonoMethodSignature *sig;
2337 int i, n, lParamArea;
2339 ArgInfo *ainfo = NULL;
2341 MonoMethodHeader *header;
2344 sig = call->signature;
2345 n = sig->param_count + sig->hasthis;
2346 DEBUG (g_print ("Call requires: %d parameters\n",n));
2348 cinfo = get_call_info (cfg, cfg->mempool, sig);
2350 stackSize = cinfo->sz.stack_size + cinfo->sz.local_size +
2351 cinfo->sz.parm_size + cinfo->sz.offset;
2352 call->stack_usage = MAX(stackSize, call->stack_usage);
2353 lParamArea = MAX((call->stack_usage-S390_MINIMAL_STACK_SIZE-cinfo->sz.parm_size), 0);
2354 cfg->param_area = MAX(((signed) cfg->param_area), lParamArea);
2355 cfg->flags |= MONO_CFG_HAS_CALLS;
2357 if (cinfo->struct_ret) {
2358 MONO_INST_NEW (cfg, ins, OP_MOVE);
2359 ins->sreg1 = call->vret_var->dreg;
2360 ins->dreg = mono_alloc_preg (cfg);
2361 MONO_ADD_INS (cfg->cbb, ins);
2362 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, cinfo->ret.reg, FALSE);
2365 header = cfg->header;
2366 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2371 for (i = 0; i < n; ++i) {
2374 ainfo = cinfo->args + i;
2375 if (i >= sig->hasthis)
2376 t = sig->params [i - sig->hasthis];
2378 t = &mono_defaults.int_class->byval_arg;
2379 t = mini_get_underlying_type (t);
2381 in = call->args [i];
2383 if ((sig->call_convention == MONO_CALL_VARARG) &&
2385 (i == sig->sentinelpos)) {
2386 emit_sig_cookie (cfg, call, cinfo);
2389 switch (ainfo->regtype) {
2390 case RegTypeGeneral:
2391 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2394 if (MONO_TYPE_ISSTRUCT (t)) {
2395 /* Valuetype passed in one fp register */
2396 ainfo->regtype = RegTypeStructByValInFP;
2399 if (ainfo->size == 4)
2400 ainfo->regtype = RegTypeFPR4;
2401 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2404 case RegTypeStructByVal:
2405 case RegTypeStructByAddr:
2406 case RegTypeStructByAddrOnStack: {
2410 if (sig->params [i - sig->hasthis]->type == MONO_TYPE_TYPEDBYREF) {
2411 size = sizeof (MonoTypedRef);
2412 align = sizeof (gpointer);
2416 size = mono_type_native_stack_size (&in->klass->byval_arg, &align);
2419 * Other backends use mono_type_stack_size (), but that
2420 * aligns the size to 8, which is larger than the size of
2421 * the source, leading to reads of invalid memory if the
2422 * source is at the end of address space.
2424 size = mono_class_value_size (in->klass, &align);
2427 g_assert (in->klass);
2429 ainfo->offparm += cinfo->sz.offStruct;
2431 MONO_INST_NEW (cfg, ins, OP_OUTARG_VT);
2432 ins->sreg1 = in->dreg;
2433 ins->klass = in->klass;
2434 ins->backend.size = ainfo->size;
2435 ins->inst_p0 = call;
2436 ins->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
2437 memcpy (ins->inst_p1, ainfo, sizeof (ArgInfo));
2439 MONO_ADD_INS (cfg->cbb, ins);
2441 if (ainfo->regtype == RegTypeStructByAddr) {
2443 * We use OP_OUTARG_VT to copy the valuetype to a stack location, then
2444 * use the normal OUTARG opcodes to pass the address of the location to
2447 int treg = mono_alloc_preg (cfg);
2448 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2449 frmReg, ainfo->offparm);
2450 mono_call_inst_add_outarg_reg (cfg, call, treg, ainfo->reg, FALSE);
2451 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
2452 /* The address of the valuetype is passed on the stack */
2453 int treg = mono_alloc_preg (cfg);
2454 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2455 frmReg, ainfo->offparm);
2456 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG,
2457 ainfo->reg, ainfo->offset, treg);
2459 if (cfg->compute_gc_maps) {
2462 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, t);
2468 if (!t->byref && t->type == MONO_TYPE_R4) {
2469 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG,
2470 STK_BASE, ainfo->offset + 4,
2472 } else if (!t->byref && (t->type == MONO_TYPE_R8)) {
2473 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG,
2474 STK_BASE, ainfo->offset,
2477 MONO_INST_NEW (cfg, ins, OP_STORE_MEMBASE_REG);
2478 ins->inst_destbasereg = STK_BASE;
2479 ins->inst_offset = ainfo->offset;
2480 ins->sreg1 = in->dreg;
2483 /* This is needed by MonoTypedRef->value to point to the correct data */
2484 if ((sig->call_convention == MONO_CALL_VARARG) &&
2485 (i >= sig->sentinelpos)) {
2486 switch (ainfo->size) {
2488 ins->opcode = OP_STOREI1_MEMBASE_REG;
2491 ins->opcode = OP_STOREI2_MEMBASE_REG;
2494 ins->opcode = OP_STOREI4_MEMBASE_REG;
2502 MONO_ADD_INS (cfg->cbb, ins);
2506 g_assert_not_reached ();
2512 * Handle the case where there are no implicit arguments
2514 if ((sig->call_convention == MONO_CALL_VARARG) &&
2516 (i == sig->sentinelpos)) {
2517 emit_sig_cookie (cfg, call, cinfo);
2521 /*========================= End of Function ========================*/
2523 /*------------------------------------------------------------------*/
2525 /* Name - mono_arch_emit_outarg_vt */
2527 /*------------------------------------------------------------------*/
2530 mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
2532 MonoCallInst *call = (MonoCallInst*)ins->inst_p0;
2533 ArgInfo *ainfo = (ArgInfo*)ins->inst_p1;
2534 int size = ins->backend.size;
2536 if (ainfo->regtype == RegTypeStructByVal) {
2538 arg->ins.sreg1 = ainfo->reg;
2539 arg->ins.opcode = OP_OUTARG_VT;
2540 arg->size = ainfo->size;
2541 arg->offset = ainfo->offset;
2542 arg->offPrm = ainfo->offparm + cinfo->sz.offStruct;
2544 if (ainfo->reg != STK_BASE) {
2545 MONO_OUTPUT_VTR (cfg, size, ainfo->reg, src->dreg, 0);
2547 MONO_OUTPUT_VTS (cfg, size, ainfo->reg, ainfo->offset,
2550 } else if (ainfo->regtype == RegTypeStructByValInFP) {
2551 int dreg = mono_alloc_freg (cfg);
2553 if (ainfo->size == 4) {
2554 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR4_MEMBASE, dreg, src->dreg, 0);
2555 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, dreg, dreg);
2557 g_assert (ainfo->size == 8);
2559 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR8_MEMBASE, dreg, src->dreg, 0);
2562 mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg, TRUE);
2565 MonoMethodHeader *header;
2568 header = mono_method_get_header_checked (cfg->method, &error);
2569 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
2570 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2575 MONO_EMIT_NEW_MOVE (cfg, srcReg, ainfo->offparm,
2576 src->dreg, 0, size);
2578 if (cfg->compute_gc_maps) {
2581 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, &ins->klass->byval_arg);
2586 /*========================= End of Function ========================*/
2588 /*------------------------------------------------------------------*/
2590 /* Name - mono_arch_emit_setret */
2592 /*------------------------------------------------------------------*/
2595 mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
2597 MonoType *ret = mini_get_underlying_type (mono_method_signature (method)->ret);
2600 if (ret->type == MONO_TYPE_R4) {
2601 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, s390_f0, val->dreg);
2603 } else if (ret->type == MONO_TYPE_R8) {
2604 MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, s390_f0, val->dreg);
2609 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg);
2612 /*========================= End of Function ========================*/
2614 /*------------------------------------------------------------------*/
2616 /* Name - mono_arch_instrument_mem_needs */
2618 /* Function - Allow tracing to work with this interface (with */
2619 /* an optional argument). */
2621 /*------------------------------------------------------------------*/
2624 mono_arch_instrument_mem_needs (MonoMethod *method, int *stack, int *code)
2626 /* no stack room needed now (may be needed for FASTCALL-trace support) */
2628 /* split prolog-epilog requirements? */
2629 *code = 50; /* max bytes needed: check this number */
2632 /*========================= End of Function ========================*/
2634 /*------------------------------------------------------------------*/
2636 /* Name - mono_arch_instrument_prolog */
2638 /* Function - Create an "instrumented" prolog. */
2640 /*------------------------------------------------------------------*/
2643 mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p,
2644 gboolean enable_arguments)
2651 parmOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2652 if (cfg->method->save_lmf)
2653 parmOffset -= sizeof(MonoLMF);
2654 fpOffset = parmOffset + (5*sizeof(gpointer));
2657 s390_stmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2658 s390_stdy (code, s390_f0, 0, STK_BASE, fpOffset);
2659 s390_stdy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2660 s390_stdy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2661 s390_stdy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2662 S390_SET (code, s390_r1, func);
2663 S390_SET (code, s390_r2, cfg->method);
2664 s390_lay (code, s390_r3, 0, STK_BASE, parmOffset);
2665 s390_lgr (code, s390_r4, STK_BASE);
2666 s390_aghi (code, s390_r4, cfg->stack_usage);
2667 s390_basr (code, s390_r14, s390_r1);
2668 s390_ldy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2669 s390_ldy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2670 s390_ldy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2671 s390_ldy (code, s390_f0, 0, STK_BASE, fpOffset);
2672 s390_lmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2677 /*========================= End of Function ========================*/
2679 /*------------------------------------------------------------------*/
2681 /* Name - mono_arch_instrument_epilog */
2683 /* Function - Create an epilog that will handle the returned */
2684 /* values used in instrumentation. */
2686 /*------------------------------------------------------------------*/
2689 mono_arch_instrument_epilog_full (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments, gboolean preserve_argument_registers)
2692 int save_mode = SAVE_NONE,
2695 MonoMethod *method = cfg->method;
2696 int rtype = mini_get_underlying_type (mono_method_signature (method)->ret)->type;
2698 offset = code - cfg->native_code;
2699 /*-----------------------------------------*/
2700 /* We need about 128 bytes of instructions */
2701 /*-----------------------------------------*/
2702 if (offset > (cfg->code_size - 128)) {
2703 cfg->code_size *= 2;
2704 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
2705 code = cfg->native_code + offset;
2708 saveOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2709 if (method->save_lmf)
2710 saveOffset -= sizeof(MonoLMF);
2714 case MONO_TYPE_VOID:
2715 /* special case string .ctor icall */
2716 if (strcmp (".ctor", method->name) && method->klass == mono_defaults.string_class)
2717 save_mode = SAVE_ONE;
2719 save_mode = SAVE_NONE;
2723 save_mode = SAVE_ONE;
2726 save_mode = SAVE_R4;
2729 save_mode = SAVE_R8;
2731 case MONO_TYPE_VALUETYPE:
2732 if (mono_method_signature (method)->ret->data.klass->enumtype) {
2733 rtype = mono_class_enum_basetype (mono_method_signature (method)->ret->data.klass)->type;
2736 save_mode = SAVE_STRUCT;
2739 save_mode = SAVE_ONE;
2743 switch (save_mode) {
2745 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2746 if (enable_arguments) {
2747 s390_lgr (code, s390_r3, s390_r2);
2751 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2752 if (enable_arguments) {
2753 s390_ldebr (code, s390_f0, s390_f0);
2757 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2760 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2761 if (enable_arguments) {
2762 s390_lg (code, s390_r3, 0, cfg->frame_reg,
2763 S390_MINIMAL_STACK_SIZE+cfg->param_area);
2771 S390_SET (code, s390_r1, func);
2772 S390_SET (code, s390_r2, cfg->method);
2773 s390_basr (code, s390_r14, s390_r1);
2775 switch (save_mode) {
2777 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2781 s390_ld (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2784 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2794 /*========================= End of Function ========================*/
2796 /*------------------------------------------------------------------*/
2798 /* Name - mono_arch_peephole_pass_1 */
2800 /* Function - Form a peephole pass at the code looking for */
2801 /* simple optimizations. */
2803 /*------------------------------------------------------------------*/
2806 mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
2810 /*========================= End of Function ========================*/
2812 /*------------------------------------------------------------------*/
2814 /* Name - mono_arch_peephole_pass_2 */
2816 /* Function - Form a peephole pass at the code looking for */
2817 /* simple optimizations. */
2819 /*------------------------------------------------------------------*/
2822 mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
2826 MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
2827 mono_peephole_ins (bb, ins);
2831 /*========================= End of Function ========================*/
2833 /*------------------------------------------------------------------*/
2835 /* Name - mono_arch_lowering_pass. */
2837 /*------------------------------------------------------------------*/
2840 mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
2842 MonoInst *ins, *next;
2844 MONO_BB_FOR_EACH_INS_SAFE (bb, next, ins) {
2845 switch (ins->opcode) {
2850 case OP_IDIV_UN_IMM:
2851 case OP_IREM_UN_IMM:
2856 case OP_LOCALLOC_IMM:
2857 mono_decompose_op_imm (cfg, bb, ins);
2860 if (!s390_is_imm16 (ins->inst_imm))
2861 /* This is created by the memcpy code which ignores is_inst_imm */
2862 mono_decompose_op_imm (cfg, bb, ins);
2869 bb->max_vreg = cfg->next_vreg;
2872 /*========================= End of Function ========================*/
2874 /*------------------------------------------------------------------*/
2876 /* Name - emit_float_to_int */
2878 /* Function - Create instructions which will convert a floating */
2879 /* point value to integer. */
2881 /*------------------------------------------------------------------*/
2884 emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size, gboolean is_signed)
2886 /* sreg is a float, dreg is an integer reg. */
2888 s390_cgdbr (code, dreg, 5, sreg);
2891 s390_ltgr (code, dreg, dreg);
2893 s390_oill (code, dreg, 0x80);
2894 s390_lghi (code, s390_r0, 0xff);
2895 s390_ngr (code, dreg, s390_r0);
2898 s390_ltgr (code, dreg, dreg);
2900 s390_oill (code, dreg, 0x8000);
2901 s390_llill(code, s390_r0, 0xffff);
2902 s390_ngr (code, dreg, s390_r0);
2907 S390_SET (code, s390_r13, 0x41e0000000000000llu);
2908 s390_ldgr (code, s390_f14, s390_r13);
2909 s390_ldr (code, s390_f15, sreg);
2910 s390_cdbr (code, s390_f15, s390_f14);
2911 s390_jl (code, 0); CODEPTR (code, o[0]);
2912 S390_SET (code, s390_r13, 0x41f0000000000000llu);
2913 s390_ldgr (code, s390_f14, s390_r13);
2914 s390_sdbr (code, s390_f15, s390_f14);
2915 s390_cfdbr (code, dreg, 7, s390_f15);
2917 PTRSLOT (code, o[0]);
2918 s390_cfdbr (code, dreg, 5, sreg);
2921 s390_lghi (code, s390_r0, 0xff);
2922 s390_ngr (code, dreg, s390_r0);
2925 s390_llill(code, s390_r0, 0xffff);
2926 s390_ngr (code, dreg, s390_r0);
2933 /*========================= End of Function ========================*/
2935 /*------------------------------------------------------------------*/
2937 /* Name - gboolean_is_unsigned. */
2939 /* Function - Return TRUE if next opcode is checking for un- */
2942 /*------------------------------------------------------------------*/
2945 gboolean is_unsigned (MonoInst *next)
2948 (((next->opcode >= OP_IBNE_UN) &&
2949 (next->opcode <= OP_IBLT_UN)) ||
2950 ((next->opcode >= OP_LBNE_UN) &&
2951 (next->opcode <= OP_LBLT_UN)) ||
2952 ((next->opcode >= OP_COND_EXC_NE_UN) &&
2953 (next->opcode <= OP_COND_EXC_LT_UN)) ||
2954 ((next->opcode >= OP_COND_EXC_INE_UN) &&
2955 (next->opcode <= OP_COND_EXC_ILT_UN)) ||
2956 ((next->opcode == OP_CLT_UN) ||
2957 (next->opcode == OP_CGT_UN)) ||
2958 ((next->opcode == OP_ICLT_UN) ||
2959 (next->opcode == OP_ICGT_UN) ||
2960 (next->opcode == OP_LCLT_UN) ||
2961 (next->opcode == OP_LCGT_UN))))
2967 /*========================= End of Function ========================*/
2969 /*------------------------------------------------------------------*/
2971 /* Name - mono_arch_output_basic_block */
2973 /* Function - Perform the "real" work of emitting instructions */
2974 /* that will do the work of in the basic block. */
2976 /*------------------------------------------------------------------*/
2979 mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
2984 guint8 *code = cfg->native_code + cfg->code_len;
2985 guint last_offset = 0;
2988 /* we don't align basic blocks of loops on s390 */
2990 if (cfg->verbose_level > 2)
2991 g_print ("Basic block %d starting at offset 0x%x\n", bb->block_num, bb->native_offset);
2993 if ((cfg->prof_options & MONO_PROFILE_COVERAGE) && cfg->coverage_info) {
2994 MonoProfileCoverageInfo *cov = cfg->coverage_info;
2995 g_assert (!mono_compile_aot);
2996 cov->data [bb->dfn].cil_code = bb->cil_code;
2997 /* This is not thread save, but good enough */
2998 S390_SET (code, s390_r1, &cov->data [bb->dfn].count);
2999 s390_alsi (code, 0, s390_r1, 1);
3002 MONO_BB_FOR_EACH_INS (bb, ins) {
3003 offset = code - cfg->native_code;
3005 max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
3007 if (offset > (cfg->code_size - max_len - 16)) {
3008 cfg->code_size *= 2;
3009 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
3010 code = cfg->native_code + offset;
3013 mono_debug_record_line_number (cfg, ins, offset);
3015 switch (ins->opcode) {
3016 case OP_STOREI1_MEMBASE_IMM: {
3017 s390_lghi (code, s390_r0, ins->inst_imm);
3018 S390_LONG (code, stcy, stc, s390_r0, 0,
3019 ins->inst_destbasereg, ins->inst_offset);
3022 case OP_STOREI2_MEMBASE_IMM: {
3023 s390_lghi (code, s390_r0, ins->inst_imm);
3024 S390_LONG (code, sthy, sth, s390_r0, 0,
3025 ins->inst_destbasereg, ins->inst_offset);
3028 case OP_STOREI4_MEMBASE_IMM: {
3029 s390_lgfi (code, s390_r0, ins->inst_imm);
3030 S390_LONG (code, sty, st, s390_r0, 0,
3031 ins->inst_destbasereg, ins->inst_offset);
3034 case OP_STORE_MEMBASE_IMM:
3035 case OP_STOREI8_MEMBASE_IMM: {
3036 S390_SET (code, s390_r0, ins->inst_imm);
3037 S390_LONG (code, stg, stg, s390_r0, 0,
3038 ins->inst_destbasereg, ins->inst_offset);
3041 case OP_STOREI1_MEMBASE_REG: {
3042 S390_LONG (code, stcy, stc, ins->sreg1, 0,
3043 ins->inst_destbasereg, ins->inst_offset);
3046 case OP_STOREI2_MEMBASE_REG: {
3047 S390_LONG (code, sthy, sth, ins->sreg1, 0,
3048 ins->inst_destbasereg, ins->inst_offset);
3051 case OP_STOREI4_MEMBASE_REG: {
3052 S390_LONG (code, sty, st, ins->sreg1, 0,
3053 ins->inst_destbasereg, ins->inst_offset);
3056 case OP_STORE_MEMBASE_REG:
3057 case OP_STOREI8_MEMBASE_REG: {
3058 S390_LONG (code, stg, stg, ins->sreg1, 0,
3059 ins->inst_destbasereg, ins->inst_offset);
3063 g_assert_not_reached ();
3065 case OP_LOAD_MEMBASE:
3066 case OP_LOADI8_MEMBASE: {
3067 S390_LONG (code, lg, lg, ins->dreg, 0,
3068 ins->inst_basereg, ins->inst_offset);
3071 case OP_LOADI4_MEMBASE: {
3072 S390_LONG (code, lgf, lgf, ins->dreg, 0,
3073 ins->inst_basereg, ins->inst_offset);
3076 case OP_LOADU4_MEMBASE: {
3077 S390_LONG (code, llgf, llgf, ins->dreg, 0,
3078 ins->inst_basereg, ins->inst_offset);
3081 case OP_LOADU1_MEMBASE: {
3082 S390_LONG (code, llgc, llgc, ins->dreg, 0,
3083 ins->inst_basereg, ins->inst_offset);
3086 case OP_LOADI1_MEMBASE: {
3087 S390_LONG (code, lgb, lgb, ins->dreg, 0,
3088 ins->inst_basereg, ins->inst_offset);
3091 case OP_LOADU2_MEMBASE: {
3092 S390_LONG (code, llgh, llgh, ins->dreg, 0,
3093 ins->inst_basereg, ins->inst_offset);
3096 case OP_LOADI2_MEMBASE: {
3097 S390_LONG (code, lgh, lgh, ins->dreg, 0,
3098 ins->inst_basereg, ins->inst_offset);
3101 case OP_LCONV_TO_I1: {
3102 s390_lgbr (code, ins->dreg, ins->sreg1);
3105 case OP_LCONV_TO_I2: {
3106 s390_lghr (code, ins->dreg, ins->sreg1);
3109 case OP_LCONV_TO_U1: {
3110 s390_llgcr (code, ins->dreg, ins->sreg1);
3113 case OP_LCONV_TO_U2: {
3114 s390_llghr (code, ins->dreg, ins->sreg1);
3117 case OP_ICONV_TO_I1: {
3118 s390_lgbr (code, ins->dreg, ins->sreg1);
3121 case OP_ICONV_TO_I2: {
3122 s390_lghr (code, ins->dreg, ins->sreg1);
3125 case OP_ICONV_TO_U1: {
3126 s390_llgcr (code, ins->dreg, ins->sreg1);
3129 case OP_ICONV_TO_U2: {
3130 s390_llghr (code, ins->dreg, ins->sreg1);
3135 if (is_unsigned (ins->next))
3136 s390_clgr (code, ins->sreg1, ins->sreg2);
3138 s390_cgr (code, ins->sreg1, ins->sreg2);
3142 if (is_unsigned (ins->next))
3143 s390_clr (code, ins->sreg1, ins->sreg2);
3145 s390_cr (code, ins->sreg1, ins->sreg2);
3148 case OP_COMPARE_IMM:
3149 case OP_LCOMPARE_IMM: {
3150 S390_SET (code, s390_r0, ins->inst_imm);
3151 if (is_unsigned (ins->next))
3152 s390_clgr (code, ins->sreg1, s390_r0);
3154 s390_cgr (code, ins->sreg1, s390_r0);
3157 case OP_ICOMPARE_IMM: {
3158 S390_SET (code, s390_r0, ins->inst_imm);
3159 if (is_unsigned (ins->next))
3160 s390_clr (code, ins->sreg1, s390_r0);
3162 s390_cr (code, ins->sreg1, s390_r0);
3166 mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_ABS,
3168 S390_CALL_TEMPLATE (code, s390_r14);
3173 s390_agr (code, ins->dreg, src2);
3178 s390_agr (code, ins->dreg, src2);
3183 s390_alcgr (code, ins->dreg, src2);
3187 if (ins->dreg != ins->sreg1) {
3188 s390_lgr (code, ins->dreg, ins->sreg1);
3190 if (s390_is_imm16 (ins->inst_imm)) {
3191 s390_aghi (code, ins->dreg, ins->inst_imm);
3192 } else if (s390_is_imm32 (ins->inst_imm)) {
3193 s390_agfi (code, ins->dreg, ins->inst_imm);
3195 S390_SET (code, s390_r0, ins->inst_imm);
3196 s390_agr (code, ins->dreg, s390_r0);
3201 if (ins->dreg != ins->sreg1) {
3202 s390_lgr (code, ins->dreg, ins->sreg1);
3204 g_assert (s390_is_imm16 (ins->inst_imm));
3205 s390_aghi (code, ins->dreg, ins->inst_imm);
3209 if (ins->dreg != ins->sreg1) {
3210 s390_lgr (code, ins->dreg, ins->sreg1);
3212 if (s390_is_imm16 (ins->inst_imm)) {
3213 s390_lghi (code, s390_r0, ins->inst_imm);
3214 s390_alcgr (code, ins->dreg, s390_r0);
3216 S390_SET (code, s390_r0, ins->inst_imm);
3217 s390_alcgr (code, ins->dreg, s390_r0);
3222 case OP_S390_IADD_OVF: {
3224 s390_ar (code, ins->dreg, src2);
3225 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3226 s390_lgfr (code, ins->dreg, ins->dreg);
3229 case OP_IADD_OVF_UN:
3230 case OP_S390_IADD_OVF_UN: {
3232 s390_algr (code, ins->dreg, src2);
3233 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3234 s390_llgfr (code, ins->dreg, ins->dreg);
3237 case OP_ADD_OVF_CARRY: {
3239 s390_lghi (code, s390_r0, 0);
3240 s390_lgr (code, s390_r1, s390_r0);
3241 s390_alcgr (code, s390_r0, s390_r1);
3242 s390_agr (code, ins->dreg, src2);
3243 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3244 s390_agr (code, ins->dreg, s390_r0);
3245 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3248 case OP_ADD_OVF_UN_CARRY: {
3250 s390_alcgr (code, ins->dreg, src2);
3251 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3256 s390_sgr (code, ins->dreg, src2);
3261 s390_sgr (code, ins->dreg, src2);
3266 s390_slbgr(code, ins->dreg, src2);
3270 if (ins->dreg != ins->sreg1) {
3271 s390_lgr (code, ins->dreg, ins->sreg1);
3273 if (s390_is_imm16 (-ins->inst_imm)) {
3274 s390_aghi (code, ins->dreg, -ins->inst_imm);
3275 } else if (s390_is_imm32 (-ins->inst_imm)) {
3276 s390_slgfi (code, ins->dreg, ins->inst_imm);
3278 S390_SET (code, s390_r0, ins->inst_imm);
3279 s390_slgr (code, ins->dreg, s390_r0);
3284 if (ins->dreg != ins->sreg1) {
3285 s390_lgr (code, ins->dreg, ins->sreg1);
3287 if (s390_is_imm16 (-ins->inst_imm)) {
3288 s390_aghi (code, ins->dreg, -ins->inst_imm);
3289 } else if (s390_is_imm32 (-ins->inst_imm)) {
3290 s390_slgfi (code, ins->dreg, ins->inst_imm);
3292 S390_SET (code, s390_r0, ins->inst_imm);
3293 s390_slgr (code, ins->dreg, s390_r0);
3298 if (ins->dreg != ins->sreg1) {
3299 s390_lgr (code, ins->dreg, ins->sreg1);
3301 if (s390_is_imm16 (-ins->inst_imm)) {
3302 s390_lghi (code, s390_r0, ins->inst_imm);
3303 s390_slbgr (code, ins->dreg, s390_r0);
3305 S390_SET (code, s390_r0, ins->inst_imm);
3306 s390_slbgr(code, ins->dreg, s390_r0);
3310 case OP_SUB_OVF_CARRY: {
3312 s390_lghi (code, s390_r0, 0);
3313 s390_lgr (code, s390_r1, s390_r0);
3314 s390_slbgr (code, s390_r0, s390_r1);
3315 s390_sgr (code, ins->dreg, src2);
3316 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3317 s390_agr (code, ins->dreg, s390_r0);
3318 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3321 case OP_SUB_OVF_UN_CARRY: {
3323 s390_slbgr (code, ins->dreg, src2);
3324 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3328 if (ins->sreg1 == ins->dreg) {
3329 s390_ngr (code, ins->dreg, ins->sreg2);
3332 if (ins->sreg2 == ins->dreg) {
3333 s390_ngr (code, ins->dreg, ins->sreg1);
3336 s390_lgr (code, ins->dreg, ins->sreg1);
3337 s390_ngr (code, ins->dreg, ins->sreg2);
3343 if (ins->dreg != ins->sreg1) {
3344 s390_lgr (code, ins->dreg, ins->sreg1);
3346 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3347 s390_ngr (code, ins->dreg, s390_r0);
3351 s390_lgr (code, s390_r1, ins->sreg1);
3352 s390_dsgr (code, s390_r0, ins->sreg2);
3353 s390_lgr (code, ins->dreg, s390_r1);
3357 s390_lgr (code, s390_r1, ins->sreg1);
3358 s390_lghi (code, s390_r0, 0);
3359 s390_dlgr (code, s390_r0, ins->sreg2);
3360 s390_lgr (code, ins->dreg, s390_r1);
3364 s390_lgr (code, s390_r1, ins->sreg1);
3365 s390_dsgr (code, s390_r0, ins->sreg2);
3366 s390_lgr (code, ins->dreg, s390_r0);
3370 if (s390_is_imm16 (ins->inst_imm)) {
3371 s390_lghi (code, s390_r13, ins->inst_imm);
3373 s390_lgfi (code, s390_r13, ins->inst_imm);
3375 s390_lgr (code, s390_r0, ins->sreg1);
3376 s390_dsgr (code, s390_r0, s390_r13);
3377 s390_lgfr (code, ins->dreg, s390_r0);
3381 s390_lgr (code, s390_r1, ins->sreg1);
3382 s390_lghi (code, s390_r0, 0);
3383 s390_dlgr (code, s390_r0, ins->sreg2);
3384 s390_lgr (code, ins->dreg, s390_r0);
3388 if (ins->sreg1 == ins->dreg) {
3389 s390_ogr (code, ins->dreg, ins->sreg2);
3392 if (ins->sreg2 == ins->dreg) {
3393 s390_ogr (code, ins->dreg, ins->sreg1);
3396 s390_lgr (code, ins->dreg, ins->sreg1);
3397 s390_ogr (code, ins->dreg, ins->sreg2);
3403 if (ins->dreg != ins->sreg1) {
3404 s390_lgr (code, ins->dreg, ins->sreg1);
3406 S390_SET_MASK(code, s390_r0, ins->inst_imm);
3407 s390_ogr (code, ins->dreg, s390_r0);
3411 if (ins->sreg1 == ins->dreg) {
3412 s390_xgr (code, ins->dreg, ins->sreg2);
3415 if (ins->sreg2 == ins->dreg) {
3416 s390_xgr (code, ins->dreg, ins->sreg1);
3419 s390_lgr (code, ins->dreg, ins->sreg1);
3420 s390_xgr (code, ins->dreg, ins->sreg2);
3426 if (ins->dreg != ins->sreg1) {
3427 s390_lgr (code, ins->dreg, ins->sreg1);
3429 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3430 s390_xgr (code, ins->dreg, s390_r0);
3435 s390_sllg (code, ins->dreg, ins->dreg, src2, 0);
3440 if (ins->sreg1 != ins->dreg) {
3441 s390_lgr (code, ins->dreg, ins->sreg1);
3443 s390_sllg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3448 s390_srag (code, ins->dreg, ins->dreg, src2, 0);
3453 if (ins->sreg1 != ins->dreg) {
3454 s390_lgr (code, ins->dreg, ins->sreg1);
3456 s390_srag (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3460 case OP_LSHR_UN_IMM: {
3461 if (ins->sreg1 != ins->dreg) {
3462 s390_lgr (code, ins->dreg, ins->sreg1);
3464 s390_srlg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3469 s390_srlg (code, ins->dreg, ins->dreg, src2, 0);
3473 if (ins->sreg1 != ins->dreg) {
3474 s390_lgr (code, ins->dreg, ins->sreg1);
3476 s390_lghi (code, s390_r0, -1);
3477 s390_xgr (code, ins->dreg, s390_r0);
3481 s390_lcgr (code, ins->dreg, ins->sreg1);
3486 s390_msgr (code, ins->dreg, src2);
3491 if (ins->dreg != ins->sreg1) {
3492 s390_lgr (code, ins->dreg, ins->sreg1);
3494 if (s390_is_imm16 (ins->inst_imm)) {
3495 s390_lghi (code, s390_r13, ins->inst_imm);
3496 } else if (s390_is_imm32 (ins->inst_imm)) {
3497 s390_lgfi (code, s390_r13, ins->inst_imm);
3499 S390_SET (code, s390_r13, ins->inst_imm);
3501 s390_msgr (code, ins->dreg, s390_r13);
3506 s390_ltgr (code, s390_r1, ins->sreg1);
3507 s390_jz (code, 0); CODEPTR(code, o[0]);
3508 s390_ltgr (code, s390_r0, ins->sreg2);
3510 s390_lghi (code, s390_r1, 0);
3511 s390_j (code, 0); CODEPTR(code, o[1]);
3512 s390_xgr (code, s390_r0, s390_r1);
3513 s390_msgr (code, s390_r1, ins->sreg2);
3514 s390_xgr (code, s390_r0, s390_r1);
3515 s390_srlg (code, s390_r0, s390_r0, 0, 63);
3516 s390_ltgr (code, s390_r0, s390_r0);
3517 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3518 PTRSLOT (code, o[0]);
3519 PTRSLOT (code, o[1]);
3520 s390_lgr (code, ins->dreg, s390_r1);
3523 case OP_LMUL_OVF_UN: {
3524 s390_lghi (code, s390_r0, 0);
3525 s390_lgr (code, s390_r1, ins->sreg1);
3526 s390_mlgr (code, s390_r0, ins->sreg2);
3527 s390_ltgr (code, s390_r0, s390_r0);
3528 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3529 s390_lgr (code, ins->dreg, s390_r1);
3533 g_assert_not_reached ();
3535 s390_algr (code, ins->dreg, src2);
3540 s390_agr (code, ins->dreg, src2);
3544 g_assert_not_reached ();
3546 s390_alcgr (code, ins->dreg, src2);
3550 if (ins->dreg != ins->sreg1) {
3551 s390_lgfr (code, ins->dreg, ins->sreg1);
3553 if (s390_is_imm16 (ins->inst_imm)) {
3554 s390_aghi (code, ins->dreg, ins->inst_imm);
3556 s390_afi (code, ins->dreg, ins->inst_imm);
3561 if (ins->dreg != ins->sreg1) {
3562 s390_lgfr (code, ins->dreg, ins->sreg1);
3564 if (s390_is_imm16 (ins->inst_imm)) {
3565 s390_lghi (code, s390_r0, ins->inst_imm);
3566 s390_alcgr (code, ins->dreg, s390_r0);
3568 S390_SET (code, s390_r0, ins->inst_imm);
3569 s390_alcgr (code, ins->dreg, s390_r0);
3574 case OP_S390_LADD_OVF: {
3576 s390_agr (code, ins->dreg, src2);
3577 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3580 case OP_LADD_OVF_UN:
3581 case OP_S390_LADD_OVF_UN: {
3583 s390_algr (code, ins->dreg, src2);
3584 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3588 CHECK_SRCDST_NCOM_I;
3589 s390_slgr (code, ins->dreg, src2);
3593 CHECK_SRCDST_NCOM_I;
3594 s390_sgr (code, ins->dreg, src2);
3598 CHECK_SRCDST_NCOM_I;
3599 s390_slbgr (code, ins->dreg, src2);
3603 if (ins->dreg != ins->sreg1) {
3604 s390_lgfr (code, ins->dreg, ins->sreg1);
3606 if (s390_is_imm16 (-ins->inst_imm)) {
3607 s390_aghi (code, ins->dreg, -ins->inst_imm);
3609 s390_agfi (code, ins->dreg, -ins->inst_imm);
3614 S390_SET (code, s390_r0, ins->inst_imm);
3615 s390_slgfr (code, ins->dreg, s390_r0);
3619 case OP_S390_ISUB_OVF: {
3621 s390_sr (code, ins->dreg, src2);
3622 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3623 s390_lgfr (code, ins->dreg, ins->dreg);
3626 case OP_ISUB_OVF_UN:
3627 case OP_S390_ISUB_OVF_UN: {
3629 s390_slr (code, ins->dreg, src2);
3630 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3631 s390_llgfr(code, ins->dreg, ins->dreg);
3635 case OP_S390_LSUB_OVF: {
3637 s390_sgr (code, ins->dreg, src2);
3638 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3641 case OP_LSUB_OVF_UN:
3642 case OP_S390_LSUB_OVF_UN: {
3644 s390_slgr (code, ins->dreg, src2);
3645 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3649 CHECK_SRCDST_NCOM_I;
3650 s390_ngr (code, ins->dreg, src2);
3654 if (ins->dreg != ins->sreg1) {
3655 s390_lgfr (code, ins->dreg, ins->sreg1);
3657 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3658 s390_ngr (code, ins->dreg, s390_r0);
3662 s390_lgfr (code, s390_r0, ins->sreg1);
3663 s390_srda (code, s390_r0, 0, 32);
3664 s390_dr (code, s390_r0, ins->sreg2);
3665 s390_lgfr (code, ins->dreg, s390_r1);
3669 s390_lgfr (code, s390_r0, ins->sreg1);
3670 s390_srdl (code, s390_r0, 0, 32);
3671 s390_dlr (code, s390_r0, ins->sreg2);
3672 s390_lgfr (code, ins->dreg, s390_r1);
3676 if (s390_is_imm16 (ins->inst_imm)) {
3677 s390_lghi (code, s390_r13, ins->inst_imm);
3679 s390_lgfi (code, s390_r13, ins->inst_imm);
3681 s390_lgfr (code, s390_r0, ins->sreg1);
3682 s390_srda (code, s390_r0, 0, 32);
3683 s390_dr (code, s390_r0, ins->sreg2);
3684 s390_lgfr (code, ins->dreg, s390_r1);
3688 s390_lgfr (code, s390_r0, ins->sreg1);
3689 s390_srda (code, s390_r0, 0, 32);
3690 s390_dr (code, s390_r0, ins->sreg2);
3691 s390_lgfr (code, ins->dreg, s390_r0);
3694 s390_lgfr (code, s390_r0, ins->sreg1);
3695 s390_srdl (code, s390_r0, 0, 32);
3696 s390_dlr (code, s390_r0, ins->sreg2);
3697 s390_lgfr (code, ins->dreg, s390_r0);
3701 if (s390_is_imm16 (ins->inst_imm)) {
3702 s390_lghi (code, s390_r13, ins->inst_imm);
3704 s390_lgfi (code, s390_r13, ins->inst_imm);
3706 s390_lgfr (code, s390_r0, ins->sreg1);
3707 s390_srda (code, s390_r0, 0, 32);
3708 s390_dr (code, s390_r0, ins->sreg2);
3709 s390_lgfr (code, ins->dreg, s390_r0);
3714 s390_ogr (code, ins->dreg, src2);
3718 if (ins->dreg != ins->sreg1) {
3719 s390_lgfr (code, ins->dreg, ins->sreg1);
3721 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3722 s390_ogr (code, ins->dreg, s390_r0);
3727 s390_xgr (code, ins->dreg, src2);
3731 if (ins->dreg != ins->sreg1) {
3732 s390_lgfr (code, ins->dreg, ins->sreg1);
3734 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3735 s390_xgr (code, ins->dreg, s390_r0);
3740 s390_sll (code, ins->dreg, src2, 0);
3744 if (ins->sreg1 != ins->dreg) {
3745 s390_lgfr (code, ins->dreg, ins->sreg1);
3747 s390_sll (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3752 s390_sra (code, ins->dreg, src2, 0);
3756 if (ins->sreg1 != ins->dreg) {
3757 s390_lgfr (code, ins->dreg, ins->sreg1);
3759 s390_sra (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3762 case OP_ISHR_UN_IMM: {
3763 if (ins->sreg1 != ins->dreg) {
3764 s390_lgfr (code, ins->dreg, ins->sreg1);
3766 s390_srl (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3771 s390_srl (code, ins->dreg, src2, 0);
3775 if (ins->sreg1 != ins->dreg) {
3776 s390_lgfr (code, ins->dreg, ins->sreg1);
3778 s390_lghi (code, s390_r0, -1);
3779 s390_xgr (code, ins->dreg, s390_r0);
3783 s390_lcgr (code, ins->dreg, ins->sreg1);
3788 s390_msr (code, ins->dreg, src2);
3792 if (ins->dreg != ins->sreg1) {
3793 s390_lgfr (code, ins->dreg, ins->sreg1);
3795 if (s390_is_imm16 (ins->inst_imm)) {
3796 s390_lghi (code, s390_r0, ins->inst_imm);
3798 s390_lgfi (code, s390_r0, ins->inst_imm);
3800 s390_msr (code, ins->dreg, s390_r0);
3805 s390_ltr (code, s390_r1, ins->sreg1);
3806 s390_jz (code, 0); CODEPTR(code, o[0]);
3807 s390_ltr (code, s390_r0, ins->sreg2);
3809 s390_lhi (code, s390_r1, 0);
3810 s390_j (code, 0); CODEPTR(code, o[1]);
3811 s390_xr (code, s390_r0, s390_r1);
3812 s390_msr (code, s390_r1, ins->sreg2);
3813 s390_xr (code, s390_r0, s390_r1);
3814 s390_srl (code, s390_r0, 0, 31);
3815 s390_ltr (code, s390_r0, s390_r0);
3816 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3817 PTRSLOT (code, o[0]);
3818 PTRSLOT (code, o[1]);
3819 s390_lgfr (code, ins->dreg, s390_r1);
3822 case OP_IMUL_OVF_UN: {
3823 s390_lhi (code, s390_r0, 0);
3824 s390_lr (code, s390_r1, ins->sreg1);
3825 s390_mlr (code, s390_r0, ins->sreg2);
3826 s390_ltr (code, s390_r0, s390_r0);
3827 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3828 s390_lgfr (code, ins->dreg, s390_r1);
3833 S390_SET (code, ins->dreg, ins->inst_c0);
3837 mono_add_patch_info (cfg, code - cfg->native_code,
3838 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3839 S390_LOAD_TEMPLATE (code, ins->dreg);
3842 case OP_JUMP_TABLE: {
3843 mono_add_patch_info (cfg, code - cfg->native_code,
3844 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3845 S390_LOAD_TEMPLATE (code, ins->dreg);
3849 if (ins->dreg != ins->sreg1) {
3850 s390_lgr (code, ins->dreg, ins->sreg1);
3854 case OP_LCONV_TO_I8:
3856 s390_lgfr (code, ins->dreg, ins->sreg1);
3858 case OP_LCONV_TO_I4:
3859 s390_lgfr (code, ins->dreg, ins->sreg1);
3862 case OP_LCONV_TO_U8:
3863 case OP_LCONV_TO_U4:
3865 s390_llgfr (code, ins->dreg, ins->sreg1);
3867 case OP_LCONV_TO_OVF_U4:
3868 S390_SET (code, s390_r0, 4294967295);
3869 s390_clgr (code, ins->sreg1, s390_r0);
3870 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3871 s390_ltgr (code, ins->sreg1, ins->sreg1);
3872 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3873 s390_llgfr(code, ins->dreg, ins->sreg1);
3875 case OP_LCONV_TO_OVF_I4_UN:
3876 S390_SET (code, s390_r0, 2147483647);
3877 s390_cgr (code, ins->sreg1, s390_r0);
3878 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3879 s390_ltgr (code, ins->sreg1, ins->sreg1);
3880 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3881 s390_lgfr (code, ins->dreg, ins->sreg1);
3884 if (ins->dreg != ins->sreg1) {
3885 s390_ldr (code, ins->dreg, ins->sreg1);
3888 case OP_MOVE_F_TO_I8:
3889 s390_lgdr (code, ins->dreg, ins->sreg1);
3891 case OP_MOVE_I8_TO_F:
3892 s390_ldgr (code, ins->dreg, ins->sreg1);
3894 case OP_MOVE_F_TO_I4:
3895 s390_ledbr (code, s390_f0, ins->sreg1);
3896 s390_lgdr (code, ins->dreg, s390_f0);
3897 s390_srag (code, ins->dreg, ins->dreg, 0, 32);
3899 case OP_MOVE_I4_TO_F:
3900 s390_slag (code, s390_r0, ins->sreg1, 0, 32);
3901 s390_ldgr (code, ins->dreg, s390_r0);
3902 s390_ldebr (code, ins->dreg, ins->dreg);
3904 case OP_FCONV_TO_R4:
3905 s390_ledbr (code, ins->dreg, ins->sreg1);
3906 s390_ldebr (code, ins->dreg, ins->dreg);
3908 case OP_S390_SETF4RET:
3909 s390_ledbr (code, ins->dreg, ins->sreg1);
3912 if (s390_is_imm16 (ins->inst_offset)) {
3913 s390_lghi (code, s390_r13, ins->inst_offset);
3914 } else if (s390_is_imm32 (ins->inst_offset)) {
3915 s390_lgfi (code, s390_r13, ins->inst_offset);
3917 S390_SET (code, s390_r13, ins->inst_offset);
3919 s390_ear (code, s390_r1, 0);
3920 s390_sllg(code, s390_r1, s390_r1, 0, 32);
3921 s390_ear (code, s390_r1, 1);
3922 s390_lg (code, ins->dreg, s390_r13, s390_r1, 0);
3926 if (cfg->method->save_lmf)
3927 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
3929 if (cfg->flags & MONO_CFG_HAS_TAIL) {
3930 code = emit_load_volatile_arguments (code, cfg);
3933 code = backUpStackPtr(cfg, code);
3934 s390_lg (code, s390_r14, 0, cfg->frame_reg, S390_RET_ADDR_OFFSET);
3935 mono_add_patch_info (cfg, code - cfg->native_code,
3936 MONO_PATCH_INFO_METHOD_JUMP,
3938 s390_jcl (code, S390_CC_UN, 0);
3941 case OP_CHECK_THIS: {
3942 /* ensure ins->sreg1 is not NULL */
3943 s390_lg (code, s390_r0, 0, ins->sreg1, 0);
3944 s390_ltgr (code, s390_r0, s390_r0);
3945 // EMIT_COND_SYSTEM_EXCEPTION (S390_CC_ZR, "NullReferenceException");
3949 int offset = cfg->sig_cookie + cfg->stack_usage;
3951 if (s390_is_imm16 (offset)) {
3952 s390_lghi (code, s390_r0, offset);
3953 } else if (s390_is_imm32 (offset)) {
3954 s390_lgfi (code, s390_r0, offset);
3956 S390_SET (code, s390_r0, offset);
3958 s390_agr (code, s390_r0, cfg->frame_reg);
3959 s390_stg (code, s390_r0, 0, ins->sreg1, 0);
3963 call = (MonoCallInst*)ins;
3964 if (ins->flags & MONO_INST_HAS_METHOD)
3965 mono_add_patch_info (cfg, code-cfg->native_code,
3966 MONO_PATCH_INFO_METHOD,
3969 mono_add_patch_info (cfg, code-cfg->native_code,
3970 MONO_PATCH_INFO_ABS,
3972 S390_CALL_TEMPLATE (code, s390_r14);
3973 if (call->signature->ret->type == MONO_TYPE_R4)
3974 s390_ldebr (code, s390_f0, s390_f0);
3982 call = (MonoCallInst*)ins;
3983 if (ins->flags & MONO_INST_HAS_METHOD)
3984 mono_add_patch_info (cfg, code-cfg->native_code,
3985 MONO_PATCH_INFO_METHOD,
3988 mono_add_patch_info (cfg, code-cfg->native_code,
3989 MONO_PATCH_INFO_ABS,
3991 S390_CALL_TEMPLATE (code, s390_r14);
3994 case OP_FCALL_REG: {
3995 call = (MonoCallInst*)ins;
3996 s390_lgr (code, s390_r1, ins->sreg1);
3997 s390_basr (code, s390_r14, s390_r1);
3998 if (call->signature->ret->type == MONO_TYPE_R4)
3999 s390_ldebr (code, s390_f0, s390_f0);
4005 case OP_VOIDCALL_REG:
4007 s390_lgr (code, s390_r1, ins->sreg1);
4008 s390_basr (code, s390_r14, s390_r1);
4011 case OP_FCALL_MEMBASE: {
4012 call = (MonoCallInst*)ins;
4013 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4014 s390_basr (code, s390_r14, s390_r1);
4015 if (call->signature->ret->type == MONO_TYPE_R4)
4016 s390_ldebr (code, s390_f0, s390_f0);
4019 case OP_LCALL_MEMBASE:
4020 case OP_VCALL_MEMBASE:
4021 case OP_VCALL2_MEMBASE:
4022 case OP_VOIDCALL_MEMBASE:
4023 case OP_CALL_MEMBASE: {
4024 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4025 s390_basr (code, s390_r14, s390_r1);
4032 if (cfg->param_area == 0)
4033 alloca_skip = S390_MINIMAL_STACK_SIZE;
4035 alloca_skip = cfg->param_area;
4037 area_offset = S390_ALIGN(alloca_skip, S390_STACK_ALIGNMENT);
4038 s390_lgr (code, s390_r1, ins->sreg1);
4039 if (ins->flags & MONO_INST_INIT)
4040 s390_lgr (code, s390_r0, ins->sreg1);
4041 s390_aghi (code, s390_r1, 14);
4042 s390_srlg (code, s390_r1, s390_r1, 0, 3);
4043 s390_sllg (code, s390_r1, s390_r1, 0, 3);
4044 if (cfg->method->save_lmf) {
4045 /*----------------------------------*/
4046 /* we have to adjust lmf ebp value */
4047 /*----------------------------------*/
4048 int lmfOffset = cfg->stack_usage - sizeof(MonoLMF);
4050 s390_lgr (code, s390_r13, cfg->frame_reg);
4051 if (s390_is_imm16(lmfOffset)) {
4052 s390_aghi (code, s390_r13, lmfOffset);
4053 } else if (s390_is_imm32(lmfOffset)) {
4054 s390_agfi (code, s390_r13, lmfOffset);
4056 S390_SET (code, s390_r13, lmfOffset);
4058 s390_lgr (code, s390_r14, STK_BASE);
4059 s390_sgr (code, s390_r14, s390_r1);
4060 s390_stg (code, s390_r14, 0, s390_r13,
4061 G_STRUCT_OFFSET(MonoLMF, ebp));
4063 s390_lg (code, s390_r13, 0, STK_BASE, 0);
4064 s390_sgr (code, STK_BASE, s390_r1);
4065 s390_stg (code, s390_r13, 0, STK_BASE, 0);
4066 s390_la (code, ins->dreg, 0, STK_BASE, area_offset);
4067 s390_srlg (code, ins->dreg, ins->dreg, 0, 3);
4068 s390_sllg (code, ins->dreg, ins->dreg, 0, 3);
4069 if (ins->flags & MONO_INST_INIT) {
4070 s390_lgr (code, s390_r1, s390_r0);
4071 s390_lgr (code, s390_r0, ins->dreg);
4072 s390_lgr (code, s390_r14, s390_r12);
4073 s390_lghi (code, s390_r13, 0);
4074 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4076 s390_lgr (code, s390_r12, s390_r14);
4081 s390_lgr (code, s390_r2, ins->sreg1);
4082 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4083 (gpointer) "mono_arch_throw_exception");
4084 S390_CALL_TEMPLATE(code, s390_r14);
4088 s390_lgr (code, s390_r2, ins->sreg1);
4089 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4090 (gpointer) "mono_arch_rethrow_exception");
4091 S390_CALL_TEMPLATE(code, s390_r14);
4094 case OP_START_HANDLER: {
4095 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4097 S390_LONG (code, stg, stg, s390_r14, 0,
4098 spvar->inst_basereg,
4099 spvar->inst_offset);
4102 case OP_ENDFILTER: {
4103 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4105 if (ins->sreg1 != s390_r2)
4106 s390_lgr(code, s390_r2, ins->sreg1);
4107 S390_LONG (code, lg, lg, s390_r14, 0,
4108 spvar->inst_basereg,
4109 spvar->inst_offset);
4110 s390_br (code, s390_r14);
4113 case OP_ENDFINALLY: {
4114 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4116 S390_LONG (code, lg, lg, s390_r14, 0,
4117 spvar->inst_basereg,
4118 spvar->inst_offset);
4119 s390_br (code, s390_r14);
4122 case OP_CALL_HANDLER: {
4123 mono_add_patch_info (cfg, code-cfg->native_code,
4124 MONO_PATCH_INFO_BB, ins->inst_target_bb);
4125 s390_brasl (code, s390_r14, 0);
4126 mono_cfg_add_try_hole (cfg, ins->inst_eh_block, code, bb);
4130 ins->inst_c0 = code - cfg->native_code;
4133 case OP_RELAXED_NOP:
4136 case OP_DUMMY_STORE:
4137 case OP_NOT_REACHED:
4141 case OP_IL_SEQ_POINT:
4142 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4144 case OP_SEQ_POINT: {
4147 if (cfg->compile_aot)
4151 * Read from the single stepping trigger page. This will cause a
4152 * SIGSEGV when single stepping is enabled.
4153 * We do this _before_ the breakpoint, so single stepping after
4154 * a breakpoint is hit will step to the next IL offset.
4156 if (ins->flags & MONO_INST_SINGLE_STEP_LOC) {
4157 breakpointCode.pTrigger = ss_trigger_page;
4158 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
4159 code += BREAKPOINT_SIZE;
4162 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4165 * A placeholder for a possible breakpoint inserted by
4166 * mono_arch_set_breakpoint ().
4168 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); ++i)
4172 * Add an additional nop so skipping the bp doesn't cause the ip to point
4173 * to another IL offset.
4179 case OP_GENERIC_CLASS_INIT: {
4180 static int byte_offset = -1;
4181 static guint8 bitmask;
4184 g_assert (ins->sreg1 == S390_FIRST_ARG_REG);
4186 if (byte_offset < 0)
4187 mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);
4189 s390_tm (code, ins->sreg1, byte_offset, bitmask);
4190 s390_jo (code, 0); CODEPTR(code, jump);
4192 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4193 "mono_generic_class_init");
4194 S390_CALL_TEMPLATE(code, s390_r14);
4196 PTRSLOT (code, jump);
4198 ins->flags |= MONO_INST_GC_CALLSITE;
4199 ins->backend.pc_offset = code - cfg->native_code;
4203 EMIT_UNCOND_BRANCH(ins);
4206 s390_br (code, ins->sreg1);
4212 s390_lghi(code, ins->dreg, 1);
4214 s390_lghi(code, ins->dreg, 0);
4220 s390_lghi(code, ins->dreg, 1);
4222 s390_lghi(code, ins->dreg, 0);
4228 s390_lghi(code, ins->dreg, 1);
4230 s390_lghi(code, ins->dreg, 0);
4236 s390_lghi(code, ins->dreg, 1);
4238 s390_lghi(code, ins->dreg, 0);
4244 s390_lghi(code, ins->dreg, 1);
4246 s390_lghi(code, ins->dreg, 0);
4249 case OP_COND_EXC_EQ:
4250 case OP_COND_EXC_IEQ:
4251 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_EQ, ins->inst_p1);
4253 case OP_COND_EXC_NE_UN:
4254 case OP_COND_EXC_INE_UN:
4255 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NE, ins->inst_p1);
4257 case OP_COND_EXC_LT:
4258 case OP_COND_EXC_ILT:
4259 case OP_COND_EXC_LT_UN:
4260 case OP_COND_EXC_ILT_UN:
4261 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, ins->inst_p1);
4263 case OP_COND_EXC_GT:
4264 case OP_COND_EXC_IGT:
4265 case OP_COND_EXC_GT_UN:
4266 case OP_COND_EXC_IGT_UN:
4267 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, ins->inst_p1);
4269 case OP_COND_EXC_GE:
4270 case OP_COND_EXC_IGE:
4271 case OP_COND_EXC_GE_UN:
4272 case OP_COND_EXC_IGE_UN:
4273 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GE, ins->inst_p1);
4275 case OP_COND_EXC_LE:
4276 case OP_COND_EXC_ILE:
4277 case OP_COND_EXC_LE_UN:
4278 case OP_COND_EXC_ILE_UN:
4279 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LE, ins->inst_p1);
4281 case OP_COND_EXC_OV:
4282 case OP_COND_EXC_IOV:
4283 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, ins->inst_p1);
4285 case OP_COND_EXC_NO:
4286 case OP_COND_EXC_INO:
4287 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NO, ins->inst_p1);
4290 case OP_COND_EXC_IC:
4291 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, ins->inst_p1);
4293 case OP_COND_EXC_NC:
4294 case OP_COND_EXC_INC:
4295 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, ins->inst_p1);
4299 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4303 EMIT_COND_BRANCH (ins, S390_CC_NE);
4309 EMIT_COND_BRANCH (ins, S390_CC_LT);
4315 EMIT_COND_BRANCH (ins, S390_CC_GT);
4321 EMIT_COND_BRANCH (ins, S390_CC_GE);
4327 EMIT_COND_BRANCH (ins, S390_CC_LE);
4330 /* floating point opcodes */
4332 if (*((double *) ins->inst_p0) == 0) {
4333 s390_lzdr (code, ins->dreg);
4335 S390_SET (code, s390_r13, ins->inst_p0);
4336 s390_ld (code, ins->dreg, 0, s390_r13, 0);
4341 if (*((float *) ins->inst_p0) == 0) {
4342 s390_lzdr (code, ins->dreg);
4344 S390_SET (code, s390_r13, ins->inst_p0);
4345 s390_ldeb (code, ins->dreg, 0, s390_r13, 0);
4349 case OP_STORER8_MEMBASE_REG: {
4350 S390_LONG (code, stdy, std, ins->sreg1, 0,
4351 ins->inst_destbasereg, ins->inst_offset);
4354 case OP_LOADR8_MEMBASE: {
4355 S390_LONG (code, ldy, ld, ins->dreg, 0,
4356 ins->inst_basereg, ins->inst_offset);
4359 case OP_STORER4_MEMBASE_REG: {
4360 s390_ledbr (code, s390_f15, ins->sreg1);
4361 S390_LONG (code, stey, ste, s390_f15, 0,
4362 ins->inst_destbasereg, ins->inst_offset);
4365 case OP_LOADR4_MEMBASE: {
4366 S390_LONG (code, ley, le, s390_f15, 0,
4367 ins->inst_basereg, ins->inst_offset);
4368 s390_ldebr (code, ins->dreg, s390_f15);
4371 case OP_ICONV_TO_R_UN: {
4372 if (mono_hwcap_s390x_has_fpe) {
4373 s390_cdlfbr (code, ins->dreg, 5, ins->sreg1, 0);
4375 s390_llgfr (code, s390_r0, ins->sreg1);
4376 s390_cdgbr (code, ins->dreg, s390_r0);
4380 case OP_LCONV_TO_R_UN: {
4381 if (mono_hwcap_s390x_has_fpe) {
4382 s390_cdlgbr (code, ins->dreg, 5, ins->sreg1, 0);
4385 s390_cxgbr (code, s390_f12, ins->sreg1);
4386 s390_ltgr (code, ins->sreg1, ins->sreg1);
4387 s390_jnl (code, 0); CODEPTR(code, jump);
4388 S390_SET (code, s390_r13, 0x403f000000000000llu);
4389 s390_lgdr (code, s390_f13, s390_r13);
4390 s390_lzdr (code, s390_f15);
4391 s390_axbr (code, s390_f12, s390_f13);
4392 PTRSLOT(code, jump);
4393 s390_ldxbr (code, s390_f13, s390_f12);
4394 s390_ldr (code, ins->dreg, s390_f13);
4398 case OP_LCONV_TO_R4:
4399 case OP_ICONV_TO_R4: {
4400 s390_cegbr (code, ins->dreg, ins->sreg1);
4401 s390_ldebr (code, ins->dreg, ins->dreg);
4404 case OP_LCONV_TO_R8:
4405 case OP_ICONV_TO_R8: {
4406 s390_cdgbr (code, ins->dreg, ins->sreg1);
4409 case OP_FCONV_TO_I1:
4410 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4411 s390_ltgr (code, ins->dreg, ins->dreg);
4413 s390_oill (code, ins->dreg, 0x80);
4414 s390_lghi (code, s390_r0, 0xff);
4415 s390_ngr (code, ins->dreg, s390_r0);
4417 case OP_FCONV_TO_U1:
4418 if (mono_hwcap_s390x_has_fpe) {
4419 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4420 s390_lghi (code, s390_r0, 0xff);
4421 s390_ngr (code, ins->dreg, s390_r0);
4423 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 1, FALSE);
4426 case OP_FCONV_TO_I2:
4427 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4428 s390_ltgr (code, ins->dreg, ins->dreg);
4430 s390_oill (code, ins->dreg, 0x8000);
4431 s390_llill (code, s390_r0, 0xffff);
4432 s390_ngr (code, ins->dreg, s390_r0);
4434 case OP_FCONV_TO_U2:
4435 if (mono_hwcap_s390x_has_fpe) {
4436 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4437 s390_llill (code, s390_r0, 0xffff);
4438 s390_ngr (code, ins->dreg, s390_r0);
4440 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 2, FALSE);
4443 case OP_FCONV_TO_I4:
4445 s390_cfdbr (code, ins->dreg, 5, ins->sreg1);
4447 case OP_FCONV_TO_U4:
4449 if (mono_hwcap_s390x_has_fpe) {
4450 s390_clfdbr (code, ins->dreg, 5, ins->sreg1, 0);
4452 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE);
4455 case OP_FCONV_TO_I8:
4456 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4458 case OP_FCONV_TO_U8:
4459 if (mono_hwcap_s390x_has_fpe) {
4460 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4462 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 8, FALSE);
4465 case OP_LCONV_TO_OVF_I: {
4466 /* Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000 */
4468 s390_ltgr (code, ins->sreg2, ins->sreg2);
4469 s390_jnl (code, 0); CODEPTR(code, o[0]);
4470 s390_ltgr (code, ins->sreg1, ins->sreg1);
4471 s390_jnl (code, 0); CODEPTR(code, o[1]);
4472 s390_lhi (code, s390_r13, -1);
4473 s390_cgr (code, ins->sreg1, s390_r13);
4474 s390_jnz (code, 0); CODEPTR(code, o[2]);
4475 if (ins->dreg != ins->sreg2)
4476 s390_lgr (code, ins->dreg, ins->sreg2);
4477 s390_j (code, 0); CODEPTR(code, o[3]);
4478 PTRSLOT(code, o[0]);
4479 s390_jz (code, 0); CODEPTR(code, o[4]);
4480 PTRSLOT(code, o[1]);
4481 PTRSLOT(code, o[2]);
4482 mono_add_patch_info (cfg, code - cfg->native_code,
4483 MONO_PATCH_INFO_EXC, "OverflowException");
4484 s390_brasl (code, s390_r14, 0);
4485 PTRSLOT(code, o[3]);
4486 PTRSLOT(code, o[4]);
4490 s390_lpdbr (code, ins->dreg, ins->sreg1);
4494 s390_sqdbr (code, ins->dreg, ins->sreg1);
4499 s390_adbr (code, ins->dreg, src2);
4503 CHECK_SRCDST_NCOM_F;
4504 s390_sdbr (code, ins->dreg, src2);
4509 s390_mdbr (code, ins->dreg, src2);
4513 CHECK_SRCDST_NCOM_F;
4514 s390_ddbr (code, ins->dreg, src2);
4518 s390_lcdbr (code, ins->dreg, ins->sreg1);
4522 CHECK_SRCDST_NCOM_F;
4523 s390_didbr (code, ins->dreg, src2, 5, s390_f15);
4527 s390_cdbr (code, ins->sreg1, ins->sreg2);
4531 s390_cdbr (code, ins->sreg1, ins->sreg2);
4532 s390_lghi (code, ins->dreg, 1);
4534 s390_lghi (code, ins->dreg, 0);
4538 s390_cdbr (code, ins->sreg1, ins->sreg2);
4539 s390_lghi (code, ins->dreg, 1);
4541 s390_lghi (code, ins->dreg, 0);
4545 s390_cdbr (code, ins->sreg1, ins->sreg2);
4546 s390_lghi (code, ins->dreg, 1);
4548 s390_lghi (code, ins->dreg, 0);
4552 s390_cdbr (code, ins->sreg1, ins->sreg2);
4553 s390_lghi (code, ins->dreg, 1);
4555 s390_lghi (code, ins->dreg, 0);
4559 s390_cdbr (code, ins->sreg1, ins->sreg2);
4560 s390_lghi (code, ins->dreg, 1);
4562 s390_lghi (code, ins->dreg, 0);
4567 s390_jo (code, 0); CODEPTR(code, o);
4568 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4573 EMIT_COND_BRANCH (ins, S390_CC_NE|S390_CC_OV);
4577 s390_jo (code, 0); CODEPTR(code, o);
4578 EMIT_COND_BRANCH (ins, S390_CC_LT);
4583 EMIT_COND_BRANCH (ins, S390_CC_LT|S390_CC_OV);
4587 s390_jo (code, 0); CODEPTR(code, o);
4588 EMIT_COND_BRANCH (ins, S390_CC_GT);
4593 EMIT_COND_BRANCH (ins, S390_CC_GT|S390_CC_OV);
4597 s390_jo (code, 0); CODEPTR(code, o);
4598 EMIT_COND_BRANCH (ins, S390_CC_GE);
4603 EMIT_COND_BRANCH (ins, S390_CC_GE|S390_CC_OV);
4607 s390_jo (code, 0); CODEPTR(code, o);
4608 EMIT_COND_BRANCH (ins, S390_CC_LE);
4613 EMIT_COND_BRANCH (ins, S390_CC_LE|S390_CC_OV);
4617 s390_lhi (code, s390_r13, 0x7f);
4618 s390_tcdb (code, ins->sreg1, 0, s390_r13, 0);
4619 s390_jz (code, 0); CODEPTR(code, o);
4620 mono_add_patch_info (cfg, code - cfg->native_code,
4621 MONO_PATCH_INFO_EXC, "OverflowException");
4622 s390_brasl (code, s390_r14,0);
4626 case OP_S390_MOVE: {
4627 if (ins->backend.size > 0) {
4628 if (ins->backend.size <= 256) {
4629 s390_mvc (code, ins->backend.size, ins->dreg,
4630 ins->inst_offset, ins->sreg1, ins->inst_imm);
4632 s390_lgr (code, s390_r0, ins->dreg);
4633 if (ins->inst_offset > 0) {
4634 if (s390_is_imm16 (ins->inst_offset)) {
4635 s390_aghi (code, s390_r0, ins->inst_offset);
4636 } else if (s390_is_imm32 (ins->inst_offset)) {
4637 s390_agfi (code, s390_r0, ins->inst_offset);
4639 S390_SET (code, s390_r13, ins->inst_offset);
4640 s390_agr (code, s390_r0, s390_r13);
4643 s390_lgr (code, s390_r12, ins->sreg1);
4644 if (ins->inst_imm > 0) {
4645 if (s390_is_imm16 (ins->inst_imm)) {
4646 s390_aghi (code, s390_r12, ins->inst_imm);
4647 } else if (s390_is_imm32 (ins->inst_imm)) {
4648 s390_agfi (code, s390_r12, ins->inst_imm);
4650 S390_SET (code, s390_r13, ins->inst_imm);
4651 s390_agr (code, s390_r12, s390_r13);
4654 if (s390_is_imm16 (ins->backend.size)) {
4655 s390_lghi (code, s390_r1, ins->backend.size);
4656 } else if (s390_is_imm32 (ins->inst_offset)) {
4657 s390_agfi (code, s390_r1, ins->backend.size);
4659 S390_SET (code, s390_r13, ins->backend.size);
4660 s390_agr (code, s390_r1, s390_r13);
4662 s390_lgr (code, s390_r13, s390_r1);
4663 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4669 case OP_ATOMIC_ADD_I8: {
4670 s390_lgr (code, s390_r1, ins->sreg2);
4671 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4672 s390_agr (code, s390_r1, s390_r0);
4673 s390_csg (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4674 s390_jnz (code, -10);
4675 s390_lgr (code, ins->dreg, s390_r1);
4678 case OP_ATOMIC_EXCHANGE_I8: {
4679 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4680 s390_csg (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
4681 s390_jnz (code, -6);
4682 s390_lgr (code, ins->dreg, s390_r0);
4685 case OP_ATOMIC_ADD_I4: {
4686 s390_lgfr(code, s390_r1, ins->sreg2);
4687 s390_lgf (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4688 s390_agr (code, s390_r1, s390_r0);
4689 s390_cs (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4690 s390_jnz (code, -9);
4691 s390_lgfr(code, ins->dreg, s390_r1);
4694 case OP_ATOMIC_EXCHANGE_I4: {
4695 s390_l (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4696 s390_cs (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
4697 s390_jnz (code, -4);
4698 s390_lgfr(code, ins->dreg, s390_r0);
4701 case OP_S390_BKCHAIN: {
4702 s390_lgr (code, ins->dreg, ins->sreg1);
4703 if (s390_is_imm16 (cfg->stack_offset)) {
4704 s390_aghi (code, ins->dreg, cfg->stack_offset);
4705 } else if (s390_is_imm32 (cfg->stack_offset)) {
4706 s390_agfi (code, ins->dreg, cfg->stack_offset);
4708 S390_SET (code, s390_r13, cfg->stack_offset);
4709 s390_agr (code, ins->dreg, s390_r13);
4713 case OP_MEMORY_BARRIER:
4716 case OP_GC_SAFE_POINT: {
4719 g_assert (mono_threads_is_coop_enabled ());
4721 s390_chi (code, ins->sreg1, 1);
4722 s390_je (code, 0); CODEPTR(code, br);
4723 mono_add_patch_info (cfg, code- cfg->native_code, MONO_PATCH_INFO_ABS,
4724 mono_threads_state_poll);
4725 S390_CALL_TEMPLATE (code, s390_r14);
4729 case OP_GC_LIVENESS_DEF:
4730 case OP_GC_LIVENESS_USE:
4731 case OP_GC_PARAM_SLOT_LIVENESS_DEF:
4732 ins->backend.pc_offset = code - cfg->native_code;
4734 case OP_GC_SPILL_SLOT_LIVENESS_DEF:
4735 ins->backend.pc_offset = code - cfg->native_code;
4736 bb->spill_slot_defs = g_slist_prepend_mempool (cfg->mempool, bb->spill_slot_defs, ins);
4738 #ifdef MONO_ARCH_SIMD_INTRINSICS
4740 s390x_addps (code, ins->sreg1, ins->sreg2);
4743 s390x_divps (code, ins->sreg1, ins->sreg2);
4746 s390x_mulps (code, ins->sreg1, ins->sreg2);
4749 s390x_subps (code, ins->sreg1, ins->sreg2);
4752 s390x_maxps (code, ins->sreg1, ins->sreg2);
4755 s390x_minps (code, ins->sreg1, ins->sreg2);
4758 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
4759 s390x_cmpps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4762 s390x_andps (code, ins->sreg1, ins->sreg2);
4765 s390x_andnps (code, ins->sreg1, ins->sreg2);
4768 s390x_orps (code, ins->sreg1, ins->sreg2);
4771 s390x_xorps (code, ins->sreg1, ins->sreg2);
4774 s390x_sqrtps (code, ins->dreg, ins->sreg1);
4777 s390x_rsqrtps (code, ins->dreg, ins->sreg1);
4780 s390x_rcpps (code, ins->dreg, ins->sreg1);
4783 s390x_addsubps (code, ins->sreg1, ins->sreg2);
4786 s390x_haddps (code, ins->sreg1, ins->sreg2);
4789 s390x_hsubps (code, ins->sreg1, ins->sreg2);
4792 s390x_movshdup (code, ins->dreg, ins->sreg1);
4795 s390x_movsldup (code, ins->dreg, ins->sreg1);
4798 case OP_PSHUFLEW_HIGH:
4799 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4800 s390x_pshufhw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4802 case OP_PSHUFLEW_LOW:
4803 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4804 s390x_pshuflw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4807 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4808 s390x_pshufd_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4811 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4812 s390x_shufps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4815 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0x3);
4816 s390x_shufpd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4820 s390x_addpd (code, ins->sreg1, ins->sreg2);
4823 s390x_divpd (code, ins->sreg1, ins->sreg2);
4826 s390x_mulpd (code, ins->sreg1, ins->sreg2);
4829 s390x_subpd (code, ins->sreg1, ins->sreg2);
4832 s390x_maxpd (code, ins->sreg1, ins->sreg2);
4835 s390x_minpd (code, ins->sreg1, ins->sreg2);
4838 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
4839 s390x_cmppd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4842 s390x_andpd (code, ins->sreg1, ins->sreg2);
4845 s390x_andnpd (code, ins->sreg1, ins->sreg2);
4848 s390x_orpd (code, ins->sreg1, ins->sreg2);
4851 s390x_xorpd (code, ins->sreg1, ins->sreg2);
4854 s390x_sqrtpd (code, ins->dreg, ins->sreg1);
4857 s390x_addsubpd (code, ins->sreg1, ins->sreg2);
4860 s390x_haddpd (code, ins->sreg1, ins->sreg2);
4863 s390x_hsubpd (code, ins->sreg1, ins->sreg2);
4866 s390x_movddup (code, ins->dreg, ins->sreg1);
4869 case OP_EXTRACT_MASK:
4870 s390x_pmovmskb (code, ins->dreg, ins->sreg1);
4874 s390x_pand (code, ins->sreg1, ins->sreg2);
4877 s390x_por (code, ins->sreg1, ins->sreg2);
4880 s390x_pxor (code, ins->sreg1, ins->sreg2);
4884 s390x_paddb (code, ins->sreg1, ins->sreg2);
4887 s390x_paddw (code, ins->sreg1, ins->sreg2);
4890 s390x_paddd (code, ins->sreg1, ins->sreg2);
4893 s390x_paddq (code, ins->sreg1, ins->sreg2);
4897 s390x_psubb (code, ins->sreg1, ins->sreg2);
4900 s390x_psubw (code, ins->sreg1, ins->sreg2);
4903 s390x_psubd (code, ins->sreg1, ins->sreg2);
4906 s390x_psubq (code, ins->sreg1, ins->sreg2);
4910 s390x_pmaxub (code, ins->sreg1, ins->sreg2);
4913 s390x_pmaxuw (code, ins->sreg1, ins->sreg2);
4916 s390x_pmaxud (code, ins->sreg1, ins->sreg2);
4920 s390x_pmaxsb (code, ins->sreg1, ins->sreg2);
4923 s390x_pmaxsw (code, ins->sreg1, ins->sreg2);
4926 s390x_pmaxsd (code, ins->sreg1, ins->sreg2);
4930 s390x_pavgb (code, ins->sreg1, ins->sreg2);
4933 s390x_pavgw (code, ins->sreg1, ins->sreg2);
4937 s390x_pminub (code, ins->sreg1, ins->sreg2);
4940 s390x_pminuw (code, ins->sreg1, ins->sreg2);
4943 s390x_pminud (code, ins->sreg1, ins->sreg2);
4947 s390x_pminsb (code, ins->sreg1, ins->sreg2);
4950 s390x_pminsw (code, ins->sreg1, ins->sreg2);
4953 s390x_pminsd (code, ins->sreg1, ins->sreg2);
4957 s390x_pcmpeqb (code, ins->sreg1, ins->sreg2);
4960 s390x_pcmpeqw (code, ins->sreg1, ins->sreg2);
4963 s390x_pcmpeqd (code, ins->sreg1, ins->sreg2);
4966 s390x_pcmpeqq (code, ins->sreg1, ins->sreg2);
4970 s390x_pcmpgtb (code, ins->sreg1, ins->sreg2);
4973 s390x_pcmpgtw (code, ins->sreg1, ins->sreg2);
4976 s390x_pcmpgtd (code, ins->sreg1, ins->sreg2);
4979 s390x_pcmpgtq (code, ins->sreg1, ins->sreg2);
4982 case OP_PSUM_ABS_DIFF:
4983 s390x_psadbw (code, ins->sreg1, ins->sreg2);
4986 case OP_UNPACK_LOWB:
4987 s390x_punpcklbw (code, ins->sreg1, ins->sreg2);
4989 case OP_UNPACK_LOWW:
4990 s390x_punpcklwd (code, ins->sreg1, ins->sreg2);
4992 case OP_UNPACK_LOWD:
4993 s390x_punpckldq (code, ins->sreg1, ins->sreg2);
4995 case OP_UNPACK_LOWQ:
4996 s390x_punpcklqdq (code, ins->sreg1, ins->sreg2);
4998 case OP_UNPACK_LOWPS:
4999 s390x_unpcklps (code, ins->sreg1, ins->sreg2);
5001 case OP_UNPACK_LOWPD:
5002 s390x_unpcklpd (code, ins->sreg1, ins->sreg2);
5005 case OP_UNPACK_HIGHB:
5006 s390x_punpckhbw (code, ins->sreg1, ins->sreg2);
5008 case OP_UNPACK_HIGHW:
5009 s390x_punpckhwd (code, ins->sreg1, ins->sreg2);
5011 case OP_UNPACK_HIGHD:
5012 s390x_punpckhdq (code, ins->sreg1, ins->sreg2);
5014 case OP_UNPACK_HIGHQ:
5015 s390x_punpckhqdq (code, ins->sreg1, ins->sreg2);
5017 case OP_UNPACK_HIGHPS:
5018 s390x_unpckhps (code, ins->sreg1, ins->sreg2);
5020 case OP_UNPACK_HIGHPD:
5021 s390x_unpckhpd (code, ins->sreg1, ins->sreg2);
5025 s390x_packsswb (code, ins->sreg1, ins->sreg2);
5028 s390x_packssdw (code, ins->sreg1, ins->sreg2);
5031 s390x_packuswb (code, ins->sreg1, ins->sreg2);
5034 s390x_packusdw (code, ins->sreg1, ins->sreg2);
5037 case OP_PADDB_SAT_UN:
5038 s390x_paddusb (code, ins->sreg1, ins->sreg2);
5040 case OP_PSUBB_SAT_UN:
5041 s390x_psubusb (code, ins->sreg1, ins->sreg2);
5043 case OP_PADDW_SAT_UN:
5044 s390x_paddusw (code, ins->sreg1, ins->sreg2);
5046 case OP_PSUBW_SAT_UN:
5047 s390x_psubusw (code, ins->sreg1, ins->sreg2);
5051 s390x_paddsb (code, ins->sreg1, ins->sreg2);
5054 s390x_psubsb (code, ins->sreg1, ins->sreg2);
5057 s390x_paddsw (code, ins->sreg1, ins->sreg2);
5060 s390x_psubsw (code, ins->sreg1, ins->sreg2);
5064 s390x_pmullw (code, ins->sreg1, ins->sreg2);
5067 s390x_pmulld (code, ins->sreg1, ins->sreg2);
5070 s390x_pmuludq (code, ins->sreg1, ins->sreg2);
5072 case OP_PMULW_HIGH_UN:
5073 s390x_pmulhuw (code, ins->sreg1, ins->sreg2);
5076 s390x_pmulhw (code, ins->sreg1, ins->sreg2);
5080 s390x_psrlw_reg_imm (code, ins->dreg, ins->inst_imm);
5083 s390x_psrlw (code, ins->dreg, ins->sreg2);
5087 s390x_psraw_reg_imm (code, ins->dreg, ins->inst_imm);
5090 s390x_psraw (code, ins->dreg, ins->sreg2);
5094 s390x_psllw_reg_imm (code, ins->dreg, ins->inst_imm);
5097 s390x_psllw (code, ins->dreg, ins->sreg2);
5101 s390x_psrld_reg_imm (code, ins->dreg, ins->inst_imm);
5104 s390x_psrld (code, ins->dreg, ins->sreg2);
5108 s390x_psrad_reg_imm (code, ins->dreg, ins->inst_imm);
5111 s390x_psrad (code, ins->dreg, ins->sreg2);
5115 s390x_pslld_reg_imm (code, ins->dreg, ins->inst_imm);
5118 s390x_pslld (code, ins->dreg, ins->sreg2);
5122 s390x_psrlq_reg_imm (code, ins->dreg, ins->inst_imm);
5125 s390x_psrlq (code, ins->dreg, ins->sreg2);
5128 /*TODO: This is appart of the sse spec but not added
5130 s390x_psraq_reg_imm (code, ins->dreg, ins->inst_imm);
5133 s390x_psraq (code, ins->dreg, ins->sreg2);
5138 s390x_psllq_reg_imm (code, ins->dreg, ins->inst_imm);
5141 s390x_psllq (code, ins->dreg, ins->sreg2);
5144 s390x_cvtdq2pd (code, ins->dreg, ins->sreg1);
5147 s390x_cvtdq2ps (code, ins->dreg, ins->sreg1);
5150 s390x_cvtpd2dq (code, ins->dreg, ins->sreg1);
5153 s390x_cvtpd2ps (code, ins->dreg, ins->sreg1);
5156 s390x_cvtps2dq (code, ins->dreg, ins->sreg1);
5159 s390x_cvtps2pd (code, ins->dreg, ins->sreg1);
5162 s390x_cvttpd2dq (code, ins->dreg, ins->sreg1);
5165 s390x_cvttps2dq (code, ins->dreg, ins->sreg1);
5169 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5172 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5176 amd64_movhlps (code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg1);
5177 amd64_movd_reg_xreg_size (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG, 8);
5179 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 8);
5184 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5186 amd64_shift_reg_imm (code, X86_SHR, ins->dreg, ins->inst_c0 * 8);
5187 amd64_widen_reg (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I1, FALSE);
5191 /*amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5193 amd64_shift_reg_imm_size (code, X86_SHR, ins->dreg, 16, 4);*/
5194 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5195 amd64_widen_reg_size (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I2, TRUE, 4);
5199 amd64_movhlps (code, ins->dreg, ins->sreg1);
5201 s390x_movsd (code, ins->dreg, ins->sreg1);
5204 s390x_pinsrw_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5206 case OP_EXTRACTX_U2:
5207 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5209 case OP_INSERTX_U1_SLOW:
5210 /*sreg1 is the extracted ireg (scratch)
5211 /sreg2 is the to be inserted ireg (scratch)
5212 /dreg is the xreg to receive the value*/
5214 /*clear the bits from the extracted word*/
5215 amd64_alu_reg_imm (code, X86_AND, ins->sreg1, ins->inst_c0 & 1 ? 0x00FF : 0xFF00);
5216 /*shift the value to insert if needed*/
5217 if (ins->inst_c0 & 1)
5218 amd64_shift_reg_imm_size (code, X86_SHL, ins->sreg2, 8, 4);
5219 /*join them together*/
5220 amd64_alu (code, X86_OR, ins->sreg1, ins->sreg2);
5221 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0 / 2);
5223 case OP_INSERTX_I4_SLOW:
5224 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2);
5225 amd64_shift_reg_imm (code, X86_SHR, ins->sreg2, 16);
5226 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2 + 1);
5228 case OP_INSERTX_I8_SLOW:
5229 amd64_movd_xreg_reg_size(code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg2, 8);
5231 amd64_movlhps (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5233 s390x_movsd (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5236 case OP_INSERTX_R4_SLOW:
5237 switch (ins->inst_c0) {
5240 s390x_movss (code, ins->dreg, ins->sreg2);
5242 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5245 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5247 s390x_movss (code, ins->dreg, ins->sreg2);
5249 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5250 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5253 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5255 s390x_movss (code, ins->dreg, ins->sreg2);
5257 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5258 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5261 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5263 s390x_movss (code, ins->dreg, ins->sreg2);
5265 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5266 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5270 case OP_INSERTX_R8_SLOW:
5272 amd64_movlhps (code, ins->dreg, ins->sreg2);
5274 s390x_movsd (code, ins->dreg, ins->sreg2);
5276 case OP_STOREX_MEMBASE_REG:
5277 case OP_STOREX_MEMBASE:
5278 s390x_movups_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5280 case OP_LOADX_MEMBASE:
5281 s390x_movups_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5283 case OP_LOADX_ALIGNED_MEMBASE:
5284 s390x_movaps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5286 case OP_STOREX_ALIGNED_MEMBASE_REG:
5287 s390x_movaps_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5289 case OP_STOREX_NTA_MEMBASE_REG:
5290 s390x_movntps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5292 case OP_PREFETCH_MEMBASE:
5293 s390x_prefetch_reg_membase (code, ins->backend.arg_info, ins->sreg1, ins->inst_offset);
5297 /*FIXME the peephole pass should have killed this*/
5298 if (ins->dreg != ins->sreg1)
5299 s390x_movaps (code, ins->dreg, ins->sreg1);
5302 s390x_pxor (code, ins->dreg, ins->dreg);
5304 case OP_ICONV_TO_R4_RAW:
5305 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5308 case OP_FCONV_TO_R8_X:
5309 s390x_movsd (code, ins->dreg, ins->sreg1);
5312 case OP_XCONV_R8_TO_I4:
5313 s390x_cvttsd2si_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5314 switch (ins->backend.source_opcode) {
5315 case OP_FCONV_TO_I1:
5316 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, FALSE);
5318 case OP_FCONV_TO_U1:
5319 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, FALSE);
5321 case OP_FCONV_TO_I2:
5322 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, TRUE);
5324 case OP_FCONV_TO_U2:
5325 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, TRUE);
5331 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 0);
5332 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 1);
5333 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5336 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5337 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5340 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 8);
5341 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5345 s390x_movsd (code, ins->dreg, ins->sreg1);
5347 s390x_movsd (code, ins->dreg, ins->sreg1);
5348 s390x_cvtsd2ss (code, ins->dreg, ins->dreg);
5350 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5353 s390x_movsd (code, ins->dreg, ins->sreg1);
5354 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5358 g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
5359 g_assert_not_reached ();
5362 if ((cfg->opt & MONO_OPT_BRANCH) && ((code - cfg->native_code - offset) > max_len)) {
5363 g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %ld)",
5364 mono_inst_name (ins->opcode), max_len, code - cfg->native_code - offset);
5365 g_assert_not_reached ();
5368 last_offset = offset;
5371 cfg->code_len = code - cfg->native_code;
5374 /*========================= End of Function ========================*/
5376 /*------------------------------------------------------------------*/
5378 /* Name - mono_arch_register_lowlevel_calls */
5380 /* Function - Register routines to help with --trace operation. */
5382 /*------------------------------------------------------------------*/
5385 mono_arch_register_lowlevel_calls (void)
5389 /*========================= End of Function ========================*/
5391 /*------------------------------------------------------------------*/
5393 /* Name - mono_arch_patch_code */
5395 /* Function - Process the patch data created during the */
5396 /* instruction build process. This resolves jumps, */
5397 /* calls, variables etc. */
5399 /*------------------------------------------------------------------*/
5402 mono_arch_patch_code (MonoCompile *cfg, MonoMethod *method, MonoDomain *domain,
5403 guint8 *code, MonoJumpInfo *ji, gboolean run_cctors,
5406 MonoJumpInfo *patch_info;
5408 mono_error_init (error);
5410 for (patch_info = ji; patch_info; patch_info = patch_info->next) {
5411 unsigned char *ip = patch_info->ip.i + code;
5412 gconstpointer target = NULL;
5414 target = mono_resolve_patch_target (method, domain, code,
5415 patch_info, run_cctors, error);
5416 return_if_nok (error);
5418 switch (patch_info->type) {
5419 case MONO_PATCH_INFO_IP:
5420 case MONO_PATCH_INFO_LDSTR:
5421 case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
5422 case MONO_PATCH_INFO_LDTOKEN:
5423 case MONO_PATCH_INFO_EXC:
5424 s390_patch_addr (ip, (guint64) target);
5426 case MONO_PATCH_INFO_METHOD:
5427 case MONO_PATCH_INFO_INTERNAL_METHOD:
5428 case MONO_PATCH_INFO_JIT_ICALL_ADDR:
5429 case MONO_PATCH_INFO_RGCTX_FETCH:
5430 case MONO_PATCH_INFO_ABS: {
5431 S390_EMIT_CALL (ip, target);
5434 case MONO_PATCH_INFO_SWITCH:
5435 /*----------------------------------*/
5436 /* ip points at the basr r13,0/j +4 */
5437 /* instruction the vtable value */
5438 /* follows this (i.e. ip+6) */
5439 /*----------------------------------*/
5440 S390_EMIT_LOAD (ip, target);
5442 case MONO_PATCH_INFO_METHODCONST:
5443 case MONO_PATCH_INFO_CLASS:
5444 case MONO_PATCH_INFO_IMAGE:
5445 case MONO_PATCH_INFO_FIELD:
5446 case MONO_PATCH_INFO_IID:
5447 case MONO_PATCH_INFO_EXC_NAME:
5448 target = S390_RELATIVE(target, ip);
5449 s390_patch_rel (ip, (guint64) target);
5451 case MONO_PATCH_INFO_R4:
5452 case MONO_PATCH_INFO_R8:
5453 case MONO_PATCH_INFO_METHOD_REL:
5454 g_assert_not_reached ();
5457 target = S390_RELATIVE(target, ip);
5459 s390_patch_rel (ip, (guint64) target);
5464 /*========================= End of Function ========================*/
5466 /*------------------------------------------------------------------*/
5468 /* Name - emit_load_volatile_arguments */
5470 /* Function - Emit the instructions to reload parameter regist- */
5471 /* registers for use with "tail" operations. */
5473 /* The register loading operations performed here */
5474 /* are the mirror of the store operations performed */
5475 /* in mono_arch_emit_prolog and need to be kept in */
5476 /* synchronization with it. */
5478 /*------------------------------------------------------------------*/
5481 emit_load_volatile_arguments (guint8 *code, MonoCompile *cfg)
5484 MonoMethod *method = cfg->method;
5485 MonoMethodSignature *sig = mono_method_signature(method);
5489 cinfo = get_call_info (NULL, NULL, sig);
5491 if (cinfo->struct_ret) {
5492 ArgInfo *ainfo = &cinfo->ret;
5493 inst = cfg->vret_addr;
5494 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5497 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5498 ArgInfo *ainfo = cinfo->args + i;
5499 inst = cfg->args [pos];
5501 if (inst->opcode == OP_REGVAR) {
5502 if (ainfo->regtype == RegTypeGeneral)
5503 s390_lgr (code, ainfo->reg, inst->dreg);
5504 else if (ainfo->regtype == RegTypeFP) {
5505 if (inst->dreg != ainfo->reg) {
5506 if (ainfo->size == 4) {
5507 s390_ldebr (code, ainfo->reg, inst->dreg);
5509 s390_ldr (code, ainfo->reg, inst->dreg);
5513 else if (ainfo->regtype == RegTypeBase) {
5515 g_assert_not_reached ();
5517 if (ainfo->regtype == RegTypeGeneral) {
5518 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5519 g_assert_not_reached();
5520 switch (ainfo->size) {
5522 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5525 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5528 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5531 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5534 } else if (ainfo->regtype == RegTypeBase) {
5535 } else if (ainfo->regtype == RegTypeFP) {
5536 if (ainfo->size == 8)
5537 s390_ld (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5538 else if (ainfo->size == 4)
5539 s390_le (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5541 g_assert_not_reached ();
5542 } else if (ainfo->regtype == RegTypeStructByVal) {
5543 if (ainfo->reg != STK_BASE) {
5544 switch (ainfo->size) {
5546 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5549 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5552 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5555 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5559 } else if (ainfo->regtype == RegTypeStructByAddr) {
5560 if (ainfo->reg != STK_BASE) {
5561 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5564 g_assert_not_reached ();
5572 /*========================= End of Function ========================*/
5574 /*------------------------------------------------------------------*/
5576 /* Name - mono_arch_emit_prolog */
5578 /* Function - Create the instruction sequence for a function */
5581 /*------------------------------------------------------------------*/
5584 mono_arch_emit_prolog (MonoCompile *cfg)
5586 MonoMethod *method = cfg->method;
5588 MonoMethodSignature *sig;
5590 long alloc_size, pos, max_offset, i, cfa_offset = 0;
5599 cfg->code_size = 512;
5601 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
5603 cfg->code_size += 256;
5604 } else if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
5605 cfg->code_size += 256;
5607 if (method->save_lmf)
5608 cfg->code_size += 200;
5610 cfg->native_code = code = g_malloc (cfg->code_size);
5612 mono_emit_unwind_op_def_cfa (cfg, code, STK_BASE, 0);
5613 emit_unwind_regs(cfg, code, s390_r6, s390_r14, S390_REG_SAVE_OFFSET);
5614 s390_stmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
5615 mono_emit_unwind_op_offset (cfg, code, s390_r14, S390_RET_ADDR_OFFSET);
5616 mini_gc_set_slot_type_from_cfa (cfg, S390_RET_ADDR_OFFSET, SLOT_NOREF);
5618 if (cfg->arch.bkchain_reg != -1)
5619 s390_lgr (code, cfg->arch.bkchain_reg, STK_BASE);
5621 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
5622 cfg->used_int_regs |= 1 << 11;
5625 alloc_size = cfg->stack_offset;
5627 cfg->stack_usage = cfa_offset = alloc_size;
5628 mono_emit_unwind_op_def_cfa_offset (cfg, code, alloc_size);
5629 s390_lgr (code, s390_r11, STK_BASE);
5630 if (s390_is_imm16 (alloc_size)) {
5631 s390_aghi (code, STK_BASE, -alloc_size);
5632 } else if (s390_is_imm32 (alloc_size)) {
5633 s390_agfi (code, STK_BASE, -alloc_size);
5635 int stackSize = alloc_size;
5636 while (stackSize > INT_MAX) {
5637 s390_agfi (code, STK_BASE, -INT_MAX);
5638 stackSize -= INT_MAX;
5640 s390_agfi (code, STK_BASE, -stackSize);
5642 s390_stg (code, s390_r11, 0, STK_BASE, 0);
5644 if (cfg->frame_reg != STK_BASE)
5645 s390_lgr (code, s390_r11, STK_BASE);
5647 mono_emit_unwind_op_def_cfa_reg (cfg, code, cfg->frame_reg);
5649 /* store runtime generic context */
5650 if (cfg->rgctx_var) {
5651 g_assert (cfg->rgctx_var->opcode == OP_REGOFFSET);
5653 s390_stg (code, MONO_ARCH_RGCTX_REG, 0,
5654 cfg->rgctx_var->inst_basereg,
5655 cfg->rgctx_var->inst_offset);
5658 /* compute max_offset in order to use short forward jumps
5659 * we always do it on s390 because the immediate displacement
5660 * for jumps is too small
5663 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
5665 bb->max_offset = max_offset;
5667 if (cfg->prof_options & MONO_PROFILE_COVERAGE)
5670 MONO_BB_FOR_EACH_INS (bb, ins)
5671 max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
5674 /* load arguments allocated to register from the stack */
5675 sig = mono_method_signature (method);
5678 cinfo = get_call_info (cfg, cfg->mempool, sig);
5680 if (cinfo->struct_ret) {
5681 ArgInfo *ainfo = &cinfo->ret;
5682 inst = cfg->vret_addr;
5683 inst->backend.size = ainfo->vtsize;
5684 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5687 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5688 ArgInfo *ainfo = cinfo->args + i;
5689 inst = cfg->args [pos];
5691 if (inst->opcode == OP_VTARG_ADDR)
5692 inst = inst->inst_left;
5694 if (inst->opcode == OP_REGVAR) {
5695 if (ainfo->regtype == RegTypeGeneral)
5696 s390_lgr (code, inst->dreg, ainfo->reg);
5697 else if (ainfo->regtype == RegTypeFP) {
5698 if (inst->dreg != ainfo->reg) {
5699 if (ainfo->size == 4) {
5700 s390_ledbr (code, inst->dreg, ainfo->reg);
5702 s390_ldr (code, inst->dreg, ainfo->reg);
5706 else if (ainfo->regtype == RegTypeBase) {
5707 s390_lgr (code, s390_r13, STK_BASE);
5708 s390_aghi (code, s390_r13, alloc_size);
5709 s390_lg (code, inst->dreg, 0, s390_r13, ainfo->offset);
5711 g_assert_not_reached ();
5713 if (cfg->verbose_level > 2)
5714 g_print ("Argument %d assigned to register %s\n",
5715 pos, mono_arch_regname (inst->dreg));
5717 if (ainfo->regtype == RegTypeGeneral) {
5718 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5719 g_assert_not_reached();
5720 switch (ainfo->size) {
5722 s390_stc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5725 s390_sth (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5728 s390_st (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5731 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5734 } else if (ainfo->regtype == RegTypeBase) {
5735 } else if (ainfo->regtype == RegTypeFP) {
5736 if (ainfo->size == 8)
5737 s390_std (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5738 else if (ainfo->size == 4)
5739 s390_ste (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5741 g_assert_not_reached ();
5742 } else if (ainfo->regtype == RegTypeStructByVal) {
5743 int doffset = inst->inst_offset;
5745 if (ainfo->reg != STK_BASE)
5749 s390_lgr (code, s390_r13, STK_BASE);
5750 s390_aghi (code, s390_r13, alloc_size);
5753 size = (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE
5754 ? mono_class_native_size(mono_class_from_mono_type(inst->inst_vtype), NULL)
5759 if (ainfo->reg == STK_BASE)
5760 s390_ic (code, reg, 0, s390_r13, ainfo->offset+7);
5761 s390_stc (code, reg, 0, inst->inst_basereg, doffset);
5764 if (ainfo->reg == STK_BASE)
5765 s390_lh (code, reg, 0, s390_r13, ainfo->offset+6);
5766 s390_sth (code, reg, 0, inst->inst_basereg, doffset);
5769 if (ainfo->reg == STK_BASE)
5770 s390_l (code, reg, 0, s390_r13, ainfo->offset+4);
5771 s390_st (code, reg, 0, inst->inst_basereg, doffset);
5774 if (ainfo->reg == STK_BASE)
5775 s390_lg (code, reg, 0, s390_r13, ainfo->offset);
5776 s390_stg (code, reg, 0, inst->inst_basereg, doffset);
5779 } else if (ainfo->regtype == RegTypeStructByAddr) {
5780 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5781 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
5783 g_assert_not_reached ();
5788 if (method->save_lmf) {
5789 /*---------------------------------------------------------------*/
5790 /* build the MonoLMF structure on the stack - see mini-s390x.h */
5791 /*---------------------------------------------------------------*/
5792 lmfOffset = alloc_size - sizeof(MonoLMF);
5794 s390_lgr (code, s390_r13, cfg->frame_reg);
5795 s390_aghi (code, s390_r13, lmfOffset);
5797 /*---------------------------------------------------------------*/
5798 /* Preserve the parameter registers while we fix up the lmf */
5799 /*---------------------------------------------------------------*/
5800 s390_stmg (code, s390_r2, s390_r6, s390_r13,
5801 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
5803 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[0]), SLOT_NOREF);
5804 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[1]), SLOT_NOREF);
5805 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[2]), SLOT_NOREF);
5806 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[3]), SLOT_NOREF);
5807 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[4]), SLOT_NOREF);
5809 /*---------------------------------------------------------------*/
5810 /* On return from this call r2 have the address of the &lmf */
5811 /*---------------------------------------------------------------*/
5812 if (lmf_addr_tls_offset == -1) {
5813 mono_add_patch_info (cfg, code - cfg->native_code,
5814 MONO_PATCH_INFO_INTERNAL_METHOD,
5815 (gpointer)"mono_get_lmf_addr");
5816 S390_CALL_TEMPLATE(code, s390_r1);
5818 /*-------------------------------------------------------*/
5819 /* Get LMF by getting value from thread level storage */
5820 /*-------------------------------------------------------*/
5821 s390_ear (code, s390_r1, 0);
5822 s390_sllg(code, s390_r1, s390_r1, 0, 32);
5823 s390_ear (code, s390_r1, 1);
5824 s390_lg (code, s390_r2, 0, s390_r1, lmf_addr_tls_offset);
5827 /*---------------------------------------------------------------*/
5828 /* Set lmf.lmf_addr = jit_tls->lmf */
5829 /*---------------------------------------------------------------*/
5830 s390_stg (code, s390_r2, 0, s390_r13,
5831 G_STRUCT_OFFSET(MonoLMF, lmf_addr));
5832 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, lmf_addr), SLOT_NOREF);
5834 /*---------------------------------------------------------------*/
5835 /* Get current lmf */
5836 /*---------------------------------------------------------------*/
5837 s390_lg (code, s390_r0, 0, s390_r2, 0);
5839 /*---------------------------------------------------------------*/
5840 /* Set our lmf as the current lmf */
5841 /*---------------------------------------------------------------*/
5842 s390_stg (code, s390_r13, 0, s390_r2, 0);
5844 /*---------------------------------------------------------------*/
5845 /* Have our lmf.previous_lmf point to the last lmf */
5846 /*---------------------------------------------------------------*/
5847 s390_stg (code, s390_r0, 0, s390_r13,
5848 G_STRUCT_OFFSET(MonoLMF, previous_lmf));
5849 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), SLOT_NOREF);
5851 /*---------------------------------------------------------------*/
5852 /* save method info */
5853 /*---------------------------------------------------------------*/
5854 S390_SET (code, s390_r1, method);
5855 s390_stg (code, s390_r1, 0, s390_r13,
5856 G_STRUCT_OFFSET(MonoLMF, method));
5857 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, method), SLOT_NOREF);
5859 /*---------------------------------------------------------------*/
5860 /* save the current IP */
5861 /*---------------------------------------------------------------*/
5862 s390_stg (code, STK_BASE, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp));
5863 s390_basr (code, s390_r1, 0);
5864 s390_stg (code, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip));
5865 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, ebp), SLOT_NOREF);
5866 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, eip), SLOT_NOREF);
5868 /*---------------------------------------------------------------*/
5869 /* Save general and floating point registers */
5870 /*---------------------------------------------------------------*/
5871 s390_stmg (code, s390_r2, s390_r12, s390_r13,
5872 G_STRUCT_OFFSET(MonoLMF, gregs[2]));
5873 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[0]), SLOT_NOREF);
5874 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[1]), SLOT_NOREF);
5875 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[2]), SLOT_NOREF);
5876 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[3]), SLOT_NOREF);
5877 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[4]), SLOT_NOREF);
5878 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[5]), SLOT_NOREF);
5879 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[6]), SLOT_NOREF);
5880 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[7]), SLOT_NOREF);
5881 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[8]), SLOT_NOREF);
5882 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[9]), SLOT_NOREF);
5883 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[10]), SLOT_NOREF);
5885 fpOffset = lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, fregs[0]);
5886 for (i = 0; i < 16; i++) {
5887 s390_std (code, i, 0, s390_r13,
5888 G_STRUCT_OFFSET(MonoLMF, fregs[i]));
5889 mini_gc_set_slot_type_from_fp (cfg, fpOffset, SLOT_NOREF);
5890 fpOffset += sizeof(double);
5893 /*---------------------------------------------------------------*/
5894 /* Restore the parameter registers now that we've set up the lmf */
5895 /*---------------------------------------------------------------*/
5896 s390_lmg (code, s390_r2, s390_r6, s390_r13,
5897 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
5900 if (cfg->method->save_lmf)
5901 argsClobbered = TRUE;
5904 argsClobbered = TRUE;
5905 code = mono_arch_instrument_prolog (cfg, enter_method, code, TRUE);
5908 if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
5909 argsClobbered = TRUE;
5912 * Optimize the common case of the first bblock making a call with the same
5913 * arguments as the method. This works because the arguments are still in their
5914 * original argument registers.
5916 if (!argsClobbered) {
5917 MonoBasicBlock *first_bb = cfg->bb_entry;
5919 int filter = FILTER_IL_SEQ_POINT;
5921 next = mono_bb_first_inst (first_bb, filter);
5922 if (!next && first_bb->next_bb) {
5923 first_bb = first_bb->next_bb;
5924 next = mono_bb_first_inst (first_bb, filter);
5927 if (first_bb->in_count > 1)
5930 for (i = 0; next && i < sig->param_count + sig->hasthis; ++i) {
5931 ArgInfo *ainfo = cinfo->args + i;
5932 gboolean match = FALSE;
5934 inst = cfg->args [i];
5935 if (inst->opcode != OP_REGVAR) {
5936 switch (ainfo->regtype) {
5937 case RegTypeGeneral: {
5938 if (((next->opcode == OP_LOAD_MEMBASE) ||
5939 (next->opcode == OP_LOADI4_MEMBASE)) &&
5940 next->inst_basereg == inst->inst_basereg &&
5941 next->inst_offset == inst->inst_offset) {
5942 if (next->dreg == ainfo->reg) {
5946 next->opcode = OP_MOVE;
5947 next->sreg1 = ainfo->reg;
5948 /* Only continue if the instruction doesn't change argument regs */
5949 if (next->dreg == ainfo->reg)
5959 /* Argument allocated to (non-volatile) register */
5960 switch (ainfo->regtype) {
5961 case RegTypeGeneral:
5962 if (next->opcode == OP_MOVE &&
5963 next->sreg1 == inst->dreg &&
5964 next->dreg == ainfo->reg) {
5975 next = mono_inst_next (next, filter);
5982 cfg->code_len = code - cfg->native_code;
5983 g_assert (cfg->code_len < cfg->code_size);
5988 /*========================= End of Function ========================*/
5990 /*------------------------------------------------------------------*/
5992 /* Name - mono_arch_emit_epilog */
5994 /* Function - Emit the instructions for a function epilog. */
5996 /*------------------------------------------------------------------*/
5999 mono_arch_emit_epilog (MonoCompile *cfg)
6001 MonoMethod *method = cfg->method;
6004 int max_epilog_size = 96;
6006 if (cfg->method->save_lmf)
6007 max_epilog_size += 128;
6009 if (mono_jit_trace_calls != NULL)
6010 max_epilog_size += 128;
6011 else if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
6012 max_epilog_size += 128;
6014 while ((cfg->code_len + max_epilog_size) > (cfg->code_size - 16)) {
6015 cfg->code_size *= 2;
6016 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6017 cfg->stat_code_reallocs++;
6020 code = cfg->native_code + cfg->code_len;
6022 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
6023 code = mono_arch_instrument_epilog (cfg, leave_method, code, TRUE);
6027 if (method->save_lmf)
6028 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
6030 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
6031 s390_lg (code, STK_BASE, 0, STK_BASE, 0);
6033 code = backUpStackPtr(cfg, code);
6035 s390_lmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
6036 s390_br (code, s390_r14);
6038 cfg->code_len = code - cfg->native_code;
6040 g_assert (cfg->code_len < cfg->code_size);
6044 /*========================= End of Function ========================*/
6046 /*------------------------------------------------------------------*/
6048 /* Name - mono_arch_emit_exceptions */
6050 /* Function - Emit the blocks to handle exception conditions. */
6052 /*------------------------------------------------------------------*/
6055 mono_arch_emit_exceptions (MonoCompile *cfg)
6057 MonoJumpInfo *patch_info;
6063 MonoClass *exc_classes [MAX_EXC];
6064 guint8 *exc_throw_start [MAX_EXC];
6066 for (patch_info = cfg->patch_info;
6068 patch_info = patch_info->next) {
6069 if (patch_info->type == MONO_PATCH_INFO_EXC)
6073 code_size = exc_count * 48;
6075 while ((cfg->code_len + code_size) > (cfg->code_size - 16)) {
6076 cfg->code_size *= 2;
6077 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6078 cfg->stat_code_reallocs++;
6081 code = cfg->native_code + cfg->code_len;
6083 /*---------------------------------------------------------------------*/
6084 /* Add code to raise exceptions */
6085 /*---------------------------------------------------------------------*/
6086 for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
6087 switch (patch_info->type) {
6088 case MONO_PATCH_INFO_EXC: {
6089 guint8 *ip = patch_info->ip.i + cfg->native_code;
6090 MonoClass *exc_class;
6093 /*-----------------------------------------------------*/
6094 /* Patch the branch in epilog to come here */
6095 /*-----------------------------------------------------*/
6096 s390_patch_rel (ip + 2, (guint64) S390_RELATIVE(code,ip));
6098 exc_class = mono_class_load_from_name (mono_defaults.corlib,
6100 patch_info->data.name);
6101 throw_ip = patch_info->ip.i;
6103 for (iExc = 0; iExc < nThrows; ++iExc)
6104 if (exc_classes [iExc] == exc_class)
6107 if (iExc < nThrows) {
6108 s390_jcl (code, S390_CC_UN,
6109 (guint64) exc_throw_start [iExc]);
6110 patch_info->type = MONO_PATCH_INFO_NONE;
6113 if (nThrows < MAX_EXC) {
6114 exc_classes [nThrows] = exc_class;
6115 exc_throw_start [nThrows] = code;
6118 /*---------------------------------------------*/
6119 /* Patch the parameter passed to the handler */
6120 /*---------------------------------------------*/
6121 S390_SET (code, s390_r2, exc_class->type_token);
6122 /*---------------------------------------------*/
6123 /* Load return address & parameter register */
6124 /*---------------------------------------------*/
6125 s390_larl (code, s390_r14, (guint64)S390_RELATIVE((patch_info->ip.i +
6126 cfg->native_code + 8), code));
6127 /*---------------------------------------------*/
6128 /* Reuse the current patch to set the jump */
6129 /*---------------------------------------------*/
6130 patch_info->type = MONO_PATCH_INFO_INTERNAL_METHOD;
6131 patch_info->data.name = "mono_arch_throw_corlib_exception";
6132 patch_info->ip.i = code - cfg->native_code;
6133 S390_BR_TEMPLATE (code, s390_r1);
6143 cfg->code_len = code - cfg->native_code;
6145 g_assert (cfg->code_len < cfg->code_size);
6149 /*========================= End of Function ========================*/
6151 /*------------------------------------------------------------------*/
6153 /* Name - mono_arch_finish_init */
6155 /* Function - Setup the JIT's Thread Level Specific Data. */
6157 /*------------------------------------------------------------------*/
6160 mono_arch_finish_init (void)
6162 appdomain_tls_offset = mono_domain_get_tls_offset();
6163 lmf_tls_offset = mono_get_lmf_tls_offset();
6164 lmf_addr_tls_offset = mono_get_lmf_addr_tls_offset();
6167 /*========================= End of Function ========================*/
6169 /*------------------------------------------------------------------*/
6171 /* Name - mono_arch_free_jit_tls_data */
6173 /* Function - Free tls data. */
6175 /*------------------------------------------------------------------*/
6178 mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
6182 /*========================= End of Function ========================*/
6184 /*------------------------------------------------------------------*/
6186 /* Name - mono_arch_emit_inst_for_method */
6188 /*------------------------------------------------------------------*/
6191 mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
6196 /*========================= End of Function ========================*/
6198 /*------------------------------------------------------------------*/
6200 /* Name - mono_arch_decompose_opts */
6202 /* Function - Decompose opcode into a System z opcode. */
6204 /*------------------------------------------------------------------*/
6207 mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
6210 * Have to rename these to avoid being decomposed normally, since the normal
6211 * decomposition does not work on S390.
6213 switch (ins->opcode) {
6215 ins->opcode = OP_S390_ISUB_OVF;
6217 case OP_ISUB_OVF_UN:
6218 ins->opcode = OP_S390_ISUB_OVF_UN;
6221 ins->opcode = OP_S390_IADD_OVF;
6223 case OP_IADD_OVF_UN:
6224 ins->opcode = OP_S390_IADD_OVF_UN;
6227 ins->opcode = OP_S390_LADD_OVF;
6229 case OP_LADD_OVF_UN:
6230 ins->opcode = OP_S390_LADD_OVF_UN;
6233 ins->opcode = OP_S390_LSUB_OVF;
6235 case OP_LSUB_OVF_UN:
6236 ins->opcode = OP_S390_LSUB_OVF_UN;
6243 /*========================= End of Function ========================*/
6245 /*------------------------------------------------------------------*/
6247 /* Name - mono_arch_print_tree */
6249 /* Function - Print platform-specific opcode details. */
6251 /* Returns - 1 - opcode details have been printed */
6252 /* 0 - opcode details have not been printed */
6254 /*------------------------------------------------------------------*/
6257 mono_arch_print_tree (MonoInst *tree, int arity)
6261 switch (tree->opcode) {
6262 case OP_S390_LOADARG:
6263 case OP_S390_ARGREG:
6264 case OP_S390_ARGPTR:
6265 printf ("[0x%lx(%s)]", tree->inst_offset,
6266 mono_arch_regname (tree->inst_basereg));
6269 case OP_S390_STKARG:
6270 printf ("[0x%lx(previous_frame)]",
6275 printf ("[0x%lx(%d,%s),0x%lx(%s)]",
6276 tree->inst_offset, tree->backend.size,
6277 mono_arch_regname(tree->dreg),
6279 mono_arch_regname(tree->sreg1));
6282 case OP_S390_SETF4RET:
6283 printf ("[f%s,f%s]",
6284 mono_arch_regname (tree->dreg),
6285 mono_arch_regname (tree->sreg1));
6289 printf ("[0x%lx(0x%lx,%s)]", tree->inst_offset,
6291 mono_arch_regname (tree->sreg1));
6294 case OP_S390_BKCHAIN:
6295 printf ("[previous_frame(%s)]",
6296 mono_arch_regname (tree->sreg1));
6304 /*========================= End of Function ========================*/
6306 /*------------------------------------------------------------------*/
6308 /* Name - mono_arch_regalloc_cost */
6310 /* Function - Determine the cost, in the number of memory */
6311 /* references, of the action of allocating the var- */
6312 /* iable VMV into a register during global register */
6315 /* Returns - Cost */
6317 /*------------------------------------------------------------------*/
6320 mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
6326 /*========================= End of Function ========================*/
6328 /*------------------------------------------------------------------*/
6330 /* Name - mono_arch_flush_register_windows */
6336 /*------------------------------------------------------------------*/
6339 mono_arch_flush_register_windows (void)
6343 /*========================= End of Function ========================*/
6345 /*------------------------------------------------------------------*/
6347 /* Name - mono_arch_is_inst_imm */
6349 /* Function - Determine if operand qualifies as an immediate */
6350 /* value. For s390 this is a value -32768-32768 */
6352 /* Returns - True|False - is [not] immediate value. */
6354 /*------------------------------------------------------------------*/
6357 mono_arch_is_inst_imm (gint64 imm)
6359 return s390_is_imm32 (imm);
6362 /*========================= End of Function ========================*/
6364 /*------------------------------------------------------------------*/
6366 /* Name - mono_arch_get_patch_offset */
6368 /* Function - Dummy entry point until s390x supports aot. */
6370 /* Returns - Offset for patch. */
6372 /*------------------------------------------------------------------*/
6375 mono_arch_get_patch_offset (guint8 *code)
6380 /*========================= End of Function ========================*/
6382 /*------------------------------------------------------------------*/
6384 /* Name - mono_arch_context_get_int_reg. */
6388 /* Returns - Return a register from the context. */
6390 /*------------------------------------------------------------------*/
6393 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
6395 return ((mgreg_t) ctx->uc_mcontext.gregs[reg]);
6398 /*========================= End of Function ========================*/
6400 /*------------------------------------------------------------------*/
6402 /* Name - mono_arch_context_set_int_reg. */
6404 /* Function - Set a value in a specified register. */
6406 /*------------------------------------------------------------------*/
6409 mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val)
6411 ctx->uc_mcontext.gregs[reg] = val;
6414 /*========================= End of Function ========================*/
6416 /*------------------------------------------------------------------*/
6418 /* Name - mono_arch_get_this_arg_from_call. */
6422 /*------------------------------------------------------------------*/
6425 mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
6427 return (gpointer) regs [s390_r2];
6430 /*========================= End of Function ========================*/
6432 /*------------------------------------------------------------------*/
6434 /* Name - mono_arch_install_handler_block_guard */
6438 /*------------------------------------------------------------------*/
6441 mono_arch_install_handler_block_guard (MonoJitInfo *ji, MonoJitExceptionInfo *clause,
6442 MonoContext *ctx, gpointer new_value)
6445 gpointer *sp, old_value;
6448 offset = clause->exvar_offset;
6451 bp = MONO_CONTEXT_GET_BP (ctx);
6452 sp = *(gpointer*)(bp + offset);
6455 if (old_value < ji->code_start || (char*)old_value > ((char*)ji->code_start + ji->code_size))
6463 /*========================= End of Function ========================*/
6465 /*------------------------------------------------------------------*/
6467 /* Name - get_delegate_invoke_impl. */
6471 /*------------------------------------------------------------------*/
6474 get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 param_count, gboolean aot)
6476 guint8 *code, *start;
6481 start = code = mono_global_codeman_reserve (size);
6483 /* Replace the this argument with the target */
6484 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6485 s390_lg (code, s390_r2, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, target));
6486 s390_br (code, s390_r1);
6487 g_assert ((code - start) <= size);
6489 mono_arch_flush_icache (start, size);
6493 size = 32 + param_count * 8;
6494 start = code = mono_global_codeman_reserve (size);
6496 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6497 /* slide down the arguments */
6498 for (i = 0; i < param_count; ++i) {
6499 s390_lgr (code, (s390_r2 + i), (s390_r2 + i + 1));
6501 s390_br (code, s390_r1);
6503 g_assert ((code - start) <= size);
6505 mono_arch_flush_icache (start, size);
6508 mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
6511 *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
6513 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
6514 *info = mono_tramp_info_create (name, start, code - start, NULL, NULL);
6521 /*========================= End of Function ========================*/
6523 /*------------------------------------------------------------------*/
6525 /* Name - mono_arch_get_delegate_invoke_impls. */
6529 /*------------------------------------------------------------------*/
6532 mono_arch_get_delegate_invoke_impls (void)
6535 MonoTrampInfo *info;
6538 get_delegate_invoke_impl (&info, TRUE, 0, TRUE);
6539 res = g_slist_prepend (res, info);
6541 for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
6542 get_delegate_invoke_impl (&info, FALSE, i, TRUE);
6543 res = g_slist_prepend (res, info);
6549 /*========================= End of Function ========================*/
6551 /*------------------------------------------------------------------*/
6553 /* Name - mono_arch_get_delegate_invoke_impl. */
6557 /*------------------------------------------------------------------*/
6560 mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target)
6562 guint8 *code, *start;
6564 /* FIXME: Support more cases */
6565 if (MONO_TYPE_ISSTRUCT (sig->ret))
6569 static guint8* cached = NULL;
6574 if (mono_aot_only) {
6575 start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
6577 MonoTrampInfo *info;
6578 start = get_delegate_invoke_impl (&info, TRUE, 0, FALSE);
6579 mono_tramp_info_register (info, NULL);
6582 mono_memory_barrier ();
6586 static guint8* cache [MAX_ARCH_DELEGATE_PARAMS + 1] = {NULL};
6589 if (sig->param_count > MAX_ARCH_DELEGATE_PARAMS)
6591 for (i = 0; i < sig->param_count; ++i)
6592 if (!mono_is_regsize_var (sig->params [i]))
6596 code = cache [sig->param_count];
6600 if (mono_aot_only) {
6601 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", sig->param_count);
6602 start = mono_aot_get_trampoline (name);
6605 MonoTrampInfo *info;
6606 start = get_delegate_invoke_impl (&info, FALSE, sig->param_count, FALSE);
6607 mono_tramp_info_register (info, NULL);
6610 mono_memory_barrier ();
6612 cache [sig->param_count] = start;
6617 /*========================= End of Function ========================*/
6619 /*------------------------------------------------------------------*/
6621 /* Name - mono_arch_get_delegate_virtual_invoke_impl. */
6625 /*------------------------------------------------------------------*/
6628 mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method,
6629 int offset, gboolean load_imt_reg)
6631 guint8 *code, *start;
6634 start = code = mono_global_codeman_reserve (size);
6637 * Replace the "this" argument with the target
6639 s390_lgr (code, s390_r1, s390_r2);
6640 s390_lg (code, s390_r2, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, target));
6643 * Load the IMT register, if needed
6646 s390_lg (code, MONO_ARCH_IMT_REG, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, method));
6652 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET(MonoObject, vtable));
6654 s390_agfi(code, s390_r1, offset);
6656 s390_lg (code, s390_r1, 0, s390_r1, 0);
6657 s390_br (code, s390_r1);
6662 /*========================= End of Function ========================*/
6664 /*------------------------------------------------------------------*/
6666 /* Name - mono_arch_build_imt_trampoline. */
6670 /*------------------------------------------------------------------*/
6673 mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain,
6674 MonoIMTCheckItem **imt_entries, int count,
6675 gpointer fail_tramp)
6679 guchar *code, *start;
6682 for (i = 0; i < count; ++i) {
6683 MonoIMTCheckItem *item = imt_entries [i];
6684 if (item->is_equals) {
6685 if (item->check_target_idx) {
6686 if (!item->compare_done)
6687 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6688 if (item->has_target_code)
6689 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE;
6691 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE +
6695 item->chunk_size += CMP_SIZE + 2 * BR_SIZE + JUMP_SIZE +
6697 if (!item->has_target_code)
6698 item->chunk_size += LOAD_SIZE;
6700 item->chunk_size += LOADCON_SIZE + LOAD_SIZE + BR_SIZE;
6701 #if ENABLE_WRONG_METHOD_CHECK
6702 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6707 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6708 imt_entries [item->check_target_idx]->compare_done = TRUE;
6710 size += item->chunk_size;
6714 code = mono_method_alloc_generic_virtual_trampoline (domain, size);
6716 code = mono_domain_code_reserve (domain, size);
6720 for (i = 0; i < count; ++i) {
6721 MonoIMTCheckItem *item = imt_entries [i];
6722 item->code_target = (guint8 *) code;
6723 if (item->is_equals) {
6724 if (item->check_target_idx) {
6725 if (!item->compare_done) {
6726 S390_SET (code, s390_r0, item->key);
6727 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
6729 item->jmp_code = (guint8*) code;
6730 s390_jcl (code, S390_CC_NE, 0);
6732 if (item->has_target_code) {
6733 S390_SET (code, s390_r1, item->value.target_code);
6735 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6736 s390_lg (code, s390_r1, 0, s390_r1, 0);
6738 s390_br (code, s390_r1);
6743 S390_SET (code, s390_r0, item->key);
6744 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
6745 item->jmp_code = (guint8*) code;
6746 s390_jcl (code, S390_CC_NE, 0);
6747 if (item->has_target_code) {
6748 S390_SET (code, s390_r1, item->value.target_code);
6751 S390_SET (code, s390_r1,
6752 (&(vtable->vtable [item->value.vtable_slot])));
6753 s390_lg (code, s390_r1, 0, s390_r1, 0);
6755 s390_br (code, s390_r1);
6756 target = (gint64) S390_RELATIVE(code, item->jmp_code);
6757 s390_patch_rel(item->jmp_code+2, target);
6758 S390_SET (code, s390_r1, fail_tramp);
6759 s390_br (code, s390_r1);
6760 item->jmp_code = NULL;
6762 /* enable the commented code to assert on wrong method */
6763 #if ENABLE_WRONG_METHOD_CHECK
6764 g_assert_not_reached ();
6766 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6767 s390_lg (code, s390_r1, 0, s390_r1, 0);
6768 s390_br (code, s390_r1);
6772 S390_SET (code, s390_r0, item->key);
6773 s390_cgr (code, MONO_ARCH_IMT_REG, s390_r0);
6774 item->jmp_code = (guint8 *) code;
6775 s390_jcl (code, S390_CC_GE, 0);
6779 * patch the branches to get to the target items
6781 for (i = 0; i < count; ++i) {
6782 MonoIMTCheckItem *item = imt_entries [i];
6783 if (item->jmp_code) {
6784 if (item->check_target_idx) {
6786 offset = (gint64) S390_RELATIVE(imt_entries [item->check_target_idx]->code_target,
6788 s390_patch_rel ((guchar *) item->jmp_code + 2, (guint64) offset);
6793 mono_arch_flush_icache ((guint8*)start, (code - start));
6794 mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL);
6797 mono_stats.imt_trampolines_size += (code - start);
6799 g_assert (code - start <= size);
6801 snprintf(trampName, sizeof(trampName), "%d_imt_trampoline", domain->domain_id);
6802 mono_tramp_info_register (mono_tramp_info_create (trampName, start, code - start, NULL, NULL), domain);
6807 /*========================= End of Function ========================*/
6809 /*------------------------------------------------------------------*/
6811 /* Name - mono_arch_find_imt_method. */
6813 /* Function - Get the method address from MONO_ARCH_IMT_REG */
6814 /* found in the save area. */
6816 /*------------------------------------------------------------------*/
6819 mono_arch_find_imt_method (mgreg_t *regs, guint8 *code)
6821 return ((MonoMethod *) regs [MONO_ARCH_IMT_REG]);
6824 /*========================= End of Function ========================*/
6826 /*------------------------------------------------------------------*/
6828 /* Name - mono_arch_find_static_call_vtable */
6830 /* Function - Find the static call vtable. */
6832 /*------------------------------------------------------------------*/
6835 mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
6837 mgreg_t *r = (mgreg_t*)regs;
6839 return (MonoVTable*)(gsize) r [MONO_ARCH_RGCTX_REG];
6842 /*========================= End of Function ========================*/
6844 /*------------------------------------------------------------------*/
6846 /* Name - mono_arch_get_cie_program */
6848 /* Function - Find the static call vtable. */
6850 /*------------------------------------------------------------------*/
6853 mono_arch_get_cie_program (void)
6857 mono_add_unwind_op_def_cfa (l, 0, 0, STK_BASE, 0);
6862 /*========================= End of Function ========================*/
6864 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
6866 /*------------------------------------------------------------------*/
6868 /* Name - mono_arch_set_breakpoint. */
6870 /* Function - Set a breakpoint at the native code corresponding */
6871 /* to JI at NATIVE_OFFSET. The location should */
6872 /* contain code emitted by OP_SEQ_POINT. */
6874 /*------------------------------------------------------------------*/
6877 mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
6881 breakpointCode.pTrigger = bp_trigger_page;
6882 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
6883 code += BREAKPOINT_SIZE;
6886 /*========================= End of Function ========================*/
6888 /*------------------------------------------------------------------*/
6890 /* Name - mono_arch_clear_breakpoint. */
6892 /* Function - Clear the breakpoint at IP. */
6894 /*------------------------------------------------------------------*/
6897 mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
6902 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); i++)
6906 /*========================= End of Function ========================*/
6908 /*------------------------------------------------------------------*/
6910 /* Name - mono_arch_is_breakpoint_event. */
6914 /*------------------------------------------------------------------*/
6917 mono_arch_is_breakpoint_event (void *info, void *sigctx)
6919 siginfo_t* sinfo = (siginfo_t*) info;
6922 * Sometimes the address is off by 4
6924 if (sinfo->si_addr >= bp_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)bp_trigger_page + 128)
6930 /*========================= End of Function ========================*/
6932 /*------------------------------------------------------------------*/
6934 /* Name - mono_arch_skip_breakpoint. */
6936 /* Function - Modify the CTX so the IP is placed after the */
6937 /* breakpoint instruction, so when we resume, the */
6938 /* instruction is not executed again. */
6940 /*------------------------------------------------------------------*/
6943 mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
6945 MONO_CONTEXT_SET_IP (ctx, ((guint8*)MONO_CONTEXT_GET_IP (ctx) + sizeof(RXY_Format)));
6948 /*========================= End of Function ========================*/
6950 /*------------------------------------------------------------------*/
6952 /* Name - mono_arch_start_single_stepping. */
6954 /* Function - Start single stepping. */
6956 /*------------------------------------------------------------------*/
6959 mono_arch_start_single_stepping (void)
6961 mono_mprotect (ss_trigger_page, mono_pagesize (), 0);
6964 /*========================= End of Function ========================*/
6966 /*------------------------------------------------------------------*/
6968 /* Name - mono_arch_stop_single_stepping. */
6970 /* Function - Stop single stepping. */
6972 /*------------------------------------------------------------------*/
6975 mono_arch_stop_single_stepping (void)
6977 mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ);
6980 /*========================= End of Function ========================*/
6982 /*------------------------------------------------------------------*/
6984 /* Name - mono_arch_is_single_step_event. */
6986 /* Function - Return whether the machine state in sigctx cor- */
6987 /* responds to a single step event. */
6989 /*------------------------------------------------------------------*/
6992 mono_arch_is_single_step_event (void *info, void *sigctx)
6994 siginfo_t* sinfo = (siginfo_t*) info;
6997 * Sometimes the address is off by 4
6999 if (sinfo->si_addr >= ss_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)ss_trigger_page + 128)
7005 /*========================= End of Function ========================*/
7007 /*------------------------------------------------------------------*/
7009 /* Name - mono_arch_skip_single_step. */
7011 /* Function - Modify the ctx so the IP is placed after the */
7012 /* single step trigger instruction, so that the */
7013 /* instruction is not executed again. */
7015 /*------------------------------------------------------------------*/
7018 mono_arch_skip_single_step (MonoContext *ctx)
7020 MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + BREAKPOINT_SIZE);
7023 /*========================= End of Function ========================*/
7025 /*------------------------------------------------------------------*/
7027 /* Name - mono_arch_create_seq_point_info. */
7029 /* Function - Return a pointer to a data struction which is */
7030 /* used by the sequence point implementation in */
7033 /*------------------------------------------------------------------*/
7036 mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code)
7042 /*========================= End of Function ========================*/
7044 /*------------------------------------------------------------------*/
7046 /* Name - mono_arch_init_lmf_ext. */
7050 /*------------------------------------------------------------------*/
7053 mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
7055 ext->lmf.previous_lmf = prev_lmf;
7056 /* Mark that this is a MonoLMFExt */
7057 ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
7058 ext->lmf.ebp = (gssize)ext;
7061 /*========================= End of Function ========================*/
7065 /*------------------------------------------------------------------*/
7067 /* Name - mono_arch_cpu_enumerate_simd_versions. */
7069 /* Function - If this CPU supports vector operations then it */
7070 /* supports the equivalent of SSE1-4. */
7072 /*------------------------------------------------------------------*/
7075 mono_arch_cpu_enumerate_simd_versions (void)
7077 guint32 sseOpts = 0;
7079 if (mono_hwcap_s390x_has_vec)
7080 sseOpts = (SIMD_VERSION_SSE1 | SIMD_VERSION_SSE2 |
7081 SIMD_VERSION_SSE3 | SIMD_VERSION_SSSE3 |
7082 SIMD_VERSION_SSE41 | SIMD_VERSION_SSE42 |
7083 SIMD_VERSION_SSE4a);
7088 /*========================= End of Function ========================*/
7090 /*------------------------------------------------------------------*/
7092 /* Name - mono_arch_opcode_supported. */
7094 /* Function - Check if a given return code is supported. */
7096 /*------------------------------------------------------------------*/
7099 mono_arch_opcode_supported (int opcode)
7102 case OP_ATOMIC_ADD_I4:
7103 case OP_ATOMIC_ADD_I8:
7104 case OP_ATOMIC_EXCHANGE_I4:
7105 case OP_ATOMIC_EXCHANGE_I8:
7112 /*========================= End of Function ========================*/