3 * Function - S/390 backend for the Mono code generator.
5 * Name - Neale Ferguson (Neale.Ferguson@SoftwareAG-usa.com)
9 * Derivation - From mini-x86 & mini-ppc by -
10 * Paolo Molaro (lupus@ximian.com)
11 * Dietmar Maurer (dietmar@ximian.com)
15 /*------------------------------------------------------------------*/
17 /*------------------------------------------------------------------*/
19 #define MAX_ARCH_DELEGATE_PARAMS 7
21 #define EMIT_COND_BRANCH(ins,cond) \
23 if (ins->inst_true_bb->native_offset) { \
25 displace = ((cfg->native_code + \
26 ins->inst_true_bb->native_offset) - code) / 2; \
27 if (s390_is_imm16(displace)) { \
28 s390_brc (code, cond, displace); \
30 s390_jcl (code, cond, displace); \
33 mono_add_patch_info (cfg, code - cfg->native_code, \
34 MONO_PATCH_INFO_BB, ins->inst_true_bb); \
35 s390_jcl (code, cond, 0); \
39 #define EMIT_UNCOND_BRANCH(ins) \
41 if (ins->inst_target_bb->native_offset) { \
43 displace = ((cfg->native_code + \
44 ins->inst_target_bb->native_offset) - code) / 2; \
45 if (s390_is_imm16(displace)) { \
46 s390_brc (code, S390_CC_UN, displace); \
48 s390_jcl (code, S390_CC_UN, displace); \
51 mono_add_patch_info (cfg, code - cfg->native_code, \
52 MONO_PATCH_INFO_BB, ins->inst_target_bb); \
53 s390_jcl (code, S390_CC_UN, 0); \
57 #define EMIT_COND_SYSTEM_EXCEPTION(cond,exc_name) \
59 mono_add_patch_info (cfg, code - cfg->native_code, \
60 MONO_PATCH_INFO_EXC, exc_name); \
61 s390_jcl (code, cond, 0); \
64 #define CHECK_SRCDST_COM \
65 if (ins->dreg == ins->sreg2) { \
69 if (ins->dreg != ins->sreg1) { \
70 s390_lgr (code, ins->dreg, ins->sreg1); \
74 #define CHECK_SRCDST_NCOM \
75 if (ins->dreg == ins->sreg2) { \
77 s390_lgr (code, s390_r13, ins->sreg2); \
81 if (ins->dreg != ins->sreg1) { \
82 s390_lgr (code, ins->dreg, ins->sreg1); \
85 #define CHECK_SRCDST_COM_I \
86 if (ins->dreg == ins->sreg2) { \
90 if (ins->dreg != ins->sreg1) { \
91 s390_lgfr (code, ins->dreg, ins->sreg1); \
95 #define CHECK_SRCDST_NCOM_I \
96 if (ins->dreg == ins->sreg2) { \
98 s390_lgfr (code, s390_r13, ins->sreg2); \
102 if (ins->dreg != ins->sreg1) { \
103 s390_lgfr (code, ins->dreg, ins->sreg1); \
106 #define CHECK_SRCDST_COM_F \
107 if (ins->dreg == ins->sreg2) { \
111 if (ins->dreg != ins->sreg1) { \
112 s390_ldr (code, ins->dreg, ins->sreg1); \
116 #define CHECK_SRCDST_NCOM_F \
117 if (ins->dreg == ins->sreg2) { \
119 s390_ldr (code, s390_r13, ins->sreg2); \
123 if (ins->dreg != ins->sreg1) { \
124 s390_ldr (code, ins->dreg, ins->sreg1); \
127 #define MONO_EMIT_NEW_MOVE(cfg,dest,offset,src,imm,size) do { \
130 MONO_INST_NEW (cfg, inst, OP_NOP); \
133 inst->inst_offset = offset; \
135 inst->inst_imm = imm; \
137 if (s390_is_uimm12(offset)) { \
139 inst->inst_offset = offset; \
141 dReg = mono_alloc_preg (cfg); \
142 MONO_EMIT_NEW_BIALU_IMM(cfg, OP_ADD_IMM, \
143 dReg, dest, offset); \
145 inst->inst_offset = 0; \
147 if (s390_is_uimm12(imm)) { \
149 inst->inst_imm = imm; \
151 sReg = mono_alloc_preg (cfg); \
152 MONO_EMIT_NEW_BIALU_IMM(cfg, OP_ADD_IMM, \
154 inst->sreg1 = sReg; \
155 inst->inst_imm = 0; \
158 inst->opcode = OP_S390_MOVE; \
159 inst->backend.size = size; \
160 MONO_ADD_INS (cfg->cbb, inst); \
163 #define MONO_OUTPUT_VTR(cfg, size, dr, sr, so) do { \
164 int reg = mono_alloc_preg (cfg); \
167 MONO_EMIT_NEW_ICONST(cfg, reg, 0); \
170 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU1_MEMBASE, \
174 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU2_MEMBASE, \
178 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI4_MEMBASE, \
182 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI8_MEMBASE, \
186 mono_call_inst_add_outarg_reg(cfg, call, reg, dr, FALSE); \
189 #define MONO_OUTPUT_VTS(cfg, size, dr, dx, sr, so) do { \
193 tmpr = mono_alloc_preg (cfg); \
194 MONO_EMIT_NEW_ICONST(cfg, tmpr, 0); \
195 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
199 tmpr = mono_alloc_preg (cfg); \
200 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU1_MEMBASE, \
202 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
206 tmpr = mono_alloc_preg (cfg); \
207 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU2_MEMBASE, \
209 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
213 tmpr = mono_alloc_preg (cfg); \
214 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI4_MEMBASE, \
216 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
220 MONO_EMIT_NEW_MOVE (cfg, dr, dx, sr, so, size); \
226 #define DEBUG(a) if (cfg->verbose_level > 1) a
230 #define S390_TRACE_STACK_SIZE (5*sizeof(gpointer)+4*sizeof(gdouble))
232 #define BREAKPOINT_SIZE sizeof(breakpoint_t)
233 #define S390X_NOP_SIZE sizeof(RR_Format)
235 #define MAX(a, b) ((a) > (b) ? (a) : (b))
238 * imt trampoline size values
241 #define LOADCON_SIZE 20
245 #define ENABLE_WRONG_METHOD_CHECK 0
247 #define mono_mini_arch_lock() mono_os_mutex_lock (&mini_arch_mutex)
248 #define mono_mini_arch_unlock() mono_os_mutex_unlock (&mini_arch_mutex)
250 /*========================= End of Defines =========================*/
252 /*------------------------------------------------------------------*/
253 /* I n c l u d e s */
254 /*------------------------------------------------------------------*/
258 #include <sys/types.h>
261 #include <mono/metadata/abi-details.h>
262 #include <mono/metadata/appdomain.h>
263 #include <mono/metadata/debug-helpers.h>
264 #include <mono/metadata/profiler-private.h>
265 #include <mono/utils/mono-error.h>
266 #include <mono/utils/mono-error-internals.h>
267 #include <mono/utils/mono-math.h>
268 #include <mono/utils/mono-mmap.h>
269 #include <mono/utils/mono-hwcap.h>
270 #include <mono/utils/mono-threads.h>
272 #include "mini-s390x.h"
273 #include "cpu-s390x.h"
274 #include "support-s390x.h"
275 #include "jit-icalls.h"
280 /*========================= End of Includes ========================*/
282 /*------------------------------------------------------------------*/
283 /* T y p e d e f s */
284 /*------------------------------------------------------------------*/
296 /*------------------------------------------------------------------*/
297 /* Used by the instrument_emit_epilog */
298 /*------------------------------------------------------------------*/
309 typedef struct InstList InstList;
323 RegTypeStructByValInFP,
325 RegTypeStructByAddrOnStack
329 gint32 offset; /* offset from caller's stack */
330 gint32 offparm; /* offset from callee's stack */
331 guint16 vtsize; /* in param area */
334 guint32 size; /* Size of structure used by RegTypeStructByVal */
335 gint32 type; /* Data type of argument */
351 gint64 gr[5]; /* R2-R6 */
352 gdouble fp[3]; /* F0-F2 */
353 } __attribute__ ((__packed__)) RegParm;
361 } __attribute__ ((__packed__)) breakpoint_t;
363 /*========================= End of Typedefs ========================*/
365 /*------------------------------------------------------------------*/
366 /* P r o t o t y p e s */
367 /*------------------------------------------------------------------*/
369 static void indent (int);
370 static guint8 * backUpStackPtr(MonoCompile *, guint8 *);
371 static void decodeParm (MonoType *, void *, int);
372 static void enter_method (MonoMethod *, RegParm *, char *);
373 static void leave_method (MonoMethod *, ...);
374 static inline void add_general (guint *, size_data *, ArgInfo *);
375 static inline void add_stackParm (guint *, size_data *, ArgInfo *, gint);
376 static inline void add_float (guint *, size_data *, ArgInfo *);
377 static CallInfo * get_call_info (MonoCompile *, MonoMemPool *, MonoMethodSignature *);
378 static guchar * emit_float_to_int (MonoCompile *, guchar *, int, int, int, gboolean);
379 static guint8 * emit_load_volatile_arguments (guint8 *, MonoCompile *);
380 static __inline__ void emit_unwind_regs(MonoCompile *, guint8 *, int, int, long);
382 /*========================= End of Prototypes ======================*/
384 /*------------------------------------------------------------------*/
385 /* G l o b a l V a r i a b l e s */
386 /*------------------------------------------------------------------*/
388 int mono_exc_esp_offset = 0;
390 __thread int indent_level = 0;
393 * The code generated for sequence points reads from this location,
394 * which is made read-only when single stepping is enabled.
396 static gpointer ss_trigger_page;
399 * Enabled breakpoints read from this trigger page
401 static gpointer bp_trigger_page;
403 breakpoint_t breakpointCode;
405 static mono_mutex_t mini_arch_mutex;
407 static const char * grNames[] = {
408 "s390_r0", "s390_sp", "s390_r2", "s390_r3", "s390_r4",
409 "s390_r5", "s390_r6", "s390_r7", "s390_r8", "s390_r9",
410 "s390_r10", "s390_r11", "s390_r12", "s390_r13", "s390_r14",
414 static const char * fpNames[] = {
415 "s390_f0", "s390_f1", "s390_f2", "s390_f3", "s390_f4",
416 "s390_f5", "s390_f6", "s390_f7", "s390_f8", "s390_f9",
417 "s390_f10", "s390_f11", "s390_f12", "s390_f13", "s390_f14",
421 static const char * vrNames[] = {
422 "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7",
423 "vr8", "vr9", "vr10", "vr11", "vr12", "vr13", "vr14", "vr15",
424 "vr16", "vr17", "vr18", "vr19", "vr20", "vr21", "vr22", "vr23",
425 "vr24", "vr25", "vr26", "vr27", "vr28", "vr29", "vr30", "vr31"
428 /*====================== End of Global Variables ===================*/
430 /*------------------------------------------------------------------*/
432 /* Name - mono_arch_regname */
434 /* Function - Returns the name of the register specified by */
435 /* the input parameter. */
437 /*------------------------------------------------------------------*/
440 mono_arch_regname (int reg)
442 if (reg >= 0 && reg < 16)
443 return grNames [reg];
448 /*========================= End of Function ========================*/
450 /*------------------------------------------------------------------*/
452 /* Name - mono_arch_fregname */
454 /* Function - Returns the name of the register specified by */
455 /* the input parameter. */
457 /*------------------------------------------------------------------*/
460 mono_arch_fregname (int reg)
462 if (reg >= 0 && reg < 16)
463 return fpNames [reg];
468 /*========================= End of Function ========================*/
470 /*------------------------------------------------------------------*/
472 /* Name - mono_arch_xregname */
474 /* Function - Returns the name of the register specified by */
475 /* the input parameter. */
477 /*------------------------------------------------------------------*/
480 mono_arch_xregname (int reg)
482 if (reg < s390_VR_NREG)
483 return vrNames [reg];
488 /*========================= End of Function ========================*/
490 /*------------------------------------------------------------------*/
492 /* Name - arch_get_argument_info */
494 /* Function - Gathers information on parameters such as size, */
495 /* alignment, and padding. arg_info should be large */
496 /* enough to hold param_count + 1 entries. */
498 /* Parameters - @csig - Method signature */
499 /* @param_count - No. of parameters to consider */
500 /* @arg_info - An array to store the result info */
502 /* Returns - Size of the activation frame */
504 /*------------------------------------------------------------------*/
507 mono_arch_get_argument_info (MonoMethodSignature *csig,
509 MonoJitArgumentInfo *arg_info)
511 int k, frame_size = 0;
512 int size, align, pad;
515 if (MONO_TYPE_ISSTRUCT (csig->ret)) {
516 frame_size += sizeof (gpointer);
520 arg_info [0].offset = offset;
523 frame_size += sizeof (gpointer);
527 arg_info [0].size = frame_size;
529 for (k = 0; k < param_count; k++) {
532 size = mono_type_native_stack_size (csig->params [k], (guint32 *) &align);
534 size = mini_type_stack_size (csig->params [k], &align);
536 frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
537 arg_info [k].pad = pad;
539 arg_info [k + 1].pad = 0;
540 arg_info [k + 1].size = size;
542 arg_info [k + 1].offset = offset;
546 align = MONO_ARCH_FRAME_ALIGNMENT;
547 frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
548 arg_info [k].pad = pad;
553 /*========================= End of Function ========================*/
555 /*------------------------------------------------------------------*/
557 /* Name - emit_unwind_regs. */
559 /* Function - Determines if a value can be returned in one or */
562 /*------------------------------------------------------------------*/
564 static void __inline__
565 emit_unwind_regs(MonoCompile *cfg, guint8 *code, int start, int end, long offset)
569 for (i = start; i < end; i++) {
570 mono_emit_unwind_op_offset (cfg, code, i, offset);
571 mini_gc_set_slot_type_from_cfa (cfg, offset, SLOT_NOREF);
572 offset += sizeof(gulong);
576 /*========================= End of Function ========================*/
578 /*------------------------------------------------------------------*/
580 /* Name - retFitsInReg. */
582 /* Function - Determines if a value can be returned in one or */
585 /*------------------------------------------------------------------*/
587 static inline gboolean
588 retFitsInReg(guint32 size)
603 /*========================= End of Function ========================*/
605 /*------------------------------------------------------------------*/
607 /* Name - backStackPtr. */
609 /* Function - Restore Stack Pointer to previous frame. */
611 /*------------------------------------------------------------------*/
613 static inline guint8 *
614 backUpStackPtr(MonoCompile *cfg, guint8 *code)
616 int stackSize = cfg->stack_usage;
618 if (cfg->frame_reg != STK_BASE)
619 s390_lgr (code, STK_BASE, cfg->frame_reg);
621 if (s390_is_imm16 (stackSize)) {
622 s390_aghi (code, STK_BASE, stackSize);
624 while (stackSize > 32767) {
625 s390_aghi (code, STK_BASE, 32767);
628 s390_aghi (code, STK_BASE, stackSize);
633 /*========================= End of Function ========================*/
635 /*------------------------------------------------------------------*/
639 /* Function - Perform nice indenting to current level */
641 /*------------------------------------------------------------------*/
647 indent_level += diff;
649 printf("%p [%3d] ",(void *)pthread_self(),v);
654 indent_level += diff;
657 /*========================= End of Function ========================*/
659 /*------------------------------------------------------------------*/
661 /* Name - cvtMonoType */
663 /* Function - Convert a mono-type to a string. */
665 /*------------------------------------------------------------------*/
668 cvtMonoType(MonoTypeEnum t)
673 return "MONO_TYPE_END";
675 return "MONO_TYPE_VOID";
676 case MONO_TYPE_BOOLEAN:
677 return "MONO_TYPE_BOOLEAN";
679 return "MONO_TYPE_CHAR";
681 return "MONO_TYPE_I1";
683 return "MONO_TYPE_U1";
685 return "MONO_TYPE_I2";
687 return "MONO_TYPE_U2";
689 return "MONO_TYPE_I4";
691 return "MONO_TYPE_U4";
693 return "MONO_TYPE_I8";
695 return "MONO_TYPE_U8";
697 return "MONO_TYPE_R4";
699 return "MONO_TYPE_R8";
700 case MONO_TYPE_STRING:
701 return "MONO_TYPE_STRING";
703 return "MONO_TYPE_PTR";
704 case MONO_TYPE_BYREF:
705 return "MONO_TYPE_BYREF";
706 case MONO_TYPE_VALUETYPE:
707 return "MONO_TYPE_VALUETYPE";
708 case MONO_TYPE_CLASS:
709 return "MONO_TYPE_CLASS";
711 return "MONO_TYPE_VAR";
712 case MONO_TYPE_ARRAY:
713 return "MONO_TYPE_ARRAY";
714 case MONO_TYPE_GENERICINST:
715 return "MONO_TYPE_GENERICINST";
716 case MONO_TYPE_TYPEDBYREF:
717 return "MONO_TYPE_TYPEDBYREF";
719 return "MONO_TYPE_I";
721 return "MONO_TYPE_U";
722 case MONO_TYPE_FNPTR:
723 return "MONO_TYPE_FNPTR";
724 case MONO_TYPE_OBJECT:
725 return "MONO_TYPE_OBJECT";
726 case MONO_TYPE_SZARRAY:
727 return "MONO_TYPE_SZARRAY";
729 return "MONO_TYPE_MVAR";
730 case MONO_TYPE_CMOD_REQD:
731 return "MONO_TYPE_CMOD_REQD";
732 case MONO_TYPE_CMOD_OPT:
733 return "MONO_TYPE_CMOD_OPT";
734 case MONO_TYPE_INTERNAL:
735 return "MONO_TYPE_INTERNAL";
736 case MONO_TYPE_MODIFIER:
737 return "MONO_TYPE_MODIFIER";
738 case MONO_TYPE_SENTINEL:
739 return "MONO_TYPE_SENTINEL";
740 case MONO_TYPE_PINNED:
741 return "MONO_TYPE_PINNED";
748 /*========================= End of Function ========================*/
750 /*------------------------------------------------------------------*/
752 /* Name - decodeParm */
754 /* Function - Decode a parameter for the trace. */
756 /*------------------------------------------------------------------*/
759 decodeParmString (MonoString *s)
762 char *str = mono_string_to_utf8_checked(s, &error);
763 if (is_ok (&error)) {
764 printf("[STRING:%p:%s], ", s, str);
767 mono_error_cleanup (&error);
768 printf("[STRING:%p:], ", s);
773 decodeParm(MonoType *type, void *curParm, int size)
778 printf("[BYREF:%p], ", *((char **) curParm));
780 simpleType = mini_get_underlying_type(type)->type;
782 switch (simpleType) {
784 printf ("[INTPTR:%p], ", *((int **) curParm));
787 printf ("[UINTPTR:%p], ", *((int **) curParm));
789 case MONO_TYPE_BOOLEAN :
790 printf ("[BOOL:%ld], ", *((gint64 *) curParm));
792 case MONO_TYPE_CHAR :
793 printf ("[CHAR:%c], ", *((int *) curParm));
796 printf ("[INT1:%ld], ", *((gint64 *) curParm));
799 printf ("[INT2:%ld], ", *((gint64 *) curParm));
802 printf ("[INT4:%ld], ", *((gint64 *) curParm));
805 printf ("[UINT1:%lu], ", *((guint64 *) curParm));
808 printf ("[UINT2:%lu], ", *((guint64 *) curParm));
811 printf ("[UINT4:%lu], ", *((guint64 *) curParm));
814 printf ("[UINT8:%lu], ", *((guint64 *) curParm));
816 case MONO_TYPE_STRING : {
817 MonoString *s = *((MonoString **) curParm);
819 g_assert (((MonoObject *) s)->vtable->klass == mono_defaults.string_class);
820 decodeParmString (s);
822 printf("[STRING:null], ");
826 case MONO_TYPE_CLASS :
827 case MONO_TYPE_OBJECT : {
828 MonoObject *obj = *((MonoObject **) curParm);
830 if ((obj) && (obj->vtable)) {
831 printf("[CLASS/OBJ:");
832 klass = obj->vtable->klass;
833 printf("%p [%p] ",obj,curParm);
834 if (klass == mono_defaults.string_class) {
835 decodeParmString ((MonoString *)obj);
836 } else if (klass == mono_defaults.int32_class) {
837 printf("[INT32:%p:%d]",
838 obj, *(gint32 *)((char *)obj + sizeof (MonoObject)));
841 klass->name_space, klass->name, obj);
844 printf("[OBJECT:null], ");
849 printf("[PTR:%p], ", *((gpointer **) (curParm)));
851 case MONO_TYPE_FNPTR :
852 printf("[FNPTR:%p], ", *((gpointer **) (curParm)));
854 case MONO_TYPE_ARRAY :
855 printf("[ARRAY:%p], ", *((gpointer **) (curParm)));
857 case MONO_TYPE_SZARRAY :
858 printf("[SZARRAY:%p], ", *((gpointer **) (curParm)));
861 printf("[INT8:%ld], ", *((gint64 *) (curParm)));
864 printf("[FLOAT4:%g], ", *((float *) (curParm)));
867 printf("[FLOAT8:%g], ", *((double *) (curParm)));
869 case MONO_TYPE_VALUETYPE : {
871 MonoMarshalType *info;
873 if (type->data.klass->enumtype) {
874 simpleType = mono_class_enum_basetype (type->data.klass)->type;
875 printf("{VALUETYPE} - ");
879 info = mono_marshal_load_type_info (type->data.klass);
881 if ((info->native_size == sizeof(float)) &&
882 (info->num_fields == 1) &&
883 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
884 printf("[FLOAT4:%f], ", *((float *) (curParm)));
888 if ((info->native_size == sizeof(double)) &&
889 (info->num_fields == 1) &&
890 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
891 printf("[FLOAT8:%g], ", *((double *) (curParm)));
895 printf("[VALUETYPE:");
896 for (i = 0; i < size; i++)
897 printf("%02x,", *((guint8 *)curParm+i));
901 case MONO_TYPE_TYPEDBYREF: {
903 printf("[TYPEDBYREF:");
904 for (i = 0; i < size; i++)
905 printf("%02x,", *((guint8 *)curParm+i));
910 printf("[%s], ",cvtMonoType(simpleType));
915 /*========================= End of Function ========================*/
917 /*------------------------------------------------------------------*/
919 /* Name - enter_method */
921 /* Function - Perform tracing of the entry to the current */
924 /*------------------------------------------------------------------*/
927 enter_method (MonoMethod *method, RegParm *rParm, char *sp)
929 int i, oParm = 0, iParm = 0;
932 MonoMethodSignature *sig;
939 fname = mono_method_full_name (method, TRUE);
941 printf ("ENTER: %s ", fname);
944 ip = (*(guint64 *) (sp+S390_RET_ADDR_OFFSET));
945 printf ("ip: %p sp: %p - ", (gpointer) ip, sp);
950 sig = mono_method_signature (method);
952 cinfo = get_call_info (NULL, NULL, sig);
954 if (cinfo->struct_ret) {
955 printf ("[STRUCTRET:%p], ", (gpointer) rParm->gr[0]);
960 gpointer *this_arg = (gpointer *) rParm->gr[iParm];
961 obj = (MonoObject *) this_arg;
962 switch(method->klass->this_arg.type) {
963 case MONO_TYPE_VALUETYPE:
965 guint64 *value = (guint64 *) ((uintptr_t)this_arg + sizeof(MonoObject));
966 printf("this:[value:%p:%016lx], ", this_arg, *value);
968 printf ("this:[NULL], ");
970 case MONO_TYPE_STRING:
973 klass = obj->vtable->klass;
974 if (klass == mono_defaults.string_class) {
976 decodeParmString((MonoString *)obj);
978 printf ("this:%p[%s.%s], ",
979 obj, klass->name_space, klass->name);
982 printf("vtable:[NULL], ");
984 printf ("this:[NULL], ");
987 printf("this[%s]: %p, ",cvtMonoType(method->klass->this_arg.type),this_arg);
992 for (i = 0; i < sig->param_count; ++i) {
993 ainfo = &cinfo->args[i + oParm];
994 switch (ainfo->regtype) {
995 case RegTypeGeneral :
996 decodeParm(sig->params[i], &(rParm->gr[ainfo->reg-2]), ainfo->size);
999 decodeParm(sig->params[i], &(rParm->fp[ainfo->reg]), ainfo->size);
1002 decodeParm(sig->params[i], sp+ainfo->offset, ainfo->size);
1004 case RegTypeStructByVal :
1005 if (ainfo->reg != STK_BASE) {
1006 int offset = sizeof(glong) - ainfo->size;
1007 curParm = &(rParm->gr[ainfo->reg-2])+offset;
1010 curParm = sp+ainfo->offset;
1012 if (retFitsInReg (ainfo->vtsize))
1013 decodeParm(sig->params[i],
1017 decodeParm(sig->params[i],
1018 *((char **) curParm),
1021 case RegTypeStructByAddr :
1022 if (ainfo->reg != STK_BASE)
1023 curParm = &(rParm->gr[ainfo->reg-2]);
1025 curParm = sp+ainfo->offset;
1027 decodeParm(sig->params[i],
1028 *((char **) curParm),
1040 /*========================= End of Function ========================*/
1042 /*------------------------------------------------------------------*/
1044 /* Name - leave_method */
1048 /*------------------------------------------------------------------*/
1051 leave_method (MonoMethod *method, ...)
1058 va_start(ap, method);
1060 fname = mono_method_full_name (method, TRUE);
1062 printf ("LEAVE: %s", fname);
1065 type = mono_method_signature (method)->ret;
1068 switch (type->type) {
1069 case MONO_TYPE_VOID:
1071 case MONO_TYPE_BOOLEAN: {
1072 int val = va_arg (ap, int);
1074 printf ("[TRUE:%d]", val);
1080 case MONO_TYPE_CHAR: {
1081 int val = va_arg (ap, int);
1082 printf ("[CHAR:%d]", val);
1085 case MONO_TYPE_I1: {
1086 int val = va_arg (ap, int);
1087 printf ("[INT1:%d]", val);
1090 case MONO_TYPE_U1: {
1091 int val = va_arg (ap, int);
1092 printf ("[UINT1:%d]", val);
1095 case MONO_TYPE_I2: {
1096 int val = va_arg (ap, int);
1097 printf ("[INT2:%d]", val);
1100 case MONO_TYPE_U2: {
1101 int val = va_arg (ap, int);
1102 printf ("[UINT2:%d]", val);
1105 case MONO_TYPE_I4: {
1106 int val = va_arg (ap, int);
1107 printf ("[INT4:%d]", val);
1110 case MONO_TYPE_U4: {
1111 int val = va_arg (ap, int);
1112 printf ("[UINT4:%d]", val);
1116 gint64 val = va_arg (ap, gint64);
1117 printf ("[INT:%ld]", val);
1122 gint64 val = va_arg (ap, gint64);
1123 printf ("[UINT:%lu]", val);
1127 case MONO_TYPE_STRING: {
1128 MonoString *s = va_arg (ap, MonoString *);
1131 g_assert (((MonoObject *)s)->vtable->klass == mono_defaults.string_class);
1132 decodeParmString (s);
1134 printf ("[STRING:null], ");
1137 case MONO_TYPE_CLASS:
1138 case MONO_TYPE_OBJECT: {
1139 MonoObject *o = va_arg (ap, MonoObject *);
1141 if ((o) && (o->vtable)) {
1142 if (o->vtable->klass == mono_defaults.boolean_class) {
1143 printf ("[BOOLEAN:%p:%d]", o, *((guint8 *)o + sizeof (MonoObject)));
1144 } else if (o->vtable->klass == mono_defaults.int32_class) {
1145 printf ("[INT32:%p:%d]", o, *((gint32 *)((char *)o + sizeof (MonoObject))));
1146 } else if (o->vtable->klass == mono_defaults.int64_class) {
1147 printf ("[INT64:%p:%ld]", o, *((gint64 *)((char *)o + sizeof (MonoObject))));
1149 printf ("[%s.%s:%p]", o->vtable->klass->name_space, o->vtable->klass->name, o);
1151 printf ("[OBJECT:%p]", o);
1156 case MONO_TYPE_FNPTR:
1157 case MONO_TYPE_ARRAY:
1158 case MONO_TYPE_SZARRAY: {
1159 gpointer p = va_arg (ap, gpointer);
1160 printf ("[result=%p]", p);
1163 case MONO_TYPE_I8: {
1164 gint64 l = va_arg (ap, gint64);
1165 printf ("[LONG:%ld]", l);
1168 case MONO_TYPE_U8: {
1169 guint64 l = va_arg (ap, guint64);
1170 printf ("[ULONG:%lu]", l);
1173 case MONO_TYPE_R4: {
1174 double f = va_arg (ap, double);
1175 printf ("[FLOAT4:%g]\n", f);
1178 case MONO_TYPE_R8: {
1179 double f = va_arg (ap, double);
1180 printf ("[FLOAT8:%g]\n", f);
1183 case MONO_TYPE_VALUETYPE: {
1184 MonoMarshalType *info;
1185 if (type->data.klass->enumtype) {
1186 type = mono_class_enum_basetype (type->data.klass);
1191 info = mono_marshal_load_type_info (type->data.klass);
1193 if ((info->native_size == sizeof(float)) &&
1194 (info->num_fields == 1) &&
1195 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1196 double f = va_arg (ap, double);
1197 printf("[FLOAT4:%g]\n", (double) f);
1201 if ((info->native_size == sizeof(double)) &&
1202 (info->num_fields == 1) &&
1203 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1204 double f = va_arg (ap, double);
1205 printf("[FLOAT8:%g]\n", f);
1209 size = mono_type_size (type, &align);
1212 guint32 p = va_arg (ap, guint32);
1213 printf ("[%02x]\n",p);
1217 guint32 p = va_arg (ap, guint32);
1218 printf ("[%04x]\n",p);
1222 guint32 p = va_arg (ap, guint32);
1223 printf ("[%08x]\n",p);
1227 guint64 p = va_arg (ap, guint64);
1228 printf ("[%016lx]\n",p);
1232 gpointer p = va_arg (ap, gpointer);
1233 printf ("[VALUETYPE] %p\n",p);
1239 case MONO_TYPE_TYPEDBYREF: {
1240 guint8 *p = va_arg (ap, gpointer);
1242 size = mono_type_size (type, &align);
1249 for (j = 0; p && j < size; j++)
1250 printf ("%02x,", p [j]);
1254 printf ("[TYPEDBYREF]\n");
1258 case MONO_TYPE_GENERICINST: {
1259 printf("[GENERICINST]\n");
1262 case MONO_TYPE_MVAR: {
1266 case MONO_TYPE_CMOD_REQD: {
1267 printf("[CMOD_REQD]\n");
1270 case MONO_TYPE_CMOD_OPT: {
1271 printf("[CMOD_OPT]\n");
1274 case MONO_TYPE_INTERNAL: {
1275 printf("[INTERNAL]\n");
1279 printf ("(unknown return type %x)",
1280 mono_method_signature (method)->ret->type);
1283 ip = ((gint64) __builtin_extract_return_addr (__builtin_return_address (0)));
1284 printf (" ip: %p\n", (gpointer) ip);
1288 /*========================= End of Function ========================*/
1290 /*------------------------------------------------------------------*/
1292 /* Name - mono_arch_cpu_init */
1294 /* Function - Perform CPU specific initialization to execute */
1297 /*------------------------------------------------------------------*/
1300 mono_arch_cpu_init (void)
1304 /*========================= End of Function ========================*/
1306 /*------------------------------------------------------------------*/
1308 /* Name - mono_arch_init. */
1310 /* Function - Initialize architecture specific code. */
1312 /*------------------------------------------------------------------*/
1315 mono_arch_init (void)
1319 mono_set_partial_sharing_supported (FALSE);
1320 mono_os_mutex_init_recursive (&mini_arch_mutex);
1322 ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ, MONO_MEM_ACCOUNT_OTHER);
1323 bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ, MONO_MEM_ACCOUNT_OTHER);
1324 mono_mprotect (bp_trigger_page, mono_pagesize (), 0);
1326 code = (guint8 *) &breakpointCode;
1327 s390_basr(code, s390_r13, 0);
1329 s390_llong(code, 0);
1330 s390_lg(code, s390_r13, 0, s390_r13, 4);
1331 s390_lg(code, s390_r0, 0, s390_r13, 0);
1334 /*========================= End of Function ========================*/
1336 /*------------------------------------------------------------------*/
1338 /* Name - mono_arch_cleanup. */
1340 /* Function - Cleanup architecture specific code . */
1342 /*------------------------------------------------------------------*/
1345 mono_arch_cleanup (void)
1347 if (ss_trigger_page)
1348 mono_vfree (ss_trigger_page, mono_pagesize (), MONO_MEM_ACCOUNT_OTHER);
1349 if (bp_trigger_page)
1350 mono_vfree (bp_trigger_page, mono_pagesize (), MONO_MEM_ACCOUNT_OTHER);
1351 mono_os_mutex_destroy (&mini_arch_mutex);
1354 /*========================= End of Function ========================*/
1356 /*------------------------------------------------------------------*/
1358 /* Name - mono_arch_have_fast_tls */
1360 /* Function - Returns whether we use fast inlined thread local */
1361 /* storage managed access, instead of falling back */
1362 /* to native code. */
1364 /*------------------------------------------------------------------*/
1367 mono_arch_have_fast_tls (void)
1372 /*========================= End of Function ========================*/
1374 /*------------------------------------------------------------------*/
1376 /* Name - mono_arch_cpu_optimizations */
1378 /* Function - Returns the optimizations supported on this CPU */
1380 /*------------------------------------------------------------------*/
1383 mono_arch_cpu_optimizations (guint32 *exclude_mask)
1387 /*----------------------------------------------------------*/
1388 /* No s390-specific optimizations yet */
1389 /*----------------------------------------------------------*/
1390 *exclude_mask = MONO_OPT_LINEARS;
1394 /*========================= End of Function ========================*/
1396 /*------------------------------------------------------------------*/
1398 /* Name - mono_arch_get_allocatable_int_vars */
1402 /*------------------------------------------------------------------*/
1405 mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
1410 for (i = 0; i < cfg->num_varinfo; i++) {
1411 MonoInst *ins = cfg->varinfo [i];
1412 MonoMethodVar *vmv = MONO_VARINFO (cfg, i);
1415 if (vmv->range.first_use.abs_pos >= vmv->range.last_use.abs_pos)
1418 if (ins->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) ||
1419 (ins->opcode != OP_LOCAL && ins->opcode != OP_ARG))
1422 /* we can only allocate 32 bit values */
1423 if (mono_is_regsize_var(ins->inst_vtype)) {
1424 g_assert (MONO_VARINFO (cfg, i)->reg == -1);
1425 g_assert (i == vmv->idx);
1426 vars = mono_varlist_insert_sorted (cfg, vars, vmv, FALSE);
1433 /*========================= End of Function ========================*/
1435 /*------------------------------------------------------------------*/
1437 /* Name - mono_arch_global_int_regs */
1439 /* Function - Return a list of usable integer registers. */
1441 /*------------------------------------------------------------------*/
1444 mono_arch_get_global_int_regs (MonoCompile *cfg)
1447 MonoMethodHeader *header;
1450 header = cfg->header;
1451 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
1452 cfg->frame_reg = s390_r11;
1455 /* FIXME: s390_r12 is reserved for bkchain_reg. Only reserve it if needed */
1457 for (i = 8; i < top; ++i) {
1458 if (cfg->frame_reg != i)
1459 regs = g_list_prepend (regs, GUINT_TO_POINTER (i));
1465 /*========================= End of Function ========================*/
1467 /*------------------------------------------------------------------*/
1469 /* Name - mono_arch_flush_icache */
1471 /* Function - Flush the CPU icache. */
1473 /*------------------------------------------------------------------*/
1476 mono_arch_flush_icache (guint8 *code, gint size)
1480 /*========================= End of Function ========================*/
1482 /*------------------------------------------------------------------*/
1484 /* Name - add_general */
1486 /* Function - Determine code and stack size incremements for a */
1489 /*------------------------------------------------------------------*/
1492 add_general (guint *gr, size_data *sz, ArgInfo *ainfo)
1494 if (*gr > S390_LAST_ARG_REG) {
1495 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1496 ainfo->offset = sz->stack_size;
1497 ainfo->reg = STK_BASE;
1498 ainfo->regtype = RegTypeBase;
1499 sz->stack_size += sizeof(long);
1500 sz->local_size += sizeof(long);
1501 sz->offStruct += sizeof(long);
1502 sz->code_size += 12;
1510 /*========================= End of Function ========================*/
1512 /*------------------------------------------------------------------*/
1514 /* Name - add_stackParm */
1516 /* Function - Determine code and stack size incremements for a */
1519 /*------------------------------------------------------------------*/
1522 add_stackParm (guint *gr, size_data *sz, ArgInfo *ainfo, gint size)
1524 if (*gr > S390_LAST_ARG_REG) {
1525 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1526 ainfo->reg = STK_BASE;
1527 ainfo->offset = sz->stack_size;
1528 ainfo->regtype = RegTypeStructByAddrOnStack;
1529 sz->stack_size += sizeof (gpointer);
1530 sz->parm_size += sizeof(gpointer);
1531 sz->offStruct += sizeof(gpointer);
1534 ainfo->offset = sz->stack_size;
1535 ainfo->regtype = RegTypeStructByAddr;
1538 ainfo->offparm = sz->offset;
1539 sz->offset = S390_ALIGN(sz->offset+size, sizeof(long));
1541 ainfo->vtsize = size;
1542 sz->parm_size += size;
1545 /*========================= End of Function ========================*/
1547 /*------------------------------------------------------------------*/
1549 /* Name - add_float */
1551 /* Function - Determine code and stack size incremements for a */
1552 /* float parameter. */
1554 /*------------------------------------------------------------------*/
1557 add_float (guint *fr, size_data *sz, ArgInfo *ainfo)
1559 if ((*fr) <= S390_LAST_FPARG_REG) {
1560 ainfo->regtype = RegTypeFP;
1566 ainfo->offset = sz->stack_size;
1567 ainfo->reg = STK_BASE;
1568 ainfo->regtype = RegTypeBase;
1570 sz->stack_size += sizeof(double);
1571 sz->local_size += sizeof(double);
1572 sz->offStruct += sizeof(double);
1576 /*========================= End of Function ========================*/
1578 /*------------------------------------------------------------------*/
1580 /* Name - get_call_info */
1582 /* Function - Determine the amount of space required for code */
1583 /* and stack. In addition determine starting points */
1584 /* for stack-based parameters, and area for struct- */
1585 /* ures being returned on the stack. */
1587 /*------------------------------------------------------------------*/
1590 get_call_info (MonoCompile *cfg, MonoMemPool *mp, MonoMethodSignature *sig)
1592 guint i, fr, gr, size, pstart;
1593 int nParm = sig->hasthis + sig->param_count;
1595 guint32 simpleType, align;
1596 gboolean is_pinvoke = sig->pinvoke;
1601 cinfo = mono_mempool_alloc0 (mp, sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1603 cinfo = g_malloc0 (sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1608 cinfo->struct_ret = 0;
1612 sz->offStruct = S390_MINIMAL_STACK_SIZE;
1613 sz->stack_size = S390_MINIMAL_STACK_SIZE;
1620 /*----------------------------------------------------------*/
1621 /* We determine the size of the return code/stack in case we*/
1622 /* need to reserve a register to be used to address a stack */
1623 /* area that the callee will use. */
1624 /*----------------------------------------------------------*/
1626 ret_type = mini_get_underlying_type (sig->ret);
1627 simpleType = ret_type->type;
1629 switch (simpleType) {
1638 case MONO_TYPE_OBJECT:
1640 case MONO_TYPE_FNPTR:
1641 cinfo->ret.reg = s390_r2;
1646 cinfo->ret.reg = s390_f0;
1651 cinfo->ret.reg = s390_r2;
1654 case MONO_TYPE_GENERICINST:
1655 if (!mono_type_generic_inst_is_valuetype (sig->ret)) {
1656 cinfo->ret.reg = s390_r2;
1661 case MONO_TYPE_VALUETYPE: {
1662 MonoClass *klass = mono_class_from_mono_type (sig->ret);
1663 if (klass->enumtype) {
1664 simpleType = mono_class_enum_basetype (klass)->type;
1667 size = mini_type_stack_size_full (&klass->byval_arg, NULL, sig->pinvoke);
1669 cinfo->struct_ret = 1;
1670 cinfo->ret.size = size;
1671 cinfo->ret.vtsize = size;
1674 case MONO_TYPE_TYPEDBYREF:
1675 size = sizeof (MonoTypedRef);
1676 cinfo->struct_ret = 1;
1677 cinfo->ret.size = size;
1678 cinfo->ret.vtsize = size;
1680 case MONO_TYPE_VOID:
1683 g_error ("Can't handle as return value 0x%x", sig->ret->type);
1689 * To simplify get_this_arg_reg () and LLVM integration, emit the vret arg after
1690 * the first argument, allowing 'this' to be always passed in the first arg reg.
1691 * Also do this if the first argument is a reference type, since virtual calls
1692 * are sometimes made using calli without sig->hasthis set, like in the delegate
1695 if (cinfo->struct_ret && !is_pinvoke &&
1697 (sig->param_count > 0 &&
1698 MONO_TYPE_IS_REFERENCE (mini_get_underlying_type (sig->params [0]))))) {
1700 cinfo->args[nParm].size = sizeof (gpointer);
1701 add_general (&gr, sz, cinfo->args + nParm);
1703 cinfo->args[nParm].size = sizeof (gpointer);
1704 add_general (&gr, sz, &cinfo->args [sig->hasthis + nParm]);
1708 cinfo->vret_arg_index = 1;
1709 cinfo->ret.reg = gr;
1714 cinfo->args[nParm].size = sizeof (gpointer);
1715 add_general (&gr, sz, cinfo->args + nParm);
1719 if (cinfo->struct_ret) {
1720 cinfo->ret.reg = gr;
1725 if ((sig->call_convention == MONO_CALL_VARARG) && (sig->param_count == 0)) {
1726 gr = S390_LAST_ARG_REG + 1;
1727 fr = S390_LAST_FPARG_REG + 1;
1729 /* Emit the signature cookie just before the implicit arguments */
1730 add_general (&gr, sz, &cinfo->sigCookie);
1733 /*----------------------------------------------------------*/
1734 /* We determine the size of the parameter code and stack */
1735 /* requirements by checking the types and sizes of the */
1737 /*----------------------------------------------------------*/
1739 for (i = pstart; i < sig->param_count; ++i) {
1742 /*--------------------------------------------------*/
1743 /* Handle vararg type calls. All args are put on */
1745 /*--------------------------------------------------*/
1746 if ((sig->call_convention == MONO_CALL_VARARG) &&
1747 (i == sig->sentinelpos)) {
1748 gr = S390_LAST_ARG_REG + 1;
1749 fr = S390_LAST_FPARG_REG + 1;
1750 add_general (&gr, sz, &cinfo->sigCookie);
1753 if (sig->params [i]->byref) {
1754 add_general (&gr, sz, cinfo->args+nParm);
1755 cinfo->args[nParm].size = sizeof(gpointer);
1760 ptype = mini_get_underlying_type (sig->params [i]);
1761 simpleType = ptype->type;
1762 cinfo->args[nParm].type = simpleType;
1763 switch (simpleType) {
1766 cinfo->args[nParm].size = sizeof(char);
1767 add_general (&gr, sz, cinfo->args+nParm);
1772 cinfo->args[nParm].size = sizeof(short);
1773 add_general (&gr, sz, cinfo->args+nParm);
1778 cinfo->args[nParm].size = sizeof(int);
1779 add_general (&gr, sz, cinfo->args+nParm);
1785 case MONO_TYPE_FNPTR:
1786 case MONO_TYPE_OBJECT:
1787 cinfo->args[nParm].size = sizeof(gpointer);
1788 add_general (&gr, sz, cinfo->args+nParm);
1793 cinfo->args[nParm].size = sizeof(long long);
1794 add_general (&gr, sz, cinfo->args+nParm);
1798 cinfo->args[nParm].size = sizeof(float);
1799 add_float (&fr, sz, cinfo->args+nParm);
1803 cinfo->args[nParm].size = sizeof(double);
1804 add_float (&fr, sz, cinfo->args+nParm);
1807 case MONO_TYPE_GENERICINST:
1808 if (!mono_type_generic_inst_is_valuetype (ptype)) {
1809 cinfo->args[nParm].size = sizeof(gpointer);
1810 add_general (&gr, sz, cinfo->args+nParm);
1815 case MONO_TYPE_VALUETYPE: {
1816 MonoMarshalType *info;
1817 MonoClass *klass = mono_class_from_mono_type (ptype);
1820 size = mono_class_native_size(klass, NULL);
1822 size = mono_class_value_size(klass, NULL);
1824 if (simpleType != MONO_TYPE_GENERICINST) {
1825 info = mono_marshal_load_type_info(klass);
1827 if ((info->native_size == sizeof(float)) &&
1828 (info->num_fields == 1) &&
1829 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1830 cinfo->args[nParm].size = sizeof(float);
1831 add_float(&fr, sz, cinfo->args+nParm);
1836 if ((info->native_size == sizeof(double)) &&
1837 (info->num_fields == 1) &&
1838 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1839 cinfo->args[nParm].size = sizeof(double);
1840 add_float(&fr, sz, cinfo->args+nParm);
1846 cinfo->args[nParm].vtsize = 0;
1847 cinfo->args[nParm].size = 0;
1850 /*----------------------------------*/
1851 /* On S/390, structures of size 1, */
1852 /* 2, 4, and 8 bytes are passed in */
1853 /* (a) register(s). */
1854 /*----------------------------------*/
1860 add_general(&gr, sz, cinfo->args+nParm);
1861 cinfo->args[nParm].size = size;
1862 cinfo->args[nParm].regtype = RegTypeStructByVal;
1864 sz->local_size += sizeof(long);
1867 add_stackParm(&gr, sz, cinfo->args+nParm, size);
1872 case MONO_TYPE_TYPEDBYREF: {
1873 int size = sizeof (MonoTypedRef);
1875 cinfo->args[nParm].vtsize = 0;
1876 cinfo->args[nParm].size = 0;
1879 /*----------------------------------*/
1880 /* On S/390, structures of size 1, */
1881 /* 2, 4, and 8 bytes are passed in */
1882 /* (a) register(s). */
1883 /*----------------------------------*/
1889 add_general(&gr, sz, cinfo->args+nParm);
1890 cinfo->args[nParm].size = size;
1891 cinfo->args[nParm].regtype = RegTypeStructByVal;
1893 sz->local_size += sizeof(long);
1896 add_stackParm(&gr, sz, cinfo->args+nParm, size);
1902 g_error ("Can't trampoline 0x%x", ptype);
1906 /*----------------------------------------------------------*/
1907 /* Handle the case where there are no implicit arguments */
1908 /*----------------------------------------------------------*/
1909 if ((sig->call_convention == MONO_CALL_VARARG) &&
1912 (sig->param_count == sig->sentinelpos)) {
1913 gr = S390_LAST_ARG_REG + 1;
1914 fr = S390_LAST_FPARG_REG + 1;
1915 add_general (&gr, sz, &cinfo->sigCookie);
1918 /*----------------------------------------------------------*/
1919 /* If we are passing a structure back then if it won't be */
1920 /* in a register(s) then we make room at the end of the */
1921 /* parameters that may have been placed on the stack */
1922 /*----------------------------------------------------------*/
1923 if (cinfo->struct_ret) {
1924 cinfo->ret.offset = sz->stack_size;
1925 switch (cinfo->ret.size) {
1933 sz->stack_size += S390_ALIGN(cinfo->ret.size, align);
1938 sz->stack_size = sz->stack_size + sz->local_size + sz->parm_size +
1940 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1945 /*========================= End of Function ========================*/
1947 /*------------------------------------------------------------------*/
1949 /* Name - mono_arch_allocate_vars */
1951 /* Function - Set var information according to the calling */
1952 /* convention for S/390. The local var stuff should */
1953 /* most likely be split in another method. */
1955 /* Parameter - @m - Compile unit. */
1957 /*------------------------------------------------------------------*/
1960 mono_arch_allocate_vars (MonoCompile *cfg)
1962 MonoMethodSignature *sig;
1963 MonoMethodHeader *header;
1966 int iParm, iVar, offset, align, size, curinst;
1967 int frame_reg = STK_BASE;
1970 header = cfg->header;
1972 cfg->flags |= MONO_CFG_HAS_SPILLUP;
1974 /*---------------------------------------------------------*/
1975 /* We use the frame register also for any method that has */
1976 /* filter clauses. This way, when the handlers are called, */
1977 /* the code will reference local variables using the frame */
1978 /* reg instead of the stack pointer: if we had to restore */
1979 /* the stack pointer, we'd corrupt the method frames that */
1980 /* are already on the stack (since filters get called */
1981 /* before stack unwinding happens) when the filter code */
1982 /* would call any method. */
1983 /*---------------------------------------------------------*/
1984 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
1985 frame_reg = s390_r11;
1987 cfg->frame_reg = frame_reg;
1989 cfg->arch.bkchain_reg = -1;
1991 if (frame_reg != STK_BASE)
1992 cfg->used_int_regs |= (1 << frame_reg);
1994 if (cfg->uses_rgctx_reg)
1995 cfg->used_int_regs |= (1 << MONO_ARCH_IMT_REG);
1997 sig = mono_method_signature (cfg->method);
1999 cinfo = get_call_info (cfg, cfg->mempool, sig);
2001 if (!cinfo->struct_ret) {
2002 switch (mini_get_underlying_type (sig->ret)->type) {
2003 case MONO_TYPE_VOID:
2006 cfg->ret->opcode = OP_REGVAR;
2007 cfg->ret->dreg = s390_r2;
2012 /*--------------------------------------------------------------*/
2013 /* local vars are at a positive offset from the stack pointer */
2014 /* also note that if the function uses alloca, we use s390_r11 */
2015 /* to point at the local variables. */
2016 /* add parameter area size for called functions */
2017 /*--------------------------------------------------------------*/
2018 if (cfg->param_area == 0)
2019 offset = S390_MINIMAL_STACK_SIZE;
2021 offset = cfg->param_area;
2023 cfg->sig_cookie = 0;
2025 if (cinfo->struct_ret) {
2026 inst = cfg->vret_addr;
2027 offset = S390_ALIGN(offset, sizeof(gpointer));
2028 inst->inst_offset = offset;
2029 inst->opcode = OP_REGOFFSET;
2030 inst->inst_basereg = frame_reg;
2031 offset += sizeof(gpointer);
2032 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2033 printf ("vret_addr =");
2034 mono_print_ins (cfg->vret_addr);
2039 inst = cfg->args [0];
2040 if (inst->opcode != OP_REGVAR) {
2041 inst->opcode = OP_REGOFFSET;
2042 inst->inst_basereg = frame_reg;
2043 offset = S390_ALIGN(offset, sizeof(gpointer));
2044 inst->inst_offset = offset;
2045 offset += sizeof (gpointer);
2052 eArg = sig->param_count + sArg;
2054 if (sig->call_convention == MONO_CALL_VARARG)
2055 cfg->sig_cookie += S390_MINIMAL_STACK_SIZE;
2057 for (iParm = sArg; iParm < eArg; ++iParm) {
2058 inst = cfg->args [curinst];
2059 if (inst->opcode != OP_REGVAR) {
2060 switch (cinfo->args[iParm].regtype) {
2061 case RegTypeStructByAddr : {
2064 size = sizeof (gpointer);
2066 inst->opcode = OP_REGOFFSET;
2067 inst->inst_basereg = frame_reg;
2068 offset = S390_ALIGN (offset, sizeof (gpointer));
2069 inst->inst_offset = offset;
2071 /* Add a level of indirection */
2072 MONO_INST_NEW (cfg, indir, 0);
2074 inst->opcode = OP_VTARG_ADDR;
2075 inst->inst_left = indir;
2078 case RegTypeStructByAddrOnStack : {
2081 size = sizeof (gpointer);
2083 /* Similar to the == STK_BASE case below */
2084 cfg->arch.bkchain_reg = s390_r12;
2085 cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2087 inst->opcode = OP_REGOFFSET;
2088 inst->dreg = mono_alloc_preg (cfg);
2089 inst->inst_basereg = cfg->arch.bkchain_reg;
2090 inst->inst_offset = cinfo->args [iParm].offset;
2092 /* Add a level of indirection */
2093 MONO_INST_NEW (cfg, indir, 0);
2095 inst->opcode = OP_VTARG_ADDR;
2096 inst->inst_left = indir;
2099 case RegTypeStructByVal :
2100 size = cinfo->args[iParm].size;
2101 offset = S390_ALIGN(offset, size);
2102 inst->opcode = OP_REGOFFSET;
2103 inst->inst_basereg = frame_reg;
2104 inst->inst_offset = offset;
2107 if (cinfo->args [iParm].reg == STK_BASE) {
2109 * These arguments are in the previous frame, so we can't
2110 * compute their offset from the current frame pointer right
2111 * now, since cfg->stack_offset is not yet known, so dedicate a
2112 * register holding the previous frame pointer.
2114 cfg->arch.bkchain_reg = s390_r12;
2115 cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2117 inst->opcode = OP_REGOFFSET;
2118 inst->inst_basereg = cfg->arch.bkchain_reg;
2119 size = (cinfo->args[iParm].size < 8
2120 ? 8 - cinfo->args[iParm].size
2122 inst->inst_offset = cinfo->args [iParm].offset + size;
2123 size = sizeof (long);
2125 inst->opcode = OP_REGOFFSET;
2126 inst->inst_basereg = frame_reg;
2127 size = (cinfo->args[iParm].size < 8
2130 offset = S390_ALIGN(offset, size);
2131 if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
2132 inst->inst_offset = offset;
2134 inst->inst_offset = offset + (8 - size);
2139 if ((sig->call_convention == MONO_CALL_VARARG) &&
2140 (cinfo->args[iParm].regtype != RegTypeGeneral) &&
2141 (iParm < sig->sentinelpos))
2142 cfg->sig_cookie += size;
2143 printf("%s %4d cookine %x\n",__FUNCTION__,__LINE__,cfg->sig_cookie);
2146 offset += MAX(size, 8);
2151 cfg->locals_min_stack_offset = offset;
2153 curinst = cfg->locals_start;
2154 for (iVar = curinst; iVar < cfg->num_varinfo; ++iVar) {
2155 inst = cfg->varinfo [iVar];
2156 if ((inst->flags & MONO_INST_IS_DEAD) ||
2157 (inst->opcode == OP_REGVAR))
2160 /*--------------------------------------------------*/
2161 /* inst->backend.is_pinvoke indicates native sized */
2162 /* value typs this is used by the pinvoke wrappers */
2163 /* when they call functions returning structure */
2164 /*--------------------------------------------------*/
2165 if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype))
2166 size = mono_class_native_size (mono_class_from_mono_type(inst->inst_vtype),
2167 (guint32 *) &align);
2169 size = mono_type_size (inst->inst_vtype, &align);
2171 offset = S390_ALIGN(offset, align);
2172 inst->inst_offset = offset;
2173 inst->opcode = OP_REGOFFSET;
2174 inst->inst_basereg = frame_reg;
2176 DEBUG (g_print("allocating local %d to %ld, size: %d\n",
2177 iVar, inst->inst_offset, size));
2180 cfg->locals_max_stack_offset = offset;
2182 /*------------------------------------------------------*/
2183 /* Allow space for the trace method stack area if needed*/
2184 /*------------------------------------------------------*/
2185 if ((mono_jit_trace_calls != NULL && mono_trace_eval (cfg->method)))
2186 offset += S390_TRACE_STACK_SIZE;
2188 /*------------------------------------------------------*/
2189 /* Reserve space to save LMF and caller saved registers */
2190 /*------------------------------------------------------*/
2191 if (cfg->method->save_lmf)
2192 offset += sizeof (MonoLMF);
2194 /*------------------------------------------------------*/
2195 /* align the offset */
2196 /*------------------------------------------------------*/
2197 cfg->stack_offset = S390_ALIGN(offset, S390_STACK_ALIGNMENT);
2199 /*------------------------------------------------------*/
2200 /* Fix offsets for args whose value is in parent frame */
2201 /*------------------------------------------------------*/
2202 for (iParm = sArg; iParm < eArg; ++iParm) {
2203 inst = cfg->args [iParm];
2205 if (inst->opcode == OP_S390_STKARG) {
2206 inst->opcode = OP_REGOFFSET;
2207 inst->inst_offset += cfg->stack_offset;
2212 /*========================= End of Function ========================*/
2214 /*------------------------------------------------------------------*/
2216 /* Name - mono_arch_create_vars */
2218 /*------------------------------------------------------------------*/
2221 mono_arch_create_vars (MonoCompile *cfg)
2223 MonoMethodSignature *sig;
2226 sig = mono_method_signature (cfg->method);
2228 cinfo = get_call_info (cfg, cfg->mempool, sig);
2230 if (cinfo->struct_ret) {
2231 cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG);
2232 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2233 printf ("vret_addr = ");
2234 mono_print_ins (cfg->vret_addr);
2239 /*========================= End of Function ========================*/
2241 /*------------------------------------------------------------------*/
2243 /* Name - add_outarg_reg2. */
2245 /*------------------------------------------------------------------*/
2248 add_outarg_reg2 (MonoCompile *cfg, MonoCallInst *call, ArgStorage storage, int reg, MonoInst *tree)
2253 case RegTypeGeneral:
2254 MONO_INST_NEW (cfg, ins, OP_MOVE);
2255 ins->dreg = mono_alloc_ireg (cfg);
2256 ins->sreg1 = tree->dreg;
2257 MONO_ADD_INS (cfg->cbb, ins);
2258 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, FALSE);
2261 MONO_INST_NEW (cfg, ins, OP_FMOVE);
2262 ins->dreg = mono_alloc_freg (cfg);
2263 ins->sreg1 = tree->dreg;
2264 MONO_ADD_INS (cfg->cbb, ins);
2265 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2268 MONO_INST_NEW (cfg, ins, OP_S390_SETF4RET);
2269 ins->dreg = mono_alloc_freg (cfg);
2270 ins->sreg1 = tree->dreg;
2271 MONO_ADD_INS (cfg->cbb, ins);
2272 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2275 g_assert_not_reached ();
2279 /*========================= End of Function ========================*/
2281 /*------------------------------------------------------------------*/
2283 /* Name - emit_sig_cookie. */
2285 /*------------------------------------------------------------------*/
2288 emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo)
2290 MonoMethodSignature *tmpSig;
2293 cfg->disable_aot = TRUE;
2295 /*----------------------------------------------------------*/
2296 /* mono_ArgIterator_Setup assumes the signature cookie is */
2297 /* passed first and all the arguments which were before it */
2298 /* passed on the stack after the signature. So compensate */
2299 /* by passing a different signature. */
2300 /*----------------------------------------------------------*/
2301 tmpSig = mono_metadata_signature_dup (call->signature);
2302 tmpSig->param_count -= call->signature->sentinelpos;
2303 tmpSig->sentinelpos = 0;
2304 if (tmpSig->param_count > 0)
2305 memcpy (tmpSig->params,
2306 call->signature->params + call->signature->sentinelpos,
2307 tmpSig->param_count * sizeof(MonoType *));
2309 MONO_INST_NEW (cfg, sig_arg, OP_ICONST);
2310 sig_arg->dreg = mono_alloc_ireg (cfg);
2311 sig_arg->inst_p0 = tmpSig;
2312 MONO_ADD_INS (cfg->cbb, sig_arg);
2314 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, STK_BASE,
2315 cinfo->sigCookie.offset, sig_arg->dreg);
2318 /*========================= End of Function ========================*/
2320 /*------------------------------------------------------------------*/
2322 /* Name - mono_arch_emit_call */
2324 /*------------------------------------------------------------------*/
2327 mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
2330 MonoMethodSignature *sig;
2332 int i, n, lParamArea;
2334 ArgInfo *ainfo = NULL;
2336 MonoMethodHeader *header;
2339 sig = call->signature;
2340 n = sig->param_count + sig->hasthis;
2341 DEBUG (g_print ("Call requires: %d parameters\n",n));
2343 cinfo = get_call_info (cfg, cfg->mempool, sig);
2345 stackSize = cinfo->sz.stack_size + cinfo->sz.local_size +
2346 cinfo->sz.parm_size + cinfo->sz.offset;
2347 call->stack_usage = MAX(stackSize, call->stack_usage);
2348 lParamArea = MAX((call->stack_usage-S390_MINIMAL_STACK_SIZE-cinfo->sz.parm_size), 0);
2349 cfg->param_area = MAX(((signed) cfg->param_area), lParamArea);
2350 cfg->flags |= MONO_CFG_HAS_CALLS;
2352 if (cinfo->struct_ret) {
2353 MONO_INST_NEW (cfg, ins, OP_MOVE);
2354 ins->sreg1 = call->vret_var->dreg;
2355 ins->dreg = mono_alloc_preg (cfg);
2356 MONO_ADD_INS (cfg->cbb, ins);
2357 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, cinfo->ret.reg, FALSE);
2360 header = cfg->header;
2361 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2366 for (i = 0; i < n; ++i) {
2369 ainfo = cinfo->args + i;
2370 if (i >= sig->hasthis)
2371 t = sig->params [i - sig->hasthis];
2373 t = &mono_defaults.int_class->byval_arg;
2374 t = mini_get_underlying_type (t);
2376 in = call->args [i];
2378 if ((sig->call_convention == MONO_CALL_VARARG) &&
2380 (i == sig->sentinelpos)) {
2381 emit_sig_cookie (cfg, call, cinfo);
2384 switch (ainfo->regtype) {
2385 case RegTypeGeneral:
2386 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2389 if (MONO_TYPE_ISSTRUCT (t)) {
2390 /* Valuetype passed in one fp register */
2391 ainfo->regtype = RegTypeStructByValInFP;
2394 if (ainfo->size == 4)
2395 ainfo->regtype = RegTypeFPR4;
2396 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2399 case RegTypeStructByVal:
2400 case RegTypeStructByAddr:
2401 case RegTypeStructByAddrOnStack: {
2405 if (sig->params [i - sig->hasthis]->type == MONO_TYPE_TYPEDBYREF) {
2406 size = sizeof (MonoTypedRef);
2407 align = sizeof (gpointer);
2411 size = mono_type_native_stack_size (&in->klass->byval_arg, &align);
2414 * Other backends use mono_type_stack_size (), but that
2415 * aligns the size to 8, which is larger than the size of
2416 * the source, leading to reads of invalid memory if the
2417 * source is at the end of address space.
2419 size = mono_class_value_size (in->klass, &align);
2422 g_assert (in->klass);
2424 ainfo->offparm += cinfo->sz.offStruct;
2426 MONO_INST_NEW (cfg, ins, OP_OUTARG_VT);
2427 ins->sreg1 = in->dreg;
2428 ins->klass = in->klass;
2429 ins->backend.size = ainfo->size;
2430 ins->inst_p0 = call;
2431 ins->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
2432 memcpy (ins->inst_p1, ainfo, sizeof (ArgInfo));
2434 MONO_ADD_INS (cfg->cbb, ins);
2436 if (ainfo->regtype == RegTypeStructByAddr) {
2438 * We use OP_OUTARG_VT to copy the valuetype to a stack location, then
2439 * use the normal OUTARG opcodes to pass the address of the location to
2442 int treg = mono_alloc_preg (cfg);
2443 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2444 frmReg, ainfo->offparm);
2445 mono_call_inst_add_outarg_reg (cfg, call, treg, ainfo->reg, FALSE);
2446 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
2447 /* The address of the valuetype is passed on the stack */
2448 int treg = mono_alloc_preg (cfg);
2449 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2450 frmReg, ainfo->offparm);
2451 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG,
2452 ainfo->reg, ainfo->offset, treg);
2454 if (cfg->compute_gc_maps) {
2457 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, t);
2463 if (!t->byref && t->type == MONO_TYPE_R4) {
2464 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG,
2465 STK_BASE, ainfo->offset + 4,
2467 } else if (!t->byref && (t->type == MONO_TYPE_R8)) {
2468 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG,
2469 STK_BASE, ainfo->offset,
2472 MONO_INST_NEW (cfg, ins, OP_STORE_MEMBASE_REG);
2473 ins->inst_destbasereg = STK_BASE;
2474 ins->inst_offset = ainfo->offset;
2475 ins->sreg1 = in->dreg;
2478 /* This is needed by MonoTypedRef->value to point to the correct data */
2479 if ((sig->call_convention == MONO_CALL_VARARG) &&
2480 (i >= sig->sentinelpos)) {
2481 switch (ainfo->size) {
2483 ins->opcode = OP_STOREI1_MEMBASE_REG;
2486 ins->opcode = OP_STOREI2_MEMBASE_REG;
2489 ins->opcode = OP_STOREI4_MEMBASE_REG;
2497 MONO_ADD_INS (cfg->cbb, ins);
2501 g_assert_not_reached ();
2507 * Handle the case where there are no implicit arguments
2509 if ((sig->call_convention == MONO_CALL_VARARG) &&
2511 (i == sig->sentinelpos)) {
2512 emit_sig_cookie (cfg, call, cinfo);
2516 /*========================= End of Function ========================*/
2518 /*------------------------------------------------------------------*/
2520 /* Name - mono_arch_emit_outarg_vt */
2522 /*------------------------------------------------------------------*/
2525 mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
2527 MonoCallInst *call = (MonoCallInst*)ins->inst_p0;
2528 ArgInfo *ainfo = (ArgInfo*)ins->inst_p1;
2529 int size = ins->backend.size;
2531 if (ainfo->regtype == RegTypeStructByVal) {
2533 arg->ins.sreg1 = ainfo->reg;
2534 arg->ins.opcode = OP_OUTARG_VT;
2535 arg->size = ainfo->size;
2536 arg->offset = ainfo->offset;
2537 arg->offPrm = ainfo->offparm + cinfo->sz.offStruct;
2539 if (ainfo->reg != STK_BASE) {
2540 MONO_OUTPUT_VTR (cfg, size, ainfo->reg, src->dreg, 0);
2542 MONO_OUTPUT_VTS (cfg, size, ainfo->reg, ainfo->offset,
2545 } else if (ainfo->regtype == RegTypeStructByValInFP) {
2546 int dreg = mono_alloc_freg (cfg);
2548 if (ainfo->size == 4) {
2549 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR4_MEMBASE, dreg, src->dreg, 0);
2550 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, dreg, dreg);
2552 g_assert (ainfo->size == 8);
2554 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR8_MEMBASE, dreg, src->dreg, 0);
2557 mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg, TRUE);
2560 MonoMethodHeader *header;
2563 header = mono_method_get_header_checked (cfg->method, &error);
2564 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
2565 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2570 MONO_EMIT_NEW_MOVE (cfg, srcReg, ainfo->offparm,
2571 src->dreg, 0, size);
2573 if (cfg->compute_gc_maps) {
2576 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, &ins->klass->byval_arg);
2581 /*========================= End of Function ========================*/
2583 /*------------------------------------------------------------------*/
2585 /* Name - mono_arch_emit_setret */
2587 /*------------------------------------------------------------------*/
2590 mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
2592 MonoType *ret = mini_get_underlying_type (mono_method_signature (method)->ret);
2595 if (ret->type == MONO_TYPE_R4) {
2596 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, s390_f0, val->dreg);
2598 } else if (ret->type == MONO_TYPE_R8) {
2599 MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, s390_f0, val->dreg);
2604 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg);
2607 /*========================= End of Function ========================*/
2609 /*------------------------------------------------------------------*/
2611 /* Name - mono_arch_instrument_mem_needs */
2613 /* Function - Allow tracing to work with this interface (with */
2614 /* an optional argument). */
2616 /*------------------------------------------------------------------*/
2619 mono_arch_instrument_mem_needs (MonoMethod *method, int *stack, int *code)
2621 /* no stack room needed now (may be needed for FASTCALL-trace support) */
2623 /* split prolog-epilog requirements? */
2624 *code = 50; /* max bytes needed: check this number */
2627 /*========================= End of Function ========================*/
2629 /*------------------------------------------------------------------*/
2631 /* Name - mono_arch_instrument_prolog */
2633 /* Function - Create an "instrumented" prolog. */
2635 /*------------------------------------------------------------------*/
2638 mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p,
2639 gboolean enable_arguments)
2646 parmOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2647 if (cfg->method->save_lmf)
2648 parmOffset -= sizeof(MonoLMF);
2649 fpOffset = parmOffset + (5*sizeof(gpointer));
2652 s390_stmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2653 s390_stdy (code, s390_f0, 0, STK_BASE, fpOffset);
2654 s390_stdy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2655 s390_stdy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2656 s390_stdy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2657 S390_SET (code, s390_r1, func);
2658 S390_SET (code, s390_r2, cfg->method);
2659 s390_lay (code, s390_r3, 0, STK_BASE, parmOffset);
2660 s390_lgr (code, s390_r4, STK_BASE);
2661 s390_aghi (code, s390_r4, cfg->stack_usage);
2662 s390_basr (code, s390_r14, s390_r1);
2663 s390_ldy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2664 s390_ldy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2665 s390_ldy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2666 s390_ldy (code, s390_f0, 0, STK_BASE, fpOffset);
2667 s390_lmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2672 /*========================= End of Function ========================*/
2674 /*------------------------------------------------------------------*/
2676 /* Name - mono_arch_instrument_epilog */
2678 /* Function - Create an epilog that will handle the returned */
2679 /* values used in instrumentation. */
2681 /*------------------------------------------------------------------*/
2684 mono_arch_instrument_epilog_full (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments, gboolean preserve_argument_registers)
2687 int save_mode = SAVE_NONE,
2690 MonoMethod *method = cfg->method;
2691 int rtype = mini_get_underlying_type (mono_method_signature (method)->ret)->type;
2693 offset = code - cfg->native_code;
2694 /*-----------------------------------------*/
2695 /* We need about 128 bytes of instructions */
2696 /*-----------------------------------------*/
2697 if (offset > (cfg->code_size - 128)) {
2698 cfg->code_size *= 2;
2699 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
2700 code = cfg->native_code + offset;
2703 saveOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2704 if (method->save_lmf)
2705 saveOffset -= sizeof(MonoLMF);
2709 case MONO_TYPE_VOID:
2710 /* special case string .ctor icall */
2711 if (strcmp (".ctor", method->name) && method->klass == mono_defaults.string_class)
2712 save_mode = SAVE_ONE;
2714 save_mode = SAVE_NONE;
2718 save_mode = SAVE_ONE;
2721 save_mode = SAVE_R4;
2724 save_mode = SAVE_R8;
2726 case MONO_TYPE_VALUETYPE:
2727 if (mono_method_signature (method)->ret->data.klass->enumtype) {
2728 rtype = mono_class_enum_basetype (mono_method_signature (method)->ret->data.klass)->type;
2731 save_mode = SAVE_STRUCT;
2734 save_mode = SAVE_ONE;
2738 switch (save_mode) {
2740 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2741 if (enable_arguments) {
2742 s390_lgr (code, s390_r3, s390_r2);
2746 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2747 if (enable_arguments) {
2748 s390_ldebr (code, s390_f0, s390_f0);
2752 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2755 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2756 if (enable_arguments) {
2757 s390_lg (code, s390_r3, 0, cfg->frame_reg,
2758 S390_MINIMAL_STACK_SIZE+cfg->param_area);
2766 S390_SET (code, s390_r1, func);
2767 S390_SET (code, s390_r2, cfg->method);
2768 s390_basr (code, s390_r14, s390_r1);
2770 switch (save_mode) {
2772 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2776 s390_ld (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2779 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2789 /*========================= End of Function ========================*/
2791 /*------------------------------------------------------------------*/
2793 /* Name - mono_arch_peephole_pass_1 */
2795 /* Function - Form a peephole pass at the code looking for */
2796 /* simple optimizations. */
2798 /*------------------------------------------------------------------*/
2801 mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
2805 /*========================= End of Function ========================*/
2807 /*------------------------------------------------------------------*/
2809 /* Name - mono_arch_peephole_pass_2 */
2811 /* Function - Form a peephole pass at the code looking for */
2812 /* simple optimizations. */
2814 /*------------------------------------------------------------------*/
2817 mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
2821 MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
2822 mono_peephole_ins (bb, ins);
2826 /*========================= End of Function ========================*/
2828 /*------------------------------------------------------------------*/
2830 /* Name - mono_arch_lowering_pass. */
2832 /*------------------------------------------------------------------*/
2835 mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
2837 MonoInst *ins, *next;
2839 MONO_BB_FOR_EACH_INS_SAFE (bb, next, ins) {
2840 switch (ins->opcode) {
2845 case OP_IDIV_UN_IMM:
2846 case OP_IREM_UN_IMM:
2851 case OP_LOCALLOC_IMM:
2852 mono_decompose_op_imm (cfg, bb, ins);
2855 if (!s390_is_imm16 (ins->inst_imm))
2856 /* This is created by the memcpy code which ignores is_inst_imm */
2857 mono_decompose_op_imm (cfg, bb, ins);
2864 bb->max_vreg = cfg->next_vreg;
2867 /*========================= End of Function ========================*/
2869 /*------------------------------------------------------------------*/
2871 /* Name - emit_float_to_int */
2873 /* Function - Create instructions which will convert a floating */
2874 /* point value to integer. */
2876 /*------------------------------------------------------------------*/
2879 emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size, gboolean is_signed)
2881 /* sreg is a float, dreg is an integer reg. */
2883 s390_cgdbr (code, dreg, 5, sreg);
2886 s390_ltgr (code, dreg, dreg);
2888 s390_oill (code, dreg, 0x80);
2889 s390_lghi (code, s390_r0, 0xff);
2890 s390_ngr (code, dreg, s390_r0);
2893 s390_ltgr (code, dreg, dreg);
2895 s390_oill (code, dreg, 0x8000);
2896 s390_llill(code, s390_r0, 0xffff);
2897 s390_ngr (code, dreg, s390_r0);
2902 S390_SET (code, s390_r13, 0x41e0000000000000llu);
2903 s390_ldgr (code, s390_f14, s390_r13);
2904 s390_ldr (code, s390_f15, sreg);
2905 s390_cdbr (code, s390_f15, s390_f14);
2906 s390_jl (code, 0); CODEPTR (code, o[0]);
2907 S390_SET (code, s390_r13, 0x41f0000000000000llu);
2908 s390_ldgr (code, s390_f14, s390_r13);
2909 s390_sdbr (code, s390_f15, s390_f14);
2910 s390_cfdbr (code, dreg, 7, s390_f15);
2912 PTRSLOT (code, o[0]);
2913 s390_cfdbr (code, dreg, 5, sreg);
2916 s390_lghi (code, s390_r0, 0xff);
2917 s390_ngr (code, dreg, s390_r0);
2920 s390_llill(code, s390_r0, 0xffff);
2921 s390_ngr (code, dreg, s390_r0);
2928 /*========================= End of Function ========================*/
2930 /*------------------------------------------------------------------*/
2932 /* Name - gboolean_is_unsigned. */
2934 /* Function - Return TRUE if next opcode is checking for un- */
2937 /*------------------------------------------------------------------*/
2940 gboolean is_unsigned (MonoInst *next)
2943 (((next->opcode >= OP_IBNE_UN) &&
2944 (next->opcode <= OP_IBLT_UN)) ||
2945 ((next->opcode >= OP_LBNE_UN) &&
2946 (next->opcode <= OP_LBLT_UN)) ||
2947 ((next->opcode >= OP_COND_EXC_NE_UN) &&
2948 (next->opcode <= OP_COND_EXC_LT_UN)) ||
2949 ((next->opcode >= OP_COND_EXC_INE_UN) &&
2950 (next->opcode <= OP_COND_EXC_ILT_UN)) ||
2951 ((next->opcode == OP_CLT_UN) ||
2952 (next->opcode == OP_CGT_UN)) ||
2953 ((next->opcode == OP_ICLT_UN) ||
2954 (next->opcode == OP_ICGT_UN) ||
2955 (next->opcode == OP_LCLT_UN) ||
2956 (next->opcode == OP_LCGT_UN))))
2962 /*========================= End of Function ========================*/
2964 /*------------------------------------------------------------------*/
2966 /* Name - mono_arch_output_basic_block */
2968 /* Function - Perform the "real" work of emitting instructions */
2969 /* that will do the work of in the basic block. */
2971 /*------------------------------------------------------------------*/
2974 mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
2979 guint8 *code = cfg->native_code + cfg->code_len;
2980 guint last_offset = 0;
2983 /* we don't align basic blocks of loops on s390 */
2985 if (cfg->verbose_level > 2)
2986 g_print ("Basic block %d starting at offset 0x%x\n", bb->block_num, bb->native_offset);
2988 if ((cfg->prof_options & MONO_PROFILE_COVERAGE) && cfg->coverage_info) {
2989 MonoProfileCoverageInfo *cov = cfg->coverage_info;
2990 g_assert (!mono_compile_aot);
2991 cov->data [bb->dfn].cil_code = bb->cil_code;
2992 /* This is not thread save, but good enough */
2993 S390_SET (code, s390_r1, &cov->data [bb->dfn].count);
2994 s390_alsi (code, 0, s390_r1, 1);
2997 MONO_BB_FOR_EACH_INS (bb, ins) {
2998 offset = code - cfg->native_code;
3000 max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
3002 if (offset > (cfg->code_size - max_len - 16)) {
3003 cfg->code_size *= 2;
3004 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
3005 code = cfg->native_code + offset;
3008 mono_debug_record_line_number (cfg, ins, offset);
3010 switch (ins->opcode) {
3011 case OP_STOREI1_MEMBASE_IMM: {
3012 s390_lghi (code, s390_r0, ins->inst_imm);
3013 S390_LONG (code, stcy, stc, s390_r0, 0,
3014 ins->inst_destbasereg, ins->inst_offset);
3017 case OP_STOREI2_MEMBASE_IMM: {
3018 s390_lghi (code, s390_r0, ins->inst_imm);
3019 S390_LONG (code, sthy, sth, s390_r0, 0,
3020 ins->inst_destbasereg, ins->inst_offset);
3023 case OP_STOREI4_MEMBASE_IMM: {
3024 s390_lgfi (code, s390_r0, ins->inst_imm);
3025 S390_LONG (code, sty, st, s390_r0, 0,
3026 ins->inst_destbasereg, ins->inst_offset);
3029 case OP_STORE_MEMBASE_IMM:
3030 case OP_STOREI8_MEMBASE_IMM: {
3031 S390_SET (code, s390_r0, ins->inst_imm);
3032 S390_LONG (code, stg, stg, s390_r0, 0,
3033 ins->inst_destbasereg, ins->inst_offset);
3036 case OP_STOREI1_MEMBASE_REG: {
3037 S390_LONG (code, stcy, stc, ins->sreg1, 0,
3038 ins->inst_destbasereg, ins->inst_offset);
3041 case OP_STOREI2_MEMBASE_REG: {
3042 S390_LONG (code, sthy, sth, ins->sreg1, 0,
3043 ins->inst_destbasereg, ins->inst_offset);
3046 case OP_STOREI4_MEMBASE_REG: {
3047 S390_LONG (code, sty, st, ins->sreg1, 0,
3048 ins->inst_destbasereg, ins->inst_offset);
3051 case OP_STORE_MEMBASE_REG:
3052 case OP_STOREI8_MEMBASE_REG: {
3053 S390_LONG (code, stg, stg, ins->sreg1, 0,
3054 ins->inst_destbasereg, ins->inst_offset);
3058 g_assert_not_reached ();
3060 case OP_LOAD_MEMBASE:
3061 case OP_LOADI8_MEMBASE: {
3062 S390_LONG (code, lg, lg, ins->dreg, 0,
3063 ins->inst_basereg, ins->inst_offset);
3066 case OP_LOADI4_MEMBASE: {
3067 S390_LONG (code, lgf, lgf, ins->dreg, 0,
3068 ins->inst_basereg, ins->inst_offset);
3071 case OP_LOADU4_MEMBASE: {
3072 S390_LONG (code, llgf, llgf, ins->dreg, 0,
3073 ins->inst_basereg, ins->inst_offset);
3076 case OP_LOADU1_MEMBASE: {
3077 S390_LONG (code, llgc, llgc, ins->dreg, 0,
3078 ins->inst_basereg, ins->inst_offset);
3081 case OP_LOADI1_MEMBASE: {
3082 S390_LONG (code, lgb, lgb, ins->dreg, 0,
3083 ins->inst_basereg, ins->inst_offset);
3086 case OP_LOADU2_MEMBASE: {
3087 S390_LONG (code, llgh, llgh, ins->dreg, 0,
3088 ins->inst_basereg, ins->inst_offset);
3091 case OP_LOADI2_MEMBASE: {
3092 S390_LONG (code, lgh, lgh, ins->dreg, 0,
3093 ins->inst_basereg, ins->inst_offset);
3096 case OP_LCONV_TO_I1: {
3097 s390_lgbr (code, ins->dreg, ins->sreg1);
3100 case OP_LCONV_TO_I2: {
3101 s390_lghr (code, ins->dreg, ins->sreg1);
3104 case OP_LCONV_TO_U1: {
3105 s390_llgcr (code, ins->dreg, ins->sreg1);
3108 case OP_LCONV_TO_U2: {
3109 s390_llghr (code, ins->dreg, ins->sreg1);
3112 case OP_ICONV_TO_I1: {
3113 s390_lgbr (code, ins->dreg, ins->sreg1);
3116 case OP_ICONV_TO_I2: {
3117 s390_lghr (code, ins->dreg, ins->sreg1);
3120 case OP_ICONV_TO_U1: {
3121 s390_llgcr (code, ins->dreg, ins->sreg1);
3124 case OP_ICONV_TO_U2: {
3125 s390_llghr (code, ins->dreg, ins->sreg1);
3130 if (is_unsigned (ins->next))
3131 s390_clgr (code, ins->sreg1, ins->sreg2);
3133 s390_cgr (code, ins->sreg1, ins->sreg2);
3137 if (is_unsigned (ins->next))
3138 s390_clr (code, ins->sreg1, ins->sreg2);
3140 s390_cr (code, ins->sreg1, ins->sreg2);
3143 case OP_COMPARE_IMM:
3144 case OP_LCOMPARE_IMM: {
3145 S390_SET (code, s390_r0, ins->inst_imm);
3146 if (is_unsigned (ins->next))
3147 s390_clgr (code, ins->sreg1, s390_r0);
3149 s390_cgr (code, ins->sreg1, s390_r0);
3152 case OP_ICOMPARE_IMM: {
3153 S390_SET (code, s390_r0, ins->inst_imm);
3154 if (is_unsigned (ins->next))
3155 s390_clr (code, ins->sreg1, s390_r0);
3157 s390_cr (code, ins->sreg1, s390_r0);
3161 mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_ABS,
3163 S390_CALL_TEMPLATE (code, s390_r14);
3168 s390_agr (code, ins->dreg, src2);
3173 s390_agr (code, ins->dreg, src2);
3178 s390_alcgr (code, ins->dreg, src2);
3182 if (ins->dreg != ins->sreg1) {
3183 s390_lgr (code, ins->dreg, ins->sreg1);
3185 if (s390_is_imm16 (ins->inst_imm)) {
3186 s390_aghi (code, ins->dreg, ins->inst_imm);
3187 } else if (s390_is_imm32 (ins->inst_imm)) {
3188 s390_agfi (code, ins->dreg, ins->inst_imm);
3190 S390_SET (code, s390_r0, ins->inst_imm);
3191 s390_agr (code, ins->dreg, s390_r0);
3196 if (ins->dreg != ins->sreg1) {
3197 s390_lgr (code, ins->dreg, ins->sreg1);
3199 g_assert (s390_is_imm16 (ins->inst_imm));
3200 s390_aghi (code, ins->dreg, ins->inst_imm);
3204 if (ins->dreg != ins->sreg1) {
3205 s390_lgr (code, ins->dreg, ins->sreg1);
3207 if (s390_is_imm16 (ins->inst_imm)) {
3208 s390_lghi (code, s390_r0, ins->inst_imm);
3209 s390_alcgr (code, ins->dreg, s390_r0);
3211 S390_SET (code, s390_r0, ins->inst_imm);
3212 s390_alcgr (code, ins->dreg, s390_r0);
3217 case OP_S390_IADD_OVF: {
3219 s390_ar (code, ins->dreg, src2);
3220 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3221 s390_lgfr (code, ins->dreg, ins->dreg);
3224 case OP_IADD_OVF_UN:
3225 case OP_S390_IADD_OVF_UN: {
3227 s390_algr (code, ins->dreg, src2);
3228 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3229 s390_llgfr (code, ins->dreg, ins->dreg);
3232 case OP_ADD_OVF_CARRY: {
3234 s390_lghi (code, s390_r0, 0);
3235 s390_lgr (code, s390_r1, s390_r0);
3236 s390_alcgr (code, s390_r0, s390_r1);
3237 s390_agr (code, ins->dreg, src2);
3238 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3239 s390_agr (code, ins->dreg, s390_r0);
3240 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3243 case OP_ADD_OVF_UN_CARRY: {
3245 s390_alcgr (code, ins->dreg, src2);
3246 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3251 s390_sgr (code, ins->dreg, src2);
3256 s390_sgr (code, ins->dreg, src2);
3261 s390_slbgr(code, ins->dreg, src2);
3265 if (ins->dreg != ins->sreg1) {
3266 s390_lgr (code, ins->dreg, ins->sreg1);
3268 if (s390_is_imm16 (-ins->inst_imm)) {
3269 s390_aghi (code, ins->dreg, -ins->inst_imm);
3270 } else if (s390_is_imm32 (-ins->inst_imm)) {
3271 s390_slgfi (code, ins->dreg, ins->inst_imm);
3273 S390_SET (code, s390_r0, ins->inst_imm);
3274 s390_slgr (code, ins->dreg, s390_r0);
3279 if (ins->dreg != ins->sreg1) {
3280 s390_lgr (code, ins->dreg, ins->sreg1);
3282 if (s390_is_imm16 (-ins->inst_imm)) {
3283 s390_aghi (code, ins->dreg, -ins->inst_imm);
3284 } else if (s390_is_imm32 (-ins->inst_imm)) {
3285 s390_slgfi (code, ins->dreg, ins->inst_imm);
3287 S390_SET (code, s390_r0, ins->inst_imm);
3288 s390_slgr (code, ins->dreg, s390_r0);
3293 if (ins->dreg != ins->sreg1) {
3294 s390_lgr (code, ins->dreg, ins->sreg1);
3296 if (s390_is_imm16 (-ins->inst_imm)) {
3297 s390_lghi (code, s390_r0, ins->inst_imm);
3298 s390_slbgr (code, ins->dreg, s390_r0);
3300 S390_SET (code, s390_r0, ins->inst_imm);
3301 s390_slbgr(code, ins->dreg, s390_r0);
3305 case OP_SUB_OVF_CARRY: {
3307 s390_lghi (code, s390_r0, 0);
3308 s390_lgr (code, s390_r1, s390_r0);
3309 s390_slbgr (code, s390_r0, s390_r1);
3310 s390_sgr (code, ins->dreg, src2);
3311 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3312 s390_agr (code, ins->dreg, s390_r0);
3313 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3316 case OP_SUB_OVF_UN_CARRY: {
3318 s390_slbgr (code, ins->dreg, src2);
3319 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3323 if (ins->sreg1 == ins->dreg) {
3324 s390_ngr (code, ins->dreg, ins->sreg2);
3327 if (ins->sreg2 == ins->dreg) {
3328 s390_ngr (code, ins->dreg, ins->sreg1);
3331 s390_lgr (code, ins->dreg, ins->sreg1);
3332 s390_ngr (code, ins->dreg, ins->sreg2);
3338 if (ins->dreg != ins->sreg1) {
3339 s390_lgr (code, ins->dreg, ins->sreg1);
3341 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3342 s390_ngr (code, ins->dreg, s390_r0);
3346 s390_lgr (code, s390_r1, ins->sreg1);
3347 s390_dsgr (code, s390_r0, ins->sreg2);
3348 s390_lgr (code, ins->dreg, s390_r1);
3352 s390_lgr (code, s390_r1, ins->sreg1);
3353 s390_lghi (code, s390_r0, 0);
3354 s390_dlgr (code, s390_r0, ins->sreg2);
3355 s390_lgr (code, ins->dreg, s390_r1);
3359 s390_lgr (code, s390_r1, ins->sreg1);
3360 s390_dsgr (code, s390_r0, ins->sreg2);
3361 s390_lgr (code, ins->dreg, s390_r0);
3365 if (s390_is_imm16 (ins->inst_imm)) {
3366 s390_lghi (code, s390_r13, ins->inst_imm);
3368 s390_lgfi (code, s390_r13, ins->inst_imm);
3370 s390_lgr (code, s390_r0, ins->sreg1);
3371 s390_dsgr (code, s390_r0, s390_r13);
3372 s390_lgfr (code, ins->dreg, s390_r0);
3376 s390_lgr (code, s390_r1, ins->sreg1);
3377 s390_lghi (code, s390_r0, 0);
3378 s390_dlgr (code, s390_r0, ins->sreg2);
3379 s390_lgr (code, ins->dreg, s390_r0);
3383 if (ins->sreg1 == ins->dreg) {
3384 s390_ogr (code, ins->dreg, ins->sreg2);
3387 if (ins->sreg2 == ins->dreg) {
3388 s390_ogr (code, ins->dreg, ins->sreg1);
3391 s390_lgr (code, ins->dreg, ins->sreg1);
3392 s390_ogr (code, ins->dreg, ins->sreg2);
3398 if (ins->dreg != ins->sreg1) {
3399 s390_lgr (code, ins->dreg, ins->sreg1);
3401 S390_SET_MASK(code, s390_r0, ins->inst_imm);
3402 s390_ogr (code, ins->dreg, s390_r0);
3406 if (ins->sreg1 == ins->dreg) {
3407 s390_xgr (code, ins->dreg, ins->sreg2);
3410 if (ins->sreg2 == ins->dreg) {
3411 s390_xgr (code, ins->dreg, ins->sreg1);
3414 s390_lgr (code, ins->dreg, ins->sreg1);
3415 s390_xgr (code, ins->dreg, ins->sreg2);
3421 if (ins->dreg != ins->sreg1) {
3422 s390_lgr (code, ins->dreg, ins->sreg1);
3424 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3425 s390_xgr (code, ins->dreg, s390_r0);
3430 s390_sllg (code, ins->dreg, ins->dreg, src2, 0);
3435 if (ins->sreg1 != ins->dreg) {
3436 s390_lgr (code, ins->dreg, ins->sreg1);
3438 s390_sllg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3443 s390_srag (code, ins->dreg, ins->dreg, src2, 0);
3448 if (ins->sreg1 != ins->dreg) {
3449 s390_lgr (code, ins->dreg, ins->sreg1);
3451 s390_srag (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3455 case OP_LSHR_UN_IMM: {
3456 if (ins->sreg1 != ins->dreg) {
3457 s390_lgr (code, ins->dreg, ins->sreg1);
3459 s390_srlg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3464 s390_srlg (code, ins->dreg, ins->dreg, src2, 0);
3468 if (ins->sreg1 != ins->dreg) {
3469 s390_lgr (code, ins->dreg, ins->sreg1);
3471 s390_lghi (code, s390_r0, -1);
3472 s390_xgr (code, ins->dreg, s390_r0);
3476 s390_lcgr (code, ins->dreg, ins->sreg1);
3481 s390_msgr (code, ins->dreg, src2);
3486 if (ins->dreg != ins->sreg1) {
3487 s390_lgr (code, ins->dreg, ins->sreg1);
3489 if (s390_is_imm16 (ins->inst_imm)) {
3490 s390_lghi (code, s390_r13, ins->inst_imm);
3491 } else if (s390_is_imm32 (ins->inst_imm)) {
3492 s390_lgfi (code, s390_r13, ins->inst_imm);
3494 S390_SET (code, s390_r13, ins->inst_imm);
3496 s390_msgr (code, ins->dreg, s390_r13);
3501 s390_ltgr (code, s390_r1, ins->sreg1);
3502 s390_jz (code, 0); CODEPTR(code, o[0]);
3503 s390_ltgr (code, s390_r0, ins->sreg2);
3505 s390_lghi (code, s390_r1, 0);
3506 s390_j (code, 0); CODEPTR(code, o[1]);
3507 s390_xgr (code, s390_r0, s390_r1);
3508 s390_msgr (code, s390_r1, ins->sreg2);
3509 s390_xgr (code, s390_r0, s390_r1);
3510 s390_srlg (code, s390_r0, s390_r0, 0, 63);
3511 s390_ltgr (code, s390_r0, s390_r0);
3512 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3513 PTRSLOT (code, o[0]);
3514 PTRSLOT (code, o[1]);
3515 s390_lgr (code, ins->dreg, s390_r1);
3518 case OP_LMUL_OVF_UN: {
3519 s390_lghi (code, s390_r0, 0);
3520 s390_lgr (code, s390_r1, ins->sreg1);
3521 s390_mlgr (code, s390_r0, ins->sreg2);
3522 s390_ltgr (code, s390_r0, s390_r0);
3523 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3524 s390_lgr (code, ins->dreg, s390_r1);
3528 g_assert_not_reached ();
3530 s390_algr (code, ins->dreg, src2);
3535 s390_agr (code, ins->dreg, src2);
3539 g_assert_not_reached ();
3541 s390_alcgr (code, ins->dreg, src2);
3545 if (ins->dreg != ins->sreg1) {
3546 s390_lgfr (code, ins->dreg, ins->sreg1);
3548 if (s390_is_imm16 (ins->inst_imm)) {
3549 s390_aghi (code, ins->dreg, ins->inst_imm);
3551 s390_afi (code, ins->dreg, ins->inst_imm);
3556 if (ins->dreg != ins->sreg1) {
3557 s390_lgfr (code, ins->dreg, ins->sreg1);
3559 if (s390_is_imm16 (ins->inst_imm)) {
3560 s390_lghi (code, s390_r0, ins->inst_imm);
3561 s390_alcgr (code, ins->dreg, s390_r0);
3563 S390_SET (code, s390_r0, ins->inst_imm);
3564 s390_alcgr (code, ins->dreg, s390_r0);
3569 case OP_S390_LADD_OVF: {
3571 s390_agr (code, ins->dreg, src2);
3572 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3575 case OP_LADD_OVF_UN:
3576 case OP_S390_LADD_OVF_UN: {
3578 s390_algr (code, ins->dreg, src2);
3579 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3583 CHECK_SRCDST_NCOM_I;
3584 s390_slgr (code, ins->dreg, src2);
3588 CHECK_SRCDST_NCOM_I;
3589 s390_sgr (code, ins->dreg, src2);
3593 CHECK_SRCDST_NCOM_I;
3594 s390_slbgr (code, ins->dreg, src2);
3598 if (ins->dreg != ins->sreg1) {
3599 s390_lgfr (code, ins->dreg, ins->sreg1);
3601 if (s390_is_imm16 (-ins->inst_imm)) {
3602 s390_aghi (code, ins->dreg, -ins->inst_imm);
3604 s390_agfi (code, ins->dreg, -ins->inst_imm);
3609 S390_SET (code, s390_r0, ins->inst_imm);
3610 s390_slgfr (code, ins->dreg, s390_r0);
3614 case OP_S390_ISUB_OVF: {
3616 s390_sr (code, ins->dreg, src2);
3617 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3618 s390_lgfr (code, ins->dreg, ins->dreg);
3621 case OP_ISUB_OVF_UN:
3622 case OP_S390_ISUB_OVF_UN: {
3624 s390_slr (code, ins->dreg, src2);
3625 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3626 s390_llgfr(code, ins->dreg, ins->dreg);
3630 case OP_S390_LSUB_OVF: {
3632 s390_sgr (code, ins->dreg, src2);
3633 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3636 case OP_LSUB_OVF_UN:
3637 case OP_S390_LSUB_OVF_UN: {
3639 s390_slgr (code, ins->dreg, src2);
3640 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3644 CHECK_SRCDST_NCOM_I;
3645 s390_ngr (code, ins->dreg, src2);
3649 if (ins->dreg != ins->sreg1) {
3650 s390_lgfr (code, ins->dreg, ins->sreg1);
3652 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3653 s390_ngr (code, ins->dreg, s390_r0);
3657 s390_lgfr (code, s390_r0, ins->sreg1);
3658 s390_srda (code, s390_r0, 0, 32);
3659 s390_dr (code, s390_r0, ins->sreg2);
3660 s390_lgfr (code, ins->dreg, s390_r1);
3664 s390_lgfr (code, s390_r0, ins->sreg1);
3665 s390_srdl (code, s390_r0, 0, 32);
3666 s390_dlr (code, s390_r0, ins->sreg2);
3667 s390_lgfr (code, ins->dreg, s390_r1);
3671 if (s390_is_imm16 (ins->inst_imm)) {
3672 s390_lghi (code, s390_r13, ins->inst_imm);
3674 s390_lgfi (code, s390_r13, ins->inst_imm);
3676 s390_lgfr (code, s390_r0, ins->sreg1);
3677 s390_srda (code, s390_r0, 0, 32);
3678 s390_dr (code, s390_r0, ins->sreg2);
3679 s390_lgfr (code, ins->dreg, s390_r1);
3683 s390_lgfr (code, s390_r0, ins->sreg1);
3684 s390_srda (code, s390_r0, 0, 32);
3685 s390_dr (code, s390_r0, ins->sreg2);
3686 s390_lgfr (code, ins->dreg, s390_r0);
3689 s390_lgfr (code, s390_r0, ins->sreg1);
3690 s390_srdl (code, s390_r0, 0, 32);
3691 s390_dlr (code, s390_r0, ins->sreg2);
3692 s390_lgfr (code, ins->dreg, s390_r0);
3696 if (s390_is_imm16 (ins->inst_imm)) {
3697 s390_lghi (code, s390_r13, ins->inst_imm);
3699 s390_lgfi (code, s390_r13, ins->inst_imm);
3701 s390_lgfr (code, s390_r0, ins->sreg1);
3702 s390_srda (code, s390_r0, 0, 32);
3703 s390_dr (code, s390_r0, ins->sreg2);
3704 s390_lgfr (code, ins->dreg, s390_r0);
3709 s390_ogr (code, ins->dreg, src2);
3713 if (ins->dreg != ins->sreg1) {
3714 s390_lgfr (code, ins->dreg, ins->sreg1);
3716 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3717 s390_ogr (code, ins->dreg, s390_r0);
3722 s390_xgr (code, ins->dreg, src2);
3726 if (ins->dreg != ins->sreg1) {
3727 s390_lgfr (code, ins->dreg, ins->sreg1);
3729 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3730 s390_xgr (code, ins->dreg, s390_r0);
3735 s390_sll (code, ins->dreg, src2, 0);
3739 if (ins->sreg1 != ins->dreg) {
3740 s390_lgfr (code, ins->dreg, ins->sreg1);
3742 s390_sll (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3747 s390_sra (code, ins->dreg, src2, 0);
3751 if (ins->sreg1 != ins->dreg) {
3752 s390_lgfr (code, ins->dreg, ins->sreg1);
3754 s390_sra (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3757 case OP_ISHR_UN_IMM: {
3758 if (ins->sreg1 != ins->dreg) {
3759 s390_lgfr (code, ins->dreg, ins->sreg1);
3761 s390_srl (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3766 s390_srl (code, ins->dreg, src2, 0);
3770 if (ins->sreg1 != ins->dreg) {
3771 s390_lgfr (code, ins->dreg, ins->sreg1);
3773 s390_lghi (code, s390_r0, -1);
3774 s390_xgr (code, ins->dreg, s390_r0);
3778 s390_lcgr (code, ins->dreg, ins->sreg1);
3783 s390_msr (code, ins->dreg, src2);
3787 if (ins->dreg != ins->sreg1) {
3788 s390_lgfr (code, ins->dreg, ins->sreg1);
3790 if (s390_is_imm16 (ins->inst_imm)) {
3791 s390_lghi (code, s390_r0, ins->inst_imm);
3793 s390_lgfi (code, s390_r0, ins->inst_imm);
3795 s390_msr (code, ins->dreg, s390_r0);
3800 s390_ltr (code, s390_r1, ins->sreg1);
3801 s390_jz (code, 0); CODEPTR(code, o[0]);
3802 s390_ltr (code, s390_r0, ins->sreg2);
3804 s390_lhi (code, s390_r1, 0);
3805 s390_j (code, 0); CODEPTR(code, o[1]);
3806 s390_xr (code, s390_r0, s390_r1);
3807 s390_msr (code, s390_r1, ins->sreg2);
3808 s390_xr (code, s390_r0, s390_r1);
3809 s390_srl (code, s390_r0, 0, 31);
3810 s390_ltr (code, s390_r0, s390_r0);
3811 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3812 PTRSLOT (code, o[0]);
3813 PTRSLOT (code, o[1]);
3814 s390_lgfr (code, ins->dreg, s390_r1);
3817 case OP_IMUL_OVF_UN: {
3818 s390_lhi (code, s390_r0, 0);
3819 s390_lr (code, s390_r1, ins->sreg1);
3820 s390_mlr (code, s390_r0, ins->sreg2);
3821 s390_ltr (code, s390_r0, s390_r0);
3822 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3823 s390_lgfr (code, ins->dreg, s390_r1);
3828 S390_SET (code, ins->dreg, ins->inst_c0);
3832 mono_add_patch_info (cfg, code - cfg->native_code,
3833 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3834 S390_LOAD_TEMPLATE (code, ins->dreg);
3837 case OP_JUMP_TABLE: {
3838 mono_add_patch_info (cfg, code - cfg->native_code,
3839 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3840 S390_LOAD_TEMPLATE (code, ins->dreg);
3844 if (ins->dreg != ins->sreg1) {
3845 s390_lgr (code, ins->dreg, ins->sreg1);
3849 case OP_LCONV_TO_I8:
3851 s390_lgfr (code, ins->dreg, ins->sreg1);
3853 case OP_LCONV_TO_I4:
3854 s390_lgfr (code, ins->dreg, ins->sreg1);
3857 case OP_LCONV_TO_U8:
3858 case OP_LCONV_TO_U4:
3860 s390_llgfr (code, ins->dreg, ins->sreg1);
3862 case OP_LCONV_TO_OVF_U4:
3863 S390_SET (code, s390_r0, 4294967295);
3864 s390_clgr (code, ins->sreg1, s390_r0);
3865 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3866 s390_ltgr (code, ins->sreg1, ins->sreg1);
3867 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3868 s390_llgfr(code, ins->dreg, ins->sreg1);
3870 case OP_LCONV_TO_OVF_I4_UN:
3871 S390_SET (code, s390_r0, 2147483647);
3872 s390_cgr (code, ins->sreg1, s390_r0);
3873 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3874 s390_ltgr (code, ins->sreg1, ins->sreg1);
3875 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3876 s390_lgfr (code, ins->dreg, ins->sreg1);
3879 if (ins->dreg != ins->sreg1) {
3880 s390_ldr (code, ins->dreg, ins->sreg1);
3883 case OP_MOVE_F_TO_I8:
3884 s390_lgdr (code, ins->dreg, ins->sreg1);
3886 case OP_MOVE_I8_TO_F:
3887 s390_ldgr (code, ins->dreg, ins->sreg1);
3889 case OP_MOVE_F_TO_I4:
3890 s390_ledbr (code, s390_f0, ins->sreg1);
3891 s390_lgdr (code, ins->dreg, s390_f0);
3892 s390_srag (code, ins->dreg, ins->dreg, 0, 32);
3894 case OP_MOVE_I4_TO_F:
3895 s390_slag (code, s390_r0, ins->sreg1, 0, 32);
3896 s390_ldgr (code, ins->dreg, s390_r0);
3897 s390_ldebr (code, ins->dreg, ins->dreg);
3899 case OP_FCONV_TO_R4:
3900 s390_ledbr (code, ins->dreg, ins->sreg1);
3901 s390_ldebr (code, ins->dreg, ins->dreg);
3903 case OP_S390_SETF4RET:
3904 s390_ledbr (code, ins->dreg, ins->sreg1);
3907 if (s390_is_imm16 (ins->inst_offset)) {
3908 s390_lghi (code, s390_r13, ins->inst_offset);
3909 } else if (s390_is_imm32 (ins->inst_offset)) {
3910 s390_lgfi (code, s390_r13, ins->inst_offset);
3912 S390_SET (code, s390_r13, ins->inst_offset);
3914 s390_ear (code, s390_r1, 0);
3915 s390_sllg(code, s390_r1, s390_r1, 0, 32);
3916 s390_ear (code, s390_r1, 1);
3917 s390_lg (code, ins->dreg, s390_r13, s390_r1, 0);
3921 if (s390_is_imm16 (ins->inst_offset)) {
3922 s390_lghi (code, s390_r13, ins->inst_offset);
3923 } else if (s390_is_imm32 (ins->inst_offset)) {
3924 s390_lgfi (code, s390_r13, ins->inst_offset);
3926 S390_SET (code, s390_r13, ins->inst_offset);
3928 s390_ear (code, s390_r1, 0);
3929 s390_sllg(code, s390_r1, s390_r1, 0, 32);
3930 s390_ear (code, s390_r1, 1);
3931 s390_stg (code, ins->sreg1, s390_r13, s390_r1, 0);
3935 if (cfg->method->save_lmf)
3936 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
3938 if (cfg->flags & MONO_CFG_HAS_TAIL) {
3939 code = emit_load_volatile_arguments (code, cfg);
3942 code = backUpStackPtr(cfg, code);
3943 s390_lg (code, s390_r14, 0, cfg->frame_reg, S390_RET_ADDR_OFFSET);
3944 mono_add_patch_info (cfg, code - cfg->native_code,
3945 MONO_PATCH_INFO_METHOD_JUMP,
3947 s390_jcl (code, S390_CC_UN, 0);
3950 case OP_CHECK_THIS: {
3951 /* ensure ins->sreg1 is not NULL */
3952 s390_lg (code, s390_r0, 0, ins->sreg1, 0);
3953 s390_ltgr (code, s390_r0, s390_r0);
3954 // EMIT_COND_SYSTEM_EXCEPTION (S390_CC_ZR, "NullReferenceException");
3958 int offset = cfg->sig_cookie + cfg->stack_usage;
3960 if (s390_is_imm16 (offset)) {
3961 s390_lghi (code, s390_r0, offset);
3962 } else if (s390_is_imm32 (offset)) {
3963 s390_lgfi (code, s390_r0, offset);
3965 S390_SET (code, s390_r0, offset);
3967 s390_agr (code, s390_r0, cfg->frame_reg);
3968 s390_stg (code, s390_r0, 0, ins->sreg1, 0);
3972 call = (MonoCallInst*)ins;
3973 if (ins->flags & MONO_INST_HAS_METHOD)
3974 mono_add_patch_info (cfg, code-cfg->native_code,
3975 MONO_PATCH_INFO_METHOD,
3978 mono_add_patch_info (cfg, code-cfg->native_code,
3979 MONO_PATCH_INFO_ABS,
3981 S390_CALL_TEMPLATE (code, s390_r14);
3982 if (call->signature->ret->type == MONO_TYPE_R4)
3983 s390_ldebr (code, s390_f0, s390_f0);
3991 call = (MonoCallInst*)ins;
3992 if (ins->flags & MONO_INST_HAS_METHOD)
3993 mono_add_patch_info (cfg, code-cfg->native_code,
3994 MONO_PATCH_INFO_METHOD,
3997 mono_add_patch_info (cfg, code-cfg->native_code,
3998 MONO_PATCH_INFO_ABS,
4000 S390_CALL_TEMPLATE (code, s390_r14);
4003 case OP_FCALL_REG: {
4004 call = (MonoCallInst*)ins;
4005 s390_lgr (code, s390_r1, ins->sreg1);
4006 s390_basr (code, s390_r14, s390_r1);
4007 if (call->signature->ret->type == MONO_TYPE_R4)
4008 s390_ldebr (code, s390_f0, s390_f0);
4014 case OP_VOIDCALL_REG:
4016 s390_lgr (code, s390_r1, ins->sreg1);
4017 s390_basr (code, s390_r14, s390_r1);
4020 case OP_FCALL_MEMBASE: {
4021 call = (MonoCallInst*)ins;
4022 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4023 s390_basr (code, s390_r14, s390_r1);
4024 if (call->signature->ret->type == MONO_TYPE_R4)
4025 s390_ldebr (code, s390_f0, s390_f0);
4028 case OP_LCALL_MEMBASE:
4029 case OP_VCALL_MEMBASE:
4030 case OP_VCALL2_MEMBASE:
4031 case OP_VOIDCALL_MEMBASE:
4032 case OP_CALL_MEMBASE: {
4033 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4034 s390_basr (code, s390_r14, s390_r1);
4041 if (cfg->param_area == 0)
4042 alloca_skip = S390_MINIMAL_STACK_SIZE;
4044 alloca_skip = cfg->param_area;
4046 area_offset = S390_ALIGN(alloca_skip, S390_STACK_ALIGNMENT);
4047 s390_lgr (code, s390_r1, ins->sreg1);
4048 if (ins->flags & MONO_INST_INIT)
4049 s390_lgr (code, s390_r0, ins->sreg1);
4050 s390_aghi (code, s390_r1, 14);
4051 s390_srlg (code, s390_r1, s390_r1, 0, 3);
4052 s390_sllg (code, s390_r1, s390_r1, 0, 3);
4053 if (cfg->method->save_lmf) {
4054 /*----------------------------------*/
4055 /* we have to adjust lmf ebp value */
4056 /*----------------------------------*/
4057 int lmfOffset = cfg->stack_usage - sizeof(MonoLMF);
4059 s390_lgr (code, s390_r13, cfg->frame_reg);
4060 if (s390_is_imm16(lmfOffset)) {
4061 s390_aghi (code, s390_r13, lmfOffset);
4062 } else if (s390_is_imm32(lmfOffset)) {
4063 s390_agfi (code, s390_r13, lmfOffset);
4065 S390_SET (code, s390_r13, lmfOffset);
4067 s390_lgr (code, s390_r14, STK_BASE);
4068 s390_sgr (code, s390_r14, s390_r1);
4069 s390_stg (code, s390_r14, 0, s390_r13,
4070 G_STRUCT_OFFSET(MonoLMF, ebp));
4072 s390_lg (code, s390_r13, 0, STK_BASE, 0);
4073 s390_sgr (code, STK_BASE, s390_r1);
4074 s390_stg (code, s390_r13, 0, STK_BASE, 0);
4075 s390_la (code, ins->dreg, 0, STK_BASE, area_offset);
4076 s390_srlg (code, ins->dreg, ins->dreg, 0, 3);
4077 s390_sllg (code, ins->dreg, ins->dreg, 0, 3);
4078 if (ins->flags & MONO_INST_INIT) {
4079 s390_lgr (code, s390_r1, s390_r0);
4080 s390_lgr (code, s390_r0, ins->dreg);
4081 s390_lgr (code, s390_r14, s390_r12);
4082 s390_lghi (code, s390_r13, 0);
4083 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4085 s390_lgr (code, s390_r12, s390_r14);
4090 s390_lgr (code, s390_r2, ins->sreg1);
4091 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4092 (gpointer) "mono_arch_throw_exception");
4093 S390_CALL_TEMPLATE(code, s390_r14);
4097 s390_lgr (code, s390_r2, ins->sreg1);
4098 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4099 (gpointer) "mono_arch_rethrow_exception");
4100 S390_CALL_TEMPLATE(code, s390_r14);
4103 case OP_START_HANDLER: {
4104 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4106 S390_LONG (code, stg, stg, s390_r14, 0,
4107 spvar->inst_basereg,
4108 spvar->inst_offset);
4111 case OP_ENDFILTER: {
4112 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4114 if (ins->sreg1 != s390_r2)
4115 s390_lgr(code, s390_r2, ins->sreg1);
4116 S390_LONG (code, lg, lg, s390_r14, 0,
4117 spvar->inst_basereg,
4118 spvar->inst_offset);
4119 s390_br (code, s390_r14);
4122 case OP_ENDFINALLY: {
4123 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4125 S390_LONG (code, lg, lg, s390_r14, 0,
4126 spvar->inst_basereg,
4127 spvar->inst_offset);
4128 s390_br (code, s390_r14);
4131 case OP_CALL_HANDLER: {
4132 mono_add_patch_info (cfg, code-cfg->native_code,
4133 MONO_PATCH_INFO_BB, ins->inst_target_bb);
4134 s390_brasl (code, s390_r14, 0);
4135 mono_cfg_add_try_hole (cfg, ins->inst_eh_block, code, bb);
4139 ins->inst_c0 = code - cfg->native_code;
4142 case OP_RELAXED_NOP:
4145 case OP_DUMMY_STORE:
4146 case OP_NOT_REACHED:
4150 case OP_IL_SEQ_POINT:
4151 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4153 case OP_SEQ_POINT: {
4156 if (cfg->compile_aot)
4160 * Read from the single stepping trigger page. This will cause a
4161 * SIGSEGV when single stepping is enabled.
4162 * We do this _before_ the breakpoint, so single stepping after
4163 * a breakpoint is hit will step to the next IL offset.
4165 if (ins->flags & MONO_INST_SINGLE_STEP_LOC) {
4166 breakpointCode.pTrigger = ss_trigger_page;
4167 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
4168 code += BREAKPOINT_SIZE;
4171 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4174 * A placeholder for a possible breakpoint inserted by
4175 * mono_arch_set_breakpoint ().
4177 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); ++i)
4181 * Add an additional nop so skipping the bp doesn't cause the ip to point
4182 * to another IL offset.
4188 case OP_GENERIC_CLASS_INIT: {
4189 static int byte_offset = -1;
4190 static guint8 bitmask;
4193 g_assert (ins->sreg1 == S390_FIRST_ARG_REG);
4195 if (byte_offset < 0)
4196 mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);
4198 s390_tm (code, ins->sreg1, byte_offset, bitmask);
4199 s390_jo (code, 0); CODEPTR(code, jump);
4201 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4202 "mono_generic_class_init");
4203 S390_CALL_TEMPLATE(code, s390_r14);
4205 PTRSLOT (code, jump);
4207 ins->flags |= MONO_INST_GC_CALLSITE;
4208 ins->backend.pc_offset = code - cfg->native_code;
4212 EMIT_UNCOND_BRANCH(ins);
4215 s390_br (code, ins->sreg1);
4221 s390_lghi(code, ins->dreg, 1);
4223 s390_lghi(code, ins->dreg, 0);
4229 s390_lghi(code, ins->dreg, 1);
4231 s390_lghi(code, ins->dreg, 0);
4237 s390_lghi(code, ins->dreg, 1);
4239 s390_lghi(code, ins->dreg, 0);
4245 s390_lghi(code, ins->dreg, 1);
4247 s390_lghi(code, ins->dreg, 0);
4253 s390_lghi(code, ins->dreg, 1);
4255 s390_lghi(code, ins->dreg, 0);
4258 case OP_COND_EXC_EQ:
4259 case OP_COND_EXC_IEQ:
4260 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_EQ, ins->inst_p1);
4262 case OP_COND_EXC_NE_UN:
4263 case OP_COND_EXC_INE_UN:
4264 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NE, ins->inst_p1);
4266 case OP_COND_EXC_LT:
4267 case OP_COND_EXC_ILT:
4268 case OP_COND_EXC_LT_UN:
4269 case OP_COND_EXC_ILT_UN:
4270 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, ins->inst_p1);
4272 case OP_COND_EXC_GT:
4273 case OP_COND_EXC_IGT:
4274 case OP_COND_EXC_GT_UN:
4275 case OP_COND_EXC_IGT_UN:
4276 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, ins->inst_p1);
4278 case OP_COND_EXC_GE:
4279 case OP_COND_EXC_IGE:
4280 case OP_COND_EXC_GE_UN:
4281 case OP_COND_EXC_IGE_UN:
4282 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GE, ins->inst_p1);
4284 case OP_COND_EXC_LE:
4285 case OP_COND_EXC_ILE:
4286 case OP_COND_EXC_LE_UN:
4287 case OP_COND_EXC_ILE_UN:
4288 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LE, ins->inst_p1);
4290 case OP_COND_EXC_OV:
4291 case OP_COND_EXC_IOV:
4292 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, ins->inst_p1);
4294 case OP_COND_EXC_NO:
4295 case OP_COND_EXC_INO:
4296 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NO, ins->inst_p1);
4299 case OP_COND_EXC_IC:
4300 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, ins->inst_p1);
4302 case OP_COND_EXC_NC:
4303 case OP_COND_EXC_INC:
4304 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, ins->inst_p1);
4308 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4312 EMIT_COND_BRANCH (ins, S390_CC_NE);
4318 EMIT_COND_BRANCH (ins, S390_CC_LT);
4324 EMIT_COND_BRANCH (ins, S390_CC_GT);
4330 EMIT_COND_BRANCH (ins, S390_CC_GE);
4336 EMIT_COND_BRANCH (ins, S390_CC_LE);
4339 /* floating point opcodes */
4341 if (*((double *) ins->inst_p0) == 0) {
4342 s390_lzdr (code, ins->dreg);
4344 S390_SET (code, s390_r13, ins->inst_p0);
4345 s390_ld (code, ins->dreg, 0, s390_r13, 0);
4350 if (*((float *) ins->inst_p0) == 0) {
4351 s390_lzdr (code, ins->dreg);
4353 S390_SET (code, s390_r13, ins->inst_p0);
4354 s390_ldeb (code, ins->dreg, 0, s390_r13, 0);
4358 case OP_STORER8_MEMBASE_REG: {
4359 S390_LONG (code, stdy, std, ins->sreg1, 0,
4360 ins->inst_destbasereg, ins->inst_offset);
4363 case OP_LOADR8_MEMBASE: {
4364 S390_LONG (code, ldy, ld, ins->dreg, 0,
4365 ins->inst_basereg, ins->inst_offset);
4368 case OP_STORER4_MEMBASE_REG: {
4369 s390_ledbr (code, s390_f15, ins->sreg1);
4370 S390_LONG (code, stey, ste, s390_f15, 0,
4371 ins->inst_destbasereg, ins->inst_offset);
4374 case OP_LOADR4_MEMBASE: {
4375 S390_LONG (code, ley, le, s390_f15, 0,
4376 ins->inst_basereg, ins->inst_offset);
4377 s390_ldebr (code, ins->dreg, s390_f15);
4380 case OP_ICONV_TO_R_UN: {
4381 if (mono_hwcap_s390x_has_fpe) {
4382 s390_cdlfbr (code, ins->dreg, 5, ins->sreg1, 0);
4384 s390_llgfr (code, s390_r0, ins->sreg1);
4385 s390_cdgbr (code, ins->dreg, s390_r0);
4389 case OP_LCONV_TO_R_UN: {
4390 if (mono_hwcap_s390x_has_fpe) {
4391 s390_cdlgbr (code, ins->dreg, 5, ins->sreg1, 0);
4394 s390_cxgbr (code, s390_f12, ins->sreg1);
4395 s390_ltgr (code, ins->sreg1, ins->sreg1);
4396 s390_jnl (code, 0); CODEPTR(code, jump);
4397 S390_SET (code, s390_r13, 0x403f000000000000llu);
4398 s390_lgdr (code, s390_f13, s390_r13);
4399 s390_lzdr (code, s390_f15);
4400 s390_axbr (code, s390_f12, s390_f13);
4401 PTRSLOT(code, jump);
4402 s390_ldxbr (code, s390_f13, s390_f12);
4403 s390_ldr (code, ins->dreg, s390_f13);
4407 case OP_LCONV_TO_R4:
4408 case OP_ICONV_TO_R4: {
4409 s390_cegbr (code, ins->dreg, ins->sreg1);
4410 s390_ldebr (code, ins->dreg, ins->dreg);
4413 case OP_LCONV_TO_R8:
4414 case OP_ICONV_TO_R8: {
4415 s390_cdgbr (code, ins->dreg, ins->sreg1);
4418 case OP_FCONV_TO_I1:
4419 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4420 s390_ltgr (code, ins->dreg, ins->dreg);
4422 s390_oill (code, ins->dreg, 0x80);
4423 s390_lghi (code, s390_r0, 0xff);
4424 s390_ngr (code, ins->dreg, s390_r0);
4426 case OP_FCONV_TO_U1:
4427 if (mono_hwcap_s390x_has_fpe) {
4428 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4429 s390_lghi (code, s390_r0, 0xff);
4430 s390_ngr (code, ins->dreg, s390_r0);
4432 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 1, FALSE);
4435 case OP_FCONV_TO_I2:
4436 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4437 s390_ltgr (code, ins->dreg, ins->dreg);
4439 s390_oill (code, ins->dreg, 0x8000);
4440 s390_llill (code, s390_r0, 0xffff);
4441 s390_ngr (code, ins->dreg, s390_r0);
4443 case OP_FCONV_TO_U2:
4444 if (mono_hwcap_s390x_has_fpe) {
4445 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4446 s390_llill (code, s390_r0, 0xffff);
4447 s390_ngr (code, ins->dreg, s390_r0);
4449 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 2, FALSE);
4452 case OP_FCONV_TO_I4:
4454 s390_cfdbr (code, ins->dreg, 5, ins->sreg1);
4456 case OP_FCONV_TO_U4:
4458 if (mono_hwcap_s390x_has_fpe) {
4459 s390_clfdbr (code, ins->dreg, 5, ins->sreg1, 0);
4461 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE);
4464 case OP_FCONV_TO_I8:
4465 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4467 case OP_FCONV_TO_U8:
4468 if (mono_hwcap_s390x_has_fpe) {
4469 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4471 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 8, FALSE);
4474 case OP_LCONV_TO_OVF_I: {
4475 /* Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000 */
4477 s390_ltgr (code, ins->sreg2, ins->sreg2);
4478 s390_jnl (code, 0); CODEPTR(code, o[0]);
4479 s390_ltgr (code, ins->sreg1, ins->sreg1);
4480 s390_jnl (code, 0); CODEPTR(code, o[1]);
4481 s390_lhi (code, s390_r13, -1);
4482 s390_cgr (code, ins->sreg1, s390_r13);
4483 s390_jnz (code, 0); CODEPTR(code, o[2]);
4484 if (ins->dreg != ins->sreg2)
4485 s390_lgr (code, ins->dreg, ins->sreg2);
4486 s390_j (code, 0); CODEPTR(code, o[3]);
4487 PTRSLOT(code, o[0]);
4488 s390_jz (code, 0); CODEPTR(code, o[4]);
4489 PTRSLOT(code, o[1]);
4490 PTRSLOT(code, o[2]);
4491 mono_add_patch_info (cfg, code - cfg->native_code,
4492 MONO_PATCH_INFO_EXC, "OverflowException");
4493 s390_brasl (code, s390_r14, 0);
4494 PTRSLOT(code, o[3]);
4495 PTRSLOT(code, o[4]);
4499 s390_lpdbr (code, ins->dreg, ins->sreg1);
4503 s390_sqdbr (code, ins->dreg, ins->sreg1);
4508 s390_adbr (code, ins->dreg, src2);
4512 CHECK_SRCDST_NCOM_F;
4513 s390_sdbr (code, ins->dreg, src2);
4518 s390_mdbr (code, ins->dreg, src2);
4522 CHECK_SRCDST_NCOM_F;
4523 s390_ddbr (code, ins->dreg, src2);
4527 s390_lcdbr (code, ins->dreg, ins->sreg1);
4531 CHECK_SRCDST_NCOM_F;
4532 s390_didbr (code, ins->dreg, src2, 5, s390_f15);
4536 s390_cdbr (code, ins->sreg1, ins->sreg2);
4540 s390_cdbr (code, ins->sreg1, ins->sreg2);
4541 s390_lghi (code, ins->dreg, 1);
4543 s390_lghi (code, ins->dreg, 0);
4547 s390_cdbr (code, ins->sreg1, ins->sreg2);
4548 s390_lghi (code, ins->dreg, 1);
4550 s390_lghi (code, ins->dreg, 0);
4554 s390_cdbr (code, ins->sreg1, ins->sreg2);
4555 s390_lghi (code, ins->dreg, 1);
4557 s390_lghi (code, ins->dreg, 0);
4561 s390_cdbr (code, ins->sreg1, ins->sreg2);
4562 s390_lghi (code, ins->dreg, 1);
4564 s390_lghi (code, ins->dreg, 0);
4568 s390_cdbr (code, ins->sreg1, ins->sreg2);
4569 s390_lghi (code, ins->dreg, 1);
4571 s390_lghi (code, ins->dreg, 0);
4576 s390_jo (code, 0); CODEPTR(code, o);
4577 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4582 EMIT_COND_BRANCH (ins, S390_CC_NE|S390_CC_OV);
4586 s390_jo (code, 0); CODEPTR(code, o);
4587 EMIT_COND_BRANCH (ins, S390_CC_LT);
4592 EMIT_COND_BRANCH (ins, S390_CC_LT|S390_CC_OV);
4596 s390_jo (code, 0); CODEPTR(code, o);
4597 EMIT_COND_BRANCH (ins, S390_CC_GT);
4602 EMIT_COND_BRANCH (ins, S390_CC_GT|S390_CC_OV);
4606 s390_jo (code, 0); CODEPTR(code, o);
4607 EMIT_COND_BRANCH (ins, S390_CC_GE);
4612 EMIT_COND_BRANCH (ins, S390_CC_GE|S390_CC_OV);
4616 s390_jo (code, 0); CODEPTR(code, o);
4617 EMIT_COND_BRANCH (ins, S390_CC_LE);
4622 EMIT_COND_BRANCH (ins, S390_CC_LE|S390_CC_OV);
4626 s390_lhi (code, s390_r13, 0x7f);
4627 s390_tcdb (code, ins->sreg1, 0, s390_r13, 0);
4628 s390_jz (code, 0); CODEPTR(code, o);
4629 mono_add_patch_info (cfg, code - cfg->native_code,
4630 MONO_PATCH_INFO_EXC, "OverflowException");
4631 s390_brasl (code, s390_r14,0);
4635 case OP_S390_MOVE: {
4636 if (ins->backend.size > 0) {
4637 if (ins->backend.size <= 256) {
4638 s390_mvc (code, ins->backend.size, ins->dreg,
4639 ins->inst_offset, ins->sreg1, ins->inst_imm);
4641 s390_lgr (code, s390_r0, ins->dreg);
4642 if (ins->inst_offset > 0) {
4643 if (s390_is_imm16 (ins->inst_offset)) {
4644 s390_aghi (code, s390_r0, ins->inst_offset);
4645 } else if (s390_is_imm32 (ins->inst_offset)) {
4646 s390_agfi (code, s390_r0, ins->inst_offset);
4648 S390_SET (code, s390_r13, ins->inst_offset);
4649 s390_agr (code, s390_r0, s390_r13);
4652 s390_lgr (code, s390_r12, ins->sreg1);
4653 if (ins->inst_imm > 0) {
4654 if (s390_is_imm16 (ins->inst_imm)) {
4655 s390_aghi (code, s390_r12, ins->inst_imm);
4656 } else if (s390_is_imm32 (ins->inst_imm)) {
4657 s390_agfi (code, s390_r12, ins->inst_imm);
4659 S390_SET (code, s390_r13, ins->inst_imm);
4660 s390_agr (code, s390_r12, s390_r13);
4663 if (s390_is_imm16 (ins->backend.size)) {
4664 s390_lghi (code, s390_r1, ins->backend.size);
4665 } else if (s390_is_imm32 (ins->inst_offset)) {
4666 s390_agfi (code, s390_r1, ins->backend.size);
4668 S390_SET (code, s390_r13, ins->backend.size);
4669 s390_agr (code, s390_r1, s390_r13);
4671 s390_lgr (code, s390_r13, s390_r1);
4672 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4678 case OP_ATOMIC_ADD_I8: {
4679 s390_lgr (code, s390_r1, ins->sreg2);
4680 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4681 s390_agr (code, s390_r1, s390_r0);
4682 s390_csg (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4683 s390_jnz (code, -10);
4684 s390_lgr (code, ins->dreg, s390_r1);
4687 case OP_ATOMIC_EXCHANGE_I8: {
4688 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4689 s390_csg (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
4690 s390_jnz (code, -6);
4691 s390_lgr (code, ins->dreg, s390_r0);
4694 case OP_ATOMIC_ADD_I4: {
4695 s390_lgfr(code, s390_r1, ins->sreg2);
4696 s390_lgf (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4697 s390_agr (code, s390_r1, s390_r0);
4698 s390_cs (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4699 s390_jnz (code, -9);
4700 s390_lgfr(code, ins->dreg, s390_r1);
4703 case OP_ATOMIC_EXCHANGE_I4: {
4704 s390_l (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4705 s390_cs (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
4706 s390_jnz (code, -4);
4707 s390_lgfr(code, ins->dreg, s390_r0);
4710 case OP_S390_BKCHAIN: {
4711 s390_lgr (code, ins->dreg, ins->sreg1);
4712 if (s390_is_imm16 (cfg->stack_offset)) {
4713 s390_aghi (code, ins->dreg, cfg->stack_offset);
4714 } else if (s390_is_imm32 (cfg->stack_offset)) {
4715 s390_agfi (code, ins->dreg, cfg->stack_offset);
4717 S390_SET (code, s390_r13, cfg->stack_offset);
4718 s390_agr (code, ins->dreg, s390_r13);
4722 case OP_MEMORY_BARRIER:
4725 case OP_GC_SAFE_POINT: {
4728 g_assert (mono_threads_is_coop_enabled ());
4730 s390_chi (code, ins->sreg1, 1);
4731 s390_je (code, 0); CODEPTR(code, br);
4732 mono_add_patch_info (cfg, code- cfg->native_code, MONO_PATCH_INFO_ABS,
4733 mono_threads_state_poll);
4734 S390_CALL_TEMPLATE (code, s390_r14);
4738 case OP_GC_LIVENESS_DEF:
4739 case OP_GC_LIVENESS_USE:
4740 case OP_GC_PARAM_SLOT_LIVENESS_DEF:
4741 ins->backend.pc_offset = code - cfg->native_code;
4743 case OP_GC_SPILL_SLOT_LIVENESS_DEF:
4744 ins->backend.pc_offset = code - cfg->native_code;
4745 bb->spill_slot_defs = g_slist_prepend_mempool (cfg->mempool, bb->spill_slot_defs, ins);
4747 #ifdef MONO_ARCH_SIMD_INTRINSICS
4749 s390x_addps (code, ins->sreg1, ins->sreg2);
4752 s390x_divps (code, ins->sreg1, ins->sreg2);
4755 s390x_mulps (code, ins->sreg1, ins->sreg2);
4758 s390x_subps (code, ins->sreg1, ins->sreg2);
4761 s390x_maxps (code, ins->sreg1, ins->sreg2);
4764 s390x_minps (code, ins->sreg1, ins->sreg2);
4767 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
4768 s390x_cmpps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4771 s390x_andps (code, ins->sreg1, ins->sreg2);
4774 s390x_andnps (code, ins->sreg1, ins->sreg2);
4777 s390x_orps (code, ins->sreg1, ins->sreg2);
4780 s390x_xorps (code, ins->sreg1, ins->sreg2);
4783 s390x_sqrtps (code, ins->dreg, ins->sreg1);
4786 s390x_rsqrtps (code, ins->dreg, ins->sreg1);
4789 s390x_rcpps (code, ins->dreg, ins->sreg1);
4792 s390x_addsubps (code, ins->sreg1, ins->sreg2);
4795 s390x_haddps (code, ins->sreg1, ins->sreg2);
4798 s390x_hsubps (code, ins->sreg1, ins->sreg2);
4801 s390x_movshdup (code, ins->dreg, ins->sreg1);
4804 s390x_movsldup (code, ins->dreg, ins->sreg1);
4807 case OP_PSHUFLEW_HIGH:
4808 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4809 s390x_pshufhw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4811 case OP_PSHUFLEW_LOW:
4812 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4813 s390x_pshuflw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4816 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4817 s390x_pshufd_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4820 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4821 s390x_shufps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4824 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0x3);
4825 s390x_shufpd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4829 s390x_addpd (code, ins->sreg1, ins->sreg2);
4832 s390x_divpd (code, ins->sreg1, ins->sreg2);
4835 s390x_mulpd (code, ins->sreg1, ins->sreg2);
4838 s390x_subpd (code, ins->sreg1, ins->sreg2);
4841 s390x_maxpd (code, ins->sreg1, ins->sreg2);
4844 s390x_minpd (code, ins->sreg1, ins->sreg2);
4847 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
4848 s390x_cmppd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4851 s390x_andpd (code, ins->sreg1, ins->sreg2);
4854 s390x_andnpd (code, ins->sreg1, ins->sreg2);
4857 s390x_orpd (code, ins->sreg1, ins->sreg2);
4860 s390x_xorpd (code, ins->sreg1, ins->sreg2);
4863 s390x_sqrtpd (code, ins->dreg, ins->sreg1);
4866 s390x_addsubpd (code, ins->sreg1, ins->sreg2);
4869 s390x_haddpd (code, ins->sreg1, ins->sreg2);
4872 s390x_hsubpd (code, ins->sreg1, ins->sreg2);
4875 s390x_movddup (code, ins->dreg, ins->sreg1);
4878 case OP_EXTRACT_MASK:
4879 s390x_pmovmskb (code, ins->dreg, ins->sreg1);
4883 s390x_pand (code, ins->sreg1, ins->sreg2);
4886 s390x_por (code, ins->sreg1, ins->sreg2);
4889 s390x_pxor (code, ins->sreg1, ins->sreg2);
4893 s390x_paddb (code, ins->sreg1, ins->sreg2);
4896 s390x_paddw (code, ins->sreg1, ins->sreg2);
4899 s390x_paddd (code, ins->sreg1, ins->sreg2);
4902 s390x_paddq (code, ins->sreg1, ins->sreg2);
4906 s390x_psubb (code, ins->sreg1, ins->sreg2);
4909 s390x_psubw (code, ins->sreg1, ins->sreg2);
4912 s390x_psubd (code, ins->sreg1, ins->sreg2);
4915 s390x_psubq (code, ins->sreg1, ins->sreg2);
4919 s390x_pmaxub (code, ins->sreg1, ins->sreg2);
4922 s390x_pmaxuw (code, ins->sreg1, ins->sreg2);
4925 s390x_pmaxud (code, ins->sreg1, ins->sreg2);
4929 s390x_pmaxsb (code, ins->sreg1, ins->sreg2);
4932 s390x_pmaxsw (code, ins->sreg1, ins->sreg2);
4935 s390x_pmaxsd (code, ins->sreg1, ins->sreg2);
4939 s390x_pavgb (code, ins->sreg1, ins->sreg2);
4942 s390x_pavgw (code, ins->sreg1, ins->sreg2);
4946 s390x_pminub (code, ins->sreg1, ins->sreg2);
4949 s390x_pminuw (code, ins->sreg1, ins->sreg2);
4952 s390x_pminud (code, ins->sreg1, ins->sreg2);
4956 s390x_pminsb (code, ins->sreg1, ins->sreg2);
4959 s390x_pminsw (code, ins->sreg1, ins->sreg2);
4962 s390x_pminsd (code, ins->sreg1, ins->sreg2);
4966 s390x_pcmpeqb (code, ins->sreg1, ins->sreg2);
4969 s390x_pcmpeqw (code, ins->sreg1, ins->sreg2);
4972 s390x_pcmpeqd (code, ins->sreg1, ins->sreg2);
4975 s390x_pcmpeqq (code, ins->sreg1, ins->sreg2);
4979 s390x_pcmpgtb (code, ins->sreg1, ins->sreg2);
4982 s390x_pcmpgtw (code, ins->sreg1, ins->sreg2);
4985 s390x_pcmpgtd (code, ins->sreg1, ins->sreg2);
4988 s390x_pcmpgtq (code, ins->sreg1, ins->sreg2);
4991 case OP_PSUM_ABS_DIFF:
4992 s390x_psadbw (code, ins->sreg1, ins->sreg2);
4995 case OP_UNPACK_LOWB:
4996 s390x_punpcklbw (code, ins->sreg1, ins->sreg2);
4998 case OP_UNPACK_LOWW:
4999 s390x_punpcklwd (code, ins->sreg1, ins->sreg2);
5001 case OP_UNPACK_LOWD:
5002 s390x_punpckldq (code, ins->sreg1, ins->sreg2);
5004 case OP_UNPACK_LOWQ:
5005 s390x_punpcklqdq (code, ins->sreg1, ins->sreg2);
5007 case OP_UNPACK_LOWPS:
5008 s390x_unpcklps (code, ins->sreg1, ins->sreg2);
5010 case OP_UNPACK_LOWPD:
5011 s390x_unpcklpd (code, ins->sreg1, ins->sreg2);
5014 case OP_UNPACK_HIGHB:
5015 s390x_punpckhbw (code, ins->sreg1, ins->sreg2);
5017 case OP_UNPACK_HIGHW:
5018 s390x_punpckhwd (code, ins->sreg1, ins->sreg2);
5020 case OP_UNPACK_HIGHD:
5021 s390x_punpckhdq (code, ins->sreg1, ins->sreg2);
5023 case OP_UNPACK_HIGHQ:
5024 s390x_punpckhqdq (code, ins->sreg1, ins->sreg2);
5026 case OP_UNPACK_HIGHPS:
5027 s390x_unpckhps (code, ins->sreg1, ins->sreg2);
5029 case OP_UNPACK_HIGHPD:
5030 s390x_unpckhpd (code, ins->sreg1, ins->sreg2);
5034 s390x_packsswb (code, ins->sreg1, ins->sreg2);
5037 s390x_packssdw (code, ins->sreg1, ins->sreg2);
5040 s390x_packuswb (code, ins->sreg1, ins->sreg2);
5043 s390x_packusdw (code, ins->sreg1, ins->sreg2);
5046 case OP_PADDB_SAT_UN:
5047 s390x_paddusb (code, ins->sreg1, ins->sreg2);
5049 case OP_PSUBB_SAT_UN:
5050 s390x_psubusb (code, ins->sreg1, ins->sreg2);
5052 case OP_PADDW_SAT_UN:
5053 s390x_paddusw (code, ins->sreg1, ins->sreg2);
5055 case OP_PSUBW_SAT_UN:
5056 s390x_psubusw (code, ins->sreg1, ins->sreg2);
5060 s390x_paddsb (code, ins->sreg1, ins->sreg2);
5063 s390x_psubsb (code, ins->sreg1, ins->sreg2);
5066 s390x_paddsw (code, ins->sreg1, ins->sreg2);
5069 s390x_psubsw (code, ins->sreg1, ins->sreg2);
5073 s390x_pmullw (code, ins->sreg1, ins->sreg2);
5076 s390x_pmulld (code, ins->sreg1, ins->sreg2);
5079 s390x_pmuludq (code, ins->sreg1, ins->sreg2);
5081 case OP_PMULW_HIGH_UN:
5082 s390x_pmulhuw (code, ins->sreg1, ins->sreg2);
5085 s390x_pmulhw (code, ins->sreg1, ins->sreg2);
5089 s390x_psrlw_reg_imm (code, ins->dreg, ins->inst_imm);
5092 s390x_psrlw (code, ins->dreg, ins->sreg2);
5096 s390x_psraw_reg_imm (code, ins->dreg, ins->inst_imm);
5099 s390x_psraw (code, ins->dreg, ins->sreg2);
5103 s390x_psllw_reg_imm (code, ins->dreg, ins->inst_imm);
5106 s390x_psllw (code, ins->dreg, ins->sreg2);
5110 s390x_psrld_reg_imm (code, ins->dreg, ins->inst_imm);
5113 s390x_psrld (code, ins->dreg, ins->sreg2);
5117 s390x_psrad_reg_imm (code, ins->dreg, ins->inst_imm);
5120 s390x_psrad (code, ins->dreg, ins->sreg2);
5124 s390x_pslld_reg_imm (code, ins->dreg, ins->inst_imm);
5127 s390x_pslld (code, ins->dreg, ins->sreg2);
5131 s390x_psrlq_reg_imm (code, ins->dreg, ins->inst_imm);
5134 s390x_psrlq (code, ins->dreg, ins->sreg2);
5137 /*TODO: This is appart of the sse spec but not added
5139 s390x_psraq_reg_imm (code, ins->dreg, ins->inst_imm);
5142 s390x_psraq (code, ins->dreg, ins->sreg2);
5147 s390x_psllq_reg_imm (code, ins->dreg, ins->inst_imm);
5150 s390x_psllq (code, ins->dreg, ins->sreg2);
5153 s390x_cvtdq2pd (code, ins->dreg, ins->sreg1);
5156 s390x_cvtdq2ps (code, ins->dreg, ins->sreg1);
5159 s390x_cvtpd2dq (code, ins->dreg, ins->sreg1);
5162 s390x_cvtpd2ps (code, ins->dreg, ins->sreg1);
5165 s390x_cvtps2dq (code, ins->dreg, ins->sreg1);
5168 s390x_cvtps2pd (code, ins->dreg, ins->sreg1);
5171 s390x_cvttpd2dq (code, ins->dreg, ins->sreg1);
5174 s390x_cvttps2dq (code, ins->dreg, ins->sreg1);
5178 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5181 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5185 amd64_movhlps (code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg1);
5186 amd64_movd_reg_xreg_size (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG, 8);
5188 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 8);
5193 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5195 amd64_shift_reg_imm (code, X86_SHR, ins->dreg, ins->inst_c0 * 8);
5196 amd64_widen_reg (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I1, FALSE);
5200 /*amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5202 amd64_shift_reg_imm_size (code, X86_SHR, ins->dreg, 16, 4);*/
5203 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5204 amd64_widen_reg_size (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I2, TRUE, 4);
5208 amd64_movhlps (code, ins->dreg, ins->sreg1);
5210 s390x_movsd (code, ins->dreg, ins->sreg1);
5213 s390x_pinsrw_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5215 case OP_EXTRACTX_U2:
5216 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5218 case OP_INSERTX_U1_SLOW:
5219 /*sreg1 is the extracted ireg (scratch)
5220 /sreg2 is the to be inserted ireg (scratch)
5221 /dreg is the xreg to receive the value*/
5223 /*clear the bits from the extracted word*/
5224 amd64_alu_reg_imm (code, X86_AND, ins->sreg1, ins->inst_c0 & 1 ? 0x00FF : 0xFF00);
5225 /*shift the value to insert if needed*/
5226 if (ins->inst_c0 & 1)
5227 amd64_shift_reg_imm_size (code, X86_SHL, ins->sreg2, 8, 4);
5228 /*join them together*/
5229 amd64_alu (code, X86_OR, ins->sreg1, ins->sreg2);
5230 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0 / 2);
5232 case OP_INSERTX_I4_SLOW:
5233 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2);
5234 amd64_shift_reg_imm (code, X86_SHR, ins->sreg2, 16);
5235 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2 + 1);
5237 case OP_INSERTX_I8_SLOW:
5238 amd64_movd_xreg_reg_size(code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg2, 8);
5240 amd64_movlhps (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5242 s390x_movsd (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5245 case OP_INSERTX_R4_SLOW:
5246 switch (ins->inst_c0) {
5249 s390x_movss (code, ins->dreg, ins->sreg2);
5251 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5254 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5256 s390x_movss (code, ins->dreg, ins->sreg2);
5258 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5259 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5262 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5264 s390x_movss (code, ins->dreg, ins->sreg2);
5266 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5267 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5270 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5272 s390x_movss (code, ins->dreg, ins->sreg2);
5274 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5275 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5279 case OP_INSERTX_R8_SLOW:
5281 amd64_movlhps (code, ins->dreg, ins->sreg2);
5283 s390x_movsd (code, ins->dreg, ins->sreg2);
5285 case OP_STOREX_MEMBASE_REG:
5286 case OP_STOREX_MEMBASE:
5287 s390x_movups_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5289 case OP_LOADX_MEMBASE:
5290 s390x_movups_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5292 case OP_LOADX_ALIGNED_MEMBASE:
5293 s390x_movaps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5295 case OP_STOREX_ALIGNED_MEMBASE_REG:
5296 s390x_movaps_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5298 case OP_STOREX_NTA_MEMBASE_REG:
5299 s390x_movntps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5301 case OP_PREFETCH_MEMBASE:
5302 s390x_prefetch_reg_membase (code, ins->backend.arg_info, ins->sreg1, ins->inst_offset);
5306 /*FIXME the peephole pass should have killed this*/
5307 if (ins->dreg != ins->sreg1)
5308 s390x_movaps (code, ins->dreg, ins->sreg1);
5311 s390x_pxor (code, ins->dreg, ins->dreg);
5313 case OP_ICONV_TO_R4_RAW:
5314 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5317 case OP_FCONV_TO_R8_X:
5318 s390x_movsd (code, ins->dreg, ins->sreg1);
5321 case OP_XCONV_R8_TO_I4:
5322 s390x_cvttsd2si_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5323 switch (ins->backend.source_opcode) {
5324 case OP_FCONV_TO_I1:
5325 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, FALSE);
5327 case OP_FCONV_TO_U1:
5328 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, FALSE);
5330 case OP_FCONV_TO_I2:
5331 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, TRUE);
5333 case OP_FCONV_TO_U2:
5334 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, TRUE);
5340 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 0);
5341 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 1);
5342 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5345 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5346 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5349 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 8);
5350 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5354 s390x_movsd (code, ins->dreg, ins->sreg1);
5356 s390x_movsd (code, ins->dreg, ins->sreg1);
5357 s390x_cvtsd2ss (code, ins->dreg, ins->dreg);
5359 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5362 s390x_movsd (code, ins->dreg, ins->sreg1);
5363 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5367 g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
5368 g_assert_not_reached ();
5371 if ((cfg->opt & MONO_OPT_BRANCH) && ((code - cfg->native_code - offset) > max_len)) {
5372 g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %ld)",
5373 mono_inst_name (ins->opcode), max_len, code - cfg->native_code - offset);
5374 g_assert_not_reached ();
5377 last_offset = offset;
5380 cfg->code_len = code - cfg->native_code;
5383 /*========================= End of Function ========================*/
5385 /*------------------------------------------------------------------*/
5387 /* Name - mono_arch_register_lowlevel_calls */
5389 /* Function - Register routines to help with --trace operation. */
5391 /*------------------------------------------------------------------*/
5394 mono_arch_register_lowlevel_calls (void)
5398 /*========================= End of Function ========================*/
5400 /*------------------------------------------------------------------*/
5402 /* Name - mono_arch_patch_code */
5404 /* Function - Process the patch data created during the */
5405 /* instruction build process. This resolves jumps, */
5406 /* calls, variables etc. */
5408 /*------------------------------------------------------------------*/
5411 mono_arch_patch_code (MonoCompile *cfg, MonoMethod *method, MonoDomain *domain,
5412 guint8 *code, MonoJumpInfo *ji, gboolean run_cctors,
5415 MonoJumpInfo *patch_info;
5419 for (patch_info = ji; patch_info; patch_info = patch_info->next) {
5420 unsigned char *ip = patch_info->ip.i + code;
5421 gconstpointer target = NULL;
5423 target = mono_resolve_patch_target (method, domain, code,
5424 patch_info, run_cctors, error);
5425 return_if_nok (error);
5427 switch (patch_info->type) {
5428 case MONO_PATCH_INFO_IP:
5429 case MONO_PATCH_INFO_LDSTR:
5430 case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
5431 case MONO_PATCH_INFO_LDTOKEN:
5432 case MONO_PATCH_INFO_EXC:
5433 s390_patch_addr (ip, (guint64) target);
5435 case MONO_PATCH_INFO_METHOD:
5436 case MONO_PATCH_INFO_INTERNAL_METHOD:
5437 case MONO_PATCH_INFO_JIT_ICALL_ADDR:
5438 case MONO_PATCH_INFO_RGCTX_FETCH:
5439 case MONO_PATCH_INFO_ABS: {
5440 S390_EMIT_CALL (ip, target);
5443 case MONO_PATCH_INFO_SWITCH:
5444 /*----------------------------------*/
5445 /* ip points at the basr r13,0/j +4 */
5446 /* instruction the vtable value */
5447 /* follows this (i.e. ip+6) */
5448 /*----------------------------------*/
5449 S390_EMIT_LOAD (ip, target);
5451 case MONO_PATCH_INFO_METHODCONST:
5452 case MONO_PATCH_INFO_CLASS:
5453 case MONO_PATCH_INFO_IMAGE:
5454 case MONO_PATCH_INFO_FIELD:
5455 case MONO_PATCH_INFO_IID:
5456 case MONO_PATCH_INFO_EXC_NAME:
5457 target = S390_RELATIVE(target, ip);
5458 s390_patch_rel (ip, (guint64) target);
5460 case MONO_PATCH_INFO_R4:
5461 case MONO_PATCH_INFO_R8:
5462 case MONO_PATCH_INFO_METHOD_REL:
5463 g_assert_not_reached ();
5466 target = S390_RELATIVE(target, ip);
5468 s390_patch_rel (ip, (guint64) target);
5473 /*========================= End of Function ========================*/
5475 /*------------------------------------------------------------------*/
5477 /* Name - emit_load_volatile_arguments */
5479 /* Function - Emit the instructions to reload parameter regist- */
5480 /* registers for use with "tail" operations. */
5482 /* The register loading operations performed here */
5483 /* are the mirror of the store operations performed */
5484 /* in mono_arch_emit_prolog and need to be kept in */
5485 /* synchronization with it. */
5487 /*------------------------------------------------------------------*/
5490 emit_load_volatile_arguments (guint8 *code, MonoCompile *cfg)
5493 MonoMethod *method = cfg->method;
5494 MonoMethodSignature *sig = mono_method_signature(method);
5498 cinfo = get_call_info (NULL, NULL, sig);
5500 if (cinfo->struct_ret) {
5501 ArgInfo *ainfo = &cinfo->ret;
5502 inst = cfg->vret_addr;
5503 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5506 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5507 ArgInfo *ainfo = cinfo->args + i;
5508 inst = cfg->args [pos];
5510 if (inst->opcode == OP_REGVAR) {
5511 if (ainfo->regtype == RegTypeGeneral)
5512 s390_lgr (code, ainfo->reg, inst->dreg);
5513 else if (ainfo->regtype == RegTypeFP) {
5514 if (inst->dreg != ainfo->reg) {
5515 if (ainfo->size == 4) {
5516 s390_ldebr (code, ainfo->reg, inst->dreg);
5518 s390_ldr (code, ainfo->reg, inst->dreg);
5522 else if (ainfo->regtype == RegTypeBase) {
5524 g_assert_not_reached ();
5526 if (ainfo->regtype == RegTypeGeneral) {
5527 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5528 g_assert_not_reached();
5529 switch (ainfo->size) {
5531 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5534 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5537 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5540 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5543 } else if (ainfo->regtype == RegTypeBase) {
5544 } else if (ainfo->regtype == RegTypeFP) {
5545 if (ainfo->size == 8)
5546 s390_ld (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5547 else if (ainfo->size == 4)
5548 s390_le (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5550 g_assert_not_reached ();
5551 } else if (ainfo->regtype == RegTypeStructByVal) {
5552 if (ainfo->reg != STK_BASE) {
5553 switch (ainfo->size) {
5555 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5558 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5561 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5564 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5568 } else if (ainfo->regtype == RegTypeStructByAddr) {
5569 if (ainfo->reg != STK_BASE) {
5570 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5573 g_assert_not_reached ();
5581 /*========================= End of Function ========================*/
5583 /*------------------------------------------------------------------*/
5585 /* Name - mono_arch_emit_prolog */
5587 /* Function - Create the instruction sequence for a function */
5590 /*------------------------------------------------------------------*/
5593 mono_arch_emit_prolog (MonoCompile *cfg)
5595 MonoMethod *method = cfg->method;
5597 MonoMethodSignature *sig;
5599 long alloc_size, pos, max_offset, i, cfa_offset = 0;
5608 cfg->code_size = 512;
5610 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
5612 cfg->code_size += 256;
5615 if (method->save_lmf)
5616 cfg->code_size += 200;
5618 cfg->native_code = code = g_malloc (cfg->code_size);
5620 mono_emit_unwind_op_def_cfa (cfg, code, STK_BASE, 0);
5621 emit_unwind_regs(cfg, code, s390_r6, s390_r14, S390_REG_SAVE_OFFSET);
5622 s390_stmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
5623 mono_emit_unwind_op_offset (cfg, code, s390_r14, S390_RET_ADDR_OFFSET);
5624 mini_gc_set_slot_type_from_cfa (cfg, S390_RET_ADDR_OFFSET, SLOT_NOREF);
5626 if (cfg->arch.bkchain_reg != -1)
5627 s390_lgr (code, cfg->arch.bkchain_reg, STK_BASE);
5629 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
5630 cfg->used_int_regs |= 1 << 11;
5633 alloc_size = cfg->stack_offset;
5635 cfg->stack_usage = cfa_offset = alloc_size;
5636 mono_emit_unwind_op_def_cfa_offset (cfg, code, alloc_size);
5637 s390_lgr (code, s390_r11, STK_BASE);
5638 if (s390_is_imm16 (alloc_size)) {
5639 s390_aghi (code, STK_BASE, -alloc_size);
5640 } else if (s390_is_imm32 (alloc_size)) {
5641 s390_agfi (code, STK_BASE, -alloc_size);
5643 int stackSize = alloc_size;
5644 while (stackSize > INT_MAX) {
5645 s390_agfi (code, STK_BASE, -INT_MAX);
5646 stackSize -= INT_MAX;
5648 s390_agfi (code, STK_BASE, -stackSize);
5650 s390_stg (code, s390_r11, 0, STK_BASE, 0);
5652 if (cfg->frame_reg != STK_BASE)
5653 s390_lgr (code, s390_r11, STK_BASE);
5655 mono_emit_unwind_op_def_cfa_reg (cfg, code, cfg->frame_reg);
5657 /* store runtime generic context */
5658 if (cfg->rgctx_var) {
5659 g_assert (cfg->rgctx_var->opcode == OP_REGOFFSET);
5661 s390_stg (code, MONO_ARCH_RGCTX_REG, 0,
5662 cfg->rgctx_var->inst_basereg,
5663 cfg->rgctx_var->inst_offset);
5666 /* compute max_offset in order to use short forward jumps
5667 * we always do it on s390 because the immediate displacement
5668 * for jumps is too small
5671 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
5673 bb->max_offset = max_offset;
5675 if (cfg->prof_options & MONO_PROFILE_COVERAGE)
5678 MONO_BB_FOR_EACH_INS (bb, ins)
5679 max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
5682 /* load arguments allocated to register from the stack */
5683 sig = mono_method_signature (method);
5686 cinfo = get_call_info (cfg, cfg->mempool, sig);
5688 if (cinfo->struct_ret) {
5689 ArgInfo *ainfo = &cinfo->ret;
5690 inst = cfg->vret_addr;
5691 inst->backend.size = ainfo->vtsize;
5692 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5695 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5696 ArgInfo *ainfo = cinfo->args + i;
5697 inst = cfg->args [pos];
5699 if (inst->opcode == OP_VTARG_ADDR)
5700 inst = inst->inst_left;
5702 if (inst->opcode == OP_REGVAR) {
5703 if (ainfo->regtype == RegTypeGeneral)
5704 s390_lgr (code, inst->dreg, ainfo->reg);
5705 else if (ainfo->regtype == RegTypeFP) {
5706 if (inst->dreg != ainfo->reg) {
5707 if (ainfo->size == 4) {
5708 s390_ledbr (code, inst->dreg, ainfo->reg);
5710 s390_ldr (code, inst->dreg, ainfo->reg);
5714 else if (ainfo->regtype == RegTypeBase) {
5715 s390_lgr (code, s390_r13, STK_BASE);
5716 s390_aghi (code, s390_r13, alloc_size);
5717 s390_lg (code, inst->dreg, 0, s390_r13, ainfo->offset);
5719 g_assert_not_reached ();
5721 if (cfg->verbose_level > 2)
5722 g_print ("Argument %d assigned to register %s\n",
5723 pos, mono_arch_regname (inst->dreg));
5725 if (ainfo->regtype == RegTypeGeneral) {
5726 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5727 g_assert_not_reached();
5728 switch (ainfo->size) {
5730 s390_stc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5733 s390_sth (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5736 s390_st (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5739 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5742 } else if (ainfo->regtype == RegTypeBase) {
5743 } else if (ainfo->regtype == RegTypeFP) {
5744 if (ainfo->size == 8)
5745 s390_std (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5746 else if (ainfo->size == 4)
5747 s390_ste (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5749 g_assert_not_reached ();
5750 } else if (ainfo->regtype == RegTypeStructByVal) {
5751 int doffset = inst->inst_offset;
5753 if (ainfo->reg != STK_BASE)
5757 s390_lgr (code, s390_r13, STK_BASE);
5758 s390_aghi (code, s390_r13, alloc_size);
5761 size = (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE
5762 ? mono_class_native_size(mono_class_from_mono_type(inst->inst_vtype), NULL)
5767 if (ainfo->reg == STK_BASE)
5768 s390_ic (code, reg, 0, s390_r13, ainfo->offset+7);
5769 s390_stc (code, reg, 0, inst->inst_basereg, doffset);
5772 if (ainfo->reg == STK_BASE)
5773 s390_lh (code, reg, 0, s390_r13, ainfo->offset+6);
5774 s390_sth (code, reg, 0, inst->inst_basereg, doffset);
5777 if (ainfo->reg == STK_BASE)
5778 s390_l (code, reg, 0, s390_r13, ainfo->offset+4);
5779 s390_st (code, reg, 0, inst->inst_basereg, doffset);
5782 if (ainfo->reg == STK_BASE)
5783 s390_lg (code, reg, 0, s390_r13, ainfo->offset);
5784 s390_stg (code, reg, 0, inst->inst_basereg, doffset);
5787 } else if (ainfo->regtype == RegTypeStructByAddr) {
5788 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5789 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
5791 g_assert_not_reached ();
5796 if (method->save_lmf) {
5797 /*---------------------------------------------------------------*/
5798 /* build the MonoLMF structure on the stack - see mini-s390x.h */
5799 /*---------------------------------------------------------------*/
5800 lmfOffset = alloc_size - sizeof(MonoLMF);
5802 s390_lgr (code, s390_r13, cfg->frame_reg);
5803 s390_aghi (code, s390_r13, lmfOffset);
5805 /*---------------------------------------------------------------*/
5806 /* Preserve the parameter registers while we fix up the lmf */
5807 /*---------------------------------------------------------------*/
5808 s390_stmg (code, s390_r2, s390_r6, s390_r13,
5809 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
5811 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[0]), SLOT_NOREF);
5812 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[1]), SLOT_NOREF);
5813 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[2]), SLOT_NOREF);
5814 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[3]), SLOT_NOREF);
5815 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[4]), SLOT_NOREF);
5817 /*---------------------------------------------------------------*/
5818 /* On return from this call r2 have the address of the &lmf */
5819 /*---------------------------------------------------------------*/
5820 mono_add_patch_info (cfg, code - cfg->native_code,
5821 MONO_PATCH_INFO_INTERNAL_METHOD,
5822 (gpointer)"mono_tls_get_lmf_addr");
5823 S390_CALL_TEMPLATE(code, s390_r1);
5825 /*---------------------------------------------------------------*/
5826 /* Set lmf.lmf_addr = jit_tls->lmf */
5827 /*---------------------------------------------------------------*/
5828 s390_stg (code, s390_r2, 0, s390_r13,
5829 G_STRUCT_OFFSET(MonoLMF, lmf_addr));
5830 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, lmf_addr), SLOT_NOREF);
5832 /*---------------------------------------------------------------*/
5833 /* Get current lmf */
5834 /*---------------------------------------------------------------*/
5835 s390_lg (code, s390_r0, 0, s390_r2, 0);
5837 /*---------------------------------------------------------------*/
5838 /* Set our lmf as the current lmf */
5839 /*---------------------------------------------------------------*/
5840 s390_stg (code, s390_r13, 0, s390_r2, 0);
5842 /*---------------------------------------------------------------*/
5843 /* Have our lmf.previous_lmf point to the last lmf */
5844 /*---------------------------------------------------------------*/
5845 s390_stg (code, s390_r0, 0, s390_r13,
5846 G_STRUCT_OFFSET(MonoLMF, previous_lmf));
5847 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), SLOT_NOREF);
5849 /*---------------------------------------------------------------*/
5850 /* save method info */
5851 /*---------------------------------------------------------------*/
5852 S390_SET (code, s390_r1, method);
5853 s390_stg (code, s390_r1, 0, s390_r13,
5854 G_STRUCT_OFFSET(MonoLMF, method));
5855 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, method), SLOT_NOREF);
5857 /*---------------------------------------------------------------*/
5858 /* save the current IP */
5859 /*---------------------------------------------------------------*/
5860 s390_stg (code, STK_BASE, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp));
5861 s390_basr (code, s390_r1, 0);
5862 s390_stg (code, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip));
5863 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, ebp), SLOT_NOREF);
5864 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, eip), SLOT_NOREF);
5866 /*---------------------------------------------------------------*/
5867 /* Save general and floating point registers */
5868 /*---------------------------------------------------------------*/
5869 s390_stmg (code, s390_r2, s390_r12, s390_r13,
5870 G_STRUCT_OFFSET(MonoLMF, gregs[2]));
5871 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[0]), SLOT_NOREF);
5872 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[1]), SLOT_NOREF);
5873 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[2]), SLOT_NOREF);
5874 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[3]), SLOT_NOREF);
5875 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[4]), SLOT_NOREF);
5876 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[5]), SLOT_NOREF);
5877 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[6]), SLOT_NOREF);
5878 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[7]), SLOT_NOREF);
5879 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[8]), SLOT_NOREF);
5880 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[9]), SLOT_NOREF);
5881 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[10]), SLOT_NOREF);
5883 fpOffset = lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, fregs[0]);
5884 for (i = 0; i < 16; i++) {
5885 s390_std (code, i, 0, s390_r13,
5886 G_STRUCT_OFFSET(MonoLMF, fregs[i]));
5887 mini_gc_set_slot_type_from_fp (cfg, fpOffset, SLOT_NOREF);
5888 fpOffset += sizeof(double);
5891 /*---------------------------------------------------------------*/
5892 /* Restore the parameter registers now that we've set up the lmf */
5893 /*---------------------------------------------------------------*/
5894 s390_lmg (code, s390_r2, s390_r6, s390_r13,
5895 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
5898 if (cfg->method->save_lmf)
5899 argsClobbered = TRUE;
5902 argsClobbered = TRUE;
5903 code = mono_arch_instrument_prolog (cfg, enter_method, code, TRUE);
5907 * Optimize the common case of the first bblock making a call with the same
5908 * arguments as the method. This works because the arguments are still in their
5909 * original argument registers.
5911 if (!argsClobbered) {
5912 MonoBasicBlock *first_bb = cfg->bb_entry;
5914 int filter = FILTER_IL_SEQ_POINT;
5916 next = mono_bb_first_inst (first_bb, filter);
5917 if (!next && first_bb->next_bb) {
5918 first_bb = first_bb->next_bb;
5919 next = mono_bb_first_inst (first_bb, filter);
5922 if (first_bb->in_count > 1)
5925 for (i = 0; next && i < sig->param_count + sig->hasthis; ++i) {
5926 ArgInfo *ainfo = cinfo->args + i;
5927 gboolean match = FALSE;
5929 inst = cfg->args [i];
5930 if (inst->opcode != OP_REGVAR) {
5931 switch (ainfo->regtype) {
5932 case RegTypeGeneral: {
5933 if (((next->opcode == OP_LOAD_MEMBASE) ||
5934 (next->opcode == OP_LOADI4_MEMBASE)) &&
5935 next->inst_basereg == inst->inst_basereg &&
5936 next->inst_offset == inst->inst_offset) {
5937 if (next->dreg == ainfo->reg) {
5941 next->opcode = OP_MOVE;
5942 next->sreg1 = ainfo->reg;
5943 /* Only continue if the instruction doesn't change argument regs */
5944 if (next->dreg == ainfo->reg)
5954 /* Argument allocated to (non-volatile) register */
5955 switch (ainfo->regtype) {
5956 case RegTypeGeneral:
5957 if (next->opcode == OP_MOVE &&
5958 next->sreg1 == inst->dreg &&
5959 next->dreg == ainfo->reg) {
5970 next = mono_inst_next (next, filter);
5977 cfg->code_len = code - cfg->native_code;
5978 g_assert (cfg->code_len < cfg->code_size);
5983 /*========================= End of Function ========================*/
5985 /*------------------------------------------------------------------*/
5987 /* Name - mono_arch_emit_epilog */
5989 /* Function - Emit the instructions for a function epilog. */
5991 /*------------------------------------------------------------------*/
5994 mono_arch_emit_epilog (MonoCompile *cfg)
5996 MonoMethod *method = cfg->method;
5999 int max_epilog_size = 96;
6001 if (cfg->method->save_lmf)
6002 max_epilog_size += 128;
6004 if (mono_jit_trace_calls != NULL)
6005 max_epilog_size += 128;
6007 while ((cfg->code_len + max_epilog_size) > (cfg->code_size - 16)) {
6008 cfg->code_size *= 2;
6009 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6010 cfg->stat_code_reallocs++;
6013 code = cfg->native_code + cfg->code_len;
6015 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
6016 code = mono_arch_instrument_epilog (cfg, leave_method, code, TRUE);
6020 if (method->save_lmf)
6021 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
6023 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
6024 s390_lg (code, STK_BASE, 0, STK_BASE, 0);
6026 code = backUpStackPtr(cfg, code);
6028 s390_lmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
6029 s390_br (code, s390_r14);
6031 cfg->code_len = code - cfg->native_code;
6033 g_assert (cfg->code_len < cfg->code_size);
6037 /*========================= End of Function ========================*/
6039 /*------------------------------------------------------------------*/
6041 /* Name - mono_arch_emit_exceptions */
6043 /* Function - Emit the blocks to handle exception conditions. */
6045 /*------------------------------------------------------------------*/
6048 mono_arch_emit_exceptions (MonoCompile *cfg)
6050 MonoJumpInfo *patch_info;
6056 MonoClass *exc_classes [MAX_EXC];
6057 guint8 *exc_throw_start [MAX_EXC];
6059 for (patch_info = cfg->patch_info;
6061 patch_info = patch_info->next) {
6062 if (patch_info->type == MONO_PATCH_INFO_EXC)
6066 code_size = exc_count * 48;
6068 while ((cfg->code_len + code_size) > (cfg->code_size - 16)) {
6069 cfg->code_size *= 2;
6070 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6071 cfg->stat_code_reallocs++;
6074 code = cfg->native_code + cfg->code_len;
6076 /*---------------------------------------------------------------------*/
6077 /* Add code to raise exceptions */
6078 /*---------------------------------------------------------------------*/
6079 for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
6080 switch (patch_info->type) {
6081 case MONO_PATCH_INFO_EXC: {
6082 guint8 *ip = patch_info->ip.i + cfg->native_code;
6083 MonoClass *exc_class;
6086 /*-----------------------------------------------------*/
6087 /* Patch the branch in epilog to come here */
6088 /*-----------------------------------------------------*/
6089 s390_patch_rel (ip + 2, (guint64) S390_RELATIVE(code,ip));
6091 exc_class = mono_class_load_from_name (mono_defaults.corlib,
6093 patch_info->data.name);
6094 throw_ip = patch_info->ip.i;
6096 for (iExc = 0; iExc < nThrows; ++iExc)
6097 if (exc_classes [iExc] == exc_class)
6100 if (iExc < nThrows) {
6101 s390_jcl (code, S390_CC_UN,
6102 (guint64) exc_throw_start [iExc]);
6103 patch_info->type = MONO_PATCH_INFO_NONE;
6106 if (nThrows < MAX_EXC) {
6107 exc_classes [nThrows] = exc_class;
6108 exc_throw_start [nThrows] = code;
6111 /*---------------------------------------------*/
6112 /* Patch the parameter passed to the handler */
6113 /*---------------------------------------------*/
6114 S390_SET (code, s390_r2, exc_class->type_token);
6115 /*---------------------------------------------*/
6116 /* Load return address & parameter register */
6117 /*---------------------------------------------*/
6118 s390_larl (code, s390_r14, (guint64)S390_RELATIVE((patch_info->ip.i +
6119 cfg->native_code + 8), code));
6120 /*---------------------------------------------*/
6121 /* Reuse the current patch to set the jump */
6122 /*---------------------------------------------*/
6123 patch_info->type = MONO_PATCH_INFO_INTERNAL_METHOD;
6124 patch_info->data.name = "mono_arch_throw_corlib_exception";
6125 patch_info->ip.i = code - cfg->native_code;
6126 S390_BR_TEMPLATE (code, s390_r1);
6136 cfg->code_len = code - cfg->native_code;
6138 g_assert (cfg->code_len < cfg->code_size);
6142 /*========================= End of Function ========================*/
6144 /*------------------------------------------------------------------*/
6146 /* Name - mono_arch_finish_init */
6148 /* Function - Setup the JIT's Thread Level Specific Data. */
6150 /*------------------------------------------------------------------*/
6153 mono_arch_finish_init (void)
6157 /*========================= End of Function ========================*/
6159 /*------------------------------------------------------------------*/
6161 /* Name - mono_arch_free_jit_tls_data */
6163 /* Function - Free tls data. */
6165 /*------------------------------------------------------------------*/
6168 mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
6172 /*========================= End of Function ========================*/
6174 /*------------------------------------------------------------------*/
6176 /* Name - mono_arch_emit_inst_for_method */
6178 /*------------------------------------------------------------------*/
6181 mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
6186 /*========================= End of Function ========================*/
6188 /*------------------------------------------------------------------*/
6190 /* Name - mono_arch_decompose_opts */
6192 /* Function - Decompose opcode into a System z opcode. */
6194 /*------------------------------------------------------------------*/
6197 mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
6200 * Have to rename these to avoid being decomposed normally, since the normal
6201 * decomposition does not work on S390.
6203 switch (ins->opcode) {
6205 ins->opcode = OP_S390_ISUB_OVF;
6207 case OP_ISUB_OVF_UN:
6208 ins->opcode = OP_S390_ISUB_OVF_UN;
6211 ins->opcode = OP_S390_IADD_OVF;
6213 case OP_IADD_OVF_UN:
6214 ins->opcode = OP_S390_IADD_OVF_UN;
6217 ins->opcode = OP_S390_LADD_OVF;
6219 case OP_LADD_OVF_UN:
6220 ins->opcode = OP_S390_LADD_OVF_UN;
6223 ins->opcode = OP_S390_LSUB_OVF;
6225 case OP_LSUB_OVF_UN:
6226 ins->opcode = OP_S390_LSUB_OVF_UN;
6233 /*========================= End of Function ========================*/
6235 /*------------------------------------------------------------------*/
6237 /* Name - mono_arch_print_tree */
6239 /* Function - Print platform-specific opcode details. */
6241 /* Returns - 1 - opcode details have been printed */
6242 /* 0 - opcode details have not been printed */
6244 /*------------------------------------------------------------------*/
6247 mono_arch_print_tree (MonoInst *tree, int arity)
6251 switch (tree->opcode) {
6252 case OP_S390_LOADARG:
6253 case OP_S390_ARGREG:
6254 case OP_S390_ARGPTR:
6255 printf ("[0x%lx(%s)]", tree->inst_offset,
6256 mono_arch_regname (tree->inst_basereg));
6259 case OP_S390_STKARG:
6260 printf ("[0x%lx(previous_frame)]",
6265 printf ("[0x%lx(%d,%s),0x%lx(%s)]",
6266 tree->inst_offset, tree->backend.size,
6267 mono_arch_regname(tree->dreg),
6269 mono_arch_regname(tree->sreg1));
6272 case OP_S390_SETF4RET:
6273 printf ("[f%s,f%s]",
6274 mono_arch_regname (tree->dreg),
6275 mono_arch_regname (tree->sreg1));
6279 printf ("[0x%lx(0x%lx,%s)]", tree->inst_offset,
6281 mono_arch_regname (tree->sreg1));
6285 printf ("[0x%lx(0x%lx,%s)]", tree->inst_offset,
6287 mono_arch_regname (tree->sreg1));
6290 case OP_S390_BKCHAIN:
6291 printf ("[previous_frame(%s)]",
6292 mono_arch_regname (tree->sreg1));
6300 /*========================= End of Function ========================*/
6302 /*------------------------------------------------------------------*/
6304 /* Name - mono_arch_regalloc_cost */
6306 /* Function - Determine the cost, in the number of memory */
6307 /* references, of the action of allocating the var- */
6308 /* iable VMV into a register during global register */
6311 /* Returns - Cost */
6313 /*------------------------------------------------------------------*/
6316 mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
6322 /*========================= End of Function ========================*/
6324 /*------------------------------------------------------------------*/
6326 /* Name - mono_arch_flush_register_windows */
6332 /*------------------------------------------------------------------*/
6335 mono_arch_flush_register_windows (void)
6339 /*========================= End of Function ========================*/
6341 /*------------------------------------------------------------------*/
6343 /* Name - mono_arch_is_inst_imm */
6345 /* Function - Determine if operand qualifies as an immediate */
6346 /* value. For s390 this is a value -32768-32768 */
6348 /* Returns - True|False - is [not] immediate value. */
6350 /*------------------------------------------------------------------*/
6353 mono_arch_is_inst_imm (gint64 imm)
6355 return s390_is_imm32 (imm);
6358 /*========================= End of Function ========================*/
6360 /*------------------------------------------------------------------*/
6362 /* Name - mono_arch_get_patch_offset */
6364 /* Function - Dummy entry point until s390x supports aot. */
6366 /* Returns - Offset for patch. */
6368 /*------------------------------------------------------------------*/
6371 mono_arch_get_patch_offset (guint8 *code)
6376 /*========================= End of Function ========================*/
6378 /*------------------------------------------------------------------*/
6380 /* Name - mono_arch_context_get_int_reg. */
6384 /* Returns - Return a register from the context. */
6386 /*------------------------------------------------------------------*/
6389 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
6391 return ((mgreg_t) ctx->uc_mcontext.gregs[reg]);
6394 /*========================= End of Function ========================*/
6396 /*------------------------------------------------------------------*/
6398 /* Name - mono_arch_context_set_int_reg. */
6400 /* Function - Set a value in a specified register. */
6402 /*------------------------------------------------------------------*/
6405 mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val)
6407 ctx->uc_mcontext.gregs[reg] = val;
6410 /*========================= End of Function ========================*/
6412 /*------------------------------------------------------------------*/
6414 /* Name - mono_arch_get_this_arg_from_call. */
6418 /*------------------------------------------------------------------*/
6421 mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
6423 return (gpointer) regs [s390_r2];
6426 /*========================= End of Function ========================*/
6428 /*------------------------------------------------------------------*/
6430 /* Name - mono_arch_install_handler_block_guard */
6434 /*------------------------------------------------------------------*/
6437 mono_arch_install_handler_block_guard (MonoJitInfo *ji, MonoJitExceptionInfo *clause,
6438 MonoContext *ctx, gpointer new_value)
6441 gpointer *sp, old_value;
6444 offset = clause->exvar_offset;
6447 bp = MONO_CONTEXT_GET_BP (ctx);
6448 sp = *(gpointer*)(bp + offset);
6451 if (old_value < ji->code_start || (char*)old_value > ((char*)ji->code_start + ji->code_size))
6459 /*========================= End of Function ========================*/
6461 /*------------------------------------------------------------------*/
6463 /* Name - get_delegate_invoke_impl. */
6467 /*------------------------------------------------------------------*/
6470 get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 param_count, gboolean aot)
6472 guint8 *code, *start;
6477 start = code = mono_global_codeman_reserve (size);
6479 /* Replace the this argument with the target */
6480 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6481 s390_lg (code, s390_r2, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, target));
6482 s390_br (code, s390_r1);
6483 g_assert ((code - start) <= size);
6485 mono_arch_flush_icache (start, size);
6489 size = 32 + param_count * 8;
6490 start = code = mono_global_codeman_reserve (size);
6492 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6493 /* slide down the arguments */
6494 for (i = 0; i < param_count; ++i) {
6495 s390_lgr (code, (s390_r2 + i), (s390_r2 + i + 1));
6497 s390_br (code, s390_r1);
6499 g_assert ((code - start) <= size);
6501 mono_arch_flush_icache (start, size);
6504 mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
6507 *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
6509 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
6510 *info = mono_tramp_info_create (name, start, code - start, NULL, NULL);
6517 /*========================= End of Function ========================*/
6519 /*------------------------------------------------------------------*/
6521 /* Name - mono_arch_get_delegate_invoke_impls. */
6525 /*------------------------------------------------------------------*/
6528 mono_arch_get_delegate_invoke_impls (void)
6531 MonoTrampInfo *info;
6534 get_delegate_invoke_impl (&info, TRUE, 0, TRUE);
6535 res = g_slist_prepend (res, info);
6537 for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
6538 get_delegate_invoke_impl (&info, FALSE, i, TRUE);
6539 res = g_slist_prepend (res, info);
6545 /*========================= End of Function ========================*/
6547 /*------------------------------------------------------------------*/
6549 /* Name - mono_arch_get_delegate_invoke_impl. */
6553 /*------------------------------------------------------------------*/
6556 mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target)
6558 guint8 *code, *start;
6560 /* FIXME: Support more cases */
6561 if (MONO_TYPE_ISSTRUCT (sig->ret))
6565 static guint8* cached = NULL;
6570 if (mono_aot_only) {
6571 start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
6573 MonoTrampInfo *info;
6574 start = get_delegate_invoke_impl (&info, TRUE, 0, FALSE);
6575 mono_tramp_info_register (info, NULL);
6578 mono_memory_barrier ();
6582 static guint8* cache [MAX_ARCH_DELEGATE_PARAMS + 1] = {NULL};
6585 if (sig->param_count > MAX_ARCH_DELEGATE_PARAMS)
6587 for (i = 0; i < sig->param_count; ++i)
6588 if (!mono_is_regsize_var (sig->params [i]))
6592 code = cache [sig->param_count];
6596 if (mono_aot_only) {
6597 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", sig->param_count);
6598 start = mono_aot_get_trampoline (name);
6601 MonoTrampInfo *info;
6602 start = get_delegate_invoke_impl (&info, FALSE, sig->param_count, FALSE);
6603 mono_tramp_info_register (info, NULL);
6606 mono_memory_barrier ();
6608 cache [sig->param_count] = start;
6613 /*========================= End of Function ========================*/
6615 /*------------------------------------------------------------------*/
6617 /* Name - mono_arch_get_delegate_virtual_invoke_impl. */
6621 /*------------------------------------------------------------------*/
6624 mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method,
6625 int offset, gboolean load_imt_reg)
6627 guint8 *code, *start;
6630 start = code = mono_global_codeman_reserve (size);
6633 * Replace the "this" argument with the target
6635 s390_lgr (code, s390_r1, s390_r2);
6636 s390_lg (code, s390_r2, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, target));
6639 * Load the IMT register, if needed
6642 s390_lg (code, MONO_ARCH_IMT_REG, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, method));
6648 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET(MonoObject, vtable));
6650 s390_agfi(code, s390_r1, offset);
6652 s390_lg (code, s390_r1, 0, s390_r1, 0);
6653 s390_br (code, s390_r1);
6658 /*========================= End of Function ========================*/
6660 /*------------------------------------------------------------------*/
6662 /* Name - mono_arch_build_imt_trampoline. */
6666 /*------------------------------------------------------------------*/
6669 mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain,
6670 MonoIMTCheckItem **imt_entries, int count,
6671 gpointer fail_tramp)
6675 guchar *code, *start;
6678 for (i = 0; i < count; ++i) {
6679 MonoIMTCheckItem *item = imt_entries [i];
6680 if (item->is_equals) {
6681 if (item->check_target_idx) {
6682 if (!item->compare_done)
6683 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6684 if (item->has_target_code)
6685 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE;
6687 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE +
6691 item->chunk_size += CMP_SIZE + 2 * BR_SIZE + JUMP_SIZE +
6693 if (!item->has_target_code)
6694 item->chunk_size += LOAD_SIZE;
6696 item->chunk_size += LOADCON_SIZE + LOAD_SIZE + BR_SIZE;
6697 #if ENABLE_WRONG_METHOD_CHECK
6698 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6703 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6704 imt_entries [item->check_target_idx]->compare_done = TRUE;
6706 size += item->chunk_size;
6710 code = mono_method_alloc_generic_virtual_trampoline (domain, size);
6712 code = mono_domain_code_reserve (domain, size);
6716 for (i = 0; i < count; ++i) {
6717 MonoIMTCheckItem *item = imt_entries [i];
6718 item->code_target = (guint8 *) code;
6719 if (item->is_equals) {
6720 if (item->check_target_idx) {
6721 if (!item->compare_done) {
6722 S390_SET (code, s390_r0, item->key);
6723 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
6725 item->jmp_code = (guint8*) code;
6726 s390_jcl (code, S390_CC_NE, 0);
6728 if (item->has_target_code) {
6729 S390_SET (code, s390_r1, item->value.target_code);
6731 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6732 s390_lg (code, s390_r1, 0, s390_r1, 0);
6734 s390_br (code, s390_r1);
6739 S390_SET (code, s390_r0, item->key);
6740 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
6741 item->jmp_code = (guint8*) code;
6742 s390_jcl (code, S390_CC_NE, 0);
6743 if (item->has_target_code) {
6744 S390_SET (code, s390_r1, item->value.target_code);
6747 S390_SET (code, s390_r1,
6748 (&(vtable->vtable [item->value.vtable_slot])));
6749 s390_lg (code, s390_r1, 0, s390_r1, 0);
6751 s390_br (code, s390_r1);
6752 target = (gint64) S390_RELATIVE(code, item->jmp_code);
6753 s390_patch_rel(item->jmp_code+2, target);
6754 S390_SET (code, s390_r1, fail_tramp);
6755 s390_br (code, s390_r1);
6756 item->jmp_code = NULL;
6758 /* enable the commented code to assert on wrong method */
6759 #if ENABLE_WRONG_METHOD_CHECK
6760 g_assert_not_reached ();
6762 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6763 s390_lg (code, s390_r1, 0, s390_r1, 0);
6764 s390_br (code, s390_r1);
6768 S390_SET (code, s390_r0, item->key);
6769 s390_cgr (code, MONO_ARCH_IMT_REG, s390_r0);
6770 item->jmp_code = (guint8 *) code;
6771 s390_jcl (code, S390_CC_GE, 0);
6775 * patch the branches to get to the target items
6777 for (i = 0; i < count; ++i) {
6778 MonoIMTCheckItem *item = imt_entries [i];
6779 if (item->jmp_code) {
6780 if (item->check_target_idx) {
6782 offset = (gint64) S390_RELATIVE(imt_entries [item->check_target_idx]->code_target,
6784 s390_patch_rel ((guchar *) item->jmp_code + 2, (guint64) offset);
6789 mono_arch_flush_icache ((guint8*)start, (code - start));
6790 mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL);
6793 mono_stats.imt_trampolines_size += (code - start);
6795 g_assert (code - start <= size);
6797 snprintf(trampName, sizeof(trampName), "%d_imt_trampoline", domain->domain_id);
6798 mono_tramp_info_register (mono_tramp_info_create (trampName, start, code - start, NULL, NULL), domain);
6803 /*========================= End of Function ========================*/
6805 /*------------------------------------------------------------------*/
6807 /* Name - mono_arch_find_imt_method. */
6809 /* Function - Get the method address from MONO_ARCH_IMT_REG */
6810 /* found in the save area. */
6812 /*------------------------------------------------------------------*/
6815 mono_arch_find_imt_method (mgreg_t *regs, guint8 *code)
6817 return ((MonoMethod *) regs [MONO_ARCH_IMT_REG]);
6820 /*========================= End of Function ========================*/
6822 /*------------------------------------------------------------------*/
6824 /* Name - mono_arch_find_static_call_vtable */
6826 /* Function - Find the static call vtable. */
6828 /*------------------------------------------------------------------*/
6831 mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
6833 mgreg_t *r = (mgreg_t*)regs;
6835 return (MonoVTable*)(gsize) r [MONO_ARCH_RGCTX_REG];
6838 /*========================= End of Function ========================*/
6840 /*------------------------------------------------------------------*/
6842 /* Name - mono_arch_get_cie_program */
6844 /* Function - Find the static call vtable. */
6846 /*------------------------------------------------------------------*/
6849 mono_arch_get_cie_program (void)
6853 mono_add_unwind_op_def_cfa (l, 0, 0, STK_BASE, 0);
6858 /*========================= End of Function ========================*/
6860 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
6862 /*------------------------------------------------------------------*/
6864 /* Name - mono_arch_set_breakpoint. */
6866 /* Function - Set a breakpoint at the native code corresponding */
6867 /* to JI at NATIVE_OFFSET. The location should */
6868 /* contain code emitted by OP_SEQ_POINT. */
6870 /*------------------------------------------------------------------*/
6873 mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
6877 breakpointCode.pTrigger = bp_trigger_page;
6878 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
6879 code += BREAKPOINT_SIZE;
6882 /*========================= End of Function ========================*/
6884 /*------------------------------------------------------------------*/
6886 /* Name - mono_arch_clear_breakpoint. */
6888 /* Function - Clear the breakpoint at IP. */
6890 /*------------------------------------------------------------------*/
6893 mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
6898 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); i++)
6902 /*========================= End of Function ========================*/
6904 /*------------------------------------------------------------------*/
6906 /* Name - mono_arch_is_breakpoint_event. */
6910 /*------------------------------------------------------------------*/
6913 mono_arch_is_breakpoint_event (void *info, void *sigctx)
6915 siginfo_t* sinfo = (siginfo_t*) info;
6918 * Sometimes the address is off by 4
6920 if (sinfo->si_addr >= bp_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)bp_trigger_page + 128)
6926 /*========================= End of Function ========================*/
6928 /*------------------------------------------------------------------*/
6930 /* Name - mono_arch_skip_breakpoint. */
6932 /* Function - Modify the CTX so the IP is placed after the */
6933 /* breakpoint instruction, so when we resume, the */
6934 /* instruction is not executed again. */
6936 /*------------------------------------------------------------------*/
6939 mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
6941 MONO_CONTEXT_SET_IP (ctx, ((guint8*)MONO_CONTEXT_GET_IP (ctx) + sizeof(RXY_Format)));
6944 /*========================= End of Function ========================*/
6946 /*------------------------------------------------------------------*/
6948 /* Name - mono_arch_start_single_stepping. */
6950 /* Function - Start single stepping. */
6952 /*------------------------------------------------------------------*/
6955 mono_arch_start_single_stepping (void)
6957 mono_mprotect (ss_trigger_page, mono_pagesize (), 0);
6960 /*========================= End of Function ========================*/
6962 /*------------------------------------------------------------------*/
6964 /* Name - mono_arch_stop_single_stepping. */
6966 /* Function - Stop single stepping. */
6968 /*------------------------------------------------------------------*/
6971 mono_arch_stop_single_stepping (void)
6973 mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ);
6976 /*========================= End of Function ========================*/
6978 /*------------------------------------------------------------------*/
6980 /* Name - mono_arch_is_single_step_event. */
6982 /* Function - Return whether the machine state in sigctx cor- */
6983 /* responds to a single step event. */
6985 /*------------------------------------------------------------------*/
6988 mono_arch_is_single_step_event (void *info, void *sigctx)
6990 siginfo_t* sinfo = (siginfo_t*) info;
6993 * Sometimes the address is off by 4
6995 if (sinfo->si_addr >= ss_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)ss_trigger_page + 128)
7001 /*========================= End of Function ========================*/
7003 /*------------------------------------------------------------------*/
7005 /* Name - mono_arch_skip_single_step. */
7007 /* Function - Modify the ctx so the IP is placed after the */
7008 /* single step trigger instruction, so that the */
7009 /* instruction is not executed again. */
7011 /*------------------------------------------------------------------*/
7014 mono_arch_skip_single_step (MonoContext *ctx)
7016 MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + BREAKPOINT_SIZE);
7019 /*========================= End of Function ========================*/
7021 /*------------------------------------------------------------------*/
7023 /* Name - mono_arch_create_seq_point_info. */
7025 /* Function - Return a pointer to a data struction which is */
7026 /* used by the sequence point implementation in */
7029 /*------------------------------------------------------------------*/
7032 mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code)
7038 /*========================= End of Function ========================*/
7040 /*------------------------------------------------------------------*/
7042 /* Name - mono_arch_init_lmf_ext. */
7046 /*------------------------------------------------------------------*/
7049 mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
7051 ext->lmf.previous_lmf = prev_lmf;
7052 /* Mark that this is a MonoLMFExt */
7053 ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
7054 ext->lmf.ebp = (gssize)ext;
7057 /*========================= End of Function ========================*/
7061 /*------------------------------------------------------------------*/
7063 /* Name - mono_arch_cpu_enumerate_simd_versions. */
7065 /* Function - If this CPU supports vector operations then it */
7066 /* supports the equivalent of SSE1-4. */
7068 /*------------------------------------------------------------------*/
7071 mono_arch_cpu_enumerate_simd_versions (void)
7073 guint32 sseOpts = 0;
7075 if (mono_hwcap_s390x_has_vec)
7076 sseOpts = (SIMD_VERSION_SSE1 | SIMD_VERSION_SSE2 |
7077 SIMD_VERSION_SSE3 | SIMD_VERSION_SSSE3 |
7078 SIMD_VERSION_SSE41 | SIMD_VERSION_SSE42 |
7079 SIMD_VERSION_SSE4a);
7084 /*========================= End of Function ========================*/
7086 /*------------------------------------------------------------------*/
7088 /* Name - mono_arch_opcode_supported. */
7090 /* Function - Check if a given return code is supported. */
7092 /*------------------------------------------------------------------*/
7095 mono_arch_opcode_supported (int opcode)
7098 case OP_ATOMIC_ADD_I4:
7099 case OP_ATOMIC_ADD_I8:
7100 case OP_ATOMIC_EXCHANGE_I4:
7101 case OP_ATOMIC_EXCHANGE_I8:
7108 /*========================= End of Function ========================*/