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;
395 * The code generated for sequence points reads from this location,
396 * which is made read-only when single stepping is enabled.
398 static gpointer ss_trigger_page;
401 * Enabled breakpoints read from this trigger page
403 static gpointer bp_trigger_page;
405 breakpoint_t breakpointCode;
407 static mono_mutex_t mini_arch_mutex;
409 static const char * grNames[] = {
410 "s390_r0", "s390_sp", "s390_r2", "s390_r3", "s390_r4",
411 "s390_r5", "s390_r6", "s390_r7", "s390_r8", "s390_r9",
412 "s390_r10", "s390_r11", "s390_r12", "s390_r13", "s390_r14",
416 static const char * fpNames[] = {
417 "s390_f0", "s390_f1", "s390_f2", "s390_f3", "s390_f4",
418 "s390_f5", "s390_f6", "s390_f7", "s390_f8", "s390_f9",
419 "s390_f10", "s390_f11", "s390_f12", "s390_f13", "s390_f14",
423 static const char * vrNames[] = {
424 "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7",
425 "vr8", "vr9", "vr10", "vr11", "vr12", "vr13", "vr14", "vr15",
426 "vr16", "vr17", "vr18", "vr19", "vr20", "vr21", "vr22", "vr23",
427 "vr24", "vr25", "vr26", "vr27", "vr28", "vr29", "vr30", "vr31"
430 /*====================== End of Global Variables ===================*/
432 /*------------------------------------------------------------------*/
434 /* Name - mono_arch_regname */
436 /* Function - Returns the name of the register specified by */
437 /* the input parameter. */
439 /*------------------------------------------------------------------*/
442 mono_arch_regname (int reg)
444 if (reg >= 0 && reg < 16)
445 return grNames [reg];
450 /*========================= End of Function ========================*/
452 /*------------------------------------------------------------------*/
454 /* Name - mono_arch_fregname */
456 /* Function - Returns the name of the register specified by */
457 /* the input parameter. */
459 /*------------------------------------------------------------------*/
462 mono_arch_fregname (int reg)
464 if (reg >= 0 && reg < 16)
465 return fpNames [reg];
470 /*========================= End of Function ========================*/
472 /*------------------------------------------------------------------*/
474 /* Name - mono_arch_xregname */
476 /* Function - Returns the name of the register specified by */
477 /* the input parameter. */
479 /*------------------------------------------------------------------*/
482 mono_arch_xregname (int reg)
484 if (reg < s390_VR_NREG)
485 return vrNames [reg];
490 /*========================= End of Function ========================*/
492 /*------------------------------------------------------------------*/
494 /* Name - arch_get_argument_info */
496 /* Function - Gathers information on parameters such as size, */
497 /* alignment, and padding. arg_info should be large */
498 /* enough to hold param_count + 1 entries. */
500 /* Parameters - @csig - Method signature */
501 /* @param_count - No. of parameters to consider */
502 /* @arg_info - An array to store the result info */
504 /* Returns - Size of the activation frame */
506 /*------------------------------------------------------------------*/
509 mono_arch_get_argument_info (MonoMethodSignature *csig,
511 MonoJitArgumentInfo *arg_info)
513 int k, frame_size = 0;
514 int size, align, pad;
517 if (MONO_TYPE_ISSTRUCT (csig->ret)) {
518 frame_size += sizeof (gpointer);
522 arg_info [0].offset = offset;
525 frame_size += sizeof (gpointer);
529 arg_info [0].size = frame_size;
531 for (k = 0; k < param_count; k++) {
534 size = mono_type_native_stack_size (csig->params [k], (guint32 *) &align);
536 size = mini_type_stack_size (csig->params [k], &align);
538 frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
539 arg_info [k].pad = pad;
541 arg_info [k + 1].pad = 0;
542 arg_info [k + 1].size = size;
544 arg_info [k + 1].offset = offset;
548 align = MONO_ARCH_FRAME_ALIGNMENT;
549 frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
550 arg_info [k].pad = pad;
555 /*========================= End of Function ========================*/
557 /*------------------------------------------------------------------*/
559 /* Name - emit_unwind_regs. */
561 /* Function - Determines if a value can be returned in one or */
564 /*------------------------------------------------------------------*/
566 static void __inline__
567 emit_unwind_regs(MonoCompile *cfg, guint8 *code, int start, int end, long offset)
571 for (i = start; i < end; i++) {
572 mono_emit_unwind_op_offset (cfg, code, i, offset);
573 mini_gc_set_slot_type_from_cfa (cfg, offset, SLOT_NOREF);
574 offset += sizeof(gulong);
578 /*========================= End of Function ========================*/
580 /*------------------------------------------------------------------*/
582 /* Name - retFitsInReg. */
584 /* Function - Determines if a value can be returned in one or */
587 /*------------------------------------------------------------------*/
589 static inline gboolean
590 retFitsInReg(guint32 size)
605 /*========================= End of Function ========================*/
607 /*------------------------------------------------------------------*/
609 /* Name - backStackPtr. */
611 /* Function - Restore Stack Pointer to previous frame. */
613 /*------------------------------------------------------------------*/
615 static inline guint8 *
616 backUpStackPtr(MonoCompile *cfg, guint8 *code)
618 int stackSize = cfg->stack_usage;
620 if (cfg->frame_reg != STK_BASE)
621 s390_lgr (code, STK_BASE, cfg->frame_reg);
623 if (s390_is_imm16 (stackSize)) {
624 s390_aghi (code, STK_BASE, stackSize);
626 while (stackSize > 32767) {
627 s390_aghi (code, STK_BASE, 32767);
630 s390_aghi (code, STK_BASE, stackSize);
635 /*========================= End of Function ========================*/
637 /*------------------------------------------------------------------*/
641 /* Function - Perform nice indenting to current level */
643 /*------------------------------------------------------------------*/
649 indent_level += diff;
651 printf("%p [%3d] ",(void *)pthread_self(),v);
656 indent_level += diff;
659 /*========================= End of Function ========================*/
661 /*------------------------------------------------------------------*/
663 /* Name - cvtMonoType */
665 /* Function - Convert a mono-type to a string. */
667 /*------------------------------------------------------------------*/
670 cvtMonoType(MonoTypeEnum t)
675 return "MONO_TYPE_END";
677 return "MONO_TYPE_VOID";
678 case MONO_TYPE_BOOLEAN:
679 return "MONO_TYPE_BOOLEAN";
681 return "MONO_TYPE_CHAR";
683 return "MONO_TYPE_I1";
685 return "MONO_TYPE_U1";
687 return "MONO_TYPE_I2";
689 return "MONO_TYPE_U2";
691 return "MONO_TYPE_I4";
693 return "MONO_TYPE_U4";
695 return "MONO_TYPE_I8";
697 return "MONO_TYPE_U8";
699 return "MONO_TYPE_R4";
701 return "MONO_TYPE_R8";
702 case MONO_TYPE_STRING:
703 return "MONO_TYPE_STRING";
705 return "MONO_TYPE_PTR";
706 case MONO_TYPE_BYREF:
707 return "MONO_TYPE_BYREF";
708 case MONO_TYPE_VALUETYPE:
709 return "MONO_TYPE_VALUETYPE";
710 case MONO_TYPE_CLASS:
711 return "MONO_TYPE_CLASS";
713 return "MONO_TYPE_VAR";
714 case MONO_TYPE_ARRAY:
715 return "MONO_TYPE_ARRAY";
716 case MONO_TYPE_GENERICINST:
717 return "MONO_TYPE_GENERICINST";
718 case MONO_TYPE_TYPEDBYREF:
719 return "MONO_TYPE_TYPEDBYREF";
721 return "MONO_TYPE_I";
723 return "MONO_TYPE_U";
724 case MONO_TYPE_FNPTR:
725 return "MONO_TYPE_FNPTR";
726 case MONO_TYPE_OBJECT:
727 return "MONO_TYPE_OBJECT";
728 case MONO_TYPE_SZARRAY:
729 return "MONO_TYPE_SZARRAY";
731 return "MONO_TYPE_MVAR";
732 case MONO_TYPE_CMOD_REQD:
733 return "MONO_TYPE_CMOD_REQD";
734 case MONO_TYPE_CMOD_OPT:
735 return "MONO_TYPE_CMOD_OPT";
736 case MONO_TYPE_INTERNAL:
737 return "MONO_TYPE_INTERNAL";
738 case MONO_TYPE_MODIFIER:
739 return "MONO_TYPE_MODIFIER";
740 case MONO_TYPE_SENTINEL:
741 return "MONO_TYPE_SENTINEL";
742 case MONO_TYPE_PINNED:
743 return "MONO_TYPE_PINNED";
750 /*========================= End of Function ========================*/
752 /*------------------------------------------------------------------*/
754 /* Name - decodeParm */
756 /* Function - Decode a parameter for the trace. */
758 /*------------------------------------------------------------------*/
761 decodeParmString (MonoString *s)
764 char *str = mono_string_to_utf8_checked(s, &error);
765 if (is_ok (&error)) {
766 printf("[STRING:%p:%s], ", s, str);
769 mono_error_cleanup (&error);
770 printf("[STRING:%p:], ", s);
775 decodeParm(MonoType *type, void *curParm, int size)
780 printf("[BYREF:%p], ", *((char **) curParm));
782 simpleType = mini_get_underlying_type(type)->type;
784 switch (simpleType) {
786 printf ("[INTPTR:%p], ", *((int **) curParm));
789 printf ("[UINTPTR:%p], ", *((int **) curParm));
791 case MONO_TYPE_BOOLEAN :
792 printf ("[BOOL:%ld], ", *((gint64 *) curParm));
794 case MONO_TYPE_CHAR :
795 printf ("[CHAR:%c], ", *((int *) curParm));
798 printf ("[INT1:%ld], ", *((gint64 *) curParm));
801 printf ("[INT2:%ld], ", *((gint64 *) curParm));
804 printf ("[INT4:%ld], ", *((gint64 *) curParm));
807 printf ("[UINT1:%lu], ", *((guint64 *) curParm));
810 printf ("[UINT2:%lu], ", *((guint64 *) curParm));
813 printf ("[UINT4:%lu], ", *((guint64 *) curParm));
816 printf ("[UINT8:%lu], ", *((guint64 *) curParm));
818 case MONO_TYPE_STRING : {
819 MonoString *s = *((MonoString **) curParm);
821 g_assert (((MonoObject *) s)->vtable->klass == mono_defaults.string_class);
822 decodeParmString (s);
824 printf("[STRING:null], ");
828 case MONO_TYPE_CLASS :
829 case MONO_TYPE_OBJECT : {
830 MonoObject *obj = *((MonoObject **) curParm);
832 if ((obj) && (obj->vtable)) {
833 printf("[CLASS/OBJ:");
834 klass = obj->vtable->klass;
835 printf("%p [%p] ",obj,curParm);
836 if (klass == mono_defaults.string_class) {
837 decodeParmString ((MonoString *)obj);
838 } else if (klass == mono_defaults.int32_class) {
839 printf("[INT32:%p:%d]",
840 obj, *(gint32 *)((char *)obj + sizeof (MonoObject)));
843 klass->name_space, klass->name, obj);
846 printf("[OBJECT:null], ");
851 printf("[PTR:%p], ", *((gpointer **) (curParm)));
853 case MONO_TYPE_FNPTR :
854 printf("[FNPTR:%p], ", *((gpointer **) (curParm)));
856 case MONO_TYPE_ARRAY :
857 printf("[ARRAY:%p], ", *((gpointer **) (curParm)));
859 case MONO_TYPE_SZARRAY :
860 printf("[SZARRAY:%p], ", *((gpointer **) (curParm)));
863 printf("[INT8:%ld], ", *((gint64 *) (curParm)));
866 printf("[FLOAT4:%g], ", *((float *) (curParm)));
869 printf("[FLOAT8:%g], ", *((double *) (curParm)));
871 case MONO_TYPE_VALUETYPE : {
873 MonoMarshalType *info;
875 if (type->data.klass->enumtype) {
876 simpleType = mono_class_enum_basetype (type->data.klass)->type;
877 printf("{VALUETYPE} - ");
881 info = mono_marshal_load_type_info (type->data.klass);
883 if ((info->native_size == sizeof(float)) &&
884 (info->num_fields == 1) &&
885 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
886 printf("[FLOAT4:%f], ", *((float *) (curParm)));
890 if ((info->native_size == sizeof(double)) &&
891 (info->num_fields == 1) &&
892 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
893 printf("[FLOAT8:%g], ", *((double *) (curParm)));
897 printf("[VALUETYPE:");
898 for (i = 0; i < size; i++)
899 printf("%02x,", *((guint8 *)curParm+i));
903 case MONO_TYPE_TYPEDBYREF: {
905 printf("[TYPEDBYREF:");
906 for (i = 0; i < size; i++)
907 printf("%02x,", *((guint8 *)curParm+i));
912 printf("[%s], ",cvtMonoType(simpleType));
917 /*========================= End of Function ========================*/
919 /*------------------------------------------------------------------*/
921 /* Name - enter_method */
923 /* Function - Perform tracing of the entry to the current */
926 /*------------------------------------------------------------------*/
929 enter_method (MonoMethod *method, RegParm *rParm, char *sp)
931 int i, oParm = 0, iParm = 0;
934 MonoMethodSignature *sig;
941 fname = mono_method_full_name (method, TRUE);
943 printf ("ENTER: %s ", fname);
946 ip = (*(guint64 *) (sp+S390_RET_ADDR_OFFSET));
947 printf ("ip: %p sp: %p - ", (gpointer) ip, sp);
952 sig = mono_method_signature (method);
954 cinfo = get_call_info (NULL, NULL, sig);
956 if (cinfo->struct_ret) {
957 printf ("[STRUCTRET:%p], ", (gpointer) rParm->gr[0]);
962 gpointer *this_arg = (gpointer *) rParm->gr[iParm];
963 obj = (MonoObject *) this_arg;
964 switch(method->klass->this_arg.type) {
965 case MONO_TYPE_VALUETYPE:
967 guint64 *value = (guint64 *) ((uintptr_t)this_arg + sizeof(MonoObject));
968 printf("this:[value:%p:%016lx], ", this_arg, *value);
970 printf ("this:[NULL], ");
972 case MONO_TYPE_STRING:
975 klass = obj->vtable->klass;
976 if (klass == mono_defaults.string_class) {
978 decodeParmString((MonoString *)obj);
980 printf ("this:%p[%s.%s], ",
981 obj, klass->name_space, klass->name);
984 printf("vtable:[NULL], ");
986 printf ("this:[NULL], ");
989 printf("this[%s]: %p, ",cvtMonoType(method->klass->this_arg.type),this_arg);
994 for (i = 0; i < sig->param_count; ++i) {
995 ainfo = &cinfo->args[i + oParm];
996 switch (ainfo->regtype) {
997 case RegTypeGeneral :
998 decodeParm(sig->params[i], &(rParm->gr[ainfo->reg-2]), ainfo->size);
1001 decodeParm(sig->params[i], &(rParm->fp[ainfo->reg]), ainfo->size);
1004 decodeParm(sig->params[i], sp+ainfo->offset, ainfo->size);
1006 case RegTypeStructByVal :
1007 if (ainfo->reg != STK_BASE) {
1008 int offset = sizeof(glong) - ainfo->size;
1009 curParm = &(rParm->gr[ainfo->reg-2])+offset;
1012 curParm = sp+ainfo->offset;
1014 if (retFitsInReg (ainfo->vtsize))
1015 decodeParm(sig->params[i],
1019 decodeParm(sig->params[i],
1020 *((char **) curParm),
1023 case RegTypeStructByAddr :
1024 if (ainfo->reg != STK_BASE)
1025 curParm = &(rParm->gr[ainfo->reg-2]);
1027 curParm = sp+ainfo->offset;
1029 decodeParm(sig->params[i],
1030 *((char **) curParm),
1042 /*========================= End of Function ========================*/
1044 /*------------------------------------------------------------------*/
1046 /* Name - leave_method */
1050 /*------------------------------------------------------------------*/
1053 leave_method (MonoMethod *method, ...)
1060 va_start(ap, method);
1062 fname = mono_method_full_name (method, TRUE);
1064 printf ("LEAVE: %s", fname);
1067 type = mono_method_signature (method)->ret;
1070 switch (type->type) {
1071 case MONO_TYPE_VOID:
1073 case MONO_TYPE_BOOLEAN: {
1074 int val = va_arg (ap, int);
1076 printf ("[TRUE:%d]", val);
1082 case MONO_TYPE_CHAR: {
1083 int val = va_arg (ap, int);
1084 printf ("[CHAR:%d]", val);
1087 case MONO_TYPE_I1: {
1088 int val = va_arg (ap, int);
1089 printf ("[INT1:%d]", val);
1092 case MONO_TYPE_U1: {
1093 int val = va_arg (ap, int);
1094 printf ("[UINT1:%d]", val);
1097 case MONO_TYPE_I2: {
1098 int val = va_arg (ap, int);
1099 printf ("[INT2:%d]", val);
1102 case MONO_TYPE_U2: {
1103 int val = va_arg (ap, int);
1104 printf ("[UINT2:%d]", val);
1107 case MONO_TYPE_I4: {
1108 int val = va_arg (ap, int);
1109 printf ("[INT4:%d]", val);
1112 case MONO_TYPE_U4: {
1113 int val = va_arg (ap, int);
1114 printf ("[UINT4:%d]", val);
1118 gint64 val = va_arg (ap, gint64);
1119 printf ("[INT:%ld]", val);
1124 gint64 val = va_arg (ap, gint64);
1125 printf ("[UINT:%lu]", val);
1129 case MONO_TYPE_STRING: {
1130 MonoString *s = va_arg (ap, MonoString *);
1133 g_assert (((MonoObject *)s)->vtable->klass == mono_defaults.string_class);
1134 decodeParmString (s);
1136 printf ("[STRING:null], ");
1139 case MONO_TYPE_CLASS:
1140 case MONO_TYPE_OBJECT: {
1141 MonoObject *o = va_arg (ap, MonoObject *);
1143 if ((o) && (o->vtable)) {
1144 if (o->vtable->klass == mono_defaults.boolean_class) {
1145 printf ("[BOOLEAN:%p:%d]", o, *((guint8 *)o + sizeof (MonoObject)));
1146 } else if (o->vtable->klass == mono_defaults.int32_class) {
1147 printf ("[INT32:%p:%d]", o, *((gint32 *)((char *)o + sizeof (MonoObject))));
1148 } else if (o->vtable->klass == mono_defaults.int64_class) {
1149 printf ("[INT64:%p:%ld]", o, *((gint64 *)((char *)o + sizeof (MonoObject))));
1151 printf ("[%s.%s:%p]", o->vtable->klass->name_space, o->vtable->klass->name, o);
1153 printf ("[OBJECT:%p]", o);
1158 case MONO_TYPE_FNPTR:
1159 case MONO_TYPE_ARRAY:
1160 case MONO_TYPE_SZARRAY: {
1161 gpointer p = va_arg (ap, gpointer);
1162 printf ("[result=%p]", p);
1165 case MONO_TYPE_I8: {
1166 gint64 l = va_arg (ap, gint64);
1167 printf ("[LONG:%ld]", l);
1170 case MONO_TYPE_U8: {
1171 guint64 l = va_arg (ap, guint64);
1172 printf ("[ULONG:%lu]", l);
1175 case MONO_TYPE_R4: {
1176 double f = va_arg (ap, double);
1177 printf ("[FLOAT4:%g]\n", f);
1180 case MONO_TYPE_R8: {
1181 double f = va_arg (ap, double);
1182 printf ("[FLOAT8:%g]\n", f);
1185 case MONO_TYPE_VALUETYPE: {
1186 MonoMarshalType *info;
1187 if (type->data.klass->enumtype) {
1188 type = mono_class_enum_basetype (type->data.klass);
1193 info = mono_marshal_load_type_info (type->data.klass);
1195 if ((info->native_size == sizeof(float)) &&
1196 (info->num_fields == 1) &&
1197 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1198 double f = va_arg (ap, double);
1199 printf("[FLOAT4:%g]\n", (double) f);
1203 if ((info->native_size == sizeof(double)) &&
1204 (info->num_fields == 1) &&
1205 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1206 double f = va_arg (ap, double);
1207 printf("[FLOAT8:%g]\n", f);
1211 size = mono_type_size (type, &align);
1214 guint32 p = va_arg (ap, guint32);
1215 printf ("[%02x]\n",p);
1219 guint32 p = va_arg (ap, guint32);
1220 printf ("[%04x]\n",p);
1224 guint32 p = va_arg (ap, guint32);
1225 printf ("[%08x]\n",p);
1229 guint64 p = va_arg (ap, guint64);
1230 printf ("[%016lx]\n",p);
1234 gpointer p = va_arg (ap, gpointer);
1235 printf ("[VALUETYPE] %p\n",p);
1241 case MONO_TYPE_TYPEDBYREF: {
1242 guint8 *p = va_arg (ap, gpointer);
1244 size = mono_type_size (type, &align);
1251 for (j = 0; p && j < size; j++)
1252 printf ("%02x,", p [j]);
1256 printf ("[TYPEDBYREF]\n");
1260 case MONO_TYPE_GENERICINST: {
1261 printf("[GENERICINST]\n");
1264 case MONO_TYPE_MVAR: {
1268 case MONO_TYPE_CMOD_REQD: {
1269 printf("[CMOD_REQD]\n");
1272 case MONO_TYPE_CMOD_OPT: {
1273 printf("[CMOD_OPT]\n");
1276 case MONO_TYPE_INTERNAL: {
1277 printf("[INTERNAL]\n");
1281 printf ("(unknown return type %x)",
1282 mono_method_signature (method)->ret->type);
1285 ip = ((gint64) __builtin_extract_return_addr (__builtin_return_address (0)));
1286 printf (" ip: %p\n", (gpointer) ip);
1290 /*========================= End of Function ========================*/
1292 /*------------------------------------------------------------------*/
1294 /* Name - mono_arch_cpu_init */
1296 /* Function - Perform CPU specific initialization to execute */
1299 /*------------------------------------------------------------------*/
1302 mono_arch_cpu_init (void)
1306 /*========================= End of Function ========================*/
1308 /*------------------------------------------------------------------*/
1310 /* Name - mono_arch_init. */
1312 /* Function - Initialize architecture specific code. */
1314 /*------------------------------------------------------------------*/
1317 mono_arch_init (void)
1321 mono_set_partial_sharing_supported (FALSE);
1322 mono_os_mutex_init_recursive (&mini_arch_mutex);
1324 ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ, MONO_MEM_ACCOUNT_OTHER);
1325 bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ, MONO_MEM_ACCOUNT_OTHER);
1326 mono_mprotect (bp_trigger_page, mono_pagesize (), 0);
1328 code = (guint8 *) &breakpointCode;
1329 s390_basr(code, s390_r13, 0);
1331 s390_llong(code, 0);
1332 s390_lg(code, s390_r13, 0, s390_r13, 4);
1333 s390_lg(code, s390_r0, 0, s390_r13, 0);
1336 /*========================= End of Function ========================*/
1338 /*------------------------------------------------------------------*/
1340 /* Name - mono_arch_cleanup. */
1342 /* Function - Cleanup architecture specific code . */
1344 /*------------------------------------------------------------------*/
1347 mono_arch_cleanup (void)
1349 if (ss_trigger_page)
1350 mono_vfree (ss_trigger_page, mono_pagesize (), MONO_MEM_ACCOUNT_OTHER);
1351 if (bp_trigger_page)
1352 mono_vfree (bp_trigger_page, mono_pagesize (), MONO_MEM_ACCOUNT_OTHER);
1353 mono_os_mutex_destroy (&mini_arch_mutex);
1356 /*========================= End of Function ========================*/
1358 /*------------------------------------------------------------------*/
1360 /* Name - mono_arch_have_fast_tls */
1362 /* Function - Returns whether we use fast inlined thread local */
1363 /* storage managed access, instead of falling back */
1364 /* to native code. */
1366 /*------------------------------------------------------------------*/
1369 mono_arch_have_fast_tls (void)
1374 /*========================= End of Function ========================*/
1376 /*------------------------------------------------------------------*/
1378 /* Name - mono_arch_cpu_optimizations */
1380 /* Function - Returns the optimizations supported on this CPU */
1382 /*------------------------------------------------------------------*/
1385 mono_arch_cpu_optimizations (guint32 *exclude_mask)
1389 /*----------------------------------------------------------*/
1390 /* No s390-specific optimizations yet */
1391 /*----------------------------------------------------------*/
1392 *exclude_mask = MONO_OPT_LINEARS;
1396 /*========================= End of Function ========================*/
1398 /*------------------------------------------------------------------*/
1400 /* Name - mono_arch_get_allocatable_int_vars */
1404 /*------------------------------------------------------------------*/
1407 mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
1412 for (i = 0; i < cfg->num_varinfo; i++) {
1413 MonoInst *ins = cfg->varinfo [i];
1414 MonoMethodVar *vmv = MONO_VARINFO (cfg, i);
1417 if (vmv->range.first_use.abs_pos >= vmv->range.last_use.abs_pos)
1420 if (ins->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) ||
1421 (ins->opcode != OP_LOCAL && ins->opcode != OP_ARG))
1424 /* we can only allocate 32 bit values */
1425 if (mono_is_regsize_var(ins->inst_vtype)) {
1426 g_assert (MONO_VARINFO (cfg, i)->reg == -1);
1427 g_assert (i == vmv->idx);
1428 vars = mono_varlist_insert_sorted (cfg, vars, vmv, FALSE);
1435 /*========================= End of Function ========================*/
1437 /*------------------------------------------------------------------*/
1439 /* Name - mono_arch_global_int_regs */
1441 /* Function - Return a list of usable integer registers. */
1443 /*------------------------------------------------------------------*/
1446 mono_arch_get_global_int_regs (MonoCompile *cfg)
1449 MonoMethodHeader *header;
1452 header = cfg->header;
1453 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
1454 cfg->frame_reg = s390_r11;
1457 /* FIXME: s390_r12 is reserved for bkchain_reg. Only reserve it if needed */
1459 for (i = 8; i < top; ++i) {
1460 if (cfg->frame_reg != i)
1461 regs = g_list_prepend (regs, GUINT_TO_POINTER (i));
1467 /*========================= End of Function ========================*/
1469 /*------------------------------------------------------------------*/
1471 /* Name - mono_arch_flush_icache */
1473 /* Function - Flush the CPU icache. */
1475 /*------------------------------------------------------------------*/
1478 mono_arch_flush_icache (guint8 *code, gint size)
1482 /*========================= End of Function ========================*/
1484 /*------------------------------------------------------------------*/
1486 /* Name - add_general */
1488 /* Function - Determine code and stack size incremements for a */
1491 /*------------------------------------------------------------------*/
1494 add_general (guint *gr, size_data *sz, ArgInfo *ainfo)
1496 if (*gr > S390_LAST_ARG_REG) {
1497 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1498 ainfo->offset = sz->stack_size;
1499 ainfo->reg = STK_BASE;
1500 ainfo->regtype = RegTypeBase;
1501 sz->stack_size += sizeof(long);
1502 sz->local_size += sizeof(long);
1503 sz->offStruct += sizeof(long);
1504 sz->code_size += 12;
1512 /*========================= End of Function ========================*/
1514 /*------------------------------------------------------------------*/
1516 /* Name - add_stackParm */
1518 /* Function - Determine code and stack size incremements for a */
1521 /*------------------------------------------------------------------*/
1524 add_stackParm (guint *gr, size_data *sz, ArgInfo *ainfo, gint size)
1526 if (*gr > S390_LAST_ARG_REG) {
1527 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1528 ainfo->reg = STK_BASE;
1529 ainfo->offset = sz->stack_size;
1530 ainfo->regtype = RegTypeStructByAddrOnStack;
1531 sz->stack_size += sizeof (gpointer);
1532 sz->parm_size += sizeof(gpointer);
1533 sz->offStruct += sizeof(gpointer);
1536 ainfo->offset = sz->stack_size;
1537 ainfo->regtype = RegTypeStructByAddr;
1540 ainfo->offparm = sz->offset;
1541 sz->offset = S390_ALIGN(sz->offset+size, sizeof(long));
1543 ainfo->vtsize = size;
1544 sz->parm_size += size;
1547 /*========================= End of Function ========================*/
1549 /*------------------------------------------------------------------*/
1551 /* Name - add_float */
1553 /* Function - Determine code and stack size incremements for a */
1554 /* float parameter. */
1556 /*------------------------------------------------------------------*/
1559 add_float (guint *fr, size_data *sz, ArgInfo *ainfo)
1561 if ((*fr) <= S390_LAST_FPARG_REG) {
1562 ainfo->regtype = RegTypeFP;
1568 ainfo->offset = sz->stack_size;
1569 ainfo->reg = STK_BASE;
1570 ainfo->regtype = RegTypeBase;
1572 sz->stack_size += sizeof(double);
1573 sz->local_size += sizeof(double);
1574 sz->offStruct += sizeof(double);
1578 /*========================= End of Function ========================*/
1580 /*------------------------------------------------------------------*/
1582 /* Name - get_call_info */
1584 /* Function - Determine the amount of space required for code */
1585 /* and stack. In addition determine starting points */
1586 /* for stack-based parameters, and area for struct- */
1587 /* ures being returned on the stack. */
1589 /*------------------------------------------------------------------*/
1592 get_call_info (MonoCompile *cfg, MonoMemPool *mp, MonoMethodSignature *sig)
1594 guint i, fr, gr, size, pstart;
1595 int nParm = sig->hasthis + sig->param_count;
1597 guint32 simpleType, align;
1598 gboolean is_pinvoke = sig->pinvoke;
1603 cinfo = mono_mempool_alloc0 (mp, sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1605 cinfo = g_malloc0 (sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1610 cinfo->struct_ret = 0;
1614 sz->offStruct = S390_MINIMAL_STACK_SIZE;
1615 sz->stack_size = S390_MINIMAL_STACK_SIZE;
1622 /*----------------------------------------------------------*/
1623 /* We determine the size of the return code/stack in case we*/
1624 /* need to reserve a register to be used to address a stack */
1625 /* area that the callee will use. */
1626 /*----------------------------------------------------------*/
1628 ret_type = mini_get_underlying_type (sig->ret);
1629 simpleType = ret_type->type;
1631 switch (simpleType) {
1632 case MONO_TYPE_BOOLEAN:
1637 case MONO_TYPE_CHAR:
1642 case MONO_TYPE_CLASS:
1643 case MONO_TYPE_OBJECT:
1644 case MONO_TYPE_SZARRAY:
1645 case MONO_TYPE_ARRAY:
1647 case MONO_TYPE_FNPTR:
1648 case MONO_TYPE_STRING:
1649 cinfo->ret.reg = s390_r2;
1654 cinfo->ret.reg = s390_f0;
1659 cinfo->ret.reg = s390_r2;
1662 case MONO_TYPE_GENERICINST:
1663 if (!mono_type_generic_inst_is_valuetype (sig->ret)) {
1664 cinfo->ret.reg = s390_r2;
1669 case MONO_TYPE_VALUETYPE: {
1670 MonoClass *klass = mono_class_from_mono_type (sig->ret);
1671 if (klass->enumtype) {
1672 simpleType = mono_class_enum_basetype (klass)->type;
1675 size = mini_type_stack_size_full (&klass->byval_arg, NULL, sig->pinvoke);
1677 cinfo->struct_ret = 1;
1678 cinfo->ret.size = size;
1679 cinfo->ret.vtsize = size;
1682 case MONO_TYPE_TYPEDBYREF:
1683 size = sizeof (MonoTypedRef);
1684 cinfo->struct_ret = 1;
1685 cinfo->ret.size = size;
1686 cinfo->ret.vtsize = size;
1688 case MONO_TYPE_VOID:
1691 g_error ("Can't handle as return value 0x%x", sig->ret->type);
1697 * To simplify get_this_arg_reg () and LLVM integration, emit the vret arg after
1698 * the first argument, allowing 'this' to be always passed in the first arg reg.
1699 * Also do this if the first argument is a reference type, since virtual calls
1700 * are sometimes made using calli without sig->hasthis set, like in the delegate
1703 if (cinfo->struct_ret && !is_pinvoke &&
1705 (sig->param_count > 0 &&
1706 MONO_TYPE_IS_REFERENCE (mini_get_underlying_type (sig->params [0]))))) {
1708 cinfo->args[nParm].size = sizeof (gpointer);
1709 add_general (&gr, sz, cinfo->args + nParm);
1711 cinfo->args[nParm].size = sizeof (gpointer);
1712 add_general (&gr, sz, &cinfo->args [sig->hasthis + nParm]);
1716 cinfo->vret_arg_index = 1;
1717 cinfo->ret.reg = gr;
1722 cinfo->args[nParm].size = sizeof (gpointer);
1723 add_general (&gr, sz, cinfo->args + nParm);
1727 if (cinfo->struct_ret) {
1728 cinfo->ret.reg = gr;
1733 if ((sig->call_convention == MONO_CALL_VARARG) && (sig->param_count == 0)) {
1734 gr = S390_LAST_ARG_REG + 1;
1735 fr = S390_LAST_FPARG_REG + 1;
1737 /* Emit the signature cookie just before the implicit arguments */
1738 add_general (&gr, sz, &cinfo->sigCookie);
1741 /*----------------------------------------------------------*/
1742 /* We determine the size of the parameter code and stack */
1743 /* requirements by checking the types and sizes of the */
1745 /*----------------------------------------------------------*/
1747 for (i = pstart; i < sig->param_count; ++i) {
1750 /*--------------------------------------------------*/
1751 /* Handle vararg type calls. All args are put on */
1753 /*--------------------------------------------------*/
1754 if ((sig->call_convention == MONO_CALL_VARARG) &&
1755 (i == sig->sentinelpos)) {
1756 gr = S390_LAST_ARG_REG + 1;
1757 fr = S390_LAST_FPARG_REG + 1;
1758 add_general (&gr, sz, &cinfo->sigCookie);
1761 if (sig->params [i]->byref) {
1762 add_general (&gr, sz, cinfo->args+nParm);
1763 cinfo->args[nParm].size = sizeof(gpointer);
1768 ptype = mini_get_underlying_type (sig->params [i]);
1769 simpleType = ptype->type;
1770 cinfo->args[nParm].type = simpleType;
1771 switch (simpleType) {
1772 case MONO_TYPE_BOOLEAN:
1775 cinfo->args[nParm].size = sizeof(char);
1776 add_general (&gr, sz, cinfo->args+nParm);
1781 case MONO_TYPE_CHAR:
1782 cinfo->args[nParm].size = sizeof(short);
1783 add_general (&gr, sz, cinfo->args+nParm);
1788 cinfo->args[nParm].size = sizeof(int);
1789 add_general (&gr, sz, cinfo->args+nParm);
1795 case MONO_TYPE_FNPTR:
1796 case MONO_TYPE_CLASS:
1797 case MONO_TYPE_OBJECT:
1798 case MONO_TYPE_STRING:
1799 case MONO_TYPE_SZARRAY:
1800 case MONO_TYPE_ARRAY:
1801 cinfo->args[nParm].size = sizeof(gpointer);
1802 add_general (&gr, sz, cinfo->args+nParm);
1807 cinfo->args[nParm].size = sizeof(long long);
1808 add_general (&gr, sz, cinfo->args+nParm);
1812 cinfo->args[nParm].size = sizeof(float);
1813 add_float (&fr, sz, cinfo->args+nParm);
1817 cinfo->args[nParm].size = sizeof(double);
1818 add_float (&fr, sz, cinfo->args+nParm);
1821 case MONO_TYPE_GENERICINST:
1822 if (!mono_type_generic_inst_is_valuetype (ptype)) {
1823 cinfo->args[nParm].size = sizeof(gpointer);
1824 add_general (&gr, sz, cinfo->args+nParm);
1829 case MONO_TYPE_VALUETYPE: {
1830 MonoMarshalType *info;
1831 MonoClass *klass = mono_class_from_mono_type (ptype);
1834 size = mono_class_native_size(klass, NULL);
1836 size = mono_class_value_size(klass, NULL);
1838 if (simpleType != MONO_TYPE_GENERICINST) {
1839 info = mono_marshal_load_type_info(klass);
1841 if ((info->native_size == sizeof(float)) &&
1842 (info->num_fields == 1) &&
1843 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1844 cinfo->args[nParm].size = sizeof(float);
1845 add_float(&fr, sz, cinfo->args+nParm);
1850 if ((info->native_size == sizeof(double)) &&
1851 (info->num_fields == 1) &&
1852 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1853 cinfo->args[nParm].size = sizeof(double);
1854 add_float(&fr, sz, cinfo->args+nParm);
1860 cinfo->args[nParm].vtsize = 0;
1861 cinfo->args[nParm].size = 0;
1864 /*----------------------------------*/
1865 /* On S/390, structures of size 1, */
1866 /* 2, 4, and 8 bytes are passed in */
1867 /* (a) register(s). */
1868 /*----------------------------------*/
1874 add_general(&gr, sz, cinfo->args+nParm);
1875 cinfo->args[nParm].size = size;
1876 cinfo->args[nParm].regtype = RegTypeStructByVal;
1878 sz->local_size += sizeof(long);
1881 add_stackParm(&gr, sz, cinfo->args+nParm, size);
1886 case MONO_TYPE_TYPEDBYREF: {
1887 int size = sizeof (MonoTypedRef);
1889 cinfo->args[nParm].vtsize = 0;
1890 cinfo->args[nParm].size = 0;
1893 /*----------------------------------*/
1894 /* On S/390, structures of size 1, */
1895 /* 2, 4, and 8 bytes are passed in */
1896 /* (a) register(s). */
1897 /*----------------------------------*/
1903 add_general(&gr, sz, cinfo->args+nParm);
1904 cinfo->args[nParm].size = size;
1905 cinfo->args[nParm].regtype = RegTypeStructByVal;
1907 sz->local_size += sizeof(long);
1910 add_stackParm(&gr, sz, cinfo->args+nParm, size);
1916 g_error ("Can't trampoline 0x%x", ptype);
1920 /*----------------------------------------------------------*/
1921 /* Handle the case where there are no implicit arguments */
1922 /*----------------------------------------------------------*/
1923 if ((sig->call_convention == MONO_CALL_VARARG) &&
1926 (sig->param_count == sig->sentinelpos)) {
1927 gr = S390_LAST_ARG_REG + 1;
1928 fr = S390_LAST_FPARG_REG + 1;
1929 add_general (&gr, sz, &cinfo->sigCookie);
1932 /*----------------------------------------------------------*/
1933 /* If we are passing a structure back then if it won't be */
1934 /* in a register(s) then we make room at the end of the */
1935 /* parameters that may have been placed on the stack */
1936 /*----------------------------------------------------------*/
1937 if (cinfo->struct_ret) {
1938 cinfo->ret.offset = sz->stack_size;
1939 switch (cinfo->ret.size) {
1947 sz->stack_size += S390_ALIGN(cinfo->ret.size, align);
1952 sz->stack_size = sz->stack_size + sz->local_size + sz->parm_size +
1954 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1959 /*========================= End of Function ========================*/
1961 /*------------------------------------------------------------------*/
1963 /* Name - mono_arch_allocate_vars */
1965 /* Function - Set var information according to the calling */
1966 /* convention for S/390. The local var stuff should */
1967 /* most likely be split in another method. */
1969 /* Parameter - @m - Compile unit. */
1971 /*------------------------------------------------------------------*/
1974 mono_arch_allocate_vars (MonoCompile *cfg)
1976 MonoMethodSignature *sig;
1977 MonoMethodHeader *header;
1980 int iParm, iVar, offset, align, size, curinst;
1981 int frame_reg = STK_BASE;
1984 header = cfg->header;
1986 cfg->flags |= MONO_CFG_HAS_SPILLUP;
1988 /*---------------------------------------------------------*/
1989 /* We use the frame register also for any method that has */
1990 /* filter clauses. This way, when the handlers are called, */
1991 /* the code will reference local variables using the frame */
1992 /* reg instead of the stack pointer: if we had to restore */
1993 /* the stack pointer, we'd corrupt the method frames that */
1994 /* are already on the stack (since filters get called */
1995 /* before stack unwinding happens) when the filter code */
1996 /* would call any method. */
1997 /*---------------------------------------------------------*/
1998 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
1999 frame_reg = s390_r11;
2001 cfg->frame_reg = frame_reg;
2003 cfg->arch.bkchain_reg = -1;
2005 if (frame_reg != STK_BASE)
2006 cfg->used_int_regs |= (1 << frame_reg);
2008 if (cfg->uses_rgctx_reg)
2009 cfg->used_int_regs |= (1 << MONO_ARCH_IMT_REG);
2011 sig = mono_method_signature (cfg->method);
2013 cinfo = get_call_info (cfg, cfg->mempool, sig);
2015 if (!cinfo->struct_ret) {
2016 switch (mini_get_underlying_type (sig->ret)->type) {
2017 case MONO_TYPE_VOID:
2020 cfg->ret->opcode = OP_REGVAR;
2021 cfg->ret->dreg = s390_r2;
2026 /*--------------------------------------------------------------*/
2027 /* local vars are at a positive offset from the stack pointer */
2028 /* also note that if the function uses alloca, we use s390_r11 */
2029 /* to point at the local variables. */
2030 /* add parameter area size for called functions */
2031 /*--------------------------------------------------------------*/
2032 if (cfg->param_area == 0)
2033 offset = S390_MINIMAL_STACK_SIZE;
2035 offset = cfg->param_area;
2037 cfg->sig_cookie = 0;
2039 if (cinfo->struct_ret) {
2040 inst = cfg->vret_addr;
2041 offset = S390_ALIGN(offset, sizeof(gpointer));
2042 inst->inst_offset = offset;
2043 inst->opcode = OP_REGOFFSET;
2044 inst->inst_basereg = frame_reg;
2045 offset += sizeof(gpointer);
2046 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2047 printf ("vret_addr =");
2048 mono_print_ins (cfg->vret_addr);
2053 inst = cfg->args [0];
2054 if (inst->opcode != OP_REGVAR) {
2055 inst->opcode = OP_REGOFFSET;
2056 inst->inst_basereg = frame_reg;
2057 offset = S390_ALIGN(offset, sizeof(gpointer));
2058 inst->inst_offset = offset;
2059 offset += sizeof (gpointer);
2066 eArg = sig->param_count + sArg;
2068 if (sig->call_convention == MONO_CALL_VARARG)
2069 cfg->sig_cookie += S390_MINIMAL_STACK_SIZE;
2071 for (iParm = sArg; iParm < eArg; ++iParm) {
2072 inst = cfg->args [curinst];
2073 if (inst->opcode != OP_REGVAR) {
2074 switch (cinfo->args[iParm].regtype) {
2075 case RegTypeStructByAddr : {
2078 size = sizeof (gpointer);
2080 inst->opcode = OP_REGOFFSET;
2081 inst->inst_basereg = frame_reg;
2082 offset = S390_ALIGN (offset, sizeof (gpointer));
2083 inst->inst_offset = offset;
2085 /* Add a level of indirection */
2086 MONO_INST_NEW (cfg, indir, 0);
2088 inst->opcode = OP_VTARG_ADDR;
2089 inst->inst_left = indir;
2092 case RegTypeStructByAddrOnStack : {
2095 size = sizeof (gpointer);
2097 /* Similar to the == STK_BASE case below */
2098 cfg->arch.bkchain_reg = s390_r12;
2099 cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2101 inst->opcode = OP_REGOFFSET;
2102 inst->dreg = mono_alloc_preg (cfg);
2103 inst->inst_basereg = cfg->arch.bkchain_reg;
2104 inst->inst_offset = cinfo->args [iParm].offset;
2106 /* Add a level of indirection */
2107 MONO_INST_NEW (cfg, indir, 0);
2109 inst->opcode = OP_VTARG_ADDR;
2110 inst->inst_left = indir;
2113 case RegTypeStructByVal :
2114 size = cinfo->args[iParm].size;
2115 offset = S390_ALIGN(offset, size);
2116 inst->opcode = OP_REGOFFSET;
2117 inst->inst_basereg = frame_reg;
2118 inst->inst_offset = offset;
2121 if (cinfo->args [iParm].reg == STK_BASE) {
2123 * These arguments are in the previous frame, so we can't
2124 * compute their offset from the current frame pointer right
2125 * now, since cfg->stack_offset is not yet known, so dedicate a
2126 * register holding the previous frame pointer.
2128 cfg->arch.bkchain_reg = s390_r12;
2129 cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2131 inst->opcode = OP_REGOFFSET;
2132 inst->inst_basereg = cfg->arch.bkchain_reg;
2133 size = (cinfo->args[iParm].size < 8
2134 ? 8 - cinfo->args[iParm].size
2136 inst->inst_offset = cinfo->args [iParm].offset + size;
2137 size = sizeof (long);
2139 inst->opcode = OP_REGOFFSET;
2140 inst->inst_basereg = frame_reg;
2141 size = (cinfo->args[iParm].size < 8
2144 offset = S390_ALIGN(offset, size);
2145 if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
2146 inst->inst_offset = offset;
2148 inst->inst_offset = offset + (8 - size);
2153 if ((sig->call_convention == MONO_CALL_VARARG) &&
2154 (cinfo->args[iParm].regtype != RegTypeGeneral) &&
2155 (iParm < sig->sentinelpos))
2156 cfg->sig_cookie += size;
2157 printf("%s %4d cookine %x\n",__FUNCTION__,__LINE__,cfg->sig_cookie);
2160 offset += MAX(size, 8);
2165 cfg->locals_min_stack_offset = offset;
2167 curinst = cfg->locals_start;
2168 for (iVar = curinst; iVar < cfg->num_varinfo; ++iVar) {
2169 inst = cfg->varinfo [iVar];
2170 if ((inst->flags & MONO_INST_IS_DEAD) ||
2171 (inst->opcode == OP_REGVAR))
2174 /*--------------------------------------------------*/
2175 /* inst->backend.is_pinvoke indicates native sized */
2176 /* value typs this is used by the pinvoke wrappers */
2177 /* when they call functions returning structure */
2178 /*--------------------------------------------------*/
2179 if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype))
2180 size = mono_class_native_size (mono_class_from_mono_type(inst->inst_vtype),
2181 (guint32 *) &align);
2183 size = mono_type_size (inst->inst_vtype, &align);
2185 offset = S390_ALIGN(offset, align);
2186 inst->inst_offset = offset;
2187 inst->opcode = OP_REGOFFSET;
2188 inst->inst_basereg = frame_reg;
2190 DEBUG (g_print("allocating local %d to %ld, size: %d\n",
2191 iVar, inst->inst_offset, size));
2194 cfg->locals_max_stack_offset = offset;
2196 /*------------------------------------------------------*/
2197 /* Allow space for the trace method stack area if needed*/
2198 /*------------------------------------------------------*/
2199 if ((mono_jit_trace_calls != NULL && mono_trace_eval (cfg->method))
2200 || (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE))
2201 offset += S390_TRACE_STACK_SIZE;
2203 /*------------------------------------------------------*/
2204 /* Reserve space to save LMF and caller saved registers */
2205 /*------------------------------------------------------*/
2206 if (cfg->method->save_lmf)
2207 offset += sizeof (MonoLMF);
2209 /*------------------------------------------------------*/
2210 /* align the offset */
2211 /*------------------------------------------------------*/
2212 cfg->stack_offset = S390_ALIGN(offset, S390_STACK_ALIGNMENT);
2214 /*------------------------------------------------------*/
2215 /* Fix offsets for args whose value is in parent frame */
2216 /*------------------------------------------------------*/
2217 for (iParm = sArg; iParm < eArg; ++iParm) {
2218 inst = cfg->args [iParm];
2220 if (inst->opcode == OP_S390_STKARG) {
2221 inst->opcode = OP_REGOFFSET;
2222 inst->inst_offset += cfg->stack_offset;
2227 /*========================= End of Function ========================*/
2229 /*------------------------------------------------------------------*/
2231 /* Name - mono_arch_create_vars */
2233 /*------------------------------------------------------------------*/
2236 mono_arch_create_vars (MonoCompile *cfg)
2238 MonoMethodSignature *sig;
2241 sig = mono_method_signature (cfg->method);
2243 cinfo = get_call_info (cfg, cfg->mempool, sig);
2245 if (cinfo->struct_ret) {
2246 cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG);
2247 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2248 printf ("vret_addr = ");
2249 mono_print_ins (cfg->vret_addr);
2254 /*========================= End of Function ========================*/
2256 /*------------------------------------------------------------------*/
2258 /* Name - add_outarg_reg2. */
2260 /*------------------------------------------------------------------*/
2263 add_outarg_reg2 (MonoCompile *cfg, MonoCallInst *call, ArgStorage storage, int reg, MonoInst *tree)
2268 case RegTypeGeneral:
2269 MONO_INST_NEW (cfg, ins, OP_MOVE);
2270 ins->dreg = mono_alloc_ireg (cfg);
2271 ins->sreg1 = tree->dreg;
2272 MONO_ADD_INS (cfg->cbb, ins);
2273 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, FALSE);
2276 MONO_INST_NEW (cfg, ins, OP_FMOVE);
2277 ins->dreg = mono_alloc_freg (cfg);
2278 ins->sreg1 = tree->dreg;
2279 MONO_ADD_INS (cfg->cbb, ins);
2280 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2283 MONO_INST_NEW (cfg, ins, OP_S390_SETF4RET);
2284 ins->dreg = mono_alloc_freg (cfg);
2285 ins->sreg1 = tree->dreg;
2286 MONO_ADD_INS (cfg->cbb, ins);
2287 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2290 g_assert_not_reached ();
2294 /*========================= End of Function ========================*/
2296 /*------------------------------------------------------------------*/
2298 /* Name - emit_sig_cookie. */
2300 /*------------------------------------------------------------------*/
2303 emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo)
2305 MonoMethodSignature *tmpSig;
2308 cfg->disable_aot = TRUE;
2310 /*----------------------------------------------------------*/
2311 /* mono_ArgIterator_Setup assumes the signature cookie is */
2312 /* passed first and all the arguments which were before it */
2313 /* passed on the stack after the signature. So compensate */
2314 /* by passing a different signature. */
2315 /*----------------------------------------------------------*/
2316 tmpSig = mono_metadata_signature_dup (call->signature);
2317 tmpSig->param_count -= call->signature->sentinelpos;
2318 tmpSig->sentinelpos = 0;
2319 if (tmpSig->param_count > 0)
2320 memcpy (tmpSig->params,
2321 call->signature->params + call->signature->sentinelpos,
2322 tmpSig->param_count * sizeof(MonoType *));
2324 MONO_INST_NEW (cfg, sig_arg, OP_ICONST);
2325 sig_arg->dreg = mono_alloc_ireg (cfg);
2326 sig_arg->inst_p0 = tmpSig;
2327 MONO_ADD_INS (cfg->cbb, sig_arg);
2329 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, STK_BASE,
2330 cinfo->sigCookie.offset, sig_arg->dreg);
2333 /*========================= End of Function ========================*/
2335 /*------------------------------------------------------------------*/
2337 /* Name - mono_arch_emit_call */
2339 /*------------------------------------------------------------------*/
2342 mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
2345 MonoMethodSignature *sig;
2347 int i, n, lParamArea;
2349 ArgInfo *ainfo = NULL;
2351 MonoMethodHeader *header;
2354 sig = call->signature;
2355 n = sig->param_count + sig->hasthis;
2356 DEBUG (g_print ("Call requires: %d parameters\n",n));
2358 cinfo = get_call_info (cfg, cfg->mempool, sig);
2360 stackSize = cinfo->sz.stack_size + cinfo->sz.local_size +
2361 cinfo->sz.parm_size + cinfo->sz.offset;
2362 call->stack_usage = MAX(stackSize, call->stack_usage);
2363 lParamArea = MAX((call->stack_usage-S390_MINIMAL_STACK_SIZE-cinfo->sz.parm_size), 0);
2364 cfg->param_area = MAX(((signed) cfg->param_area), lParamArea);
2365 cfg->flags |= MONO_CFG_HAS_CALLS;
2367 if (cinfo->struct_ret) {
2368 MONO_INST_NEW (cfg, ins, OP_MOVE);
2369 ins->sreg1 = call->vret_var->dreg;
2370 ins->dreg = mono_alloc_preg (cfg);
2371 MONO_ADD_INS (cfg->cbb, ins);
2372 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, cinfo->ret.reg, FALSE);
2375 header = cfg->header;
2376 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2381 for (i = 0; i < n; ++i) {
2384 ainfo = cinfo->args + i;
2385 if (i >= sig->hasthis)
2386 t = sig->params [i - sig->hasthis];
2388 t = &mono_defaults.int_class->byval_arg;
2389 t = mini_get_underlying_type (t);
2391 in = call->args [i];
2393 if ((sig->call_convention == MONO_CALL_VARARG) &&
2395 (i == sig->sentinelpos)) {
2396 emit_sig_cookie (cfg, call, cinfo);
2399 switch (ainfo->regtype) {
2400 case RegTypeGeneral:
2401 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2404 if (MONO_TYPE_ISSTRUCT (t)) {
2405 /* Valuetype passed in one fp register */
2406 ainfo->regtype = RegTypeStructByValInFP;
2409 if (ainfo->size == 4)
2410 ainfo->regtype = RegTypeFPR4;
2411 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2414 case RegTypeStructByVal:
2415 case RegTypeStructByAddr:
2416 case RegTypeStructByAddrOnStack: {
2420 if (sig->params [i - sig->hasthis]->type == MONO_TYPE_TYPEDBYREF) {
2421 size = sizeof (MonoTypedRef);
2422 align = sizeof (gpointer);
2426 size = mono_type_native_stack_size (&in->klass->byval_arg, &align);
2429 * Other backends use mono_type_stack_size (), but that
2430 * aligns the size to 8, which is larger than the size of
2431 * the source, leading to reads of invalid memory if the
2432 * source is at the end of address space.
2434 size = mono_class_value_size (in->klass, &align);
2437 g_assert (in->klass);
2439 ainfo->offparm += cinfo->sz.offStruct;
2441 MONO_INST_NEW (cfg, ins, OP_OUTARG_VT);
2442 ins->sreg1 = in->dreg;
2443 ins->klass = in->klass;
2444 ins->backend.size = ainfo->size;
2445 ins->inst_p0 = call;
2446 ins->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
2447 memcpy (ins->inst_p1, ainfo, sizeof (ArgInfo));
2449 MONO_ADD_INS (cfg->cbb, ins);
2451 if (ainfo->regtype == RegTypeStructByAddr) {
2453 * We use OP_OUTARG_VT to copy the valuetype to a stack location, then
2454 * use the normal OUTARG opcodes to pass the address of the location to
2457 int treg = mono_alloc_preg (cfg);
2458 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2459 frmReg, ainfo->offparm);
2460 mono_call_inst_add_outarg_reg (cfg, call, treg, ainfo->reg, FALSE);
2461 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
2462 /* The address of the valuetype is passed on the stack */
2463 int treg = mono_alloc_preg (cfg);
2464 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2465 frmReg, ainfo->offparm);
2466 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG,
2467 ainfo->reg, ainfo->offset, treg);
2469 if (cfg->compute_gc_maps) {
2472 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, t);
2478 if (!t->byref && t->type == MONO_TYPE_R4) {
2479 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG,
2480 STK_BASE, ainfo->offset + 4,
2482 } else if (!t->byref && (t->type == MONO_TYPE_R8)) {
2483 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG,
2484 STK_BASE, ainfo->offset,
2487 MONO_INST_NEW (cfg, ins, OP_STORE_MEMBASE_REG);
2488 ins->inst_destbasereg = STK_BASE;
2489 ins->inst_offset = ainfo->offset;
2490 ins->sreg1 = in->dreg;
2493 /* This is needed by MonoTypedRef->value to point to the correct data */
2494 if ((sig->call_convention == MONO_CALL_VARARG) &&
2495 (i >= sig->sentinelpos)) {
2496 switch (ainfo->size) {
2498 ins->opcode = OP_STOREI1_MEMBASE_REG;
2501 ins->opcode = OP_STOREI2_MEMBASE_REG;
2504 ins->opcode = OP_STOREI4_MEMBASE_REG;
2512 MONO_ADD_INS (cfg->cbb, ins);
2516 g_assert_not_reached ();
2522 * Handle the case where there are no implicit arguments
2524 if ((sig->call_convention == MONO_CALL_VARARG) &&
2526 (i == sig->sentinelpos)) {
2527 emit_sig_cookie (cfg, call, cinfo);
2531 /*========================= End of Function ========================*/
2533 /*------------------------------------------------------------------*/
2535 /* Name - mono_arch_emit_outarg_vt */
2537 /*------------------------------------------------------------------*/
2540 mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
2542 MonoCallInst *call = (MonoCallInst*)ins->inst_p0;
2543 ArgInfo *ainfo = (ArgInfo*)ins->inst_p1;
2544 int size = ins->backend.size;
2546 if (ainfo->regtype == RegTypeStructByVal) {
2548 arg->ins.sreg1 = ainfo->reg;
2549 arg->ins.opcode = OP_OUTARG_VT;
2550 arg->size = ainfo->size;
2551 arg->offset = ainfo->offset;
2552 arg->offPrm = ainfo->offparm + cinfo->sz.offStruct;
2554 if (ainfo->reg != STK_BASE) {
2555 MONO_OUTPUT_VTR (cfg, size, ainfo->reg, src->dreg, 0);
2557 MONO_OUTPUT_VTS (cfg, size, ainfo->reg, ainfo->offset,
2560 } else if (ainfo->regtype == RegTypeStructByValInFP) {
2561 int dreg = mono_alloc_freg (cfg);
2563 if (ainfo->size == 4) {
2564 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR4_MEMBASE, dreg, src->dreg, 0);
2565 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, dreg, dreg);
2567 g_assert (ainfo->size == 8);
2569 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR8_MEMBASE, dreg, src->dreg, 0);
2572 mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg, TRUE);
2575 MonoMethodHeader *header;
2578 header = mono_method_get_header_checked (cfg->method, &error);
2579 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
2580 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2585 MONO_EMIT_NEW_MOVE (cfg, srcReg, ainfo->offparm,
2586 src->dreg, 0, size);
2588 if (cfg->compute_gc_maps) {
2591 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, &ins->klass->byval_arg);
2596 /*========================= End of Function ========================*/
2598 /*------------------------------------------------------------------*/
2600 /* Name - mono_arch_emit_setret */
2602 /*------------------------------------------------------------------*/
2605 mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
2607 MonoType *ret = mini_get_underlying_type (mono_method_signature (method)->ret);
2610 if (ret->type == MONO_TYPE_R4) {
2611 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, s390_f0, val->dreg);
2613 } else if (ret->type == MONO_TYPE_R8) {
2614 MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, s390_f0, val->dreg);
2619 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg);
2622 /*========================= End of Function ========================*/
2624 /*------------------------------------------------------------------*/
2626 /* Name - mono_arch_instrument_mem_needs */
2628 /* Function - Allow tracing to work with this interface (with */
2629 /* an optional argument). */
2631 /*------------------------------------------------------------------*/
2634 mono_arch_instrument_mem_needs (MonoMethod *method, int *stack, int *code)
2636 /* no stack room needed now (may be needed for FASTCALL-trace support) */
2638 /* split prolog-epilog requirements? */
2639 *code = 50; /* max bytes needed: check this number */
2642 /*========================= End of Function ========================*/
2644 /*------------------------------------------------------------------*/
2646 /* Name - mono_arch_instrument_prolog */
2648 /* Function - Create an "instrumented" prolog. */
2650 /*------------------------------------------------------------------*/
2653 mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p,
2654 gboolean enable_arguments)
2661 parmOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2662 if (cfg->method->save_lmf)
2663 parmOffset -= sizeof(MonoLMF);
2664 fpOffset = parmOffset + (5*sizeof(gpointer));
2667 s390_stmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2668 s390_stdy (code, s390_f0, 0, STK_BASE, fpOffset);
2669 s390_stdy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2670 s390_stdy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2671 s390_stdy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2672 S390_SET (code, s390_r1, func);
2673 S390_SET (code, s390_r2, cfg->method);
2674 s390_lay (code, s390_r3, 0, STK_BASE, parmOffset);
2675 s390_lgr (code, s390_r4, STK_BASE);
2676 s390_aghi (code, s390_r4, cfg->stack_usage);
2677 s390_basr (code, s390_r14, s390_r1);
2678 s390_ldy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2679 s390_ldy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2680 s390_ldy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2681 s390_ldy (code, s390_f0, 0, STK_BASE, fpOffset);
2682 s390_lmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2687 /*========================= End of Function ========================*/
2689 /*------------------------------------------------------------------*/
2691 /* Name - mono_arch_instrument_epilog */
2693 /* Function - Create an epilog that will handle the returned */
2694 /* values used in instrumentation. */
2696 /*------------------------------------------------------------------*/
2699 mono_arch_instrument_epilog_full (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments, gboolean preserve_argument_registers)
2702 int save_mode = SAVE_NONE,
2705 MonoMethod *method = cfg->method;
2706 int rtype = mini_get_underlying_type (mono_method_signature (method)->ret)->type;
2708 offset = code - cfg->native_code;
2709 /*-----------------------------------------*/
2710 /* We need about 128 bytes of instructions */
2711 /*-----------------------------------------*/
2712 if (offset > (cfg->code_size - 128)) {
2713 cfg->code_size *= 2;
2714 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
2715 code = cfg->native_code + offset;
2718 saveOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2719 if (method->save_lmf)
2720 saveOffset -= sizeof(MonoLMF);
2724 case MONO_TYPE_VOID:
2725 /* special case string .ctor icall */
2726 if (strcmp (".ctor", method->name) && method->klass == mono_defaults.string_class)
2727 save_mode = SAVE_ONE;
2729 save_mode = SAVE_NONE;
2733 save_mode = SAVE_ONE;
2736 save_mode = SAVE_R4;
2739 save_mode = SAVE_R8;
2741 case MONO_TYPE_VALUETYPE:
2742 if (mono_method_signature (method)->ret->data.klass->enumtype) {
2743 rtype = mono_class_enum_basetype (mono_method_signature (method)->ret->data.klass)->type;
2746 save_mode = SAVE_STRUCT;
2749 save_mode = SAVE_ONE;
2753 switch (save_mode) {
2755 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2756 if (enable_arguments) {
2757 s390_lgr (code, s390_r3, s390_r2);
2761 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2762 if (enable_arguments) {
2763 s390_ldebr (code, s390_f0, s390_f0);
2767 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2770 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2771 if (enable_arguments) {
2772 s390_lg (code, s390_r3, 0, cfg->frame_reg,
2773 S390_MINIMAL_STACK_SIZE+cfg->param_area);
2781 S390_SET (code, s390_r1, func);
2782 S390_SET (code, s390_r2, cfg->method);
2783 s390_basr (code, s390_r14, s390_r1);
2785 switch (save_mode) {
2787 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2791 s390_ld (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2794 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2804 /*========================= End of Function ========================*/
2806 /*------------------------------------------------------------------*/
2808 /* Name - mono_arch_peephole_pass_1 */
2810 /* Function - Form a peephole pass at the code looking for */
2811 /* simple optimizations. */
2813 /*------------------------------------------------------------------*/
2816 mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
2820 /*========================= End of Function ========================*/
2822 /*------------------------------------------------------------------*/
2824 /* Name - mono_arch_peephole_pass_2 */
2826 /* Function - Form a peephole pass at the code looking for */
2827 /* simple optimizations. */
2829 /*------------------------------------------------------------------*/
2832 mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
2836 MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
2837 mono_peephole_ins (bb, ins);
2841 /*========================= End of Function ========================*/
2843 /*------------------------------------------------------------------*/
2845 /* Name - mono_arch_lowering_pass. */
2847 /*------------------------------------------------------------------*/
2850 mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
2852 MonoInst *ins, *next;
2854 MONO_BB_FOR_EACH_INS_SAFE (bb, next, ins) {
2855 switch (ins->opcode) {
2860 case OP_IDIV_UN_IMM:
2861 case OP_IREM_UN_IMM:
2866 case OP_LOCALLOC_IMM:
2867 mono_decompose_op_imm (cfg, bb, ins);
2870 if (!s390_is_imm16 (ins->inst_imm))
2871 /* This is created by the memcpy code which ignores is_inst_imm */
2872 mono_decompose_op_imm (cfg, bb, ins);
2879 bb->max_vreg = cfg->next_vreg;
2882 /*========================= End of Function ========================*/
2884 /*------------------------------------------------------------------*/
2886 /* Name - emit_float_to_int */
2888 /* Function - Create instructions which will convert a floating */
2889 /* point value to integer. */
2891 /*------------------------------------------------------------------*/
2894 emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size, gboolean is_signed)
2896 /* sreg is a float, dreg is an integer reg. */
2898 s390_cgdbr (code, dreg, 5, sreg);
2901 s390_ltgr (code, dreg, dreg);
2903 s390_oill (code, dreg, 0x80);
2904 s390_lghi (code, s390_r0, 0xff);
2905 s390_ngr (code, dreg, s390_r0);
2908 s390_ltgr (code, dreg, dreg);
2910 s390_oill (code, dreg, 0x8000);
2911 s390_llill(code, s390_r0, 0xffff);
2912 s390_ngr (code, dreg, s390_r0);
2917 S390_SET (code, s390_r13, 0x41e0000000000000llu);
2918 s390_ldgr (code, s390_f14, s390_r13);
2919 s390_ldr (code, s390_f15, sreg);
2920 s390_cdbr (code, s390_f15, s390_f14);
2921 s390_jl (code, 0); CODEPTR (code, o[0]);
2922 S390_SET (code, s390_r13, 0x41f0000000000000llu);
2923 s390_ldgr (code, s390_f14, s390_r13);
2924 s390_sdbr (code, s390_f15, s390_f14);
2925 s390_cfdbr (code, dreg, 7, s390_f15);
2927 PTRSLOT (code, o[0]);
2928 s390_cfdbr (code, dreg, 5, sreg);
2931 s390_lghi (code, s390_r0, 0xff);
2932 s390_ngr (code, dreg, s390_r0);
2935 s390_llill(code, s390_r0, 0xffff);
2936 s390_ngr (code, dreg, s390_r0);
2943 /*========================= End of Function ========================*/
2945 /*------------------------------------------------------------------*/
2947 /* Name - gboolean_is_unsigned. */
2949 /* Function - Return TRUE if next opcode is checking for un- */
2952 /*------------------------------------------------------------------*/
2955 gboolean is_unsigned (MonoInst *next)
2958 (((next->opcode >= OP_IBNE_UN) &&
2959 (next->opcode <= OP_IBLT_UN)) ||
2960 ((next->opcode >= OP_LBNE_UN) &&
2961 (next->opcode <= OP_LBLT_UN)) ||
2962 ((next->opcode >= OP_COND_EXC_NE_UN) &&
2963 (next->opcode <= OP_COND_EXC_LT_UN)) ||
2964 ((next->opcode >= OP_COND_EXC_INE_UN) &&
2965 (next->opcode <= OP_COND_EXC_ILT_UN)) ||
2966 ((next->opcode == OP_CLT_UN) ||
2967 (next->opcode == OP_CGT_UN)) ||
2968 ((next->opcode == OP_ICLT_UN) ||
2969 (next->opcode == OP_ICGT_UN) ||
2970 (next->opcode == OP_LCLT_UN) ||
2971 (next->opcode == OP_LCGT_UN))))
2977 /*========================= End of Function ========================*/
2979 /*------------------------------------------------------------------*/
2981 /* Name - mono_arch_output_basic_block */
2983 /* Function - Perform the "real" work of emitting instructions */
2984 /* that will do the work of in the basic block. */
2986 /*------------------------------------------------------------------*/
2989 mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
2994 guint8 *code = cfg->native_code + cfg->code_len;
2995 guint last_offset = 0;
2998 /* we don't align basic blocks of loops on s390 */
3000 if (cfg->verbose_level > 2)
3001 g_print ("Basic block %d starting at offset 0x%x\n", bb->block_num, bb->native_offset);
3003 if ((cfg->prof_options & MONO_PROFILE_COVERAGE) && cfg->coverage_info) {
3004 MonoProfileCoverageInfo *cov = cfg->coverage_info;
3005 g_assert (!mono_compile_aot);
3006 cov->data [bb->dfn].cil_code = bb->cil_code;
3007 /* This is not thread save, but good enough */
3008 S390_SET (code, s390_r1, &cov->data [bb->dfn].count);
3009 s390_alsi (code, 0, s390_r1, 1);
3012 MONO_BB_FOR_EACH_INS (bb, ins) {
3013 offset = code - cfg->native_code;
3015 max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
3017 if (offset > (cfg->code_size - max_len - 16)) {
3018 cfg->code_size *= 2;
3019 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
3020 code = cfg->native_code + offset;
3023 mono_debug_record_line_number (cfg, ins, offset);
3025 switch (ins->opcode) {
3026 case OP_STOREI1_MEMBASE_IMM: {
3027 s390_lghi (code, s390_r0, ins->inst_imm);
3028 S390_LONG (code, stcy, stc, s390_r0, 0,
3029 ins->inst_destbasereg, ins->inst_offset);
3032 case OP_STOREI2_MEMBASE_IMM: {
3033 s390_lghi (code, s390_r0, ins->inst_imm);
3034 S390_LONG (code, sthy, sth, s390_r0, 0,
3035 ins->inst_destbasereg, ins->inst_offset);
3038 case OP_STOREI4_MEMBASE_IMM: {
3039 s390_lgfi (code, s390_r0, ins->inst_imm);
3040 S390_LONG (code, sty, st, s390_r0, 0,
3041 ins->inst_destbasereg, ins->inst_offset);
3044 case OP_STORE_MEMBASE_IMM:
3045 case OP_STOREI8_MEMBASE_IMM: {
3046 S390_SET (code, s390_r0, ins->inst_imm);
3047 S390_LONG (code, stg, stg, s390_r0, 0,
3048 ins->inst_destbasereg, ins->inst_offset);
3051 case OP_STOREI1_MEMBASE_REG: {
3052 S390_LONG (code, stcy, stc, ins->sreg1, 0,
3053 ins->inst_destbasereg, ins->inst_offset);
3056 case OP_STOREI2_MEMBASE_REG: {
3057 S390_LONG (code, sthy, sth, ins->sreg1, 0,
3058 ins->inst_destbasereg, ins->inst_offset);
3061 case OP_STOREI4_MEMBASE_REG: {
3062 S390_LONG (code, sty, st, ins->sreg1, 0,
3063 ins->inst_destbasereg, ins->inst_offset);
3066 case OP_STORE_MEMBASE_REG:
3067 case OP_STOREI8_MEMBASE_REG: {
3068 S390_LONG (code, stg, stg, ins->sreg1, 0,
3069 ins->inst_destbasereg, ins->inst_offset);
3073 g_assert_not_reached ();
3075 case OP_LOAD_MEMBASE:
3076 case OP_LOADI8_MEMBASE: {
3077 S390_LONG (code, lg, lg, ins->dreg, 0,
3078 ins->inst_basereg, ins->inst_offset);
3081 case OP_LOADI4_MEMBASE: {
3082 S390_LONG (code, lgf, lgf, ins->dreg, 0,
3083 ins->inst_basereg, ins->inst_offset);
3086 case OP_LOADU4_MEMBASE: {
3087 S390_LONG (code, llgf, llgf, ins->dreg, 0,
3088 ins->inst_basereg, ins->inst_offset);
3091 case OP_LOADU1_MEMBASE: {
3092 S390_LONG (code, llgc, llgc, ins->dreg, 0,
3093 ins->inst_basereg, ins->inst_offset);
3096 case OP_LOADI1_MEMBASE: {
3097 S390_LONG (code, lgb, lgb, ins->dreg, 0,
3098 ins->inst_basereg, ins->inst_offset);
3101 case OP_LOADU2_MEMBASE: {
3102 S390_LONG (code, llgh, llgh, ins->dreg, 0,
3103 ins->inst_basereg, ins->inst_offset);
3106 case OP_LOADI2_MEMBASE: {
3107 S390_LONG (code, lgh, lgh, ins->dreg, 0,
3108 ins->inst_basereg, ins->inst_offset);
3111 case OP_LCONV_TO_I1: {
3112 s390_lgbr (code, ins->dreg, ins->sreg1);
3115 case OP_LCONV_TO_I2: {
3116 s390_lghr (code, ins->dreg, ins->sreg1);
3119 case OP_LCONV_TO_U1: {
3120 s390_llgcr (code, ins->dreg, ins->sreg1);
3123 case OP_LCONV_TO_U2: {
3124 s390_llghr (code, ins->dreg, ins->sreg1);
3127 case OP_ICONV_TO_I1: {
3128 s390_lgbr (code, ins->dreg, ins->sreg1);
3131 case OP_ICONV_TO_I2: {
3132 s390_lghr (code, ins->dreg, ins->sreg1);
3135 case OP_ICONV_TO_U1: {
3136 s390_llgcr (code, ins->dreg, ins->sreg1);
3139 case OP_ICONV_TO_U2: {
3140 s390_llghr (code, ins->dreg, ins->sreg1);
3145 if (is_unsigned (ins->next))
3146 s390_clgr (code, ins->sreg1, ins->sreg2);
3148 s390_cgr (code, ins->sreg1, ins->sreg2);
3152 if (is_unsigned (ins->next))
3153 s390_clr (code, ins->sreg1, ins->sreg2);
3155 s390_cr (code, ins->sreg1, ins->sreg2);
3158 case OP_COMPARE_IMM:
3159 case OP_LCOMPARE_IMM: {
3160 S390_SET (code, s390_r0, ins->inst_imm);
3161 if (is_unsigned (ins->next))
3162 s390_clgr (code, ins->sreg1, s390_r0);
3164 s390_cgr (code, ins->sreg1, s390_r0);
3167 case OP_ICOMPARE_IMM: {
3168 S390_SET (code, s390_r0, ins->inst_imm);
3169 if (is_unsigned (ins->next))
3170 s390_clr (code, ins->sreg1, s390_r0);
3172 s390_cr (code, ins->sreg1, s390_r0);
3176 mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_ABS,
3178 S390_CALL_TEMPLATE (code, s390_r14);
3183 s390_agr (code, ins->dreg, src2);
3188 s390_agr (code, ins->dreg, src2);
3193 s390_alcgr (code, ins->dreg, src2);
3197 if (ins->dreg != ins->sreg1) {
3198 s390_lgr (code, ins->dreg, ins->sreg1);
3200 if (s390_is_imm16 (ins->inst_imm)) {
3201 s390_aghi (code, ins->dreg, ins->inst_imm);
3202 } else if (s390_is_imm32 (ins->inst_imm)) {
3203 s390_agfi (code, ins->dreg, ins->inst_imm);
3205 S390_SET (code, s390_r0, ins->inst_imm);
3206 s390_agr (code, ins->dreg, s390_r0);
3211 if (ins->dreg != ins->sreg1) {
3212 s390_lgr (code, ins->dreg, ins->sreg1);
3214 g_assert (s390_is_imm16 (ins->inst_imm));
3215 s390_aghi (code, ins->dreg, ins->inst_imm);
3219 if (ins->dreg != ins->sreg1) {
3220 s390_lgr (code, ins->dreg, ins->sreg1);
3222 if (s390_is_imm16 (ins->inst_imm)) {
3223 s390_lghi (code, s390_r0, ins->inst_imm);
3224 s390_alcgr (code, ins->dreg, s390_r0);
3226 S390_SET (code, s390_r0, ins->inst_imm);
3227 s390_alcgr (code, ins->dreg, s390_r0);
3232 case OP_S390_IADD_OVF: {
3234 s390_ar (code, ins->dreg, src2);
3235 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3236 s390_lgfr (code, ins->dreg, ins->dreg);
3239 case OP_IADD_OVF_UN:
3240 case OP_S390_IADD_OVF_UN: {
3242 s390_algr (code, ins->dreg, src2);
3243 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3244 s390_llgfr (code, ins->dreg, ins->dreg);
3247 case OP_ADD_OVF_CARRY: {
3249 s390_lghi (code, s390_r0, 0);
3250 s390_lgr (code, s390_r1, s390_r0);
3251 s390_alcgr (code, s390_r0, s390_r1);
3252 s390_agr (code, ins->dreg, src2);
3253 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3254 s390_agr (code, ins->dreg, s390_r0);
3255 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3258 case OP_ADD_OVF_UN_CARRY: {
3260 s390_alcgr (code, ins->dreg, src2);
3261 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3266 s390_sgr (code, ins->dreg, src2);
3271 s390_sgr (code, ins->dreg, src2);
3276 s390_slbgr(code, ins->dreg, src2);
3280 if (ins->dreg != ins->sreg1) {
3281 s390_lgr (code, ins->dreg, ins->sreg1);
3283 if (s390_is_imm16 (-ins->inst_imm)) {
3284 s390_aghi (code, ins->dreg, -ins->inst_imm);
3285 } else if (s390_is_imm32 (-ins->inst_imm)) {
3286 s390_slgfi (code, ins->dreg, ins->inst_imm);
3288 S390_SET (code, s390_r0, ins->inst_imm);
3289 s390_slgr (code, ins->dreg, s390_r0);
3294 if (ins->dreg != ins->sreg1) {
3295 s390_lgr (code, ins->dreg, ins->sreg1);
3297 if (s390_is_imm16 (-ins->inst_imm)) {
3298 s390_aghi (code, ins->dreg, -ins->inst_imm);
3299 } else if (s390_is_imm32 (-ins->inst_imm)) {
3300 s390_slgfi (code, ins->dreg, ins->inst_imm);
3302 S390_SET (code, s390_r0, ins->inst_imm);
3303 s390_slgr (code, ins->dreg, s390_r0);
3308 if (ins->dreg != ins->sreg1) {
3309 s390_lgr (code, ins->dreg, ins->sreg1);
3311 if (s390_is_imm16 (-ins->inst_imm)) {
3312 s390_lghi (code, s390_r0, ins->inst_imm);
3313 s390_slbgr (code, ins->dreg, s390_r0);
3315 S390_SET (code, s390_r0, ins->inst_imm);
3316 s390_slbgr(code, ins->dreg, s390_r0);
3320 case OP_SUB_OVF_CARRY: {
3322 s390_lghi (code, s390_r0, 0);
3323 s390_lgr (code, s390_r1, s390_r0);
3324 s390_slbgr (code, s390_r0, s390_r1);
3325 s390_sgr (code, ins->dreg, src2);
3326 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3327 s390_agr (code, ins->dreg, s390_r0);
3328 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3331 case OP_SUB_OVF_UN_CARRY: {
3333 s390_slbgr (code, ins->dreg, src2);
3334 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3338 if (ins->sreg1 == ins->dreg) {
3339 s390_ngr (code, ins->dreg, ins->sreg2);
3342 if (ins->sreg2 == ins->dreg) {
3343 s390_ngr (code, ins->dreg, ins->sreg1);
3346 s390_lgr (code, ins->dreg, ins->sreg1);
3347 s390_ngr (code, ins->dreg, ins->sreg2);
3353 if (ins->dreg != ins->sreg1) {
3354 s390_lgr (code, ins->dreg, ins->sreg1);
3356 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3357 s390_ngr (code, ins->dreg, s390_r0);
3361 s390_lgr (code, s390_r1, ins->sreg1);
3362 s390_dsgr (code, s390_r0, ins->sreg2);
3363 s390_lgr (code, ins->dreg, s390_r1);
3367 s390_lgr (code, s390_r1, ins->sreg1);
3368 s390_lghi (code, s390_r0, 0);
3369 s390_dlgr (code, s390_r0, ins->sreg2);
3370 s390_lgr (code, ins->dreg, s390_r1);
3374 s390_lgr (code, s390_r1, ins->sreg1);
3375 s390_dsgr (code, s390_r0, ins->sreg2);
3376 s390_lgr (code, ins->dreg, s390_r0);
3380 if (s390_is_imm16 (ins->inst_imm)) {
3381 s390_lghi (code, s390_r13, ins->inst_imm);
3383 s390_lgfi (code, s390_r13, ins->inst_imm);
3385 s390_lgr (code, s390_r0, ins->sreg1);
3386 s390_dsgr (code, s390_r0, s390_r13);
3387 s390_lgfr (code, ins->dreg, s390_r0);
3391 s390_lgr (code, s390_r1, ins->sreg1);
3392 s390_lghi (code, s390_r0, 0);
3393 s390_dlgr (code, s390_r0, ins->sreg2);
3394 s390_lgr (code, ins->dreg, s390_r0);
3398 if (ins->sreg1 == ins->dreg) {
3399 s390_ogr (code, ins->dreg, ins->sreg2);
3402 if (ins->sreg2 == ins->dreg) {
3403 s390_ogr (code, ins->dreg, ins->sreg1);
3406 s390_lgr (code, ins->dreg, ins->sreg1);
3407 s390_ogr (code, ins->dreg, ins->sreg2);
3413 if (ins->dreg != ins->sreg1) {
3414 s390_lgr (code, ins->dreg, ins->sreg1);
3416 S390_SET_MASK(code, s390_r0, ins->inst_imm);
3417 s390_ogr (code, ins->dreg, s390_r0);
3421 if (ins->sreg1 == ins->dreg) {
3422 s390_xgr (code, ins->dreg, ins->sreg2);
3425 if (ins->sreg2 == ins->dreg) {
3426 s390_xgr (code, ins->dreg, ins->sreg1);
3429 s390_lgr (code, ins->dreg, ins->sreg1);
3430 s390_xgr (code, ins->dreg, ins->sreg2);
3436 if (ins->dreg != ins->sreg1) {
3437 s390_lgr (code, ins->dreg, ins->sreg1);
3439 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3440 s390_xgr (code, ins->dreg, s390_r0);
3445 s390_sllg (code, ins->dreg, ins->dreg, src2, 0);
3450 if (ins->sreg1 != ins->dreg) {
3451 s390_lgr (code, ins->dreg, ins->sreg1);
3453 s390_sllg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3458 s390_srag (code, ins->dreg, ins->dreg, src2, 0);
3463 if (ins->sreg1 != ins->dreg) {
3464 s390_lgr (code, ins->dreg, ins->sreg1);
3466 s390_srag (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3470 case OP_LSHR_UN_IMM: {
3471 if (ins->sreg1 != ins->dreg) {
3472 s390_lgr (code, ins->dreg, ins->sreg1);
3474 s390_srlg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3479 s390_srlg (code, ins->dreg, ins->dreg, src2, 0);
3483 if (ins->sreg1 != ins->dreg) {
3484 s390_lgr (code, ins->dreg, ins->sreg1);
3486 s390_lghi (code, s390_r0, -1);
3487 s390_xgr (code, ins->dreg, s390_r0);
3491 s390_lcgr (code, ins->dreg, ins->sreg1);
3496 s390_msgr (code, ins->dreg, src2);
3501 if (ins->dreg != ins->sreg1) {
3502 s390_lgr (code, ins->dreg, ins->sreg1);
3504 if (s390_is_imm16 (ins->inst_imm)) {
3505 s390_lghi (code, s390_r13, ins->inst_imm);
3506 } else if (s390_is_imm32 (ins->inst_imm)) {
3507 s390_lgfi (code, s390_r13, ins->inst_imm);
3509 S390_SET (code, s390_r13, ins->inst_imm);
3511 s390_msgr (code, ins->dreg, s390_r13);
3516 s390_ltgr (code, s390_r1, ins->sreg1);
3517 s390_jz (code, 0); CODEPTR(code, o[0]);
3518 s390_ltgr (code, s390_r0, ins->sreg2);
3520 s390_lghi (code, s390_r1, 0);
3521 s390_j (code, 0); CODEPTR(code, o[1]);
3522 s390_xgr (code, s390_r0, s390_r1);
3523 s390_msgr (code, s390_r1, ins->sreg2);
3524 s390_xgr (code, s390_r0, s390_r1);
3525 s390_srlg (code, s390_r0, s390_r0, 0, 63);
3526 s390_ltgr (code, s390_r0, s390_r0);
3527 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3528 PTRSLOT (code, o[0]);
3529 PTRSLOT (code, o[1]);
3530 s390_lgr (code, ins->dreg, s390_r1);
3533 case OP_LMUL_OVF_UN: {
3534 s390_lghi (code, s390_r0, 0);
3535 s390_lgr (code, s390_r1, ins->sreg1);
3536 s390_mlgr (code, s390_r0, ins->sreg2);
3537 s390_ltgr (code, s390_r0, s390_r0);
3538 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3539 s390_lgr (code, ins->dreg, s390_r1);
3543 g_assert_not_reached ();
3545 s390_algr (code, ins->dreg, src2);
3550 s390_agr (code, ins->dreg, src2);
3554 g_assert_not_reached ();
3556 s390_alcgr (code, ins->dreg, src2);
3560 if (ins->dreg != ins->sreg1) {
3561 s390_lgfr (code, ins->dreg, ins->sreg1);
3563 if (s390_is_imm16 (ins->inst_imm)) {
3564 s390_aghi (code, ins->dreg, ins->inst_imm);
3566 s390_afi (code, ins->dreg, ins->inst_imm);
3571 if (ins->dreg != ins->sreg1) {
3572 s390_lgfr (code, ins->dreg, ins->sreg1);
3574 if (s390_is_imm16 (ins->inst_imm)) {
3575 s390_lghi (code, s390_r0, ins->inst_imm);
3576 s390_alcgr (code, ins->dreg, s390_r0);
3578 S390_SET (code, s390_r0, ins->inst_imm);
3579 s390_alcgr (code, ins->dreg, s390_r0);
3584 case OP_S390_LADD_OVF: {
3586 s390_agr (code, ins->dreg, src2);
3587 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3590 case OP_LADD_OVF_UN:
3591 case OP_S390_LADD_OVF_UN: {
3593 s390_algr (code, ins->dreg, src2);
3594 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3598 CHECK_SRCDST_NCOM_I;
3599 s390_slgr (code, ins->dreg, src2);
3603 CHECK_SRCDST_NCOM_I;
3604 s390_sgr (code, ins->dreg, src2);
3608 CHECK_SRCDST_NCOM_I;
3609 s390_slbgr (code, ins->dreg, src2);
3613 if (ins->dreg != ins->sreg1) {
3614 s390_lgfr (code, ins->dreg, ins->sreg1);
3616 if (s390_is_imm16 (-ins->inst_imm)) {
3617 s390_aghi (code, ins->dreg, -ins->inst_imm);
3619 s390_agfi (code, ins->dreg, -ins->inst_imm);
3624 S390_SET (code, s390_r0, ins->inst_imm);
3625 s390_slgfr (code, ins->dreg, s390_r0);
3629 case OP_S390_ISUB_OVF: {
3631 s390_sr (code, ins->dreg, src2);
3632 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3633 s390_lgfr (code, ins->dreg, ins->dreg);
3636 case OP_ISUB_OVF_UN:
3637 case OP_S390_ISUB_OVF_UN: {
3639 s390_slr (code, ins->dreg, src2);
3640 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3641 s390_llgfr(code, ins->dreg, ins->dreg);
3645 case OP_S390_LSUB_OVF: {
3647 s390_sgr (code, ins->dreg, src2);
3648 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3651 case OP_LSUB_OVF_UN:
3652 case OP_S390_LSUB_OVF_UN: {
3654 s390_slgr (code, ins->dreg, src2);
3655 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3659 CHECK_SRCDST_NCOM_I;
3660 s390_ngr (code, ins->dreg, src2);
3664 if (ins->dreg != ins->sreg1) {
3665 s390_lgfr (code, ins->dreg, ins->sreg1);
3667 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3668 s390_ngr (code, ins->dreg, s390_r0);
3672 s390_lgfr (code, s390_r0, ins->sreg1);
3673 s390_srda (code, s390_r0, 0, 32);
3674 s390_dr (code, s390_r0, ins->sreg2);
3675 s390_lgfr (code, ins->dreg, s390_r1);
3679 s390_lgfr (code, s390_r0, ins->sreg1);
3680 s390_srdl (code, s390_r0, 0, 32);
3681 s390_dlr (code, s390_r0, ins->sreg2);
3682 s390_lgfr (code, ins->dreg, s390_r1);
3686 if (s390_is_imm16 (ins->inst_imm)) {
3687 s390_lghi (code, s390_r13, ins->inst_imm);
3689 s390_lgfi (code, s390_r13, ins->inst_imm);
3691 s390_lgfr (code, s390_r0, ins->sreg1);
3692 s390_srda (code, s390_r0, 0, 32);
3693 s390_dr (code, s390_r0, ins->sreg2);
3694 s390_lgfr (code, ins->dreg, s390_r1);
3698 s390_lgfr (code, s390_r0, ins->sreg1);
3699 s390_srda (code, s390_r0, 0, 32);
3700 s390_dr (code, s390_r0, ins->sreg2);
3701 s390_lgfr (code, ins->dreg, s390_r0);
3704 s390_lgfr (code, s390_r0, ins->sreg1);
3705 s390_srdl (code, s390_r0, 0, 32);
3706 s390_dlr (code, s390_r0, ins->sreg2);
3707 s390_lgfr (code, ins->dreg, s390_r0);
3711 if (s390_is_imm16 (ins->inst_imm)) {
3712 s390_lghi (code, s390_r13, ins->inst_imm);
3714 s390_lgfi (code, s390_r13, ins->inst_imm);
3716 s390_lgfr (code, s390_r0, ins->sreg1);
3717 s390_srda (code, s390_r0, 0, 32);
3718 s390_dr (code, s390_r0, ins->sreg2);
3719 s390_lgfr (code, ins->dreg, s390_r0);
3724 s390_ogr (code, ins->dreg, src2);
3728 if (ins->dreg != ins->sreg1) {
3729 s390_lgfr (code, ins->dreg, ins->sreg1);
3731 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3732 s390_ogr (code, ins->dreg, s390_r0);
3737 s390_xgr (code, ins->dreg, src2);
3741 if (ins->dreg != ins->sreg1) {
3742 s390_lgfr (code, ins->dreg, ins->sreg1);
3744 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3745 s390_xgr (code, ins->dreg, s390_r0);
3750 s390_sll (code, ins->dreg, src2, 0);
3754 if (ins->sreg1 != ins->dreg) {
3755 s390_lgfr (code, ins->dreg, ins->sreg1);
3757 s390_sll (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3762 s390_sra (code, ins->dreg, src2, 0);
3766 if (ins->sreg1 != ins->dreg) {
3767 s390_lgfr (code, ins->dreg, ins->sreg1);
3769 s390_sra (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3772 case OP_ISHR_UN_IMM: {
3773 if (ins->sreg1 != ins->dreg) {
3774 s390_lgfr (code, ins->dreg, ins->sreg1);
3776 s390_srl (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3781 s390_srl (code, ins->dreg, src2, 0);
3785 if (ins->sreg1 != ins->dreg) {
3786 s390_lgfr (code, ins->dreg, ins->sreg1);
3788 s390_lghi (code, s390_r0, -1);
3789 s390_xgr (code, ins->dreg, s390_r0);
3793 s390_lcgr (code, ins->dreg, ins->sreg1);
3798 s390_msr (code, ins->dreg, src2);
3802 if (ins->dreg != ins->sreg1) {
3803 s390_lgfr (code, ins->dreg, ins->sreg1);
3805 if (s390_is_imm16 (ins->inst_imm)) {
3806 s390_lghi (code, s390_r0, ins->inst_imm);
3808 s390_lgfi (code, s390_r0, ins->inst_imm);
3810 s390_msr (code, ins->dreg, s390_r0);
3815 s390_ltr (code, s390_r1, ins->sreg1);
3816 s390_jz (code, 0); CODEPTR(code, o[0]);
3817 s390_ltr (code, s390_r0, ins->sreg2);
3819 s390_lhi (code, s390_r1, 0);
3820 s390_j (code, 0); CODEPTR(code, o[1]);
3821 s390_xr (code, s390_r0, s390_r1);
3822 s390_msr (code, s390_r1, ins->sreg2);
3823 s390_xr (code, s390_r0, s390_r1);
3824 s390_srl (code, s390_r0, 0, 31);
3825 s390_ltr (code, s390_r0, s390_r0);
3826 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3827 PTRSLOT (code, o[0]);
3828 PTRSLOT (code, o[1]);
3829 s390_lgfr (code, ins->dreg, s390_r1);
3832 case OP_IMUL_OVF_UN: {
3833 s390_lhi (code, s390_r0, 0);
3834 s390_lr (code, s390_r1, ins->sreg1);
3835 s390_mlr (code, s390_r0, ins->sreg2);
3836 s390_ltr (code, s390_r0, s390_r0);
3837 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3838 s390_lgfr (code, ins->dreg, s390_r1);
3843 S390_SET (code, ins->dreg, ins->inst_c0);
3847 mono_add_patch_info (cfg, code - cfg->native_code,
3848 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3849 S390_LOAD_TEMPLATE (code, ins->dreg);
3852 case OP_JUMP_TABLE: {
3853 mono_add_patch_info (cfg, code - cfg->native_code,
3854 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3855 S390_LOAD_TEMPLATE (code, ins->dreg);
3859 if (ins->dreg != ins->sreg1) {
3860 s390_lgr (code, ins->dreg, ins->sreg1);
3864 case OP_LCONV_TO_I8:
3866 s390_lgfr (code, ins->dreg, ins->sreg1);
3868 case OP_LCONV_TO_I4:
3869 s390_lgfr (code, ins->dreg, ins->sreg1);
3872 case OP_LCONV_TO_U8:
3873 case OP_LCONV_TO_U4:
3875 s390_llgfr (code, ins->dreg, ins->sreg1);
3877 case OP_LCONV_TO_OVF_U4:
3878 S390_SET (code, s390_r0, 4294967295);
3879 s390_clgr (code, ins->sreg1, s390_r0);
3880 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3881 s390_ltgr (code, ins->sreg1, ins->sreg1);
3882 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3883 s390_llgfr(code, ins->dreg, ins->sreg1);
3885 case OP_LCONV_TO_OVF_I4_UN:
3886 S390_SET (code, s390_r0, 2147483647);
3887 s390_cgr (code, ins->sreg1, s390_r0);
3888 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3889 s390_ltgr (code, ins->sreg1, ins->sreg1);
3890 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3891 s390_lgfr (code, ins->dreg, ins->sreg1);
3894 if (ins->dreg != ins->sreg1) {
3895 s390_ldr (code, ins->dreg, ins->sreg1);
3898 case OP_MOVE_F_TO_I8:
3899 s390_lgdr (code, ins->dreg, ins->sreg1);
3901 case OP_MOVE_I8_TO_F:
3902 s390_ldgr (code, ins->dreg, ins->sreg1);
3904 case OP_MOVE_F_TO_I4:
3905 s390_ledbr (code, s390_f0, ins->sreg1);
3906 s390_lgdr (code, ins->dreg, s390_f0);
3907 s390_srag (code, ins->dreg, ins->dreg, 0, 32);
3909 case OP_MOVE_I4_TO_F:
3910 s390_slag (code, s390_r0, ins->sreg1, 0, 32);
3911 s390_ldgr (code, ins->dreg, s390_r0);
3912 s390_ldebr (code, ins->dreg, ins->dreg);
3914 case OP_FCONV_TO_R4:
3915 s390_ledbr (code, ins->dreg, ins->sreg1);
3916 s390_ldebr (code, ins->dreg, ins->dreg);
3918 case OP_S390_SETF4RET:
3919 s390_ledbr (code, ins->dreg, ins->sreg1);
3922 if (s390_is_imm16 (ins->inst_offset)) {
3923 s390_lghi (code, s390_r13, ins->inst_offset);
3924 } else if (s390_is_imm32 (ins->inst_offset)) {
3925 s390_lgfi (code, s390_r13, ins->inst_offset);
3927 S390_SET (code, s390_r13, ins->inst_offset);
3929 s390_ear (code, s390_r1, 0);
3930 s390_sllg(code, s390_r1, s390_r1, 0, 32);
3931 s390_ear (code, s390_r1, 1);
3932 s390_lg (code, ins->dreg, s390_r13, s390_r1, 0);
3936 if (s390_is_imm16 (ins->inst_offset)) {
3937 s390_lghi (code, s390_r13, ins->inst_offset);
3938 } else if (s390_is_imm32 (ins->inst_offset)) {
3939 s390_lgfi (code, s390_r13, ins->inst_offset);
3941 S390_SET (code, s390_r13, ins->inst_offset);
3943 s390_ear (code, s390_r1, 0);
3944 s390_sllg(code, s390_r1, s390_r1, 0, 32);
3945 s390_ear (code, s390_r1, 1);
3946 s390_stg (code, ins->sreg1, s390_r13, s390_r1, 0);
3950 if (cfg->method->save_lmf)
3951 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
3953 if (cfg->flags & MONO_CFG_HAS_TAIL) {
3954 code = emit_load_volatile_arguments (code, cfg);
3957 code = backUpStackPtr(cfg, code);
3958 s390_lg (code, s390_r14, 0, cfg->frame_reg, S390_RET_ADDR_OFFSET);
3959 mono_add_patch_info (cfg, code - cfg->native_code,
3960 MONO_PATCH_INFO_METHOD_JUMP,
3962 s390_jcl (code, S390_CC_UN, 0);
3965 case OP_CHECK_THIS: {
3966 /* ensure ins->sreg1 is not NULL */
3967 s390_lg (code, s390_r0, 0, ins->sreg1, 0);
3968 s390_ltgr (code, s390_r0, s390_r0);
3969 // EMIT_COND_SYSTEM_EXCEPTION (S390_CC_ZR, "NullReferenceException");
3973 int offset = cfg->sig_cookie + cfg->stack_usage;
3975 if (s390_is_imm16 (offset)) {
3976 s390_lghi (code, s390_r0, offset);
3977 } else if (s390_is_imm32 (offset)) {
3978 s390_lgfi (code, s390_r0, offset);
3980 S390_SET (code, s390_r0, offset);
3982 s390_agr (code, s390_r0, cfg->frame_reg);
3983 s390_stg (code, s390_r0, 0, ins->sreg1, 0);
3987 call = (MonoCallInst*)ins;
3988 if (ins->flags & MONO_INST_HAS_METHOD)
3989 mono_add_patch_info (cfg, code-cfg->native_code,
3990 MONO_PATCH_INFO_METHOD,
3993 mono_add_patch_info (cfg, code-cfg->native_code,
3994 MONO_PATCH_INFO_ABS,
3996 S390_CALL_TEMPLATE (code, s390_r14);
3997 if (call->signature->ret->type == MONO_TYPE_R4)
3998 s390_ldebr (code, s390_f0, s390_f0);
4006 call = (MonoCallInst*)ins;
4007 if (ins->flags & MONO_INST_HAS_METHOD)
4008 mono_add_patch_info (cfg, code-cfg->native_code,
4009 MONO_PATCH_INFO_METHOD,
4012 mono_add_patch_info (cfg, code-cfg->native_code,
4013 MONO_PATCH_INFO_ABS,
4015 S390_CALL_TEMPLATE (code, s390_r14);
4018 case OP_FCALL_REG: {
4019 call = (MonoCallInst*)ins;
4020 s390_lgr (code, s390_r1, ins->sreg1);
4021 s390_basr (code, s390_r14, s390_r1);
4022 if (call->signature->ret->type == MONO_TYPE_R4)
4023 s390_ldebr (code, s390_f0, s390_f0);
4029 case OP_VOIDCALL_REG:
4031 s390_lgr (code, s390_r1, ins->sreg1);
4032 s390_basr (code, s390_r14, s390_r1);
4035 case OP_FCALL_MEMBASE: {
4036 call = (MonoCallInst*)ins;
4037 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4038 s390_basr (code, s390_r14, s390_r1);
4039 if (call->signature->ret->type == MONO_TYPE_R4)
4040 s390_ldebr (code, s390_f0, s390_f0);
4043 case OP_LCALL_MEMBASE:
4044 case OP_VCALL_MEMBASE:
4045 case OP_VCALL2_MEMBASE:
4046 case OP_VOIDCALL_MEMBASE:
4047 case OP_CALL_MEMBASE: {
4048 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4049 s390_basr (code, s390_r14, s390_r1);
4056 if (cfg->param_area == 0)
4057 alloca_skip = S390_MINIMAL_STACK_SIZE;
4059 alloca_skip = cfg->param_area;
4061 area_offset = S390_ALIGN(alloca_skip, S390_STACK_ALIGNMENT);
4062 s390_lgr (code, s390_r1, ins->sreg1);
4063 if (ins->flags & MONO_INST_INIT)
4064 s390_lgr (code, s390_r0, ins->sreg1);
4065 s390_aghi (code, s390_r1, 14);
4066 s390_srlg (code, s390_r1, s390_r1, 0, 3);
4067 s390_sllg (code, s390_r1, s390_r1, 0, 3);
4068 if (cfg->method->save_lmf) {
4069 /*----------------------------------*/
4070 /* we have to adjust lmf ebp value */
4071 /*----------------------------------*/
4072 int lmfOffset = cfg->stack_usage - sizeof(MonoLMF);
4074 s390_lgr (code, s390_r13, cfg->frame_reg);
4075 if (s390_is_imm16(lmfOffset)) {
4076 s390_aghi (code, s390_r13, lmfOffset);
4077 } else if (s390_is_imm32(lmfOffset)) {
4078 s390_agfi (code, s390_r13, lmfOffset);
4080 S390_SET (code, s390_r13, lmfOffset);
4082 s390_lgr (code, s390_r14, STK_BASE);
4083 s390_sgr (code, s390_r14, s390_r1);
4084 s390_stg (code, s390_r14, 0, s390_r13,
4085 G_STRUCT_OFFSET(MonoLMF, ebp));
4087 s390_lg (code, s390_r13, 0, STK_BASE, 0);
4088 s390_sgr (code, STK_BASE, s390_r1);
4089 s390_stg (code, s390_r13, 0, STK_BASE, 0);
4090 s390_la (code, ins->dreg, 0, STK_BASE, area_offset);
4091 s390_srlg (code, ins->dreg, ins->dreg, 0, 3);
4092 s390_sllg (code, ins->dreg, ins->dreg, 0, 3);
4093 if (ins->flags & MONO_INST_INIT) {
4094 s390_lgr (code, s390_r1, s390_r0);
4095 s390_lgr (code, s390_r0, ins->dreg);
4096 s390_lgr (code, s390_r14, s390_r12);
4097 s390_lghi (code, s390_r13, 0);
4098 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4100 s390_lgr (code, s390_r12, s390_r14);
4105 s390_lgr (code, s390_r2, ins->sreg1);
4106 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4107 (gpointer) "mono_arch_throw_exception");
4108 S390_CALL_TEMPLATE(code, s390_r14);
4112 s390_lgr (code, s390_r2, ins->sreg1);
4113 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4114 (gpointer) "mono_arch_rethrow_exception");
4115 S390_CALL_TEMPLATE(code, s390_r14);
4118 case OP_START_HANDLER: {
4119 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4121 S390_LONG (code, stg, stg, s390_r14, 0,
4122 spvar->inst_basereg,
4123 spvar->inst_offset);
4126 case OP_ENDFILTER: {
4127 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4129 if (ins->sreg1 != s390_r2)
4130 s390_lgr(code, s390_r2, ins->sreg1);
4131 S390_LONG (code, lg, lg, s390_r14, 0,
4132 spvar->inst_basereg,
4133 spvar->inst_offset);
4134 s390_br (code, s390_r14);
4137 case OP_ENDFINALLY: {
4138 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4140 S390_LONG (code, lg, lg, s390_r14, 0,
4141 spvar->inst_basereg,
4142 spvar->inst_offset);
4143 s390_br (code, s390_r14);
4146 case OP_CALL_HANDLER: {
4147 mono_add_patch_info (cfg, code-cfg->native_code,
4148 MONO_PATCH_INFO_BB, ins->inst_target_bb);
4149 s390_brasl (code, s390_r14, 0);
4150 mono_cfg_add_try_hole (cfg, ins->inst_eh_block, code, bb);
4154 ins->inst_c0 = code - cfg->native_code;
4157 case OP_RELAXED_NOP:
4160 case OP_DUMMY_STORE:
4161 case OP_NOT_REACHED:
4165 case OP_IL_SEQ_POINT:
4166 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4168 case OP_SEQ_POINT: {
4171 if (cfg->compile_aot)
4175 * Read from the single stepping trigger page. This will cause a
4176 * SIGSEGV when single stepping is enabled.
4177 * We do this _before_ the breakpoint, so single stepping after
4178 * a breakpoint is hit will step to the next IL offset.
4180 if (ins->flags & MONO_INST_SINGLE_STEP_LOC) {
4181 breakpointCode.pTrigger = ss_trigger_page;
4182 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
4183 code += BREAKPOINT_SIZE;
4186 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4189 * A placeholder for a possible breakpoint inserted by
4190 * mono_arch_set_breakpoint ().
4192 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); ++i)
4196 * Add an additional nop so skipping the bp doesn't cause the ip to point
4197 * to another IL offset.
4203 case OP_GENERIC_CLASS_INIT: {
4204 static int byte_offset = -1;
4205 static guint8 bitmask;
4208 g_assert (ins->sreg1 == S390_FIRST_ARG_REG);
4210 if (byte_offset < 0)
4211 mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);
4213 s390_tm (code, ins->sreg1, byte_offset, bitmask);
4214 s390_jo (code, 0); CODEPTR(code, jump);
4216 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4217 "mono_generic_class_init");
4218 S390_CALL_TEMPLATE(code, s390_r14);
4220 PTRSLOT (code, jump);
4222 ins->flags |= MONO_INST_GC_CALLSITE;
4223 ins->backend.pc_offset = code - cfg->native_code;
4227 EMIT_UNCOND_BRANCH(ins);
4230 s390_br (code, ins->sreg1);
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);
4252 s390_lghi(code, ins->dreg, 1);
4254 s390_lghi(code, ins->dreg, 0);
4260 s390_lghi(code, ins->dreg, 1);
4262 s390_lghi(code, ins->dreg, 0);
4268 s390_lghi(code, ins->dreg, 1);
4270 s390_lghi(code, ins->dreg, 0);
4273 case OP_COND_EXC_EQ:
4274 case OP_COND_EXC_IEQ:
4275 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_EQ, ins->inst_p1);
4277 case OP_COND_EXC_NE_UN:
4278 case OP_COND_EXC_INE_UN:
4279 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NE, ins->inst_p1);
4281 case OP_COND_EXC_LT:
4282 case OP_COND_EXC_ILT:
4283 case OP_COND_EXC_LT_UN:
4284 case OP_COND_EXC_ILT_UN:
4285 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, ins->inst_p1);
4287 case OP_COND_EXC_GT:
4288 case OP_COND_EXC_IGT:
4289 case OP_COND_EXC_GT_UN:
4290 case OP_COND_EXC_IGT_UN:
4291 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, ins->inst_p1);
4293 case OP_COND_EXC_GE:
4294 case OP_COND_EXC_IGE:
4295 case OP_COND_EXC_GE_UN:
4296 case OP_COND_EXC_IGE_UN:
4297 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GE, ins->inst_p1);
4299 case OP_COND_EXC_LE:
4300 case OP_COND_EXC_ILE:
4301 case OP_COND_EXC_LE_UN:
4302 case OP_COND_EXC_ILE_UN:
4303 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LE, ins->inst_p1);
4305 case OP_COND_EXC_OV:
4306 case OP_COND_EXC_IOV:
4307 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, ins->inst_p1);
4309 case OP_COND_EXC_NO:
4310 case OP_COND_EXC_INO:
4311 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NO, ins->inst_p1);
4314 case OP_COND_EXC_IC:
4315 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, ins->inst_p1);
4317 case OP_COND_EXC_NC:
4318 case OP_COND_EXC_INC:
4319 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, ins->inst_p1);
4323 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4327 EMIT_COND_BRANCH (ins, S390_CC_NE);
4333 EMIT_COND_BRANCH (ins, S390_CC_LT);
4339 EMIT_COND_BRANCH (ins, S390_CC_GT);
4345 EMIT_COND_BRANCH (ins, S390_CC_GE);
4351 EMIT_COND_BRANCH (ins, S390_CC_LE);
4354 /* floating point opcodes */
4356 if (*((double *) ins->inst_p0) == 0) {
4357 s390_lzdr (code, ins->dreg);
4359 S390_SET (code, s390_r13, ins->inst_p0);
4360 s390_ld (code, ins->dreg, 0, s390_r13, 0);
4365 if (*((float *) ins->inst_p0) == 0) {
4366 s390_lzdr (code, ins->dreg);
4368 S390_SET (code, s390_r13, ins->inst_p0);
4369 s390_ldeb (code, ins->dreg, 0, s390_r13, 0);
4373 case OP_STORER8_MEMBASE_REG: {
4374 S390_LONG (code, stdy, std, ins->sreg1, 0,
4375 ins->inst_destbasereg, ins->inst_offset);
4378 case OP_LOADR8_MEMBASE: {
4379 S390_LONG (code, ldy, ld, ins->dreg, 0,
4380 ins->inst_basereg, ins->inst_offset);
4383 case OP_STORER4_MEMBASE_REG: {
4384 s390_ledbr (code, s390_f15, ins->sreg1);
4385 S390_LONG (code, stey, ste, s390_f15, 0,
4386 ins->inst_destbasereg, ins->inst_offset);
4389 case OP_LOADR4_MEMBASE: {
4390 S390_LONG (code, ley, le, s390_f15, 0,
4391 ins->inst_basereg, ins->inst_offset);
4392 s390_ldebr (code, ins->dreg, s390_f15);
4395 case OP_ICONV_TO_R_UN: {
4396 if (mono_hwcap_s390x_has_fpe) {
4397 s390_cdlfbr (code, ins->dreg, 5, ins->sreg1, 0);
4399 s390_llgfr (code, s390_r0, ins->sreg1);
4400 s390_cdgbr (code, ins->dreg, s390_r0);
4404 case OP_LCONV_TO_R_UN: {
4405 if (mono_hwcap_s390x_has_fpe) {
4406 s390_cdlgbr (code, ins->dreg, 5, ins->sreg1, 0);
4409 s390_cxgbr (code, s390_f12, ins->sreg1);
4410 s390_ltgr (code, ins->sreg1, ins->sreg1);
4411 s390_jnl (code, 0); CODEPTR(code, jump);
4412 S390_SET (code, s390_r13, 0x403f000000000000llu);
4413 s390_lgdr (code, s390_f13, s390_r13);
4414 s390_lzdr (code, s390_f15);
4415 s390_axbr (code, s390_f12, s390_f13);
4416 PTRSLOT(code, jump);
4417 s390_ldxbr (code, s390_f13, s390_f12);
4418 s390_ldr (code, ins->dreg, s390_f13);
4422 case OP_LCONV_TO_R4:
4423 case OP_ICONV_TO_R4: {
4424 s390_cegbr (code, ins->dreg, ins->sreg1);
4425 s390_ldebr (code, ins->dreg, ins->dreg);
4428 case OP_LCONV_TO_R8:
4429 case OP_ICONV_TO_R8: {
4430 s390_cdgbr (code, ins->dreg, ins->sreg1);
4433 case OP_FCONV_TO_I1:
4434 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4435 s390_ltgr (code, ins->dreg, ins->dreg);
4437 s390_oill (code, ins->dreg, 0x80);
4438 s390_lghi (code, s390_r0, 0xff);
4439 s390_ngr (code, ins->dreg, s390_r0);
4441 case OP_FCONV_TO_U1:
4442 if (mono_hwcap_s390x_has_fpe) {
4443 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4444 s390_lghi (code, s390_r0, 0xff);
4445 s390_ngr (code, ins->dreg, s390_r0);
4447 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 1, FALSE);
4450 case OP_FCONV_TO_I2:
4451 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4452 s390_ltgr (code, ins->dreg, ins->dreg);
4454 s390_oill (code, ins->dreg, 0x8000);
4455 s390_llill (code, s390_r0, 0xffff);
4456 s390_ngr (code, ins->dreg, s390_r0);
4458 case OP_FCONV_TO_U2:
4459 if (mono_hwcap_s390x_has_fpe) {
4460 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4461 s390_llill (code, s390_r0, 0xffff);
4462 s390_ngr (code, ins->dreg, s390_r0);
4464 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 2, FALSE);
4467 case OP_FCONV_TO_I4:
4469 s390_cfdbr (code, ins->dreg, 5, ins->sreg1);
4471 case OP_FCONV_TO_U4:
4473 if (mono_hwcap_s390x_has_fpe) {
4474 s390_clfdbr (code, ins->dreg, 5, ins->sreg1, 0);
4476 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE);
4479 case OP_FCONV_TO_I8:
4480 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4482 case OP_FCONV_TO_U8:
4483 if (mono_hwcap_s390x_has_fpe) {
4484 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4486 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 8, FALSE);
4489 case OP_LCONV_TO_OVF_I: {
4490 /* Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000 */
4492 s390_ltgr (code, ins->sreg2, ins->sreg2);
4493 s390_jnl (code, 0); CODEPTR(code, o[0]);
4494 s390_ltgr (code, ins->sreg1, ins->sreg1);
4495 s390_jnl (code, 0); CODEPTR(code, o[1]);
4496 s390_lhi (code, s390_r13, -1);
4497 s390_cgr (code, ins->sreg1, s390_r13);
4498 s390_jnz (code, 0); CODEPTR(code, o[2]);
4499 if (ins->dreg != ins->sreg2)
4500 s390_lgr (code, ins->dreg, ins->sreg2);
4501 s390_j (code, 0); CODEPTR(code, o[3]);
4502 PTRSLOT(code, o[0]);
4503 s390_jz (code, 0); CODEPTR(code, o[4]);
4504 PTRSLOT(code, o[1]);
4505 PTRSLOT(code, o[2]);
4506 mono_add_patch_info (cfg, code - cfg->native_code,
4507 MONO_PATCH_INFO_EXC, "OverflowException");
4508 s390_brasl (code, s390_r14, 0);
4509 PTRSLOT(code, o[3]);
4510 PTRSLOT(code, o[4]);
4514 s390_lpdbr (code, ins->dreg, ins->sreg1);
4518 s390_sqdbr (code, ins->dreg, ins->sreg1);
4523 s390_adbr (code, ins->dreg, src2);
4527 CHECK_SRCDST_NCOM_F;
4528 s390_sdbr (code, ins->dreg, src2);
4533 s390_mdbr (code, ins->dreg, src2);
4537 CHECK_SRCDST_NCOM_F;
4538 s390_ddbr (code, ins->dreg, src2);
4542 s390_lcdbr (code, ins->dreg, ins->sreg1);
4546 CHECK_SRCDST_NCOM_F;
4547 s390_didbr (code, ins->dreg, src2, 5, s390_f15);
4551 s390_cdbr (code, ins->sreg1, ins->sreg2);
4555 s390_cdbr (code, ins->sreg1, ins->sreg2);
4556 s390_lghi (code, ins->dreg, 1);
4558 s390_lghi (code, ins->dreg, 0);
4562 s390_cdbr (code, ins->sreg1, ins->sreg2);
4563 s390_lghi (code, ins->dreg, 1);
4565 s390_lghi (code, ins->dreg, 0);
4569 s390_cdbr (code, ins->sreg1, ins->sreg2);
4570 s390_lghi (code, ins->dreg, 1);
4572 s390_lghi (code, ins->dreg, 0);
4576 s390_cdbr (code, ins->sreg1, ins->sreg2);
4577 s390_lghi (code, ins->dreg, 1);
4579 s390_lghi (code, ins->dreg, 0);
4583 s390_cdbr (code, ins->sreg1, ins->sreg2);
4584 s390_lghi (code, ins->dreg, 1);
4586 s390_lghi (code, ins->dreg, 0);
4591 s390_jo (code, 0); CODEPTR(code, o);
4592 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4597 EMIT_COND_BRANCH (ins, S390_CC_NE|S390_CC_OV);
4601 s390_jo (code, 0); CODEPTR(code, o);
4602 EMIT_COND_BRANCH (ins, S390_CC_LT);
4607 EMIT_COND_BRANCH (ins, S390_CC_LT|S390_CC_OV);
4611 s390_jo (code, 0); CODEPTR(code, o);
4612 EMIT_COND_BRANCH (ins, S390_CC_GT);
4617 EMIT_COND_BRANCH (ins, S390_CC_GT|S390_CC_OV);
4621 s390_jo (code, 0); CODEPTR(code, o);
4622 EMIT_COND_BRANCH (ins, S390_CC_GE);
4627 EMIT_COND_BRANCH (ins, S390_CC_GE|S390_CC_OV);
4631 s390_jo (code, 0); CODEPTR(code, o);
4632 EMIT_COND_BRANCH (ins, S390_CC_LE);
4637 EMIT_COND_BRANCH (ins, S390_CC_LE|S390_CC_OV);
4641 s390_lhi (code, s390_r13, 0x7f);
4642 s390_tcdb (code, ins->sreg1, 0, s390_r13, 0);
4643 s390_jz (code, 0); CODEPTR(code, o);
4644 mono_add_patch_info (cfg, code - cfg->native_code,
4645 MONO_PATCH_INFO_EXC, "OverflowException");
4646 s390_brasl (code, s390_r14,0);
4650 case OP_S390_MOVE: {
4651 if (ins->backend.size > 0) {
4652 if (ins->backend.size <= 256) {
4653 s390_mvc (code, ins->backend.size, ins->dreg,
4654 ins->inst_offset, ins->sreg1, ins->inst_imm);
4656 s390_lgr (code, s390_r0, ins->dreg);
4657 if (ins->inst_offset > 0) {
4658 if (s390_is_imm16 (ins->inst_offset)) {
4659 s390_aghi (code, s390_r0, ins->inst_offset);
4660 } else if (s390_is_imm32 (ins->inst_offset)) {
4661 s390_agfi (code, s390_r0, ins->inst_offset);
4663 S390_SET (code, s390_r13, ins->inst_offset);
4664 s390_agr (code, s390_r0, s390_r13);
4667 s390_lgr (code, s390_r12, ins->sreg1);
4668 if (ins->inst_imm > 0) {
4669 if (s390_is_imm16 (ins->inst_imm)) {
4670 s390_aghi (code, s390_r12, ins->inst_imm);
4671 } else if (s390_is_imm32 (ins->inst_imm)) {
4672 s390_agfi (code, s390_r12, ins->inst_imm);
4674 S390_SET (code, s390_r13, ins->inst_imm);
4675 s390_agr (code, s390_r12, s390_r13);
4678 if (s390_is_imm16 (ins->backend.size)) {
4679 s390_lghi (code, s390_r1, ins->backend.size);
4680 } else if (s390_is_imm32 (ins->inst_offset)) {
4681 s390_agfi (code, s390_r1, ins->backend.size);
4683 S390_SET (code, s390_r13, ins->backend.size);
4684 s390_agr (code, s390_r1, s390_r13);
4686 s390_lgr (code, s390_r13, s390_r1);
4687 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4693 case OP_ATOMIC_ADD_I8: {
4694 s390_lgr (code, s390_r1, ins->sreg2);
4695 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4696 s390_agr (code, s390_r1, s390_r0);
4697 s390_csg (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4698 s390_jnz (code, -10);
4699 s390_lgr (code, ins->dreg, s390_r1);
4702 case OP_ATOMIC_EXCHANGE_I8: {
4703 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4704 s390_csg (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
4705 s390_jnz (code, -6);
4706 s390_lgr (code, ins->dreg, s390_r0);
4709 case OP_ATOMIC_ADD_I4: {
4710 s390_lgfr(code, s390_r1, ins->sreg2);
4711 s390_lgf (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4712 s390_agr (code, s390_r1, s390_r0);
4713 s390_cs (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4714 s390_jnz (code, -9);
4715 s390_lgfr(code, ins->dreg, s390_r1);
4718 case OP_ATOMIC_EXCHANGE_I4: {
4719 s390_l (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4720 s390_cs (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
4721 s390_jnz (code, -4);
4722 s390_lgfr(code, ins->dreg, s390_r0);
4725 case OP_S390_BKCHAIN: {
4726 s390_lgr (code, ins->dreg, ins->sreg1);
4727 if (s390_is_imm16 (cfg->stack_offset)) {
4728 s390_aghi (code, ins->dreg, cfg->stack_offset);
4729 } else if (s390_is_imm32 (cfg->stack_offset)) {
4730 s390_agfi (code, ins->dreg, cfg->stack_offset);
4732 S390_SET (code, s390_r13, cfg->stack_offset);
4733 s390_agr (code, ins->dreg, s390_r13);
4737 case OP_MEMORY_BARRIER:
4740 case OP_GC_SAFE_POINT: {
4743 g_assert (mono_threads_is_coop_enabled ());
4745 s390_chi (code, ins->sreg1, 1);
4746 s390_je (code, 0); CODEPTR(code, br);
4747 mono_add_patch_info (cfg, code- cfg->native_code, MONO_PATCH_INFO_ABS,
4748 mono_threads_state_poll);
4749 S390_CALL_TEMPLATE (code, s390_r14);
4753 case OP_GC_LIVENESS_DEF:
4754 case OP_GC_LIVENESS_USE:
4755 case OP_GC_PARAM_SLOT_LIVENESS_DEF:
4756 ins->backend.pc_offset = code - cfg->native_code;
4758 case OP_GC_SPILL_SLOT_LIVENESS_DEF:
4759 ins->backend.pc_offset = code - cfg->native_code;
4760 bb->spill_slot_defs = g_slist_prepend_mempool (cfg->mempool, bb->spill_slot_defs, ins);
4762 #ifdef MONO_ARCH_SIMD_INTRINSICS
4764 s390x_addps (code, ins->sreg1, ins->sreg2);
4767 s390x_divps (code, ins->sreg1, ins->sreg2);
4770 s390x_mulps (code, ins->sreg1, ins->sreg2);
4773 s390x_subps (code, ins->sreg1, ins->sreg2);
4776 s390x_maxps (code, ins->sreg1, ins->sreg2);
4779 s390x_minps (code, ins->sreg1, ins->sreg2);
4782 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
4783 s390x_cmpps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4786 s390x_andps (code, ins->sreg1, ins->sreg2);
4789 s390x_andnps (code, ins->sreg1, ins->sreg2);
4792 s390x_orps (code, ins->sreg1, ins->sreg2);
4795 s390x_xorps (code, ins->sreg1, ins->sreg2);
4798 s390x_sqrtps (code, ins->dreg, ins->sreg1);
4801 s390x_rsqrtps (code, ins->dreg, ins->sreg1);
4804 s390x_rcpps (code, ins->dreg, ins->sreg1);
4807 s390x_addsubps (code, ins->sreg1, ins->sreg2);
4810 s390x_haddps (code, ins->sreg1, ins->sreg2);
4813 s390x_hsubps (code, ins->sreg1, ins->sreg2);
4816 s390x_movshdup (code, ins->dreg, ins->sreg1);
4819 s390x_movsldup (code, ins->dreg, ins->sreg1);
4822 case OP_PSHUFLEW_HIGH:
4823 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4824 s390x_pshufhw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4826 case OP_PSHUFLEW_LOW:
4827 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4828 s390x_pshuflw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4831 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4832 s390x_pshufd_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4835 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4836 s390x_shufps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4839 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0x3);
4840 s390x_shufpd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4844 s390x_addpd (code, ins->sreg1, ins->sreg2);
4847 s390x_divpd (code, ins->sreg1, ins->sreg2);
4850 s390x_mulpd (code, ins->sreg1, ins->sreg2);
4853 s390x_subpd (code, ins->sreg1, ins->sreg2);
4856 s390x_maxpd (code, ins->sreg1, ins->sreg2);
4859 s390x_minpd (code, ins->sreg1, ins->sreg2);
4862 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
4863 s390x_cmppd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4866 s390x_andpd (code, ins->sreg1, ins->sreg2);
4869 s390x_andnpd (code, ins->sreg1, ins->sreg2);
4872 s390x_orpd (code, ins->sreg1, ins->sreg2);
4875 s390x_xorpd (code, ins->sreg1, ins->sreg2);
4878 s390x_sqrtpd (code, ins->dreg, ins->sreg1);
4881 s390x_addsubpd (code, ins->sreg1, ins->sreg2);
4884 s390x_haddpd (code, ins->sreg1, ins->sreg2);
4887 s390x_hsubpd (code, ins->sreg1, ins->sreg2);
4890 s390x_movddup (code, ins->dreg, ins->sreg1);
4893 case OP_EXTRACT_MASK:
4894 s390x_pmovmskb (code, ins->dreg, ins->sreg1);
4898 s390x_pand (code, ins->sreg1, ins->sreg2);
4901 s390x_por (code, ins->sreg1, ins->sreg2);
4904 s390x_pxor (code, ins->sreg1, ins->sreg2);
4908 s390x_paddb (code, ins->sreg1, ins->sreg2);
4911 s390x_paddw (code, ins->sreg1, ins->sreg2);
4914 s390x_paddd (code, ins->sreg1, ins->sreg2);
4917 s390x_paddq (code, ins->sreg1, ins->sreg2);
4921 s390x_psubb (code, ins->sreg1, ins->sreg2);
4924 s390x_psubw (code, ins->sreg1, ins->sreg2);
4927 s390x_psubd (code, ins->sreg1, ins->sreg2);
4930 s390x_psubq (code, ins->sreg1, ins->sreg2);
4934 s390x_pmaxub (code, ins->sreg1, ins->sreg2);
4937 s390x_pmaxuw (code, ins->sreg1, ins->sreg2);
4940 s390x_pmaxud (code, ins->sreg1, ins->sreg2);
4944 s390x_pmaxsb (code, ins->sreg1, ins->sreg2);
4947 s390x_pmaxsw (code, ins->sreg1, ins->sreg2);
4950 s390x_pmaxsd (code, ins->sreg1, ins->sreg2);
4954 s390x_pavgb (code, ins->sreg1, ins->sreg2);
4957 s390x_pavgw (code, ins->sreg1, ins->sreg2);
4961 s390x_pminub (code, ins->sreg1, ins->sreg2);
4964 s390x_pminuw (code, ins->sreg1, ins->sreg2);
4967 s390x_pminud (code, ins->sreg1, ins->sreg2);
4971 s390x_pminsb (code, ins->sreg1, ins->sreg2);
4974 s390x_pminsw (code, ins->sreg1, ins->sreg2);
4977 s390x_pminsd (code, ins->sreg1, ins->sreg2);
4981 s390x_pcmpeqb (code, ins->sreg1, ins->sreg2);
4984 s390x_pcmpeqw (code, ins->sreg1, ins->sreg2);
4987 s390x_pcmpeqd (code, ins->sreg1, ins->sreg2);
4990 s390x_pcmpeqq (code, ins->sreg1, ins->sreg2);
4994 s390x_pcmpgtb (code, ins->sreg1, ins->sreg2);
4997 s390x_pcmpgtw (code, ins->sreg1, ins->sreg2);
5000 s390x_pcmpgtd (code, ins->sreg1, ins->sreg2);
5003 s390x_pcmpgtq (code, ins->sreg1, ins->sreg2);
5006 case OP_PSUM_ABS_DIFF:
5007 s390x_psadbw (code, ins->sreg1, ins->sreg2);
5010 case OP_UNPACK_LOWB:
5011 s390x_punpcklbw (code, ins->sreg1, ins->sreg2);
5013 case OP_UNPACK_LOWW:
5014 s390x_punpcklwd (code, ins->sreg1, ins->sreg2);
5016 case OP_UNPACK_LOWD:
5017 s390x_punpckldq (code, ins->sreg1, ins->sreg2);
5019 case OP_UNPACK_LOWQ:
5020 s390x_punpcklqdq (code, ins->sreg1, ins->sreg2);
5022 case OP_UNPACK_LOWPS:
5023 s390x_unpcklps (code, ins->sreg1, ins->sreg2);
5025 case OP_UNPACK_LOWPD:
5026 s390x_unpcklpd (code, ins->sreg1, ins->sreg2);
5029 case OP_UNPACK_HIGHB:
5030 s390x_punpckhbw (code, ins->sreg1, ins->sreg2);
5032 case OP_UNPACK_HIGHW:
5033 s390x_punpckhwd (code, ins->sreg1, ins->sreg2);
5035 case OP_UNPACK_HIGHD:
5036 s390x_punpckhdq (code, ins->sreg1, ins->sreg2);
5038 case OP_UNPACK_HIGHQ:
5039 s390x_punpckhqdq (code, ins->sreg1, ins->sreg2);
5041 case OP_UNPACK_HIGHPS:
5042 s390x_unpckhps (code, ins->sreg1, ins->sreg2);
5044 case OP_UNPACK_HIGHPD:
5045 s390x_unpckhpd (code, ins->sreg1, ins->sreg2);
5049 s390x_packsswb (code, ins->sreg1, ins->sreg2);
5052 s390x_packssdw (code, ins->sreg1, ins->sreg2);
5055 s390x_packuswb (code, ins->sreg1, ins->sreg2);
5058 s390x_packusdw (code, ins->sreg1, ins->sreg2);
5061 case OP_PADDB_SAT_UN:
5062 s390x_paddusb (code, ins->sreg1, ins->sreg2);
5064 case OP_PSUBB_SAT_UN:
5065 s390x_psubusb (code, ins->sreg1, ins->sreg2);
5067 case OP_PADDW_SAT_UN:
5068 s390x_paddusw (code, ins->sreg1, ins->sreg2);
5070 case OP_PSUBW_SAT_UN:
5071 s390x_psubusw (code, ins->sreg1, ins->sreg2);
5075 s390x_paddsb (code, ins->sreg1, ins->sreg2);
5078 s390x_psubsb (code, ins->sreg1, ins->sreg2);
5081 s390x_paddsw (code, ins->sreg1, ins->sreg2);
5084 s390x_psubsw (code, ins->sreg1, ins->sreg2);
5088 s390x_pmullw (code, ins->sreg1, ins->sreg2);
5091 s390x_pmulld (code, ins->sreg1, ins->sreg2);
5094 s390x_pmuludq (code, ins->sreg1, ins->sreg2);
5096 case OP_PMULW_HIGH_UN:
5097 s390x_pmulhuw (code, ins->sreg1, ins->sreg2);
5100 s390x_pmulhw (code, ins->sreg1, ins->sreg2);
5104 s390x_psrlw_reg_imm (code, ins->dreg, ins->inst_imm);
5107 s390x_psrlw (code, ins->dreg, ins->sreg2);
5111 s390x_psraw_reg_imm (code, ins->dreg, ins->inst_imm);
5114 s390x_psraw (code, ins->dreg, ins->sreg2);
5118 s390x_psllw_reg_imm (code, ins->dreg, ins->inst_imm);
5121 s390x_psllw (code, ins->dreg, ins->sreg2);
5125 s390x_psrld_reg_imm (code, ins->dreg, ins->inst_imm);
5128 s390x_psrld (code, ins->dreg, ins->sreg2);
5132 s390x_psrad_reg_imm (code, ins->dreg, ins->inst_imm);
5135 s390x_psrad (code, ins->dreg, ins->sreg2);
5139 s390x_pslld_reg_imm (code, ins->dreg, ins->inst_imm);
5142 s390x_pslld (code, ins->dreg, ins->sreg2);
5146 s390x_psrlq_reg_imm (code, ins->dreg, ins->inst_imm);
5149 s390x_psrlq (code, ins->dreg, ins->sreg2);
5152 /*TODO: This is appart of the sse spec but not added
5154 s390x_psraq_reg_imm (code, ins->dreg, ins->inst_imm);
5157 s390x_psraq (code, ins->dreg, ins->sreg2);
5162 s390x_psllq_reg_imm (code, ins->dreg, ins->inst_imm);
5165 s390x_psllq (code, ins->dreg, ins->sreg2);
5168 s390x_cvtdq2pd (code, ins->dreg, ins->sreg1);
5171 s390x_cvtdq2ps (code, ins->dreg, ins->sreg1);
5174 s390x_cvtpd2dq (code, ins->dreg, ins->sreg1);
5177 s390x_cvtpd2ps (code, ins->dreg, ins->sreg1);
5180 s390x_cvtps2dq (code, ins->dreg, ins->sreg1);
5183 s390x_cvtps2pd (code, ins->dreg, ins->sreg1);
5186 s390x_cvttpd2dq (code, ins->dreg, ins->sreg1);
5189 s390x_cvttps2dq (code, ins->dreg, ins->sreg1);
5193 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5196 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5200 amd64_movhlps (code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg1);
5201 amd64_movd_reg_xreg_size (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG, 8);
5203 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 8);
5208 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5210 amd64_shift_reg_imm (code, X86_SHR, ins->dreg, ins->inst_c0 * 8);
5211 amd64_widen_reg (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I1, FALSE);
5215 /*amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5217 amd64_shift_reg_imm_size (code, X86_SHR, ins->dreg, 16, 4);*/
5218 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5219 amd64_widen_reg_size (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I2, TRUE, 4);
5223 amd64_movhlps (code, ins->dreg, ins->sreg1);
5225 s390x_movsd (code, ins->dreg, ins->sreg1);
5228 s390x_pinsrw_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5230 case OP_EXTRACTX_U2:
5231 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5233 case OP_INSERTX_U1_SLOW:
5234 /*sreg1 is the extracted ireg (scratch)
5235 /sreg2 is the to be inserted ireg (scratch)
5236 /dreg is the xreg to receive the value*/
5238 /*clear the bits from the extracted word*/
5239 amd64_alu_reg_imm (code, X86_AND, ins->sreg1, ins->inst_c0 & 1 ? 0x00FF : 0xFF00);
5240 /*shift the value to insert if needed*/
5241 if (ins->inst_c0 & 1)
5242 amd64_shift_reg_imm_size (code, X86_SHL, ins->sreg2, 8, 4);
5243 /*join them together*/
5244 amd64_alu (code, X86_OR, ins->sreg1, ins->sreg2);
5245 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0 / 2);
5247 case OP_INSERTX_I4_SLOW:
5248 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2);
5249 amd64_shift_reg_imm (code, X86_SHR, ins->sreg2, 16);
5250 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2 + 1);
5252 case OP_INSERTX_I8_SLOW:
5253 amd64_movd_xreg_reg_size(code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg2, 8);
5255 amd64_movlhps (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5257 s390x_movsd (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5260 case OP_INSERTX_R4_SLOW:
5261 switch (ins->inst_c0) {
5264 s390x_movss (code, ins->dreg, ins->sreg2);
5266 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5269 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5271 s390x_movss (code, ins->dreg, ins->sreg2);
5273 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5274 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5277 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5279 s390x_movss (code, ins->dreg, ins->sreg2);
5281 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5282 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5285 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5287 s390x_movss (code, ins->dreg, ins->sreg2);
5289 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5290 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5294 case OP_INSERTX_R8_SLOW:
5296 amd64_movlhps (code, ins->dreg, ins->sreg2);
5298 s390x_movsd (code, ins->dreg, ins->sreg2);
5300 case OP_STOREX_MEMBASE_REG:
5301 case OP_STOREX_MEMBASE:
5302 s390x_movups_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5304 case OP_LOADX_MEMBASE:
5305 s390x_movups_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5307 case OP_LOADX_ALIGNED_MEMBASE:
5308 s390x_movaps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5310 case OP_STOREX_ALIGNED_MEMBASE_REG:
5311 s390x_movaps_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5313 case OP_STOREX_NTA_MEMBASE_REG:
5314 s390x_movntps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5316 case OP_PREFETCH_MEMBASE:
5317 s390x_prefetch_reg_membase (code, ins->backend.arg_info, ins->sreg1, ins->inst_offset);
5321 /*FIXME the peephole pass should have killed this*/
5322 if (ins->dreg != ins->sreg1)
5323 s390x_movaps (code, ins->dreg, ins->sreg1);
5326 s390x_pxor (code, ins->dreg, ins->dreg);
5328 case OP_ICONV_TO_R4_RAW:
5329 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5332 case OP_FCONV_TO_R8_X:
5333 s390x_movsd (code, ins->dreg, ins->sreg1);
5336 case OP_XCONV_R8_TO_I4:
5337 s390x_cvttsd2si_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5338 switch (ins->backend.source_opcode) {
5339 case OP_FCONV_TO_I1:
5340 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, FALSE);
5342 case OP_FCONV_TO_U1:
5343 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, FALSE);
5345 case OP_FCONV_TO_I2:
5346 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, TRUE);
5348 case OP_FCONV_TO_U2:
5349 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, TRUE);
5355 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 0);
5356 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 1);
5357 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5360 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5361 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5364 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 8);
5365 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5369 s390x_movsd (code, ins->dreg, ins->sreg1);
5371 s390x_movsd (code, ins->dreg, ins->sreg1);
5372 s390x_cvtsd2ss (code, ins->dreg, ins->dreg);
5374 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5377 s390x_movsd (code, ins->dreg, ins->sreg1);
5378 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5382 g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
5383 g_assert_not_reached ();
5386 if ((cfg->opt & MONO_OPT_BRANCH) && ((code - cfg->native_code - offset) > max_len)) {
5387 g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %ld)",
5388 mono_inst_name (ins->opcode), max_len, code - cfg->native_code - offset);
5389 g_assert_not_reached ();
5392 last_offset = offset;
5395 cfg->code_len = code - cfg->native_code;
5398 /*========================= End of Function ========================*/
5400 /*------------------------------------------------------------------*/
5402 /* Name - mono_arch_register_lowlevel_calls */
5404 /* Function - Register routines to help with --trace operation. */
5406 /*------------------------------------------------------------------*/
5409 mono_arch_register_lowlevel_calls (void)
5413 /*========================= End of Function ========================*/
5415 /*------------------------------------------------------------------*/
5417 /* Name - mono_arch_patch_code */
5419 /* Function - Process the patch data created during the */
5420 /* instruction build process. This resolves jumps, */
5421 /* calls, variables etc. */
5423 /*------------------------------------------------------------------*/
5426 mono_arch_patch_code (MonoCompile *cfg, MonoMethod *method, MonoDomain *domain,
5427 guint8 *code, MonoJumpInfo *ji, gboolean run_cctors,
5430 MonoJumpInfo *patch_info;
5432 mono_error_init (error);
5434 for (patch_info = ji; patch_info; patch_info = patch_info->next) {
5435 unsigned char *ip = patch_info->ip.i + code;
5436 gconstpointer target = NULL;
5438 target = mono_resolve_patch_target (method, domain, code,
5439 patch_info, run_cctors, error);
5440 return_if_nok (error);
5442 switch (patch_info->type) {
5443 case MONO_PATCH_INFO_IP:
5444 case MONO_PATCH_INFO_LDSTR:
5445 case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
5446 case MONO_PATCH_INFO_LDTOKEN:
5447 case MONO_PATCH_INFO_EXC:
5448 s390_patch_addr (ip, (guint64) target);
5450 case MONO_PATCH_INFO_METHOD:
5451 case MONO_PATCH_INFO_INTERNAL_METHOD:
5452 case MONO_PATCH_INFO_JIT_ICALL_ADDR:
5453 case MONO_PATCH_INFO_RGCTX_FETCH:
5454 case MONO_PATCH_INFO_ABS: {
5455 S390_EMIT_CALL (ip, target);
5458 case MONO_PATCH_INFO_SWITCH:
5459 /*----------------------------------*/
5460 /* ip points at the basr r13,0/j +4 */
5461 /* instruction the vtable value */
5462 /* follows this (i.e. ip+6) */
5463 /*----------------------------------*/
5464 S390_EMIT_LOAD (ip, target);
5466 case MONO_PATCH_INFO_METHODCONST:
5467 case MONO_PATCH_INFO_CLASS:
5468 case MONO_PATCH_INFO_IMAGE:
5469 case MONO_PATCH_INFO_FIELD:
5470 case MONO_PATCH_INFO_IID:
5471 case MONO_PATCH_INFO_EXC_NAME:
5472 target = S390_RELATIVE(target, ip);
5473 s390_patch_rel (ip, (guint64) target);
5475 case MONO_PATCH_INFO_R4:
5476 case MONO_PATCH_INFO_R8:
5477 case MONO_PATCH_INFO_METHOD_REL:
5478 g_assert_not_reached ();
5481 target = S390_RELATIVE(target, ip);
5483 s390_patch_rel (ip, (guint64) target);
5488 /*========================= End of Function ========================*/
5490 /*------------------------------------------------------------------*/
5492 /* Name - emit_load_volatile_arguments */
5494 /* Function - Emit the instructions to reload parameter regist- */
5495 /* registers for use with "tail" operations. */
5497 /* The register loading operations performed here */
5498 /* are the mirror of the store operations performed */
5499 /* in mono_arch_emit_prolog and need to be kept in */
5500 /* synchronization with it. */
5502 /*------------------------------------------------------------------*/
5505 emit_load_volatile_arguments (guint8 *code, MonoCompile *cfg)
5508 MonoMethod *method = cfg->method;
5509 MonoMethodSignature *sig = mono_method_signature(method);
5513 cinfo = get_call_info (NULL, NULL, sig);
5515 if (cinfo->struct_ret) {
5516 ArgInfo *ainfo = &cinfo->ret;
5517 inst = cfg->vret_addr;
5518 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5521 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5522 ArgInfo *ainfo = cinfo->args + i;
5523 inst = cfg->args [pos];
5525 if (inst->opcode == OP_REGVAR) {
5526 if (ainfo->regtype == RegTypeGeneral)
5527 s390_lgr (code, ainfo->reg, inst->dreg);
5528 else if (ainfo->regtype == RegTypeFP) {
5529 if (inst->dreg != ainfo->reg) {
5530 if (ainfo->size == 4) {
5531 s390_ldebr (code, ainfo->reg, inst->dreg);
5533 s390_ldr (code, ainfo->reg, inst->dreg);
5537 else if (ainfo->regtype == RegTypeBase) {
5539 g_assert_not_reached ();
5541 if (ainfo->regtype == RegTypeGeneral) {
5542 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5543 g_assert_not_reached();
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);
5558 } else if (ainfo->regtype == RegTypeBase) {
5559 } else if (ainfo->regtype == RegTypeFP) {
5560 if (ainfo->size == 8)
5561 s390_ld (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5562 else if (ainfo->size == 4)
5563 s390_le (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5565 g_assert_not_reached ();
5566 } else if (ainfo->regtype == RegTypeStructByVal) {
5567 if (ainfo->reg != STK_BASE) {
5568 switch (ainfo->size) {
5570 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5573 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5576 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5579 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5583 } else if (ainfo->regtype == RegTypeStructByAddr) {
5584 if (ainfo->reg != STK_BASE) {
5585 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5588 g_assert_not_reached ();
5596 /*========================= End of Function ========================*/
5598 /*------------------------------------------------------------------*/
5600 /* Name - mono_arch_emit_prolog */
5602 /* Function - Create the instruction sequence for a function */
5605 /*------------------------------------------------------------------*/
5608 mono_arch_emit_prolog (MonoCompile *cfg)
5610 MonoMethod *method = cfg->method;
5612 MonoMethodSignature *sig;
5614 long alloc_size, pos, max_offset, i, cfa_offset = 0;
5623 cfg->code_size = 512;
5625 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
5627 cfg->code_size += 256;
5628 } else if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
5629 cfg->code_size += 256;
5631 if (method->save_lmf)
5632 cfg->code_size += 200;
5634 cfg->native_code = code = g_malloc (cfg->code_size);
5636 mono_emit_unwind_op_def_cfa (cfg, code, STK_BASE, 0);
5637 emit_unwind_regs(cfg, code, s390_r6, s390_r14, S390_REG_SAVE_OFFSET);
5638 s390_stmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
5639 mono_emit_unwind_op_offset (cfg, code, s390_r14, S390_RET_ADDR_OFFSET);
5640 mini_gc_set_slot_type_from_cfa (cfg, S390_RET_ADDR_OFFSET, SLOT_NOREF);
5642 if (cfg->arch.bkchain_reg != -1)
5643 s390_lgr (code, cfg->arch.bkchain_reg, STK_BASE);
5645 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
5646 cfg->used_int_regs |= 1 << 11;
5649 alloc_size = cfg->stack_offset;
5651 cfg->stack_usage = cfa_offset = alloc_size;
5652 mono_emit_unwind_op_def_cfa_offset (cfg, code, alloc_size);
5653 s390_lgr (code, s390_r11, STK_BASE);
5654 if (s390_is_imm16 (alloc_size)) {
5655 s390_aghi (code, STK_BASE, -alloc_size);
5656 } else if (s390_is_imm32 (alloc_size)) {
5657 s390_agfi (code, STK_BASE, -alloc_size);
5659 int stackSize = alloc_size;
5660 while (stackSize > INT_MAX) {
5661 s390_agfi (code, STK_BASE, -INT_MAX);
5662 stackSize -= INT_MAX;
5664 s390_agfi (code, STK_BASE, -stackSize);
5666 s390_stg (code, s390_r11, 0, STK_BASE, 0);
5668 if (cfg->frame_reg != STK_BASE)
5669 s390_lgr (code, s390_r11, STK_BASE);
5671 mono_emit_unwind_op_def_cfa_reg (cfg, code, cfg->frame_reg);
5673 /* store runtime generic context */
5674 if (cfg->rgctx_var) {
5675 g_assert (cfg->rgctx_var->opcode == OP_REGOFFSET);
5677 s390_stg (code, MONO_ARCH_RGCTX_REG, 0,
5678 cfg->rgctx_var->inst_basereg,
5679 cfg->rgctx_var->inst_offset);
5682 /* compute max_offset in order to use short forward jumps
5683 * we always do it on s390 because the immediate displacement
5684 * for jumps is too small
5687 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
5689 bb->max_offset = max_offset;
5691 if (cfg->prof_options & MONO_PROFILE_COVERAGE)
5694 MONO_BB_FOR_EACH_INS (bb, ins)
5695 max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
5698 /* load arguments allocated to register from the stack */
5699 sig = mono_method_signature (method);
5702 cinfo = get_call_info (cfg, cfg->mempool, sig);
5704 if (cinfo->struct_ret) {
5705 ArgInfo *ainfo = &cinfo->ret;
5706 inst = cfg->vret_addr;
5707 inst->backend.size = ainfo->vtsize;
5708 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5711 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5712 ArgInfo *ainfo = cinfo->args + i;
5713 inst = cfg->args [pos];
5715 if (inst->opcode == OP_VTARG_ADDR)
5716 inst = inst->inst_left;
5718 if (inst->opcode == OP_REGVAR) {
5719 if (ainfo->regtype == RegTypeGeneral)
5720 s390_lgr (code, inst->dreg, ainfo->reg);
5721 else if (ainfo->regtype == RegTypeFP) {
5722 if (inst->dreg != ainfo->reg) {
5723 if (ainfo->size == 4) {
5724 s390_ledbr (code, inst->dreg, ainfo->reg);
5726 s390_ldr (code, inst->dreg, ainfo->reg);
5730 else if (ainfo->regtype == RegTypeBase) {
5731 s390_lgr (code, s390_r13, STK_BASE);
5732 s390_aghi (code, s390_r13, alloc_size);
5733 s390_lg (code, inst->dreg, 0, s390_r13, ainfo->offset);
5735 g_assert_not_reached ();
5737 if (cfg->verbose_level > 2)
5738 g_print ("Argument %d assigned to register %s\n",
5739 pos, mono_arch_regname (inst->dreg));
5741 if (ainfo->regtype == RegTypeGeneral) {
5742 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5743 g_assert_not_reached();
5744 switch (ainfo->size) {
5746 s390_stc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5749 s390_sth (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5752 s390_st (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5755 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5758 } else if (ainfo->regtype == RegTypeBase) {
5759 } else if (ainfo->regtype == RegTypeFP) {
5760 if (ainfo->size == 8)
5761 s390_std (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5762 else if (ainfo->size == 4)
5763 s390_ste (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5765 g_assert_not_reached ();
5766 } else if (ainfo->regtype == RegTypeStructByVal) {
5767 int doffset = inst->inst_offset;
5769 if (ainfo->reg != STK_BASE)
5773 s390_lgr (code, s390_r13, STK_BASE);
5774 s390_aghi (code, s390_r13, alloc_size);
5777 size = (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE
5778 ? mono_class_native_size(mono_class_from_mono_type(inst->inst_vtype), NULL)
5783 if (ainfo->reg == STK_BASE)
5784 s390_ic (code, reg, 0, s390_r13, ainfo->offset+7);
5785 s390_stc (code, reg, 0, inst->inst_basereg, doffset);
5788 if (ainfo->reg == STK_BASE)
5789 s390_lh (code, reg, 0, s390_r13, ainfo->offset+6);
5790 s390_sth (code, reg, 0, inst->inst_basereg, doffset);
5793 if (ainfo->reg == STK_BASE)
5794 s390_l (code, reg, 0, s390_r13, ainfo->offset+4);
5795 s390_st (code, reg, 0, inst->inst_basereg, doffset);
5798 if (ainfo->reg == STK_BASE)
5799 s390_lg (code, reg, 0, s390_r13, ainfo->offset);
5800 s390_stg (code, reg, 0, inst->inst_basereg, doffset);
5803 } else if (ainfo->regtype == RegTypeStructByAddr) {
5804 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5805 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
5807 g_assert_not_reached ();
5812 if (method->save_lmf) {
5813 /*---------------------------------------------------------------*/
5814 /* build the MonoLMF structure on the stack - see mini-s390x.h */
5815 /*---------------------------------------------------------------*/
5816 lmfOffset = alloc_size - sizeof(MonoLMF);
5818 s390_lgr (code, s390_r13, cfg->frame_reg);
5819 s390_aghi (code, s390_r13, lmfOffset);
5821 /*---------------------------------------------------------------*/
5822 /* Preserve the parameter registers while we fix up the lmf */
5823 /*---------------------------------------------------------------*/
5824 s390_stmg (code, s390_r2, s390_r6, s390_r13,
5825 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
5827 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[0]), SLOT_NOREF);
5828 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[1]), SLOT_NOREF);
5829 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[2]), SLOT_NOREF);
5830 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[3]), SLOT_NOREF);
5831 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[4]), SLOT_NOREF);
5833 /*---------------------------------------------------------------*/
5834 /* On return from this call r2 have the address of the &lmf */
5835 /*---------------------------------------------------------------*/
5836 mono_add_patch_info (cfg, code - cfg->native_code,
5837 MONO_PATCH_INFO_INTERNAL_METHOD,
5838 (gpointer)"mono_tls_get_lmf_addr");
5839 S390_CALL_TEMPLATE(code, s390_r1);
5841 /*---------------------------------------------------------------*/
5842 /* Set lmf.lmf_addr = jit_tls->lmf */
5843 /*---------------------------------------------------------------*/
5844 s390_stg (code, s390_r2, 0, s390_r13,
5845 G_STRUCT_OFFSET(MonoLMF, lmf_addr));
5846 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, lmf_addr), SLOT_NOREF);
5848 /*---------------------------------------------------------------*/
5849 /* Get current lmf */
5850 /*---------------------------------------------------------------*/
5851 s390_lg (code, s390_r0, 0, s390_r2, 0);
5853 /*---------------------------------------------------------------*/
5854 /* Set our lmf as the current lmf */
5855 /*---------------------------------------------------------------*/
5856 s390_stg (code, s390_r13, 0, s390_r2, 0);
5858 /*---------------------------------------------------------------*/
5859 /* Have our lmf.previous_lmf point to the last lmf */
5860 /*---------------------------------------------------------------*/
5861 s390_stg (code, s390_r0, 0, s390_r13,
5862 G_STRUCT_OFFSET(MonoLMF, previous_lmf));
5863 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), SLOT_NOREF);
5865 /*---------------------------------------------------------------*/
5866 /* save method info */
5867 /*---------------------------------------------------------------*/
5868 S390_SET (code, s390_r1, method);
5869 s390_stg (code, s390_r1, 0, s390_r13,
5870 G_STRUCT_OFFSET(MonoLMF, method));
5871 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, method), SLOT_NOREF);
5873 /*---------------------------------------------------------------*/
5874 /* save the current IP */
5875 /*---------------------------------------------------------------*/
5876 s390_stg (code, STK_BASE, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp));
5877 s390_basr (code, s390_r1, 0);
5878 s390_stg (code, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip));
5879 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, ebp), SLOT_NOREF);
5880 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, eip), SLOT_NOREF);
5882 /*---------------------------------------------------------------*/
5883 /* Save general and floating point registers */
5884 /*---------------------------------------------------------------*/
5885 s390_stmg (code, s390_r2, s390_r12, s390_r13,
5886 G_STRUCT_OFFSET(MonoLMF, gregs[2]));
5887 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[0]), SLOT_NOREF);
5888 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[1]), SLOT_NOREF);
5889 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[2]), SLOT_NOREF);
5890 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[3]), SLOT_NOREF);
5891 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[4]), SLOT_NOREF);
5892 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[5]), SLOT_NOREF);
5893 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[6]), SLOT_NOREF);
5894 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[7]), SLOT_NOREF);
5895 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[8]), SLOT_NOREF);
5896 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[9]), SLOT_NOREF);
5897 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[10]), SLOT_NOREF);
5899 fpOffset = lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, fregs[0]);
5900 for (i = 0; i < 16; i++) {
5901 s390_std (code, i, 0, s390_r13,
5902 G_STRUCT_OFFSET(MonoLMF, fregs[i]));
5903 mini_gc_set_slot_type_from_fp (cfg, fpOffset, SLOT_NOREF);
5904 fpOffset += sizeof(double);
5907 /*---------------------------------------------------------------*/
5908 /* Restore the parameter registers now that we've set up the lmf */
5909 /*---------------------------------------------------------------*/
5910 s390_lmg (code, s390_r2, s390_r6, s390_r13,
5911 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
5914 if (cfg->method->save_lmf)
5915 argsClobbered = TRUE;
5918 argsClobbered = TRUE;
5919 code = mono_arch_instrument_prolog (cfg, enter_method, code, TRUE);
5922 if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
5923 argsClobbered = TRUE;
5926 * Optimize the common case of the first bblock making a call with the same
5927 * arguments as the method. This works because the arguments are still in their
5928 * original argument registers.
5930 if (!argsClobbered) {
5931 MonoBasicBlock *first_bb = cfg->bb_entry;
5933 int filter = FILTER_IL_SEQ_POINT;
5935 next = mono_bb_first_inst (first_bb, filter);
5936 if (!next && first_bb->next_bb) {
5937 first_bb = first_bb->next_bb;
5938 next = mono_bb_first_inst (first_bb, filter);
5941 if (first_bb->in_count > 1)
5944 for (i = 0; next && i < sig->param_count + sig->hasthis; ++i) {
5945 ArgInfo *ainfo = cinfo->args + i;
5946 gboolean match = FALSE;
5948 inst = cfg->args [i];
5949 if (inst->opcode != OP_REGVAR) {
5950 switch (ainfo->regtype) {
5951 case RegTypeGeneral: {
5952 if (((next->opcode == OP_LOAD_MEMBASE) ||
5953 (next->opcode == OP_LOADI4_MEMBASE)) &&
5954 next->inst_basereg == inst->inst_basereg &&
5955 next->inst_offset == inst->inst_offset) {
5956 if (next->dreg == ainfo->reg) {
5960 next->opcode = OP_MOVE;
5961 next->sreg1 = ainfo->reg;
5962 /* Only continue if the instruction doesn't change argument regs */
5963 if (next->dreg == ainfo->reg)
5973 /* Argument allocated to (non-volatile) register */
5974 switch (ainfo->regtype) {
5975 case RegTypeGeneral:
5976 if (next->opcode == OP_MOVE &&
5977 next->sreg1 == inst->dreg &&
5978 next->dreg == ainfo->reg) {
5989 next = mono_inst_next (next, filter);
5996 cfg->code_len = code - cfg->native_code;
5997 g_assert (cfg->code_len < cfg->code_size);
6002 /*========================= End of Function ========================*/
6004 /*------------------------------------------------------------------*/
6006 /* Name - mono_arch_emit_epilog */
6008 /* Function - Emit the instructions for a function epilog. */
6010 /*------------------------------------------------------------------*/
6013 mono_arch_emit_epilog (MonoCompile *cfg)
6015 MonoMethod *method = cfg->method;
6018 int max_epilog_size = 96;
6020 if (cfg->method->save_lmf)
6021 max_epilog_size += 128;
6023 if (mono_jit_trace_calls != NULL)
6024 max_epilog_size += 128;
6025 else if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
6026 max_epilog_size += 128;
6028 while ((cfg->code_len + max_epilog_size) > (cfg->code_size - 16)) {
6029 cfg->code_size *= 2;
6030 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6031 cfg->stat_code_reallocs++;
6034 code = cfg->native_code + cfg->code_len;
6036 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
6037 code = mono_arch_instrument_epilog (cfg, leave_method, code, TRUE);
6041 if (method->save_lmf)
6042 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
6044 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
6045 s390_lg (code, STK_BASE, 0, STK_BASE, 0);
6047 code = backUpStackPtr(cfg, code);
6049 s390_lmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
6050 s390_br (code, s390_r14);
6052 cfg->code_len = code - cfg->native_code;
6054 g_assert (cfg->code_len < cfg->code_size);
6058 /*========================= End of Function ========================*/
6060 /*------------------------------------------------------------------*/
6062 /* Name - mono_arch_emit_exceptions */
6064 /* Function - Emit the blocks to handle exception conditions. */
6066 /*------------------------------------------------------------------*/
6069 mono_arch_emit_exceptions (MonoCompile *cfg)
6071 MonoJumpInfo *patch_info;
6077 MonoClass *exc_classes [MAX_EXC];
6078 guint8 *exc_throw_start [MAX_EXC];
6080 for (patch_info = cfg->patch_info;
6082 patch_info = patch_info->next) {
6083 if (patch_info->type == MONO_PATCH_INFO_EXC)
6087 code_size = exc_count * 48;
6089 while ((cfg->code_len + code_size) > (cfg->code_size - 16)) {
6090 cfg->code_size *= 2;
6091 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6092 cfg->stat_code_reallocs++;
6095 code = cfg->native_code + cfg->code_len;
6097 /*---------------------------------------------------------------------*/
6098 /* Add code to raise exceptions */
6099 /*---------------------------------------------------------------------*/
6100 for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
6101 switch (patch_info->type) {
6102 case MONO_PATCH_INFO_EXC: {
6103 guint8 *ip = patch_info->ip.i + cfg->native_code;
6104 MonoClass *exc_class;
6107 /*-----------------------------------------------------*/
6108 /* Patch the branch in epilog to come here */
6109 /*-----------------------------------------------------*/
6110 s390_patch_rel (ip + 2, (guint64) S390_RELATIVE(code,ip));
6112 exc_class = mono_class_load_from_name (mono_defaults.corlib,
6114 patch_info->data.name);
6115 throw_ip = patch_info->ip.i;
6117 for (iExc = 0; iExc < nThrows; ++iExc)
6118 if (exc_classes [iExc] == exc_class)
6121 if (iExc < nThrows) {
6122 s390_jcl (code, S390_CC_UN,
6123 (guint64) exc_throw_start [iExc]);
6124 patch_info->type = MONO_PATCH_INFO_NONE;
6127 if (nThrows < MAX_EXC) {
6128 exc_classes [nThrows] = exc_class;
6129 exc_throw_start [nThrows] = code;
6132 /*---------------------------------------------*/
6133 /* Patch the parameter passed to the handler */
6134 /*---------------------------------------------*/
6135 S390_SET (code, s390_r2, exc_class->type_token);
6136 /*---------------------------------------------*/
6137 /* Load return address & parameter register */
6138 /*---------------------------------------------*/
6139 s390_larl (code, s390_r14, (guint64)S390_RELATIVE((patch_info->ip.i +
6140 cfg->native_code + 8), code));
6141 /*---------------------------------------------*/
6142 /* Reuse the current patch to set the jump */
6143 /*---------------------------------------------*/
6144 patch_info->type = MONO_PATCH_INFO_INTERNAL_METHOD;
6145 patch_info->data.name = "mono_arch_throw_corlib_exception";
6146 patch_info->ip.i = code - cfg->native_code;
6147 S390_BR_TEMPLATE (code, s390_r1);
6157 cfg->code_len = code - cfg->native_code;
6159 g_assert (cfg->code_len < cfg->code_size);
6163 /*========================= End of Function ========================*/
6165 /*------------------------------------------------------------------*/
6167 /* Name - mono_arch_finish_init */
6169 /* Function - Setup the JIT's Thread Level Specific Data. */
6171 /*------------------------------------------------------------------*/
6174 mono_arch_finish_init (void)
6178 /*========================= End of Function ========================*/
6180 /*------------------------------------------------------------------*/
6182 /* Name - mono_arch_free_jit_tls_data */
6184 /* Function - Free tls data. */
6186 /*------------------------------------------------------------------*/
6189 mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
6193 /*========================= End of Function ========================*/
6195 /*------------------------------------------------------------------*/
6197 /* Name - mono_arch_emit_inst_for_method */
6199 /*------------------------------------------------------------------*/
6202 mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
6207 /*========================= End of Function ========================*/
6209 /*------------------------------------------------------------------*/
6211 /* Name - mono_arch_decompose_opts */
6213 /* Function - Decompose opcode into a System z opcode. */
6215 /*------------------------------------------------------------------*/
6218 mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
6221 * Have to rename these to avoid being decomposed normally, since the normal
6222 * decomposition does not work on S390.
6224 switch (ins->opcode) {
6226 ins->opcode = OP_S390_ISUB_OVF;
6228 case OP_ISUB_OVF_UN:
6229 ins->opcode = OP_S390_ISUB_OVF_UN;
6232 ins->opcode = OP_S390_IADD_OVF;
6234 case OP_IADD_OVF_UN:
6235 ins->opcode = OP_S390_IADD_OVF_UN;
6238 ins->opcode = OP_S390_LADD_OVF;
6240 case OP_LADD_OVF_UN:
6241 ins->opcode = OP_S390_LADD_OVF_UN;
6244 ins->opcode = OP_S390_LSUB_OVF;
6246 case OP_LSUB_OVF_UN:
6247 ins->opcode = OP_S390_LSUB_OVF_UN;
6254 /*========================= End of Function ========================*/
6256 /*------------------------------------------------------------------*/
6258 /* Name - mono_arch_print_tree */
6260 /* Function - Print platform-specific opcode details. */
6262 /* Returns - 1 - opcode details have been printed */
6263 /* 0 - opcode details have not been printed */
6265 /*------------------------------------------------------------------*/
6268 mono_arch_print_tree (MonoInst *tree, int arity)
6272 switch (tree->opcode) {
6273 case OP_S390_LOADARG:
6274 case OP_S390_ARGREG:
6275 case OP_S390_ARGPTR:
6276 printf ("[0x%lx(%s)]", tree->inst_offset,
6277 mono_arch_regname (tree->inst_basereg));
6280 case OP_S390_STKARG:
6281 printf ("[0x%lx(previous_frame)]",
6286 printf ("[0x%lx(%d,%s),0x%lx(%s)]",
6287 tree->inst_offset, tree->backend.size,
6288 mono_arch_regname(tree->dreg),
6290 mono_arch_regname(tree->sreg1));
6293 case OP_S390_SETF4RET:
6294 printf ("[f%s,f%s]",
6295 mono_arch_regname (tree->dreg),
6296 mono_arch_regname (tree->sreg1));
6300 printf ("[0x%lx(0x%lx,%s)]", tree->inst_offset,
6302 mono_arch_regname (tree->sreg1));
6306 printf ("[0x%lx(0x%lx,%s)]", tree->inst_offset,
6308 mono_arch_regname (tree->sreg1));
6311 case OP_S390_BKCHAIN:
6312 printf ("[previous_frame(%s)]",
6313 mono_arch_regname (tree->sreg1));
6321 /*========================= End of Function ========================*/
6323 /*------------------------------------------------------------------*/
6325 /* Name - mono_arch_regalloc_cost */
6327 /* Function - Determine the cost, in the number of memory */
6328 /* references, of the action of allocating the var- */
6329 /* iable VMV into a register during global register */
6332 /* Returns - Cost */
6334 /*------------------------------------------------------------------*/
6337 mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
6343 /*========================= End of Function ========================*/
6345 /*------------------------------------------------------------------*/
6347 /* Name - mono_arch_flush_register_windows */
6353 /*------------------------------------------------------------------*/
6356 mono_arch_flush_register_windows (void)
6360 /*========================= End of Function ========================*/
6362 /*------------------------------------------------------------------*/
6364 /* Name - mono_arch_is_inst_imm */
6366 /* Function - Determine if operand qualifies as an immediate */
6367 /* value. For s390 this is a value -32768-32768 */
6369 /* Returns - True|False - is [not] immediate value. */
6371 /*------------------------------------------------------------------*/
6374 mono_arch_is_inst_imm (gint64 imm)
6376 return s390_is_imm32 (imm);
6379 /*========================= End of Function ========================*/
6381 /*------------------------------------------------------------------*/
6383 /* Name - mono_arch_get_patch_offset */
6385 /* Function - Dummy entry point until s390x supports aot. */
6387 /* Returns - Offset for patch. */
6389 /*------------------------------------------------------------------*/
6392 mono_arch_get_patch_offset (guint8 *code)
6397 /*========================= End of Function ========================*/
6399 /*------------------------------------------------------------------*/
6401 /* Name - mono_arch_context_get_int_reg. */
6405 /* Returns - Return a register from the context. */
6407 /*------------------------------------------------------------------*/
6410 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
6412 return ((mgreg_t) ctx->uc_mcontext.gregs[reg]);
6415 /*========================= End of Function ========================*/
6417 /*------------------------------------------------------------------*/
6419 /* Name - mono_arch_context_set_int_reg. */
6421 /* Function - Set a value in a specified register. */
6423 /*------------------------------------------------------------------*/
6426 mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val)
6428 ctx->uc_mcontext.gregs[reg] = val;
6431 /*========================= End of Function ========================*/
6433 /*------------------------------------------------------------------*/
6435 /* Name - mono_arch_get_this_arg_from_call. */
6439 /*------------------------------------------------------------------*/
6442 mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
6444 return (gpointer) regs [s390_r2];
6447 /*========================= End of Function ========================*/
6449 /*------------------------------------------------------------------*/
6451 /* Name - mono_arch_install_handler_block_guard */
6455 /*------------------------------------------------------------------*/
6458 mono_arch_install_handler_block_guard (MonoJitInfo *ji, MonoJitExceptionInfo *clause,
6459 MonoContext *ctx, gpointer new_value)
6462 gpointer *sp, old_value;
6465 offset = clause->exvar_offset;
6468 bp = MONO_CONTEXT_GET_BP (ctx);
6469 sp = *(gpointer*)(bp + offset);
6472 if (old_value < ji->code_start || (char*)old_value > ((char*)ji->code_start + ji->code_size))
6480 /*========================= End of Function ========================*/
6482 /*------------------------------------------------------------------*/
6484 /* Name - get_delegate_invoke_impl. */
6488 /*------------------------------------------------------------------*/
6491 get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 param_count, gboolean aot)
6493 guint8 *code, *start;
6498 start = code = mono_global_codeman_reserve (size);
6500 /* Replace the this argument with the target */
6501 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6502 s390_lg (code, s390_r2, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, target));
6503 s390_br (code, s390_r1);
6504 g_assert ((code - start) <= size);
6506 mono_arch_flush_icache (start, size);
6510 size = 32 + param_count * 8;
6511 start = code = mono_global_codeman_reserve (size);
6513 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6514 /* slide down the arguments */
6515 for (i = 0; i < param_count; ++i) {
6516 s390_lgr (code, (s390_r2 + i), (s390_r2 + i + 1));
6518 s390_br (code, s390_r1);
6520 g_assert ((code - start) <= size);
6522 mono_arch_flush_icache (start, size);
6525 mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
6528 *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
6530 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
6531 *info = mono_tramp_info_create (name, start, code - start, NULL, NULL);
6538 /*========================= End of Function ========================*/
6540 /*------------------------------------------------------------------*/
6542 /* Name - mono_arch_get_delegate_invoke_impls. */
6546 /*------------------------------------------------------------------*/
6549 mono_arch_get_delegate_invoke_impls (void)
6552 MonoTrampInfo *info;
6555 get_delegate_invoke_impl (&info, TRUE, 0, TRUE);
6556 res = g_slist_prepend (res, info);
6558 for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
6559 get_delegate_invoke_impl (&info, FALSE, i, TRUE);
6560 res = g_slist_prepend (res, info);
6566 /*========================= End of Function ========================*/
6568 /*------------------------------------------------------------------*/
6570 /* Name - mono_arch_get_delegate_invoke_impl. */
6574 /*------------------------------------------------------------------*/
6577 mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target)
6579 guint8 *code, *start;
6581 /* FIXME: Support more cases */
6582 if (MONO_TYPE_ISSTRUCT (sig->ret))
6586 static guint8* cached = NULL;
6591 if (mono_aot_only) {
6592 start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
6594 MonoTrampInfo *info;
6595 start = get_delegate_invoke_impl (&info, TRUE, 0, FALSE);
6596 mono_tramp_info_register (info, NULL);
6599 mono_memory_barrier ();
6603 static guint8* cache [MAX_ARCH_DELEGATE_PARAMS + 1] = {NULL};
6606 if (sig->param_count > MAX_ARCH_DELEGATE_PARAMS)
6608 for (i = 0; i < sig->param_count; ++i)
6609 if (!mono_is_regsize_var (sig->params [i]))
6613 code = cache [sig->param_count];
6617 if (mono_aot_only) {
6618 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", sig->param_count);
6619 start = mono_aot_get_trampoline (name);
6622 MonoTrampInfo *info;
6623 start = get_delegate_invoke_impl (&info, FALSE, sig->param_count, FALSE);
6624 mono_tramp_info_register (info, NULL);
6627 mono_memory_barrier ();
6629 cache [sig->param_count] = start;
6634 /*========================= End of Function ========================*/
6636 /*------------------------------------------------------------------*/
6638 /* Name - mono_arch_get_delegate_virtual_invoke_impl. */
6642 /*------------------------------------------------------------------*/
6645 mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method,
6646 int offset, gboolean load_imt_reg)
6648 guint8 *code, *start;
6651 start = code = mono_global_codeman_reserve (size);
6654 * Replace the "this" argument with the target
6656 s390_lgr (code, s390_r1, s390_r2);
6657 s390_lg (code, s390_r2, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, target));
6660 * Load the IMT register, if needed
6663 s390_lg (code, MONO_ARCH_IMT_REG, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, method));
6669 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET(MonoObject, vtable));
6671 s390_agfi(code, s390_r1, offset);
6673 s390_lg (code, s390_r1, 0, s390_r1, 0);
6674 s390_br (code, s390_r1);
6679 /*========================= End of Function ========================*/
6681 /*------------------------------------------------------------------*/
6683 /* Name - mono_arch_build_imt_trampoline. */
6687 /*------------------------------------------------------------------*/
6690 mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain,
6691 MonoIMTCheckItem **imt_entries, int count,
6692 gpointer fail_tramp)
6696 guchar *code, *start;
6699 for (i = 0; i < count; ++i) {
6700 MonoIMTCheckItem *item = imt_entries [i];
6701 if (item->is_equals) {
6702 if (item->check_target_idx) {
6703 if (!item->compare_done)
6704 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6705 if (item->has_target_code)
6706 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE;
6708 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE +
6712 item->chunk_size += CMP_SIZE + 2 * BR_SIZE + JUMP_SIZE +
6714 if (!item->has_target_code)
6715 item->chunk_size += LOAD_SIZE;
6717 item->chunk_size += LOADCON_SIZE + LOAD_SIZE + BR_SIZE;
6718 #if ENABLE_WRONG_METHOD_CHECK
6719 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6724 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6725 imt_entries [item->check_target_idx]->compare_done = TRUE;
6727 size += item->chunk_size;
6731 code = mono_method_alloc_generic_virtual_trampoline (domain, size);
6733 code = mono_domain_code_reserve (domain, size);
6737 for (i = 0; i < count; ++i) {
6738 MonoIMTCheckItem *item = imt_entries [i];
6739 item->code_target = (guint8 *) code;
6740 if (item->is_equals) {
6741 if (item->check_target_idx) {
6742 if (!item->compare_done) {
6743 S390_SET (code, s390_r0, item->key);
6744 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
6746 item->jmp_code = (guint8*) code;
6747 s390_jcl (code, S390_CC_NE, 0);
6749 if (item->has_target_code) {
6750 S390_SET (code, s390_r1, item->value.target_code);
6752 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6753 s390_lg (code, s390_r1, 0, s390_r1, 0);
6755 s390_br (code, s390_r1);
6760 S390_SET (code, s390_r0, item->key);
6761 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
6762 item->jmp_code = (guint8*) code;
6763 s390_jcl (code, S390_CC_NE, 0);
6764 if (item->has_target_code) {
6765 S390_SET (code, s390_r1, item->value.target_code);
6768 S390_SET (code, s390_r1,
6769 (&(vtable->vtable [item->value.vtable_slot])));
6770 s390_lg (code, s390_r1, 0, s390_r1, 0);
6772 s390_br (code, s390_r1);
6773 target = (gint64) S390_RELATIVE(code, item->jmp_code);
6774 s390_patch_rel(item->jmp_code+2, target);
6775 S390_SET (code, s390_r1, fail_tramp);
6776 s390_br (code, s390_r1);
6777 item->jmp_code = NULL;
6779 /* enable the commented code to assert on wrong method */
6780 #if ENABLE_WRONG_METHOD_CHECK
6781 g_assert_not_reached ();
6783 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6784 s390_lg (code, s390_r1, 0, s390_r1, 0);
6785 s390_br (code, s390_r1);
6789 S390_SET (code, s390_r0, item->key);
6790 s390_cgr (code, MONO_ARCH_IMT_REG, s390_r0);
6791 item->jmp_code = (guint8 *) code;
6792 s390_jcl (code, S390_CC_GE, 0);
6796 * patch the branches to get to the target items
6798 for (i = 0; i < count; ++i) {
6799 MonoIMTCheckItem *item = imt_entries [i];
6800 if (item->jmp_code) {
6801 if (item->check_target_idx) {
6803 offset = (gint64) S390_RELATIVE(imt_entries [item->check_target_idx]->code_target,
6805 s390_patch_rel ((guchar *) item->jmp_code + 2, (guint64) offset);
6810 mono_arch_flush_icache ((guint8*)start, (code - start));
6811 mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL);
6814 mono_stats.imt_trampolines_size += (code - start);
6816 g_assert (code - start <= size);
6818 snprintf(trampName, sizeof(trampName), "%d_imt_trampoline", domain->domain_id);
6819 mono_tramp_info_register (mono_tramp_info_create (trampName, start, code - start, NULL, NULL), domain);
6824 /*========================= End of Function ========================*/
6826 /*------------------------------------------------------------------*/
6828 /* Name - mono_arch_find_imt_method. */
6830 /* Function - Get the method address from MONO_ARCH_IMT_REG */
6831 /* found in the save area. */
6833 /*------------------------------------------------------------------*/
6836 mono_arch_find_imt_method (mgreg_t *regs, guint8 *code)
6838 return ((MonoMethod *) regs [MONO_ARCH_IMT_REG]);
6841 /*========================= End of Function ========================*/
6843 /*------------------------------------------------------------------*/
6845 /* Name - mono_arch_find_static_call_vtable */
6847 /* Function - Find the static call vtable. */
6849 /*------------------------------------------------------------------*/
6852 mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
6854 mgreg_t *r = (mgreg_t*)regs;
6856 return (MonoVTable*)(gsize) r [MONO_ARCH_RGCTX_REG];
6859 /*========================= End of Function ========================*/
6861 /*------------------------------------------------------------------*/
6863 /* Name - mono_arch_get_cie_program */
6865 /* Function - Find the static call vtable. */
6867 /*------------------------------------------------------------------*/
6870 mono_arch_get_cie_program (void)
6874 mono_add_unwind_op_def_cfa (l, 0, 0, STK_BASE, 0);
6879 /*========================= End of Function ========================*/
6881 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
6883 /*------------------------------------------------------------------*/
6885 /* Name - mono_arch_set_breakpoint. */
6887 /* Function - Set a breakpoint at the native code corresponding */
6888 /* to JI at NATIVE_OFFSET. The location should */
6889 /* contain code emitted by OP_SEQ_POINT. */
6891 /*------------------------------------------------------------------*/
6894 mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
6898 breakpointCode.pTrigger = bp_trigger_page;
6899 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
6900 code += BREAKPOINT_SIZE;
6903 /*========================= End of Function ========================*/
6905 /*------------------------------------------------------------------*/
6907 /* Name - mono_arch_clear_breakpoint. */
6909 /* Function - Clear the breakpoint at IP. */
6911 /*------------------------------------------------------------------*/
6914 mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
6919 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); i++)
6923 /*========================= End of Function ========================*/
6925 /*------------------------------------------------------------------*/
6927 /* Name - mono_arch_is_breakpoint_event. */
6931 /*------------------------------------------------------------------*/
6934 mono_arch_is_breakpoint_event (void *info, void *sigctx)
6936 siginfo_t* sinfo = (siginfo_t*) info;
6939 * Sometimes the address is off by 4
6941 if (sinfo->si_addr >= bp_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)bp_trigger_page + 128)
6947 /*========================= End of Function ========================*/
6949 /*------------------------------------------------------------------*/
6951 /* Name - mono_arch_skip_breakpoint. */
6953 /* Function - Modify the CTX so the IP is placed after the */
6954 /* breakpoint instruction, so when we resume, the */
6955 /* instruction is not executed again. */
6957 /*------------------------------------------------------------------*/
6960 mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
6962 MONO_CONTEXT_SET_IP (ctx, ((guint8*)MONO_CONTEXT_GET_IP (ctx) + sizeof(RXY_Format)));
6965 /*========================= End of Function ========================*/
6967 /*------------------------------------------------------------------*/
6969 /* Name - mono_arch_start_single_stepping. */
6971 /* Function - Start single stepping. */
6973 /*------------------------------------------------------------------*/
6976 mono_arch_start_single_stepping (void)
6978 mono_mprotect (ss_trigger_page, mono_pagesize (), 0);
6981 /*========================= End of Function ========================*/
6983 /*------------------------------------------------------------------*/
6985 /* Name - mono_arch_stop_single_stepping. */
6987 /* Function - Stop single stepping. */
6989 /*------------------------------------------------------------------*/
6992 mono_arch_stop_single_stepping (void)
6994 mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ);
6997 /*========================= End of Function ========================*/
6999 /*------------------------------------------------------------------*/
7001 /* Name - mono_arch_is_single_step_event. */
7003 /* Function - Return whether the machine state in sigctx cor- */
7004 /* responds to a single step event. */
7006 /*------------------------------------------------------------------*/
7009 mono_arch_is_single_step_event (void *info, void *sigctx)
7011 siginfo_t* sinfo = (siginfo_t*) info;
7014 * Sometimes the address is off by 4
7016 if (sinfo->si_addr >= ss_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)ss_trigger_page + 128)
7022 /*========================= End of Function ========================*/
7024 /*------------------------------------------------------------------*/
7026 /* Name - mono_arch_skip_single_step. */
7028 /* Function - Modify the ctx so the IP is placed after the */
7029 /* single step trigger instruction, so that the */
7030 /* instruction is not executed again. */
7032 /*------------------------------------------------------------------*/
7035 mono_arch_skip_single_step (MonoContext *ctx)
7037 MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + BREAKPOINT_SIZE);
7040 /*========================= End of Function ========================*/
7042 /*------------------------------------------------------------------*/
7044 /* Name - mono_arch_create_seq_point_info. */
7046 /* Function - Return a pointer to a data struction which is */
7047 /* used by the sequence point implementation in */
7050 /*------------------------------------------------------------------*/
7053 mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code)
7059 /*========================= End of Function ========================*/
7061 /*------------------------------------------------------------------*/
7063 /* Name - mono_arch_init_lmf_ext. */
7067 /*------------------------------------------------------------------*/
7070 mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
7072 ext->lmf.previous_lmf = prev_lmf;
7073 /* Mark that this is a MonoLMFExt */
7074 ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
7075 ext->lmf.ebp = (gssize)ext;
7078 /*========================= End of Function ========================*/
7082 /*------------------------------------------------------------------*/
7084 /* Name - mono_arch_cpu_enumerate_simd_versions. */
7086 /* Function - If this CPU supports vector operations then it */
7087 /* supports the equivalent of SSE1-4. */
7089 /*------------------------------------------------------------------*/
7092 mono_arch_cpu_enumerate_simd_versions (void)
7094 guint32 sseOpts = 0;
7096 if (mono_hwcap_s390x_has_vec)
7097 sseOpts = (SIMD_VERSION_SSE1 | SIMD_VERSION_SSE2 |
7098 SIMD_VERSION_SSE3 | SIMD_VERSION_SSSE3 |
7099 SIMD_VERSION_SSE41 | SIMD_VERSION_SSE42 |
7100 SIMD_VERSION_SSE4a);
7105 /*========================= End of Function ========================*/
7107 /*------------------------------------------------------------------*/
7109 /* Name - mono_arch_opcode_supported. */
7111 /* Function - Check if a given return code is supported. */
7113 /*------------------------------------------------------------------*/
7116 mono_arch_opcode_supported (int opcode)
7119 case OP_ATOMIC_ADD_I4:
7120 case OP_ATOMIC_ADD_I8:
7121 case OP_ATOMIC_EXCHANGE_I4:
7122 case OP_ATOMIC_EXCHANGE_I8:
7129 /*========================= End of Function ========================*/