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 MONO_BB_FOR_EACH_INS (bb, ins) {
2989 offset = code - cfg->native_code;
2991 max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
2993 if (offset > (cfg->code_size - max_len - 16)) {
2994 cfg->code_size *= 2;
2995 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
2996 code = cfg->native_code + offset;
2999 mono_debug_record_line_number (cfg, ins, offset);
3001 switch (ins->opcode) {
3002 case OP_STOREI1_MEMBASE_IMM: {
3003 s390_lghi (code, s390_r0, ins->inst_imm);
3004 S390_LONG (code, stcy, stc, s390_r0, 0,
3005 ins->inst_destbasereg, ins->inst_offset);
3008 case OP_STOREI2_MEMBASE_IMM: {
3009 s390_lghi (code, s390_r0, ins->inst_imm);
3010 S390_LONG (code, sthy, sth, s390_r0, 0,
3011 ins->inst_destbasereg, ins->inst_offset);
3014 case OP_STOREI4_MEMBASE_IMM: {
3015 s390_lgfi (code, s390_r0, ins->inst_imm);
3016 S390_LONG (code, sty, st, s390_r0, 0,
3017 ins->inst_destbasereg, ins->inst_offset);
3020 case OP_STORE_MEMBASE_IMM:
3021 case OP_STOREI8_MEMBASE_IMM: {
3022 S390_SET (code, s390_r0, ins->inst_imm);
3023 S390_LONG (code, stg, stg, s390_r0, 0,
3024 ins->inst_destbasereg, ins->inst_offset);
3027 case OP_STOREI1_MEMBASE_REG: {
3028 S390_LONG (code, stcy, stc, ins->sreg1, 0,
3029 ins->inst_destbasereg, ins->inst_offset);
3032 case OP_STOREI2_MEMBASE_REG: {
3033 S390_LONG (code, sthy, sth, ins->sreg1, 0,
3034 ins->inst_destbasereg, ins->inst_offset);
3037 case OP_STOREI4_MEMBASE_REG: {
3038 S390_LONG (code, sty, st, ins->sreg1, 0,
3039 ins->inst_destbasereg, ins->inst_offset);
3042 case OP_STORE_MEMBASE_REG:
3043 case OP_STOREI8_MEMBASE_REG: {
3044 S390_LONG (code, stg, stg, ins->sreg1, 0,
3045 ins->inst_destbasereg, ins->inst_offset);
3049 g_assert_not_reached ();
3051 case OP_LOAD_MEMBASE:
3052 case OP_LOADI8_MEMBASE: {
3053 S390_LONG (code, lg, lg, ins->dreg, 0,
3054 ins->inst_basereg, ins->inst_offset);
3057 case OP_LOADI4_MEMBASE: {
3058 S390_LONG (code, lgf, lgf, ins->dreg, 0,
3059 ins->inst_basereg, ins->inst_offset);
3062 case OP_LOADU4_MEMBASE: {
3063 S390_LONG (code, llgf, llgf, ins->dreg, 0,
3064 ins->inst_basereg, ins->inst_offset);
3067 case OP_LOADU1_MEMBASE: {
3068 S390_LONG (code, llgc, llgc, ins->dreg, 0,
3069 ins->inst_basereg, ins->inst_offset);
3072 case OP_LOADI1_MEMBASE: {
3073 S390_LONG (code, lgb, lgb, ins->dreg, 0,
3074 ins->inst_basereg, ins->inst_offset);
3077 case OP_LOADU2_MEMBASE: {
3078 S390_LONG (code, llgh, llgh, ins->dreg, 0,
3079 ins->inst_basereg, ins->inst_offset);
3082 case OP_LOADI2_MEMBASE: {
3083 S390_LONG (code, lgh, lgh, ins->dreg, 0,
3084 ins->inst_basereg, ins->inst_offset);
3087 case OP_LCONV_TO_I1: {
3088 s390_lgbr (code, ins->dreg, ins->sreg1);
3091 case OP_LCONV_TO_I2: {
3092 s390_lghr (code, ins->dreg, ins->sreg1);
3095 case OP_LCONV_TO_U1: {
3096 s390_llgcr (code, ins->dreg, ins->sreg1);
3099 case OP_LCONV_TO_U2: {
3100 s390_llghr (code, ins->dreg, ins->sreg1);
3103 case OP_ICONV_TO_I1: {
3104 s390_lgbr (code, ins->dreg, ins->sreg1);
3107 case OP_ICONV_TO_I2: {
3108 s390_lghr (code, ins->dreg, ins->sreg1);
3111 case OP_ICONV_TO_U1: {
3112 s390_llgcr (code, ins->dreg, ins->sreg1);
3115 case OP_ICONV_TO_U2: {
3116 s390_llghr (code, ins->dreg, ins->sreg1);
3121 if (is_unsigned (ins->next))
3122 s390_clgr (code, ins->sreg1, ins->sreg2);
3124 s390_cgr (code, ins->sreg1, ins->sreg2);
3128 if (is_unsigned (ins->next))
3129 s390_clr (code, ins->sreg1, ins->sreg2);
3131 s390_cr (code, ins->sreg1, ins->sreg2);
3134 case OP_COMPARE_IMM:
3135 case OP_LCOMPARE_IMM: {
3136 S390_SET (code, s390_r0, ins->inst_imm);
3137 if (is_unsigned (ins->next))
3138 s390_clgr (code, ins->sreg1, s390_r0);
3140 s390_cgr (code, ins->sreg1, s390_r0);
3143 case OP_ICOMPARE_IMM: {
3144 S390_SET (code, s390_r0, ins->inst_imm);
3145 if (is_unsigned (ins->next))
3146 s390_clr (code, ins->sreg1, s390_r0);
3148 s390_cr (code, ins->sreg1, s390_r0);
3152 mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_ABS,
3154 S390_CALL_TEMPLATE (code, s390_r14);
3159 s390_agr (code, ins->dreg, src2);
3164 s390_agr (code, ins->dreg, src2);
3169 s390_alcgr (code, ins->dreg, src2);
3173 if (ins->dreg != ins->sreg1) {
3174 s390_lgr (code, ins->dreg, ins->sreg1);
3176 if (s390_is_imm16 (ins->inst_imm)) {
3177 s390_aghi (code, ins->dreg, ins->inst_imm);
3178 } else if (s390_is_imm32 (ins->inst_imm)) {
3179 s390_agfi (code, ins->dreg, ins->inst_imm);
3181 S390_SET (code, s390_r0, ins->inst_imm);
3182 s390_agr (code, ins->dreg, s390_r0);
3187 if (ins->dreg != ins->sreg1) {
3188 s390_lgr (code, ins->dreg, ins->sreg1);
3190 g_assert (s390_is_imm16 (ins->inst_imm));
3191 s390_aghi (code, ins->dreg, ins->inst_imm);
3195 if (ins->dreg != ins->sreg1) {
3196 s390_lgr (code, ins->dreg, ins->sreg1);
3198 if (s390_is_imm16 (ins->inst_imm)) {
3199 s390_lghi (code, s390_r0, ins->inst_imm);
3200 s390_alcgr (code, ins->dreg, s390_r0);
3202 S390_SET (code, s390_r0, ins->inst_imm);
3203 s390_alcgr (code, ins->dreg, s390_r0);
3208 case OP_S390_IADD_OVF: {
3210 s390_ar (code, ins->dreg, src2);
3211 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3212 s390_lgfr (code, ins->dreg, ins->dreg);
3215 case OP_IADD_OVF_UN:
3216 case OP_S390_IADD_OVF_UN: {
3218 s390_algr (code, ins->dreg, src2);
3219 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3220 s390_llgfr (code, ins->dreg, ins->dreg);
3223 case OP_ADD_OVF_CARRY: {
3225 s390_lghi (code, s390_r0, 0);
3226 s390_lgr (code, s390_r1, s390_r0);
3227 s390_alcgr (code, s390_r0, s390_r1);
3228 s390_agr (code, ins->dreg, src2);
3229 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3230 s390_agr (code, ins->dreg, s390_r0);
3231 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3234 case OP_ADD_OVF_UN_CARRY: {
3236 s390_alcgr (code, ins->dreg, src2);
3237 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3242 s390_sgr (code, ins->dreg, src2);
3247 s390_sgr (code, ins->dreg, src2);
3252 s390_slbgr(code, ins->dreg, src2);
3256 if (ins->dreg != ins->sreg1) {
3257 s390_lgr (code, ins->dreg, ins->sreg1);
3259 if (s390_is_imm16 (-ins->inst_imm)) {
3260 s390_aghi (code, ins->dreg, -ins->inst_imm);
3261 } else if (s390_is_imm32 (-ins->inst_imm)) {
3262 s390_slgfi (code, ins->dreg, ins->inst_imm);
3264 S390_SET (code, s390_r0, ins->inst_imm);
3265 s390_slgr (code, ins->dreg, s390_r0);
3270 if (ins->dreg != ins->sreg1) {
3271 s390_lgr (code, ins->dreg, ins->sreg1);
3273 if (s390_is_imm16 (-ins->inst_imm)) {
3274 s390_aghi (code, ins->dreg, -ins->inst_imm);
3275 } else if (s390_is_imm32 (-ins->inst_imm)) {
3276 s390_slgfi (code, ins->dreg, ins->inst_imm);
3278 S390_SET (code, s390_r0, ins->inst_imm);
3279 s390_slgr (code, ins->dreg, s390_r0);
3284 if (ins->dreg != ins->sreg1) {
3285 s390_lgr (code, ins->dreg, ins->sreg1);
3287 if (s390_is_imm16 (-ins->inst_imm)) {
3288 s390_lghi (code, s390_r0, ins->inst_imm);
3289 s390_slbgr (code, ins->dreg, s390_r0);
3291 S390_SET (code, s390_r0, ins->inst_imm);
3292 s390_slbgr(code, ins->dreg, s390_r0);
3296 case OP_SUB_OVF_CARRY: {
3298 s390_lghi (code, s390_r0, 0);
3299 s390_lgr (code, s390_r1, s390_r0);
3300 s390_slbgr (code, s390_r0, s390_r1);
3301 s390_sgr (code, ins->dreg, src2);
3302 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3303 s390_agr (code, ins->dreg, s390_r0);
3304 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3307 case OP_SUB_OVF_UN_CARRY: {
3309 s390_slbgr (code, ins->dreg, src2);
3310 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3314 if (ins->sreg1 == ins->dreg) {
3315 s390_ngr (code, ins->dreg, ins->sreg2);
3318 if (ins->sreg2 == ins->dreg) {
3319 s390_ngr (code, ins->dreg, ins->sreg1);
3322 s390_lgr (code, ins->dreg, ins->sreg1);
3323 s390_ngr (code, ins->dreg, ins->sreg2);
3329 if (ins->dreg != ins->sreg1) {
3330 s390_lgr (code, ins->dreg, ins->sreg1);
3332 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3333 s390_ngr (code, ins->dreg, s390_r0);
3337 s390_lgr (code, s390_r1, ins->sreg1);
3338 s390_dsgr (code, s390_r0, ins->sreg2);
3339 s390_lgr (code, ins->dreg, s390_r1);
3343 s390_lgr (code, s390_r1, ins->sreg1);
3344 s390_lghi (code, s390_r0, 0);
3345 s390_dlgr (code, s390_r0, ins->sreg2);
3346 s390_lgr (code, ins->dreg, s390_r1);
3350 s390_lgr (code, s390_r1, ins->sreg1);
3351 s390_dsgr (code, s390_r0, ins->sreg2);
3352 s390_lgr (code, ins->dreg, s390_r0);
3356 if (s390_is_imm16 (ins->inst_imm)) {
3357 s390_lghi (code, s390_r13, ins->inst_imm);
3359 s390_lgfi (code, s390_r13, ins->inst_imm);
3361 s390_lgr (code, s390_r0, ins->sreg1);
3362 s390_dsgr (code, s390_r0, s390_r13);
3363 s390_lgfr (code, ins->dreg, s390_r0);
3367 s390_lgr (code, s390_r1, ins->sreg1);
3368 s390_lghi (code, s390_r0, 0);
3369 s390_dlgr (code, s390_r0, ins->sreg2);
3370 s390_lgr (code, ins->dreg, s390_r0);
3374 if (ins->sreg1 == ins->dreg) {
3375 s390_ogr (code, ins->dreg, ins->sreg2);
3378 if (ins->sreg2 == ins->dreg) {
3379 s390_ogr (code, ins->dreg, ins->sreg1);
3382 s390_lgr (code, ins->dreg, ins->sreg1);
3383 s390_ogr (code, ins->dreg, ins->sreg2);
3389 if (ins->dreg != ins->sreg1) {
3390 s390_lgr (code, ins->dreg, ins->sreg1);
3392 S390_SET_MASK(code, s390_r0, ins->inst_imm);
3393 s390_ogr (code, ins->dreg, s390_r0);
3397 if (ins->sreg1 == ins->dreg) {
3398 s390_xgr (code, ins->dreg, ins->sreg2);
3401 if (ins->sreg2 == ins->dreg) {
3402 s390_xgr (code, ins->dreg, ins->sreg1);
3405 s390_lgr (code, ins->dreg, ins->sreg1);
3406 s390_xgr (code, ins->dreg, ins->sreg2);
3412 if (ins->dreg != ins->sreg1) {
3413 s390_lgr (code, ins->dreg, ins->sreg1);
3415 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3416 s390_xgr (code, ins->dreg, s390_r0);
3421 s390_sllg (code, ins->dreg, ins->dreg, src2, 0);
3426 if (ins->sreg1 != ins->dreg) {
3427 s390_lgr (code, ins->dreg, ins->sreg1);
3429 s390_sllg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3434 s390_srag (code, ins->dreg, ins->dreg, src2, 0);
3439 if (ins->sreg1 != ins->dreg) {
3440 s390_lgr (code, ins->dreg, ins->sreg1);
3442 s390_srag (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3446 case OP_LSHR_UN_IMM: {
3447 if (ins->sreg1 != ins->dreg) {
3448 s390_lgr (code, ins->dreg, ins->sreg1);
3450 s390_srlg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3455 s390_srlg (code, ins->dreg, ins->dreg, src2, 0);
3459 if (ins->sreg1 != ins->dreg) {
3460 s390_lgr (code, ins->dreg, ins->sreg1);
3462 s390_lghi (code, s390_r0, -1);
3463 s390_xgr (code, ins->dreg, s390_r0);
3467 s390_lcgr (code, ins->dreg, ins->sreg1);
3472 s390_msgr (code, ins->dreg, src2);
3477 if (ins->dreg != ins->sreg1) {
3478 s390_lgr (code, ins->dreg, ins->sreg1);
3480 if (s390_is_imm16 (ins->inst_imm)) {
3481 s390_lghi (code, s390_r13, ins->inst_imm);
3482 } else if (s390_is_imm32 (ins->inst_imm)) {
3483 s390_lgfi (code, s390_r13, ins->inst_imm);
3485 S390_SET (code, s390_r13, ins->inst_imm);
3487 s390_msgr (code, ins->dreg, s390_r13);
3492 s390_ltgr (code, s390_r1, ins->sreg1);
3493 s390_jz (code, 0); CODEPTR(code, o[0]);
3494 s390_ltgr (code, s390_r0, ins->sreg2);
3496 s390_lghi (code, s390_r1, 0);
3497 s390_j (code, 0); CODEPTR(code, o[1]);
3498 s390_xgr (code, s390_r0, s390_r1);
3499 s390_msgr (code, s390_r1, ins->sreg2);
3500 s390_xgr (code, s390_r0, s390_r1);
3501 s390_srlg (code, s390_r0, s390_r0, 0, 63);
3502 s390_ltgr (code, s390_r0, s390_r0);
3503 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3504 PTRSLOT (code, o[0]);
3505 PTRSLOT (code, o[1]);
3506 s390_lgr (code, ins->dreg, s390_r1);
3509 case OP_LMUL_OVF_UN: {
3510 s390_lghi (code, s390_r0, 0);
3511 s390_lgr (code, s390_r1, ins->sreg1);
3512 s390_mlgr (code, s390_r0, ins->sreg2);
3513 s390_ltgr (code, s390_r0, s390_r0);
3514 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3515 s390_lgr (code, ins->dreg, s390_r1);
3519 g_assert_not_reached ();
3521 s390_algr (code, ins->dreg, src2);
3526 s390_agr (code, ins->dreg, src2);
3530 g_assert_not_reached ();
3532 s390_alcgr (code, ins->dreg, src2);
3536 if (ins->dreg != ins->sreg1) {
3537 s390_lgfr (code, ins->dreg, ins->sreg1);
3539 if (s390_is_imm16 (ins->inst_imm)) {
3540 s390_aghi (code, ins->dreg, ins->inst_imm);
3542 s390_afi (code, ins->dreg, ins->inst_imm);
3547 if (ins->dreg != ins->sreg1) {
3548 s390_lgfr (code, ins->dreg, ins->sreg1);
3550 if (s390_is_imm16 (ins->inst_imm)) {
3551 s390_lghi (code, s390_r0, ins->inst_imm);
3552 s390_alcgr (code, ins->dreg, s390_r0);
3554 S390_SET (code, s390_r0, ins->inst_imm);
3555 s390_alcgr (code, ins->dreg, s390_r0);
3560 case OP_S390_LADD_OVF: {
3562 s390_agr (code, ins->dreg, src2);
3563 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3566 case OP_LADD_OVF_UN:
3567 case OP_S390_LADD_OVF_UN: {
3569 s390_algr (code, ins->dreg, src2);
3570 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3574 CHECK_SRCDST_NCOM_I;
3575 s390_slgr (code, ins->dreg, src2);
3579 CHECK_SRCDST_NCOM_I;
3580 s390_sgr (code, ins->dreg, src2);
3584 CHECK_SRCDST_NCOM_I;
3585 s390_slbgr (code, ins->dreg, src2);
3589 if (ins->dreg != ins->sreg1) {
3590 s390_lgfr (code, ins->dreg, ins->sreg1);
3592 if (s390_is_imm16 (-ins->inst_imm)) {
3593 s390_aghi (code, ins->dreg, -ins->inst_imm);
3595 s390_agfi (code, ins->dreg, -ins->inst_imm);
3600 S390_SET (code, s390_r0, ins->inst_imm);
3601 s390_slgfr (code, ins->dreg, s390_r0);
3605 case OP_S390_ISUB_OVF: {
3607 s390_sr (code, ins->dreg, src2);
3608 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3609 s390_lgfr (code, ins->dreg, ins->dreg);
3612 case OP_ISUB_OVF_UN:
3613 case OP_S390_ISUB_OVF_UN: {
3615 s390_slr (code, ins->dreg, src2);
3616 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3617 s390_llgfr(code, ins->dreg, ins->dreg);
3621 case OP_S390_LSUB_OVF: {
3623 s390_sgr (code, ins->dreg, src2);
3624 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3627 case OP_LSUB_OVF_UN:
3628 case OP_S390_LSUB_OVF_UN: {
3630 s390_slgr (code, ins->dreg, src2);
3631 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3635 CHECK_SRCDST_NCOM_I;
3636 s390_ngr (code, ins->dreg, src2);
3640 if (ins->dreg != ins->sreg1) {
3641 s390_lgfr (code, ins->dreg, ins->sreg1);
3643 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3644 s390_ngr (code, ins->dreg, s390_r0);
3648 s390_lgfr (code, s390_r0, ins->sreg1);
3649 s390_srda (code, s390_r0, 0, 32);
3650 s390_dr (code, s390_r0, ins->sreg2);
3651 s390_lgfr (code, ins->dreg, s390_r1);
3655 s390_lgfr (code, s390_r0, ins->sreg1);
3656 s390_srdl (code, s390_r0, 0, 32);
3657 s390_dlr (code, s390_r0, ins->sreg2);
3658 s390_lgfr (code, ins->dreg, s390_r1);
3662 if (s390_is_imm16 (ins->inst_imm)) {
3663 s390_lghi (code, s390_r13, ins->inst_imm);
3665 s390_lgfi (code, s390_r13, ins->inst_imm);
3667 s390_lgfr (code, s390_r0, ins->sreg1);
3668 s390_srda (code, s390_r0, 0, 32);
3669 s390_dr (code, s390_r0, ins->sreg2);
3670 s390_lgfr (code, ins->dreg, s390_r1);
3674 s390_lgfr (code, s390_r0, ins->sreg1);
3675 s390_srda (code, s390_r0, 0, 32);
3676 s390_dr (code, s390_r0, ins->sreg2);
3677 s390_lgfr (code, ins->dreg, s390_r0);
3680 s390_lgfr (code, s390_r0, ins->sreg1);
3681 s390_srdl (code, s390_r0, 0, 32);
3682 s390_dlr (code, s390_r0, ins->sreg2);
3683 s390_lgfr (code, ins->dreg, s390_r0);
3687 if (s390_is_imm16 (ins->inst_imm)) {
3688 s390_lghi (code, s390_r13, ins->inst_imm);
3690 s390_lgfi (code, s390_r13, ins->inst_imm);
3692 s390_lgfr (code, s390_r0, ins->sreg1);
3693 s390_srda (code, s390_r0, 0, 32);
3694 s390_dr (code, s390_r0, ins->sreg2);
3695 s390_lgfr (code, ins->dreg, s390_r0);
3700 s390_ogr (code, ins->dreg, src2);
3704 if (ins->dreg != ins->sreg1) {
3705 s390_lgfr (code, ins->dreg, ins->sreg1);
3707 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3708 s390_ogr (code, ins->dreg, s390_r0);
3713 s390_xgr (code, ins->dreg, src2);
3717 if (ins->dreg != ins->sreg1) {
3718 s390_lgfr (code, ins->dreg, ins->sreg1);
3720 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3721 s390_xgr (code, ins->dreg, s390_r0);
3726 s390_sll (code, ins->dreg, src2, 0);
3730 if (ins->sreg1 != ins->dreg) {
3731 s390_lgfr (code, ins->dreg, ins->sreg1);
3733 s390_sll (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3738 s390_sra (code, ins->dreg, src2, 0);
3742 if (ins->sreg1 != ins->dreg) {
3743 s390_lgfr (code, ins->dreg, ins->sreg1);
3745 s390_sra (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3748 case OP_ISHR_UN_IMM: {
3749 if (ins->sreg1 != ins->dreg) {
3750 s390_lgfr (code, ins->dreg, ins->sreg1);
3752 s390_srl (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3757 s390_srl (code, ins->dreg, src2, 0);
3761 if (ins->sreg1 != ins->dreg) {
3762 s390_lgfr (code, ins->dreg, ins->sreg1);
3764 s390_lghi (code, s390_r0, -1);
3765 s390_xgr (code, ins->dreg, s390_r0);
3769 s390_lcgr (code, ins->dreg, ins->sreg1);
3774 s390_msr (code, ins->dreg, src2);
3778 if (ins->dreg != ins->sreg1) {
3779 s390_lgfr (code, ins->dreg, ins->sreg1);
3781 if (s390_is_imm16 (ins->inst_imm)) {
3782 s390_lghi (code, s390_r0, ins->inst_imm);
3784 s390_lgfi (code, s390_r0, ins->inst_imm);
3786 s390_msr (code, ins->dreg, s390_r0);
3791 s390_ltr (code, s390_r1, ins->sreg1);
3792 s390_jz (code, 0); CODEPTR(code, o[0]);
3793 s390_ltr (code, s390_r0, ins->sreg2);
3795 s390_lhi (code, s390_r1, 0);
3796 s390_j (code, 0); CODEPTR(code, o[1]);
3797 s390_xr (code, s390_r0, s390_r1);
3798 s390_msr (code, s390_r1, ins->sreg2);
3799 s390_xr (code, s390_r0, s390_r1);
3800 s390_srl (code, s390_r0, 0, 31);
3801 s390_ltr (code, s390_r0, s390_r0);
3802 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3803 PTRSLOT (code, o[0]);
3804 PTRSLOT (code, o[1]);
3805 s390_lgfr (code, ins->dreg, s390_r1);
3808 case OP_IMUL_OVF_UN: {
3809 s390_lhi (code, s390_r0, 0);
3810 s390_lr (code, s390_r1, ins->sreg1);
3811 s390_mlr (code, s390_r0, ins->sreg2);
3812 s390_ltr (code, s390_r0, s390_r0);
3813 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3814 s390_lgfr (code, ins->dreg, s390_r1);
3819 S390_SET (code, ins->dreg, ins->inst_c0);
3823 mono_add_patch_info (cfg, code - cfg->native_code,
3824 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3825 S390_LOAD_TEMPLATE (code, ins->dreg);
3828 case OP_JUMP_TABLE: {
3829 mono_add_patch_info (cfg, code - cfg->native_code,
3830 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3831 S390_LOAD_TEMPLATE (code, ins->dreg);
3835 if (ins->dreg != ins->sreg1) {
3836 s390_lgr (code, ins->dreg, ins->sreg1);
3840 case OP_LCONV_TO_I8:
3842 s390_lgfr (code, ins->dreg, ins->sreg1);
3844 case OP_LCONV_TO_I4:
3845 s390_lgfr (code, ins->dreg, ins->sreg1);
3848 case OP_LCONV_TO_U8:
3849 case OP_LCONV_TO_U4:
3851 s390_llgfr (code, ins->dreg, ins->sreg1);
3853 case OP_LCONV_TO_OVF_U4:
3854 S390_SET (code, s390_r0, 4294967295);
3855 s390_clgr (code, ins->sreg1, s390_r0);
3856 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3857 s390_ltgr (code, ins->sreg1, ins->sreg1);
3858 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3859 s390_llgfr(code, ins->dreg, ins->sreg1);
3861 case OP_LCONV_TO_OVF_I4_UN:
3862 S390_SET (code, s390_r0, 2147483647);
3863 s390_cgr (code, ins->sreg1, s390_r0);
3864 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3865 s390_ltgr (code, ins->sreg1, ins->sreg1);
3866 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3867 s390_lgfr (code, ins->dreg, ins->sreg1);
3870 if (ins->dreg != ins->sreg1) {
3871 s390_ldr (code, ins->dreg, ins->sreg1);
3874 case OP_MOVE_F_TO_I8:
3875 s390_lgdr (code, ins->dreg, ins->sreg1);
3877 case OP_MOVE_I8_TO_F:
3878 s390_ldgr (code, ins->dreg, ins->sreg1);
3880 case OP_MOVE_F_TO_I4:
3881 s390_ledbr (code, s390_f0, ins->sreg1);
3882 s390_lgdr (code, ins->dreg, s390_f0);
3883 s390_srag (code, ins->dreg, ins->dreg, 0, 32);
3885 case OP_MOVE_I4_TO_F:
3886 s390_slag (code, s390_r0, ins->sreg1, 0, 32);
3887 s390_ldgr (code, ins->dreg, s390_r0);
3888 s390_ldebr (code, ins->dreg, ins->dreg);
3890 case OP_FCONV_TO_R4:
3891 s390_ledbr (code, ins->dreg, ins->sreg1);
3892 s390_ldebr (code, ins->dreg, ins->dreg);
3894 case OP_S390_SETF4RET:
3895 s390_ledbr (code, ins->dreg, ins->sreg1);
3898 if (s390_is_imm16 (ins->inst_offset)) {
3899 s390_lghi (code, s390_r13, ins->inst_offset);
3900 } else if (s390_is_imm32 (ins->inst_offset)) {
3901 s390_lgfi (code, s390_r13, ins->inst_offset);
3903 S390_SET (code, s390_r13, ins->inst_offset);
3905 s390_ear (code, s390_r1, 0);
3906 s390_sllg(code, s390_r1, s390_r1, 0, 32);
3907 s390_ear (code, s390_r1, 1);
3908 s390_lg (code, ins->dreg, s390_r13, s390_r1, 0);
3912 if (s390_is_imm16 (ins->inst_offset)) {
3913 s390_lghi (code, s390_r13, ins->inst_offset);
3914 } else if (s390_is_imm32 (ins->inst_offset)) {
3915 s390_lgfi (code, s390_r13, ins->inst_offset);
3917 S390_SET (code, s390_r13, ins->inst_offset);
3919 s390_ear (code, s390_r1, 0);
3920 s390_sllg(code, s390_r1, s390_r1, 0, 32);
3921 s390_ear (code, s390_r1, 1);
3922 s390_stg (code, ins->sreg1, s390_r13, s390_r1, 0);
3926 if (cfg->method->save_lmf)
3927 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
3929 if (cfg->flags & MONO_CFG_HAS_TAIL) {
3930 code = emit_load_volatile_arguments (code, cfg);
3933 code = backUpStackPtr(cfg, code);
3934 s390_lg (code, s390_r14, 0, cfg->frame_reg, S390_RET_ADDR_OFFSET);
3935 mono_add_patch_info (cfg, code - cfg->native_code,
3936 MONO_PATCH_INFO_METHOD_JUMP,
3938 s390_jcl (code, S390_CC_UN, 0);
3941 case OP_CHECK_THIS: {
3942 /* ensure ins->sreg1 is not NULL */
3943 s390_lg (code, s390_r0, 0, ins->sreg1, 0);
3944 s390_ltgr (code, s390_r0, s390_r0);
3945 // EMIT_COND_SYSTEM_EXCEPTION (S390_CC_ZR, "NullReferenceException");
3949 int offset = cfg->sig_cookie + cfg->stack_usage;
3951 if (s390_is_imm16 (offset)) {
3952 s390_lghi (code, s390_r0, offset);
3953 } else if (s390_is_imm32 (offset)) {
3954 s390_lgfi (code, s390_r0, offset);
3956 S390_SET (code, s390_r0, offset);
3958 s390_agr (code, s390_r0, cfg->frame_reg);
3959 s390_stg (code, s390_r0, 0, ins->sreg1, 0);
3963 call = (MonoCallInst*)ins;
3964 if (ins->flags & MONO_INST_HAS_METHOD)
3965 mono_add_patch_info (cfg, code-cfg->native_code,
3966 MONO_PATCH_INFO_METHOD,
3969 mono_add_patch_info (cfg, code-cfg->native_code,
3970 MONO_PATCH_INFO_ABS,
3972 S390_CALL_TEMPLATE (code, s390_r14);
3973 if (call->signature->ret->type == MONO_TYPE_R4)
3974 s390_ldebr (code, s390_f0, s390_f0);
3982 call = (MonoCallInst*)ins;
3983 if (ins->flags & MONO_INST_HAS_METHOD)
3984 mono_add_patch_info (cfg, code-cfg->native_code,
3985 MONO_PATCH_INFO_METHOD,
3988 mono_add_patch_info (cfg, code-cfg->native_code,
3989 MONO_PATCH_INFO_ABS,
3991 S390_CALL_TEMPLATE (code, s390_r14);
3994 case OP_FCALL_REG: {
3995 call = (MonoCallInst*)ins;
3996 s390_lgr (code, s390_r1, ins->sreg1);
3997 s390_basr (code, s390_r14, s390_r1);
3998 if (call->signature->ret->type == MONO_TYPE_R4)
3999 s390_ldebr (code, s390_f0, s390_f0);
4005 case OP_VOIDCALL_REG:
4007 s390_lgr (code, s390_r1, ins->sreg1);
4008 s390_basr (code, s390_r14, s390_r1);
4011 case OP_FCALL_MEMBASE: {
4012 call = (MonoCallInst*)ins;
4013 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4014 s390_basr (code, s390_r14, s390_r1);
4015 if (call->signature->ret->type == MONO_TYPE_R4)
4016 s390_ldebr (code, s390_f0, s390_f0);
4019 case OP_LCALL_MEMBASE:
4020 case OP_VCALL_MEMBASE:
4021 case OP_VCALL2_MEMBASE:
4022 case OP_VOIDCALL_MEMBASE:
4023 case OP_CALL_MEMBASE: {
4024 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4025 s390_basr (code, s390_r14, s390_r1);
4032 if (cfg->param_area == 0)
4033 alloca_skip = S390_MINIMAL_STACK_SIZE;
4035 alloca_skip = cfg->param_area;
4037 area_offset = S390_ALIGN(alloca_skip, S390_STACK_ALIGNMENT);
4038 s390_lgr (code, s390_r1, ins->sreg1);
4039 if (ins->flags & MONO_INST_INIT)
4040 s390_lgr (code, s390_r0, ins->sreg1);
4041 s390_aghi (code, s390_r1, 14);
4042 s390_srlg (code, s390_r1, s390_r1, 0, 3);
4043 s390_sllg (code, s390_r1, s390_r1, 0, 3);
4044 if (cfg->method->save_lmf) {
4045 /*----------------------------------*/
4046 /* we have to adjust lmf ebp value */
4047 /*----------------------------------*/
4048 int lmfOffset = cfg->stack_usage - sizeof(MonoLMF);
4050 s390_lgr (code, s390_r13, cfg->frame_reg);
4051 if (s390_is_imm16(lmfOffset)) {
4052 s390_aghi (code, s390_r13, lmfOffset);
4053 } else if (s390_is_imm32(lmfOffset)) {
4054 s390_agfi (code, s390_r13, lmfOffset);
4056 S390_SET (code, s390_r13, lmfOffset);
4058 s390_lgr (code, s390_r14, STK_BASE);
4059 s390_sgr (code, s390_r14, s390_r1);
4060 s390_stg (code, s390_r14, 0, s390_r13,
4061 G_STRUCT_OFFSET(MonoLMF, ebp));
4063 s390_lg (code, s390_r13, 0, STK_BASE, 0);
4064 s390_sgr (code, STK_BASE, s390_r1);
4065 s390_stg (code, s390_r13, 0, STK_BASE, 0);
4066 s390_la (code, ins->dreg, 0, STK_BASE, area_offset);
4067 s390_srlg (code, ins->dreg, ins->dreg, 0, 3);
4068 s390_sllg (code, ins->dreg, ins->dreg, 0, 3);
4069 if (ins->flags & MONO_INST_INIT) {
4070 s390_lgr (code, s390_r1, s390_r0);
4071 s390_lgr (code, s390_r0, ins->dreg);
4072 s390_lgr (code, s390_r14, s390_r12);
4073 s390_lghi (code, s390_r13, 0);
4074 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4076 s390_lgr (code, s390_r12, s390_r14);
4081 s390_lgr (code, s390_r2, ins->sreg1);
4082 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4083 (gpointer) "mono_arch_throw_exception");
4084 S390_CALL_TEMPLATE(code, s390_r14);
4088 s390_lgr (code, s390_r2, ins->sreg1);
4089 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4090 (gpointer) "mono_arch_rethrow_exception");
4091 S390_CALL_TEMPLATE(code, s390_r14);
4094 case OP_START_HANDLER: {
4095 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4097 S390_LONG (code, stg, stg, s390_r14, 0,
4098 spvar->inst_basereg,
4099 spvar->inst_offset);
4102 case OP_ENDFILTER: {
4103 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4105 if (ins->sreg1 != s390_r2)
4106 s390_lgr(code, s390_r2, ins->sreg1);
4107 S390_LONG (code, lg, lg, s390_r14, 0,
4108 spvar->inst_basereg,
4109 spvar->inst_offset);
4110 s390_br (code, s390_r14);
4113 case OP_ENDFINALLY: {
4114 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4116 S390_LONG (code, lg, lg, s390_r14, 0,
4117 spvar->inst_basereg,
4118 spvar->inst_offset);
4119 s390_br (code, s390_r14);
4122 case OP_CALL_HANDLER: {
4123 mono_add_patch_info (cfg, code-cfg->native_code,
4124 MONO_PATCH_INFO_BB, ins->inst_target_bb);
4125 s390_brasl (code, s390_r14, 0);
4126 mono_cfg_add_try_hole (cfg, ins->inst_eh_block, code, bb);
4130 ins->inst_c0 = code - cfg->native_code;
4133 case OP_RELAXED_NOP:
4136 case OP_DUMMY_STORE:
4137 case OP_NOT_REACHED:
4141 case OP_IL_SEQ_POINT:
4142 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4144 case OP_SEQ_POINT: {
4147 if (cfg->compile_aot)
4151 * Read from the single stepping trigger page. This will cause a
4152 * SIGSEGV when single stepping is enabled.
4153 * We do this _before_ the breakpoint, so single stepping after
4154 * a breakpoint is hit will step to the next IL offset.
4156 if (ins->flags & MONO_INST_SINGLE_STEP_LOC) {
4157 breakpointCode.pTrigger = ss_trigger_page;
4158 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
4159 code += BREAKPOINT_SIZE;
4162 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4165 * A placeholder for a possible breakpoint inserted by
4166 * mono_arch_set_breakpoint ().
4168 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); ++i)
4172 * Add an additional nop so skipping the bp doesn't cause the ip to point
4173 * to another IL offset.
4179 case OP_GENERIC_CLASS_INIT: {
4180 static int byte_offset = -1;
4181 static guint8 bitmask;
4184 g_assert (ins->sreg1 == S390_FIRST_ARG_REG);
4186 if (byte_offset < 0)
4187 mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);
4189 s390_tm (code, ins->sreg1, byte_offset, bitmask);
4190 s390_jo (code, 0); CODEPTR(code, jump);
4192 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4193 "mono_generic_class_init");
4194 S390_CALL_TEMPLATE(code, s390_r14);
4196 PTRSLOT (code, jump);
4198 ins->flags |= MONO_INST_GC_CALLSITE;
4199 ins->backend.pc_offset = code - cfg->native_code;
4203 EMIT_UNCOND_BRANCH(ins);
4206 s390_br (code, ins->sreg1);
4212 s390_lghi(code, ins->dreg, 1);
4214 s390_lghi(code, ins->dreg, 0);
4220 s390_lghi(code, ins->dreg, 1);
4222 s390_lghi(code, ins->dreg, 0);
4228 s390_lghi(code, ins->dreg, 1);
4230 s390_lghi(code, ins->dreg, 0);
4236 s390_lghi(code, ins->dreg, 1);
4238 s390_lghi(code, ins->dreg, 0);
4244 s390_lghi(code, ins->dreg, 1);
4246 s390_lghi(code, ins->dreg, 0);
4249 case OP_COND_EXC_EQ:
4250 case OP_COND_EXC_IEQ:
4251 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_EQ, ins->inst_p1);
4253 case OP_COND_EXC_NE_UN:
4254 case OP_COND_EXC_INE_UN:
4255 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NE, ins->inst_p1);
4257 case OP_COND_EXC_LT:
4258 case OP_COND_EXC_ILT:
4259 case OP_COND_EXC_LT_UN:
4260 case OP_COND_EXC_ILT_UN:
4261 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, ins->inst_p1);
4263 case OP_COND_EXC_GT:
4264 case OP_COND_EXC_IGT:
4265 case OP_COND_EXC_GT_UN:
4266 case OP_COND_EXC_IGT_UN:
4267 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, ins->inst_p1);
4269 case OP_COND_EXC_GE:
4270 case OP_COND_EXC_IGE:
4271 case OP_COND_EXC_GE_UN:
4272 case OP_COND_EXC_IGE_UN:
4273 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GE, ins->inst_p1);
4275 case OP_COND_EXC_LE:
4276 case OP_COND_EXC_ILE:
4277 case OP_COND_EXC_LE_UN:
4278 case OP_COND_EXC_ILE_UN:
4279 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LE, ins->inst_p1);
4281 case OP_COND_EXC_OV:
4282 case OP_COND_EXC_IOV:
4283 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, ins->inst_p1);
4285 case OP_COND_EXC_NO:
4286 case OP_COND_EXC_INO:
4287 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NO, ins->inst_p1);
4290 case OP_COND_EXC_IC:
4291 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, ins->inst_p1);
4293 case OP_COND_EXC_NC:
4294 case OP_COND_EXC_INC:
4295 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, ins->inst_p1);
4299 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4303 EMIT_COND_BRANCH (ins, S390_CC_NE);
4309 EMIT_COND_BRANCH (ins, S390_CC_LT);
4315 EMIT_COND_BRANCH (ins, S390_CC_GT);
4321 EMIT_COND_BRANCH (ins, S390_CC_GE);
4327 EMIT_COND_BRANCH (ins, S390_CC_LE);
4330 /* floating point opcodes */
4332 if (*((double *) ins->inst_p0) == 0) {
4333 s390_lzdr (code, ins->dreg);
4335 S390_SET (code, s390_r13, ins->inst_p0);
4336 s390_ld (code, ins->dreg, 0, s390_r13, 0);
4341 if (*((float *) ins->inst_p0) == 0) {
4342 s390_lzdr (code, ins->dreg);
4344 S390_SET (code, s390_r13, ins->inst_p0);
4345 s390_ldeb (code, ins->dreg, 0, s390_r13, 0);
4349 case OP_STORER8_MEMBASE_REG: {
4350 S390_LONG (code, stdy, std, ins->sreg1, 0,
4351 ins->inst_destbasereg, ins->inst_offset);
4354 case OP_LOADR8_MEMBASE: {
4355 S390_LONG (code, ldy, ld, ins->dreg, 0,
4356 ins->inst_basereg, ins->inst_offset);
4359 case OP_STORER4_MEMBASE_REG: {
4360 s390_ledbr (code, s390_f15, ins->sreg1);
4361 S390_LONG (code, stey, ste, s390_f15, 0,
4362 ins->inst_destbasereg, ins->inst_offset);
4365 case OP_LOADR4_MEMBASE: {
4366 S390_LONG (code, ley, le, s390_f15, 0,
4367 ins->inst_basereg, ins->inst_offset);
4368 s390_ldebr (code, ins->dreg, s390_f15);
4371 case OP_ICONV_TO_R_UN: {
4372 if (mono_hwcap_s390x_has_fpe) {
4373 s390_cdlfbr (code, ins->dreg, 5, ins->sreg1, 0);
4375 s390_llgfr (code, s390_r0, ins->sreg1);
4376 s390_cdgbr (code, ins->dreg, s390_r0);
4380 case OP_LCONV_TO_R_UN: {
4381 if (mono_hwcap_s390x_has_fpe) {
4382 s390_cdlgbr (code, ins->dreg, 5, ins->sreg1, 0);
4385 s390_cxgbr (code, s390_f12, ins->sreg1);
4386 s390_ltgr (code, ins->sreg1, ins->sreg1);
4387 s390_jnl (code, 0); CODEPTR(code, jump);
4388 S390_SET (code, s390_r13, 0x403f000000000000llu);
4389 s390_lgdr (code, s390_f13, s390_r13);
4390 s390_lzdr (code, s390_f15);
4391 s390_axbr (code, s390_f12, s390_f13);
4392 PTRSLOT(code, jump);
4393 s390_ldxbr (code, s390_f13, s390_f12);
4394 s390_ldr (code, ins->dreg, s390_f13);
4398 case OP_LCONV_TO_R4:
4399 case OP_ICONV_TO_R4: {
4400 s390_cegbr (code, ins->dreg, ins->sreg1);
4401 s390_ldebr (code, ins->dreg, ins->dreg);
4404 case OP_LCONV_TO_R8:
4405 case OP_ICONV_TO_R8: {
4406 s390_cdgbr (code, ins->dreg, ins->sreg1);
4409 case OP_FCONV_TO_I1:
4410 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4411 s390_ltgr (code, ins->dreg, ins->dreg);
4413 s390_oill (code, ins->dreg, 0x80);
4414 s390_lghi (code, s390_r0, 0xff);
4415 s390_ngr (code, ins->dreg, s390_r0);
4417 case OP_FCONV_TO_U1:
4418 if (mono_hwcap_s390x_has_fpe) {
4419 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4420 s390_lghi (code, s390_r0, 0xff);
4421 s390_ngr (code, ins->dreg, s390_r0);
4423 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 1, FALSE);
4426 case OP_FCONV_TO_I2:
4427 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4428 s390_ltgr (code, ins->dreg, ins->dreg);
4430 s390_oill (code, ins->dreg, 0x8000);
4431 s390_llill (code, s390_r0, 0xffff);
4432 s390_ngr (code, ins->dreg, s390_r0);
4434 case OP_FCONV_TO_U2:
4435 if (mono_hwcap_s390x_has_fpe) {
4436 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4437 s390_llill (code, s390_r0, 0xffff);
4438 s390_ngr (code, ins->dreg, s390_r0);
4440 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 2, FALSE);
4443 case OP_FCONV_TO_I4:
4445 s390_cfdbr (code, ins->dreg, 5, ins->sreg1);
4447 case OP_FCONV_TO_U4:
4449 if (mono_hwcap_s390x_has_fpe) {
4450 s390_clfdbr (code, ins->dreg, 5, ins->sreg1, 0);
4452 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE);
4455 case OP_FCONV_TO_I8:
4456 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4458 case OP_FCONV_TO_U8:
4459 if (mono_hwcap_s390x_has_fpe) {
4460 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4462 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 8, FALSE);
4465 case OP_LCONV_TO_OVF_I: {
4466 /* Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000 */
4468 s390_ltgr (code, ins->sreg2, ins->sreg2);
4469 s390_jnl (code, 0); CODEPTR(code, o[0]);
4470 s390_ltgr (code, ins->sreg1, ins->sreg1);
4471 s390_jnl (code, 0); CODEPTR(code, o[1]);
4472 s390_lhi (code, s390_r13, -1);
4473 s390_cgr (code, ins->sreg1, s390_r13);
4474 s390_jnz (code, 0); CODEPTR(code, o[2]);
4475 if (ins->dreg != ins->sreg2)
4476 s390_lgr (code, ins->dreg, ins->sreg2);
4477 s390_j (code, 0); CODEPTR(code, o[3]);
4478 PTRSLOT(code, o[0]);
4479 s390_jz (code, 0); CODEPTR(code, o[4]);
4480 PTRSLOT(code, o[1]);
4481 PTRSLOT(code, o[2]);
4482 mono_add_patch_info (cfg, code - cfg->native_code,
4483 MONO_PATCH_INFO_EXC, "OverflowException");
4484 s390_brasl (code, s390_r14, 0);
4485 PTRSLOT(code, o[3]);
4486 PTRSLOT(code, o[4]);
4490 s390_lpdbr (code, ins->dreg, ins->sreg1);
4494 s390_sqdbr (code, ins->dreg, ins->sreg1);
4499 s390_adbr (code, ins->dreg, src2);
4503 CHECK_SRCDST_NCOM_F;
4504 s390_sdbr (code, ins->dreg, src2);
4509 s390_mdbr (code, ins->dreg, src2);
4513 CHECK_SRCDST_NCOM_F;
4514 s390_ddbr (code, ins->dreg, src2);
4518 s390_lcdbr (code, ins->dreg, ins->sreg1);
4522 CHECK_SRCDST_NCOM_F;
4523 s390_didbr (code, ins->dreg, src2, 5, s390_f15);
4527 s390_cdbr (code, ins->sreg1, ins->sreg2);
4531 s390_cdbr (code, ins->sreg1, ins->sreg2);
4532 s390_lghi (code, ins->dreg, 1);
4534 s390_lghi (code, ins->dreg, 0);
4538 s390_cdbr (code, ins->sreg1, ins->sreg2);
4539 s390_lghi (code, ins->dreg, 1);
4541 s390_lghi (code, ins->dreg, 0);
4545 s390_cdbr (code, ins->sreg1, ins->sreg2);
4546 s390_lghi (code, ins->dreg, 1);
4548 s390_lghi (code, ins->dreg, 0);
4552 s390_cdbr (code, ins->sreg1, ins->sreg2);
4553 s390_lghi (code, ins->dreg, 1);
4555 s390_lghi (code, ins->dreg, 0);
4559 s390_cdbr (code, ins->sreg1, ins->sreg2);
4560 s390_lghi (code, ins->dreg, 1);
4562 s390_lghi (code, ins->dreg, 0);
4567 s390_jo (code, 0); CODEPTR(code, o);
4568 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4573 EMIT_COND_BRANCH (ins, S390_CC_NE|S390_CC_OV);
4577 s390_jo (code, 0); CODEPTR(code, o);
4578 EMIT_COND_BRANCH (ins, S390_CC_LT);
4583 EMIT_COND_BRANCH (ins, S390_CC_LT|S390_CC_OV);
4587 s390_jo (code, 0); CODEPTR(code, o);
4588 EMIT_COND_BRANCH (ins, S390_CC_GT);
4593 EMIT_COND_BRANCH (ins, S390_CC_GT|S390_CC_OV);
4597 s390_jo (code, 0); CODEPTR(code, o);
4598 EMIT_COND_BRANCH (ins, S390_CC_GE);
4603 EMIT_COND_BRANCH (ins, S390_CC_GE|S390_CC_OV);
4607 s390_jo (code, 0); CODEPTR(code, o);
4608 EMIT_COND_BRANCH (ins, S390_CC_LE);
4613 EMIT_COND_BRANCH (ins, S390_CC_LE|S390_CC_OV);
4617 s390_lhi (code, s390_r13, 0x7f);
4618 s390_tcdb (code, ins->sreg1, 0, s390_r13, 0);
4619 s390_jz (code, 0); CODEPTR(code, o);
4620 mono_add_patch_info (cfg, code - cfg->native_code,
4621 MONO_PATCH_INFO_EXC, "OverflowException");
4622 s390_brasl (code, s390_r14,0);
4626 case OP_S390_MOVE: {
4627 if (ins->backend.size > 0) {
4628 if (ins->backend.size <= 256) {
4629 s390_mvc (code, ins->backend.size, ins->dreg,
4630 ins->inst_offset, ins->sreg1, ins->inst_imm);
4632 s390_lgr (code, s390_r0, ins->dreg);
4633 if (ins->inst_offset > 0) {
4634 if (s390_is_imm16 (ins->inst_offset)) {
4635 s390_aghi (code, s390_r0, ins->inst_offset);
4636 } else if (s390_is_imm32 (ins->inst_offset)) {
4637 s390_agfi (code, s390_r0, ins->inst_offset);
4639 S390_SET (code, s390_r13, ins->inst_offset);
4640 s390_agr (code, s390_r0, s390_r13);
4643 s390_lgr (code, s390_r12, ins->sreg1);
4644 if (ins->inst_imm > 0) {
4645 if (s390_is_imm16 (ins->inst_imm)) {
4646 s390_aghi (code, s390_r12, ins->inst_imm);
4647 } else if (s390_is_imm32 (ins->inst_imm)) {
4648 s390_agfi (code, s390_r12, ins->inst_imm);
4650 S390_SET (code, s390_r13, ins->inst_imm);
4651 s390_agr (code, s390_r12, s390_r13);
4654 if (s390_is_imm16 (ins->backend.size)) {
4655 s390_lghi (code, s390_r1, ins->backend.size);
4656 } else if (s390_is_imm32 (ins->inst_offset)) {
4657 s390_agfi (code, s390_r1, ins->backend.size);
4659 S390_SET (code, s390_r13, ins->backend.size);
4660 s390_agr (code, s390_r1, s390_r13);
4662 s390_lgr (code, s390_r13, s390_r1);
4663 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4669 case OP_ATOMIC_ADD_I8: {
4670 s390_lgr (code, s390_r1, ins->sreg2);
4671 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4672 s390_agr (code, s390_r1, s390_r0);
4673 s390_csg (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4674 s390_jnz (code, -10);
4675 s390_lgr (code, ins->dreg, s390_r1);
4678 case OP_ATOMIC_EXCHANGE_I8: {
4679 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4680 s390_csg (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
4681 s390_jnz (code, -6);
4682 s390_lgr (code, ins->dreg, s390_r0);
4685 case OP_ATOMIC_ADD_I4: {
4686 s390_lgfr(code, s390_r1, ins->sreg2);
4687 s390_lgf (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4688 s390_agr (code, s390_r1, s390_r0);
4689 s390_cs (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4690 s390_jnz (code, -9);
4691 s390_lgfr(code, ins->dreg, s390_r1);
4694 case OP_ATOMIC_EXCHANGE_I4: {
4695 s390_l (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4696 s390_cs (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
4697 s390_jnz (code, -4);
4698 s390_lgfr(code, ins->dreg, s390_r0);
4701 case OP_S390_BKCHAIN: {
4702 s390_lgr (code, ins->dreg, ins->sreg1);
4703 if (s390_is_imm16 (cfg->stack_offset)) {
4704 s390_aghi (code, ins->dreg, cfg->stack_offset);
4705 } else if (s390_is_imm32 (cfg->stack_offset)) {
4706 s390_agfi (code, ins->dreg, cfg->stack_offset);
4708 S390_SET (code, s390_r13, cfg->stack_offset);
4709 s390_agr (code, ins->dreg, s390_r13);
4713 case OP_MEMORY_BARRIER:
4716 case OP_GC_SAFE_POINT: {
4719 g_assert (mono_threads_is_coop_enabled ());
4721 s390_chi (code, ins->sreg1, 1);
4722 s390_je (code, 0); CODEPTR(code, br);
4723 mono_add_patch_info (cfg, code- cfg->native_code, MONO_PATCH_INFO_ABS,
4724 mono_threads_state_poll);
4725 S390_CALL_TEMPLATE (code, s390_r14);
4729 case OP_GC_LIVENESS_DEF:
4730 case OP_GC_LIVENESS_USE:
4731 case OP_GC_PARAM_SLOT_LIVENESS_DEF:
4732 ins->backend.pc_offset = code - cfg->native_code;
4734 case OP_GC_SPILL_SLOT_LIVENESS_DEF:
4735 ins->backend.pc_offset = code - cfg->native_code;
4736 bb->spill_slot_defs = g_slist_prepend_mempool (cfg->mempool, bb->spill_slot_defs, ins);
4738 #ifdef MONO_ARCH_SIMD_INTRINSICS
4740 s390x_addps (code, ins->sreg1, ins->sreg2);
4743 s390x_divps (code, ins->sreg1, ins->sreg2);
4746 s390x_mulps (code, ins->sreg1, ins->sreg2);
4749 s390x_subps (code, ins->sreg1, ins->sreg2);
4752 s390x_maxps (code, ins->sreg1, ins->sreg2);
4755 s390x_minps (code, ins->sreg1, ins->sreg2);
4758 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
4759 s390x_cmpps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4762 s390x_andps (code, ins->sreg1, ins->sreg2);
4765 s390x_andnps (code, ins->sreg1, ins->sreg2);
4768 s390x_orps (code, ins->sreg1, ins->sreg2);
4771 s390x_xorps (code, ins->sreg1, ins->sreg2);
4774 s390x_sqrtps (code, ins->dreg, ins->sreg1);
4777 s390x_rsqrtps (code, ins->dreg, ins->sreg1);
4780 s390x_rcpps (code, ins->dreg, ins->sreg1);
4783 s390x_addsubps (code, ins->sreg1, ins->sreg2);
4786 s390x_haddps (code, ins->sreg1, ins->sreg2);
4789 s390x_hsubps (code, ins->sreg1, ins->sreg2);
4792 s390x_movshdup (code, ins->dreg, ins->sreg1);
4795 s390x_movsldup (code, ins->dreg, ins->sreg1);
4798 case OP_PSHUFLEW_HIGH:
4799 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4800 s390x_pshufhw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4802 case OP_PSHUFLEW_LOW:
4803 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4804 s390x_pshuflw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4807 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4808 s390x_pshufd_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4811 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4812 s390x_shufps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4815 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0x3);
4816 s390x_shufpd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4820 s390x_addpd (code, ins->sreg1, ins->sreg2);
4823 s390x_divpd (code, ins->sreg1, ins->sreg2);
4826 s390x_mulpd (code, ins->sreg1, ins->sreg2);
4829 s390x_subpd (code, ins->sreg1, ins->sreg2);
4832 s390x_maxpd (code, ins->sreg1, ins->sreg2);
4835 s390x_minpd (code, ins->sreg1, ins->sreg2);
4838 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
4839 s390x_cmppd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4842 s390x_andpd (code, ins->sreg1, ins->sreg2);
4845 s390x_andnpd (code, ins->sreg1, ins->sreg2);
4848 s390x_orpd (code, ins->sreg1, ins->sreg2);
4851 s390x_xorpd (code, ins->sreg1, ins->sreg2);
4854 s390x_sqrtpd (code, ins->dreg, ins->sreg1);
4857 s390x_addsubpd (code, ins->sreg1, ins->sreg2);
4860 s390x_haddpd (code, ins->sreg1, ins->sreg2);
4863 s390x_hsubpd (code, ins->sreg1, ins->sreg2);
4866 s390x_movddup (code, ins->dreg, ins->sreg1);
4869 case OP_EXTRACT_MASK:
4870 s390x_pmovmskb (code, ins->dreg, ins->sreg1);
4874 s390x_pand (code, ins->sreg1, ins->sreg2);
4877 s390x_por (code, ins->sreg1, ins->sreg2);
4880 s390x_pxor (code, ins->sreg1, ins->sreg2);
4884 s390x_paddb (code, ins->sreg1, ins->sreg2);
4887 s390x_paddw (code, ins->sreg1, ins->sreg2);
4890 s390x_paddd (code, ins->sreg1, ins->sreg2);
4893 s390x_paddq (code, ins->sreg1, ins->sreg2);
4897 s390x_psubb (code, ins->sreg1, ins->sreg2);
4900 s390x_psubw (code, ins->sreg1, ins->sreg2);
4903 s390x_psubd (code, ins->sreg1, ins->sreg2);
4906 s390x_psubq (code, ins->sreg1, ins->sreg2);
4910 s390x_pmaxub (code, ins->sreg1, ins->sreg2);
4913 s390x_pmaxuw (code, ins->sreg1, ins->sreg2);
4916 s390x_pmaxud (code, ins->sreg1, ins->sreg2);
4920 s390x_pmaxsb (code, ins->sreg1, ins->sreg2);
4923 s390x_pmaxsw (code, ins->sreg1, ins->sreg2);
4926 s390x_pmaxsd (code, ins->sreg1, ins->sreg2);
4930 s390x_pavgb (code, ins->sreg1, ins->sreg2);
4933 s390x_pavgw (code, ins->sreg1, ins->sreg2);
4937 s390x_pminub (code, ins->sreg1, ins->sreg2);
4940 s390x_pminuw (code, ins->sreg1, ins->sreg2);
4943 s390x_pminud (code, ins->sreg1, ins->sreg2);
4947 s390x_pminsb (code, ins->sreg1, ins->sreg2);
4950 s390x_pminsw (code, ins->sreg1, ins->sreg2);
4953 s390x_pminsd (code, ins->sreg1, ins->sreg2);
4957 s390x_pcmpeqb (code, ins->sreg1, ins->sreg2);
4960 s390x_pcmpeqw (code, ins->sreg1, ins->sreg2);
4963 s390x_pcmpeqd (code, ins->sreg1, ins->sreg2);
4966 s390x_pcmpeqq (code, ins->sreg1, ins->sreg2);
4970 s390x_pcmpgtb (code, ins->sreg1, ins->sreg2);
4973 s390x_pcmpgtw (code, ins->sreg1, ins->sreg2);
4976 s390x_pcmpgtd (code, ins->sreg1, ins->sreg2);
4979 s390x_pcmpgtq (code, ins->sreg1, ins->sreg2);
4982 case OP_PSUM_ABS_DIFF:
4983 s390x_psadbw (code, ins->sreg1, ins->sreg2);
4986 case OP_UNPACK_LOWB:
4987 s390x_punpcklbw (code, ins->sreg1, ins->sreg2);
4989 case OP_UNPACK_LOWW:
4990 s390x_punpcklwd (code, ins->sreg1, ins->sreg2);
4992 case OP_UNPACK_LOWD:
4993 s390x_punpckldq (code, ins->sreg1, ins->sreg2);
4995 case OP_UNPACK_LOWQ:
4996 s390x_punpcklqdq (code, ins->sreg1, ins->sreg2);
4998 case OP_UNPACK_LOWPS:
4999 s390x_unpcklps (code, ins->sreg1, ins->sreg2);
5001 case OP_UNPACK_LOWPD:
5002 s390x_unpcklpd (code, ins->sreg1, ins->sreg2);
5005 case OP_UNPACK_HIGHB:
5006 s390x_punpckhbw (code, ins->sreg1, ins->sreg2);
5008 case OP_UNPACK_HIGHW:
5009 s390x_punpckhwd (code, ins->sreg1, ins->sreg2);
5011 case OP_UNPACK_HIGHD:
5012 s390x_punpckhdq (code, ins->sreg1, ins->sreg2);
5014 case OP_UNPACK_HIGHQ:
5015 s390x_punpckhqdq (code, ins->sreg1, ins->sreg2);
5017 case OP_UNPACK_HIGHPS:
5018 s390x_unpckhps (code, ins->sreg1, ins->sreg2);
5020 case OP_UNPACK_HIGHPD:
5021 s390x_unpckhpd (code, ins->sreg1, ins->sreg2);
5025 s390x_packsswb (code, ins->sreg1, ins->sreg2);
5028 s390x_packssdw (code, ins->sreg1, ins->sreg2);
5031 s390x_packuswb (code, ins->sreg1, ins->sreg2);
5034 s390x_packusdw (code, ins->sreg1, ins->sreg2);
5037 case OP_PADDB_SAT_UN:
5038 s390x_paddusb (code, ins->sreg1, ins->sreg2);
5040 case OP_PSUBB_SAT_UN:
5041 s390x_psubusb (code, ins->sreg1, ins->sreg2);
5043 case OP_PADDW_SAT_UN:
5044 s390x_paddusw (code, ins->sreg1, ins->sreg2);
5046 case OP_PSUBW_SAT_UN:
5047 s390x_psubusw (code, ins->sreg1, ins->sreg2);
5051 s390x_paddsb (code, ins->sreg1, ins->sreg2);
5054 s390x_psubsb (code, ins->sreg1, ins->sreg2);
5057 s390x_paddsw (code, ins->sreg1, ins->sreg2);
5060 s390x_psubsw (code, ins->sreg1, ins->sreg2);
5064 s390x_pmullw (code, ins->sreg1, ins->sreg2);
5067 s390x_pmulld (code, ins->sreg1, ins->sreg2);
5070 s390x_pmuludq (code, ins->sreg1, ins->sreg2);
5072 case OP_PMULW_HIGH_UN:
5073 s390x_pmulhuw (code, ins->sreg1, ins->sreg2);
5076 s390x_pmulhw (code, ins->sreg1, ins->sreg2);
5080 s390x_psrlw_reg_imm (code, ins->dreg, ins->inst_imm);
5083 s390x_psrlw (code, ins->dreg, ins->sreg2);
5087 s390x_psraw_reg_imm (code, ins->dreg, ins->inst_imm);
5090 s390x_psraw (code, ins->dreg, ins->sreg2);
5094 s390x_psllw_reg_imm (code, ins->dreg, ins->inst_imm);
5097 s390x_psllw (code, ins->dreg, ins->sreg2);
5101 s390x_psrld_reg_imm (code, ins->dreg, ins->inst_imm);
5104 s390x_psrld (code, ins->dreg, ins->sreg2);
5108 s390x_psrad_reg_imm (code, ins->dreg, ins->inst_imm);
5111 s390x_psrad (code, ins->dreg, ins->sreg2);
5115 s390x_pslld_reg_imm (code, ins->dreg, ins->inst_imm);
5118 s390x_pslld (code, ins->dreg, ins->sreg2);
5122 s390x_psrlq_reg_imm (code, ins->dreg, ins->inst_imm);
5125 s390x_psrlq (code, ins->dreg, ins->sreg2);
5128 /*TODO: This is appart of the sse spec but not added
5130 s390x_psraq_reg_imm (code, ins->dreg, ins->inst_imm);
5133 s390x_psraq (code, ins->dreg, ins->sreg2);
5138 s390x_psllq_reg_imm (code, ins->dreg, ins->inst_imm);
5141 s390x_psllq (code, ins->dreg, ins->sreg2);
5144 s390x_cvtdq2pd (code, ins->dreg, ins->sreg1);
5147 s390x_cvtdq2ps (code, ins->dreg, ins->sreg1);
5150 s390x_cvtpd2dq (code, ins->dreg, ins->sreg1);
5153 s390x_cvtpd2ps (code, ins->dreg, ins->sreg1);
5156 s390x_cvtps2dq (code, ins->dreg, ins->sreg1);
5159 s390x_cvtps2pd (code, ins->dreg, ins->sreg1);
5162 s390x_cvttpd2dq (code, ins->dreg, ins->sreg1);
5165 s390x_cvttps2dq (code, ins->dreg, ins->sreg1);
5169 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5172 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5176 amd64_movhlps (code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg1);
5177 amd64_movd_reg_xreg_size (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG, 8);
5179 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 8);
5184 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5186 amd64_shift_reg_imm (code, X86_SHR, ins->dreg, ins->inst_c0 * 8);
5187 amd64_widen_reg (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I1, FALSE);
5191 /*amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5193 amd64_shift_reg_imm_size (code, X86_SHR, ins->dreg, 16, 4);*/
5194 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5195 amd64_widen_reg_size (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I2, TRUE, 4);
5199 amd64_movhlps (code, ins->dreg, ins->sreg1);
5201 s390x_movsd (code, ins->dreg, ins->sreg1);
5204 s390x_pinsrw_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5206 case OP_EXTRACTX_U2:
5207 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5209 case OP_INSERTX_U1_SLOW:
5210 /*sreg1 is the extracted ireg (scratch)
5211 /sreg2 is the to be inserted ireg (scratch)
5212 /dreg is the xreg to receive the value*/
5214 /*clear the bits from the extracted word*/
5215 amd64_alu_reg_imm (code, X86_AND, ins->sreg1, ins->inst_c0 & 1 ? 0x00FF : 0xFF00);
5216 /*shift the value to insert if needed*/
5217 if (ins->inst_c0 & 1)
5218 amd64_shift_reg_imm_size (code, X86_SHL, ins->sreg2, 8, 4);
5219 /*join them together*/
5220 amd64_alu (code, X86_OR, ins->sreg1, ins->sreg2);
5221 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0 / 2);
5223 case OP_INSERTX_I4_SLOW:
5224 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2);
5225 amd64_shift_reg_imm (code, X86_SHR, ins->sreg2, 16);
5226 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2 + 1);
5228 case OP_INSERTX_I8_SLOW:
5229 amd64_movd_xreg_reg_size(code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg2, 8);
5231 amd64_movlhps (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5233 s390x_movsd (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5236 case OP_INSERTX_R4_SLOW:
5237 switch (ins->inst_c0) {
5240 s390x_movss (code, ins->dreg, ins->sreg2);
5242 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5245 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5247 s390x_movss (code, ins->dreg, ins->sreg2);
5249 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5250 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5253 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5255 s390x_movss (code, ins->dreg, ins->sreg2);
5257 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5258 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5261 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5263 s390x_movss (code, ins->dreg, ins->sreg2);
5265 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5266 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5270 case OP_INSERTX_R8_SLOW:
5272 amd64_movlhps (code, ins->dreg, ins->sreg2);
5274 s390x_movsd (code, ins->dreg, ins->sreg2);
5276 case OP_STOREX_MEMBASE_REG:
5277 case OP_STOREX_MEMBASE:
5278 s390x_movups_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5280 case OP_LOADX_MEMBASE:
5281 s390x_movups_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5283 case OP_LOADX_ALIGNED_MEMBASE:
5284 s390x_movaps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5286 case OP_STOREX_ALIGNED_MEMBASE_REG:
5287 s390x_movaps_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5289 case OP_STOREX_NTA_MEMBASE_REG:
5290 s390x_movntps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5292 case OP_PREFETCH_MEMBASE:
5293 s390x_prefetch_reg_membase (code, ins->backend.arg_info, ins->sreg1, ins->inst_offset);
5297 /*FIXME the peephole pass should have killed this*/
5298 if (ins->dreg != ins->sreg1)
5299 s390x_movaps (code, ins->dreg, ins->sreg1);
5302 s390x_pxor (code, ins->dreg, ins->dreg);
5304 case OP_ICONV_TO_R4_RAW:
5305 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5308 case OP_FCONV_TO_R8_X:
5309 s390x_movsd (code, ins->dreg, ins->sreg1);
5312 case OP_XCONV_R8_TO_I4:
5313 s390x_cvttsd2si_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5314 switch (ins->backend.source_opcode) {
5315 case OP_FCONV_TO_I1:
5316 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, FALSE);
5318 case OP_FCONV_TO_U1:
5319 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, FALSE);
5321 case OP_FCONV_TO_I2:
5322 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, TRUE);
5324 case OP_FCONV_TO_U2:
5325 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, TRUE);
5331 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 0);
5332 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 1);
5333 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5336 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5337 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5340 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 8);
5341 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5345 s390x_movsd (code, ins->dreg, ins->sreg1);
5347 s390x_movsd (code, ins->dreg, ins->sreg1);
5348 s390x_cvtsd2ss (code, ins->dreg, ins->dreg);
5350 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5353 s390x_movsd (code, ins->dreg, ins->sreg1);
5354 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5358 g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
5359 g_assert_not_reached ();
5362 if ((cfg->opt & MONO_OPT_BRANCH) && ((code - cfg->native_code - offset) > max_len)) {
5363 g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %ld)",
5364 mono_inst_name (ins->opcode), max_len, code - cfg->native_code - offset);
5365 g_assert_not_reached ();
5368 last_offset = offset;
5371 cfg->code_len = code - cfg->native_code;
5374 /*========================= End of Function ========================*/
5376 /*------------------------------------------------------------------*/
5378 /* Name - mono_arch_register_lowlevel_calls */
5380 /* Function - Register routines to help with --trace operation. */
5382 /*------------------------------------------------------------------*/
5385 mono_arch_register_lowlevel_calls (void)
5389 /*========================= End of Function ========================*/
5391 /*------------------------------------------------------------------*/
5393 /* Name - mono_arch_patch_code */
5395 /* Function - Process the patch data created during the */
5396 /* instruction build process. This resolves jumps, */
5397 /* calls, variables etc. */
5399 /*------------------------------------------------------------------*/
5402 mono_arch_patch_code (MonoCompile *cfg, MonoMethod *method, MonoDomain *domain,
5403 guint8 *code, MonoJumpInfo *ji, gboolean run_cctors,
5406 MonoJumpInfo *patch_info;
5410 for (patch_info = ji; patch_info; patch_info = patch_info->next) {
5411 unsigned char *ip = patch_info->ip.i + code;
5412 gconstpointer target = NULL;
5414 target = mono_resolve_patch_target (method, domain, code,
5415 patch_info, run_cctors, error);
5416 return_if_nok (error);
5418 switch (patch_info->type) {
5419 case MONO_PATCH_INFO_IP:
5420 case MONO_PATCH_INFO_LDSTR:
5421 case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
5422 case MONO_PATCH_INFO_LDTOKEN:
5423 case MONO_PATCH_INFO_EXC:
5424 s390_patch_addr (ip, (guint64) target);
5426 case MONO_PATCH_INFO_METHOD:
5427 case MONO_PATCH_INFO_INTERNAL_METHOD:
5428 case MONO_PATCH_INFO_JIT_ICALL_ADDR:
5429 case MONO_PATCH_INFO_RGCTX_FETCH:
5430 case MONO_PATCH_INFO_ABS: {
5431 S390_EMIT_CALL (ip, target);
5434 case MONO_PATCH_INFO_SWITCH:
5435 /*----------------------------------*/
5436 /* ip points at the basr r13,0/j +4 */
5437 /* instruction the vtable value */
5438 /* follows this (i.e. ip+6) */
5439 /*----------------------------------*/
5440 S390_EMIT_LOAD (ip, target);
5442 case MONO_PATCH_INFO_METHODCONST:
5443 case MONO_PATCH_INFO_CLASS:
5444 case MONO_PATCH_INFO_IMAGE:
5445 case MONO_PATCH_INFO_FIELD:
5446 case MONO_PATCH_INFO_IID:
5447 case MONO_PATCH_INFO_EXC_NAME:
5448 target = S390_RELATIVE(target, ip);
5449 s390_patch_rel (ip, (guint64) target);
5451 case MONO_PATCH_INFO_R4:
5452 case MONO_PATCH_INFO_R8:
5453 case MONO_PATCH_INFO_METHOD_REL:
5454 g_assert_not_reached ();
5457 target = S390_RELATIVE(target, ip);
5459 s390_patch_rel (ip, (guint64) target);
5464 /*========================= End of Function ========================*/
5466 /*------------------------------------------------------------------*/
5468 /* Name - emit_load_volatile_arguments */
5470 /* Function - Emit the instructions to reload parameter regist- */
5471 /* registers for use with "tail" operations. */
5473 /* The register loading operations performed here */
5474 /* are the mirror of the store operations performed */
5475 /* in mono_arch_emit_prolog and need to be kept in */
5476 /* synchronization with it. */
5478 /*------------------------------------------------------------------*/
5481 emit_load_volatile_arguments (guint8 *code, MonoCompile *cfg)
5484 MonoMethod *method = cfg->method;
5485 MonoMethodSignature *sig = mono_method_signature(method);
5489 cinfo = get_call_info (NULL, NULL, sig);
5491 if (cinfo->struct_ret) {
5492 ArgInfo *ainfo = &cinfo->ret;
5493 inst = cfg->vret_addr;
5494 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5497 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5498 ArgInfo *ainfo = cinfo->args + i;
5499 inst = cfg->args [pos];
5501 if (inst->opcode == OP_REGVAR) {
5502 if (ainfo->regtype == RegTypeGeneral)
5503 s390_lgr (code, ainfo->reg, inst->dreg);
5504 else if (ainfo->regtype == RegTypeFP) {
5505 if (inst->dreg != ainfo->reg) {
5506 if (ainfo->size == 4) {
5507 s390_ldebr (code, ainfo->reg, inst->dreg);
5509 s390_ldr (code, ainfo->reg, inst->dreg);
5513 else if (ainfo->regtype == RegTypeBase) {
5515 g_assert_not_reached ();
5517 if (ainfo->regtype == RegTypeGeneral) {
5518 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5519 g_assert_not_reached();
5520 switch (ainfo->size) {
5522 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5525 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5528 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5531 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5534 } else if (ainfo->regtype == RegTypeBase) {
5535 } else if (ainfo->regtype == RegTypeFP) {
5536 if (ainfo->size == 8)
5537 s390_ld (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5538 else if (ainfo->size == 4)
5539 s390_le (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5541 g_assert_not_reached ();
5542 } else if (ainfo->regtype == RegTypeStructByVal) {
5543 if (ainfo->reg != STK_BASE) {
5544 switch (ainfo->size) {
5546 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5549 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5552 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5555 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5559 } else if (ainfo->regtype == RegTypeStructByAddr) {
5560 if (ainfo->reg != STK_BASE) {
5561 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5564 g_assert_not_reached ();
5572 /*========================= End of Function ========================*/
5574 /*------------------------------------------------------------------*/
5576 /* Name - mono_arch_emit_prolog */
5578 /* Function - Create the instruction sequence for a function */
5581 /*------------------------------------------------------------------*/
5584 mono_arch_emit_prolog (MonoCompile *cfg)
5586 MonoMethod *method = cfg->method;
5588 MonoMethodSignature *sig;
5590 long alloc_size, pos, max_offset, i, cfa_offset = 0;
5599 cfg->code_size = 512;
5601 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
5603 cfg->code_size += 256;
5606 if (method->save_lmf)
5607 cfg->code_size += 200;
5609 cfg->native_code = code = g_malloc (cfg->code_size);
5611 mono_emit_unwind_op_def_cfa (cfg, code, STK_BASE, 0);
5612 emit_unwind_regs(cfg, code, s390_r6, s390_r14, S390_REG_SAVE_OFFSET);
5613 s390_stmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
5614 mono_emit_unwind_op_offset (cfg, code, s390_r14, S390_RET_ADDR_OFFSET);
5615 mini_gc_set_slot_type_from_cfa (cfg, S390_RET_ADDR_OFFSET, SLOT_NOREF);
5617 if (cfg->arch.bkchain_reg != -1)
5618 s390_lgr (code, cfg->arch.bkchain_reg, STK_BASE);
5620 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
5621 cfg->used_int_regs |= 1 << 11;
5624 alloc_size = cfg->stack_offset;
5626 cfg->stack_usage = cfa_offset = alloc_size;
5627 mono_emit_unwind_op_def_cfa_offset (cfg, code, alloc_size);
5628 s390_lgr (code, s390_r11, STK_BASE);
5629 if (s390_is_imm16 (alloc_size)) {
5630 s390_aghi (code, STK_BASE, -alloc_size);
5631 } else if (s390_is_imm32 (alloc_size)) {
5632 s390_agfi (code, STK_BASE, -alloc_size);
5634 int stackSize = alloc_size;
5635 while (stackSize > INT_MAX) {
5636 s390_agfi (code, STK_BASE, -INT_MAX);
5637 stackSize -= INT_MAX;
5639 s390_agfi (code, STK_BASE, -stackSize);
5641 s390_stg (code, s390_r11, 0, STK_BASE, 0);
5643 if (cfg->frame_reg != STK_BASE)
5644 s390_lgr (code, s390_r11, STK_BASE);
5646 mono_emit_unwind_op_def_cfa_reg (cfg, code, cfg->frame_reg);
5648 /* store runtime generic context */
5649 if (cfg->rgctx_var) {
5650 g_assert (cfg->rgctx_var->opcode == OP_REGOFFSET);
5652 s390_stg (code, MONO_ARCH_RGCTX_REG, 0,
5653 cfg->rgctx_var->inst_basereg,
5654 cfg->rgctx_var->inst_offset);
5657 /* compute max_offset in order to use short forward jumps
5658 * we always do it on s390 because the immediate displacement
5659 * for jumps is too small
5662 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
5664 bb->max_offset = max_offset;
5666 MONO_BB_FOR_EACH_INS (bb, ins)
5667 max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
5670 /* load arguments allocated to register from the stack */
5671 sig = mono_method_signature (method);
5674 cinfo = get_call_info (cfg, cfg->mempool, sig);
5676 if (cinfo->struct_ret) {
5677 ArgInfo *ainfo = &cinfo->ret;
5678 inst = cfg->vret_addr;
5679 inst->backend.size = ainfo->vtsize;
5680 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5683 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5684 ArgInfo *ainfo = cinfo->args + i;
5685 inst = cfg->args [pos];
5687 if (inst->opcode == OP_VTARG_ADDR)
5688 inst = inst->inst_left;
5690 if (inst->opcode == OP_REGVAR) {
5691 if (ainfo->regtype == RegTypeGeneral)
5692 s390_lgr (code, inst->dreg, ainfo->reg);
5693 else if (ainfo->regtype == RegTypeFP) {
5694 if (inst->dreg != ainfo->reg) {
5695 if (ainfo->size == 4) {
5696 s390_ledbr (code, inst->dreg, ainfo->reg);
5698 s390_ldr (code, inst->dreg, ainfo->reg);
5702 else if (ainfo->regtype == RegTypeBase) {
5703 s390_lgr (code, s390_r13, STK_BASE);
5704 s390_aghi (code, s390_r13, alloc_size);
5705 s390_lg (code, inst->dreg, 0, s390_r13, ainfo->offset);
5707 g_assert_not_reached ();
5709 if (cfg->verbose_level > 2)
5710 g_print ("Argument %d assigned to register %s\n",
5711 pos, mono_arch_regname (inst->dreg));
5713 if (ainfo->regtype == RegTypeGeneral) {
5714 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5715 g_assert_not_reached();
5716 switch (ainfo->size) {
5718 s390_stc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5721 s390_sth (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5724 s390_st (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5727 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5730 } else if (ainfo->regtype == RegTypeBase) {
5731 } else if (ainfo->regtype == RegTypeFP) {
5732 if (ainfo->size == 8)
5733 s390_std (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5734 else if (ainfo->size == 4)
5735 s390_ste (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5737 g_assert_not_reached ();
5738 } else if (ainfo->regtype == RegTypeStructByVal) {
5739 int doffset = inst->inst_offset;
5741 if (ainfo->reg != STK_BASE)
5745 s390_lgr (code, s390_r13, STK_BASE);
5746 s390_aghi (code, s390_r13, alloc_size);
5749 size = (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE
5750 ? mono_class_native_size(mono_class_from_mono_type(inst->inst_vtype), NULL)
5755 if (ainfo->reg == STK_BASE)
5756 s390_ic (code, reg, 0, s390_r13, ainfo->offset+7);
5757 s390_stc (code, reg, 0, inst->inst_basereg, doffset);
5760 if (ainfo->reg == STK_BASE)
5761 s390_lh (code, reg, 0, s390_r13, ainfo->offset+6);
5762 s390_sth (code, reg, 0, inst->inst_basereg, doffset);
5765 if (ainfo->reg == STK_BASE)
5766 s390_l (code, reg, 0, s390_r13, ainfo->offset+4);
5767 s390_st (code, reg, 0, inst->inst_basereg, doffset);
5770 if (ainfo->reg == STK_BASE)
5771 s390_lg (code, reg, 0, s390_r13, ainfo->offset);
5772 s390_stg (code, reg, 0, inst->inst_basereg, doffset);
5775 } else if (ainfo->regtype == RegTypeStructByAddr) {
5776 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5777 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
5779 g_assert_not_reached ();
5784 if (method->save_lmf) {
5785 /*---------------------------------------------------------------*/
5786 /* build the MonoLMF structure on the stack - see mini-s390x.h */
5787 /*---------------------------------------------------------------*/
5788 lmfOffset = alloc_size - sizeof(MonoLMF);
5790 s390_lgr (code, s390_r13, cfg->frame_reg);
5791 s390_aghi (code, s390_r13, lmfOffset);
5793 /*---------------------------------------------------------------*/
5794 /* Preserve the parameter registers while we fix up the lmf */
5795 /*---------------------------------------------------------------*/
5796 s390_stmg (code, s390_r2, s390_r6, s390_r13,
5797 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
5799 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[0]), SLOT_NOREF);
5800 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[1]), SLOT_NOREF);
5801 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[2]), SLOT_NOREF);
5802 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[3]), SLOT_NOREF);
5803 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[4]), SLOT_NOREF);
5805 /*---------------------------------------------------------------*/
5806 /* On return from this call r2 have the address of the &lmf */
5807 /*---------------------------------------------------------------*/
5808 mono_add_patch_info (cfg, code - cfg->native_code,
5809 MONO_PATCH_INFO_INTERNAL_METHOD,
5810 (gpointer)"mono_tls_get_lmf_addr");
5811 S390_CALL_TEMPLATE(code, s390_r1);
5813 /*---------------------------------------------------------------*/
5814 /* Set lmf.lmf_addr = jit_tls->lmf */
5815 /*---------------------------------------------------------------*/
5816 s390_stg (code, s390_r2, 0, s390_r13,
5817 G_STRUCT_OFFSET(MonoLMF, lmf_addr));
5818 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, lmf_addr), SLOT_NOREF);
5820 /*---------------------------------------------------------------*/
5821 /* Get current lmf */
5822 /*---------------------------------------------------------------*/
5823 s390_lg (code, s390_r0, 0, s390_r2, 0);
5825 /*---------------------------------------------------------------*/
5826 /* Set our lmf as the current lmf */
5827 /*---------------------------------------------------------------*/
5828 s390_stg (code, s390_r13, 0, s390_r2, 0);
5830 /*---------------------------------------------------------------*/
5831 /* Have our lmf.previous_lmf point to the last lmf */
5832 /*---------------------------------------------------------------*/
5833 s390_stg (code, s390_r0, 0, s390_r13,
5834 G_STRUCT_OFFSET(MonoLMF, previous_lmf));
5835 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), SLOT_NOREF);
5837 /*---------------------------------------------------------------*/
5838 /* save method info */
5839 /*---------------------------------------------------------------*/
5840 S390_SET (code, s390_r1, method);
5841 s390_stg (code, s390_r1, 0, s390_r13,
5842 G_STRUCT_OFFSET(MonoLMF, method));
5843 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, method), SLOT_NOREF);
5845 /*---------------------------------------------------------------*/
5846 /* save the current IP */
5847 /*---------------------------------------------------------------*/
5848 s390_stg (code, STK_BASE, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp));
5849 s390_basr (code, s390_r1, 0);
5850 s390_stg (code, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip));
5851 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, ebp), SLOT_NOREF);
5852 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, eip), SLOT_NOREF);
5854 /*---------------------------------------------------------------*/
5855 /* Save general and floating point registers */
5856 /*---------------------------------------------------------------*/
5857 s390_stmg (code, s390_r2, s390_r12, s390_r13,
5858 G_STRUCT_OFFSET(MonoLMF, gregs[2]));
5859 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[0]), SLOT_NOREF);
5860 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[1]), SLOT_NOREF);
5861 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[2]), SLOT_NOREF);
5862 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[3]), SLOT_NOREF);
5863 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[4]), SLOT_NOREF);
5864 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[5]), SLOT_NOREF);
5865 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[6]), SLOT_NOREF);
5866 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[7]), SLOT_NOREF);
5867 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[8]), SLOT_NOREF);
5868 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[9]), SLOT_NOREF);
5869 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[10]), SLOT_NOREF);
5871 fpOffset = lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, fregs[0]);
5872 for (i = 0; i < 16; i++) {
5873 s390_std (code, i, 0, s390_r13,
5874 G_STRUCT_OFFSET(MonoLMF, fregs[i]));
5875 mini_gc_set_slot_type_from_fp (cfg, fpOffset, SLOT_NOREF);
5876 fpOffset += sizeof(double);
5879 /*---------------------------------------------------------------*/
5880 /* Restore the parameter registers now that we've set up the lmf */
5881 /*---------------------------------------------------------------*/
5882 s390_lmg (code, s390_r2, s390_r6, s390_r13,
5883 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
5886 if (cfg->method->save_lmf)
5887 argsClobbered = TRUE;
5890 argsClobbered = TRUE;
5891 code = mono_arch_instrument_prolog (cfg, enter_method, code, TRUE);
5895 * Optimize the common case of the first bblock making a call with the same
5896 * arguments as the method. This works because the arguments are still in their
5897 * original argument registers.
5899 if (!argsClobbered) {
5900 MonoBasicBlock *first_bb = cfg->bb_entry;
5902 int filter = FILTER_IL_SEQ_POINT;
5904 next = mono_bb_first_inst (first_bb, filter);
5905 if (!next && first_bb->next_bb) {
5906 first_bb = first_bb->next_bb;
5907 next = mono_bb_first_inst (first_bb, filter);
5910 if (first_bb->in_count > 1)
5913 for (i = 0; next && i < sig->param_count + sig->hasthis; ++i) {
5914 ArgInfo *ainfo = cinfo->args + i;
5915 gboolean match = FALSE;
5917 inst = cfg->args [i];
5918 if (inst->opcode != OP_REGVAR) {
5919 switch (ainfo->regtype) {
5920 case RegTypeGeneral: {
5921 if (((next->opcode == OP_LOAD_MEMBASE) ||
5922 (next->opcode == OP_LOADI4_MEMBASE)) &&
5923 next->inst_basereg == inst->inst_basereg &&
5924 next->inst_offset == inst->inst_offset) {
5925 if (next->dreg == ainfo->reg) {
5929 next->opcode = OP_MOVE;
5930 next->sreg1 = ainfo->reg;
5931 /* Only continue if the instruction doesn't change argument regs */
5932 if (next->dreg == ainfo->reg)
5942 /* Argument allocated to (non-volatile) register */
5943 switch (ainfo->regtype) {
5944 case RegTypeGeneral:
5945 if (next->opcode == OP_MOVE &&
5946 next->sreg1 == inst->dreg &&
5947 next->dreg == ainfo->reg) {
5958 next = mono_inst_next (next, filter);
5965 cfg->code_len = code - cfg->native_code;
5966 g_assert (cfg->code_len < cfg->code_size);
5971 /*========================= End of Function ========================*/
5973 /*------------------------------------------------------------------*/
5975 /* Name - mono_arch_emit_epilog */
5977 /* Function - Emit the instructions for a function epilog. */
5979 /*------------------------------------------------------------------*/
5982 mono_arch_emit_epilog (MonoCompile *cfg)
5984 MonoMethod *method = cfg->method;
5987 int max_epilog_size = 96;
5989 if (cfg->method->save_lmf)
5990 max_epilog_size += 128;
5992 if (mono_jit_trace_calls != NULL)
5993 max_epilog_size += 128;
5995 while ((cfg->code_len + max_epilog_size) > (cfg->code_size - 16)) {
5996 cfg->code_size *= 2;
5997 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
5998 cfg->stat_code_reallocs++;
6001 code = cfg->native_code + cfg->code_len;
6003 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
6004 code = mono_arch_instrument_epilog (cfg, leave_method, code, TRUE);
6008 if (method->save_lmf)
6009 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
6011 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
6012 s390_lg (code, STK_BASE, 0, STK_BASE, 0);
6014 code = backUpStackPtr(cfg, code);
6016 s390_lmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
6017 s390_br (code, s390_r14);
6019 cfg->code_len = code - cfg->native_code;
6021 g_assert (cfg->code_len < cfg->code_size);
6025 /*========================= End of Function ========================*/
6027 /*------------------------------------------------------------------*/
6029 /* Name - mono_arch_emit_exceptions */
6031 /* Function - Emit the blocks to handle exception conditions. */
6033 /*------------------------------------------------------------------*/
6036 mono_arch_emit_exceptions (MonoCompile *cfg)
6038 MonoJumpInfo *patch_info;
6044 MonoClass *exc_classes [MAX_EXC];
6045 guint8 *exc_throw_start [MAX_EXC];
6047 for (patch_info = cfg->patch_info;
6049 patch_info = patch_info->next) {
6050 if (patch_info->type == MONO_PATCH_INFO_EXC)
6054 code_size = exc_count * 48;
6056 while ((cfg->code_len + code_size) > (cfg->code_size - 16)) {
6057 cfg->code_size *= 2;
6058 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6059 cfg->stat_code_reallocs++;
6062 code = cfg->native_code + cfg->code_len;
6064 /*---------------------------------------------------------------------*/
6065 /* Add code to raise exceptions */
6066 /*---------------------------------------------------------------------*/
6067 for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
6068 switch (patch_info->type) {
6069 case MONO_PATCH_INFO_EXC: {
6070 guint8 *ip = patch_info->ip.i + cfg->native_code;
6071 MonoClass *exc_class;
6074 /*-----------------------------------------------------*/
6075 /* Patch the branch in epilog to come here */
6076 /*-----------------------------------------------------*/
6077 s390_patch_rel (ip + 2, (guint64) S390_RELATIVE(code,ip));
6079 exc_class = mono_class_load_from_name (mono_defaults.corlib,
6081 patch_info->data.name);
6082 throw_ip = patch_info->ip.i;
6084 for (iExc = 0; iExc < nThrows; ++iExc)
6085 if (exc_classes [iExc] == exc_class)
6088 if (iExc < nThrows) {
6089 s390_jcl (code, S390_CC_UN,
6090 (guint64) exc_throw_start [iExc]);
6091 patch_info->type = MONO_PATCH_INFO_NONE;
6094 if (nThrows < MAX_EXC) {
6095 exc_classes [nThrows] = exc_class;
6096 exc_throw_start [nThrows] = code;
6099 /*---------------------------------------------*/
6100 /* Patch the parameter passed to the handler */
6101 /*---------------------------------------------*/
6102 S390_SET (code, s390_r2, exc_class->type_token);
6103 /*---------------------------------------------*/
6104 /* Load return address & parameter register */
6105 /*---------------------------------------------*/
6106 s390_larl (code, s390_r14, (guint64)S390_RELATIVE((patch_info->ip.i +
6107 cfg->native_code + 8), code));
6108 /*---------------------------------------------*/
6109 /* Reuse the current patch to set the jump */
6110 /*---------------------------------------------*/
6111 patch_info->type = MONO_PATCH_INFO_INTERNAL_METHOD;
6112 patch_info->data.name = "mono_arch_throw_corlib_exception";
6113 patch_info->ip.i = code - cfg->native_code;
6114 S390_BR_TEMPLATE (code, s390_r1);
6124 cfg->code_len = code - cfg->native_code;
6126 g_assert (cfg->code_len < cfg->code_size);
6130 /*========================= End of Function ========================*/
6132 /*------------------------------------------------------------------*/
6134 /* Name - mono_arch_finish_init */
6136 /* Function - Setup the JIT's Thread Level Specific Data. */
6138 /*------------------------------------------------------------------*/
6141 mono_arch_finish_init (void)
6145 /*========================= End of Function ========================*/
6147 /*------------------------------------------------------------------*/
6149 /* Name - mono_arch_free_jit_tls_data */
6151 /* Function - Free tls data. */
6153 /*------------------------------------------------------------------*/
6156 mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
6160 /*========================= End of Function ========================*/
6162 /*------------------------------------------------------------------*/
6164 /* Name - mono_arch_emit_inst_for_method */
6166 /*------------------------------------------------------------------*/
6169 mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
6174 /*========================= End of Function ========================*/
6176 /*------------------------------------------------------------------*/
6178 /* Name - mono_arch_decompose_opts */
6180 /* Function - Decompose opcode into a System z opcode. */
6182 /*------------------------------------------------------------------*/
6185 mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
6188 * Have to rename these to avoid being decomposed normally, since the normal
6189 * decomposition does not work on S390.
6191 switch (ins->opcode) {
6193 ins->opcode = OP_S390_ISUB_OVF;
6195 case OP_ISUB_OVF_UN:
6196 ins->opcode = OP_S390_ISUB_OVF_UN;
6199 ins->opcode = OP_S390_IADD_OVF;
6201 case OP_IADD_OVF_UN:
6202 ins->opcode = OP_S390_IADD_OVF_UN;
6205 ins->opcode = OP_S390_LADD_OVF;
6207 case OP_LADD_OVF_UN:
6208 ins->opcode = OP_S390_LADD_OVF_UN;
6211 ins->opcode = OP_S390_LSUB_OVF;
6213 case OP_LSUB_OVF_UN:
6214 ins->opcode = OP_S390_LSUB_OVF_UN;
6221 /*========================= End of Function ========================*/
6223 /*------------------------------------------------------------------*/
6225 /* Name - mono_arch_print_tree */
6227 /* Function - Print platform-specific opcode details. */
6229 /* Returns - 1 - opcode details have been printed */
6230 /* 0 - opcode details have not been printed */
6232 /*------------------------------------------------------------------*/
6235 mono_arch_print_tree (MonoInst *tree, int arity)
6239 switch (tree->opcode) {
6240 case OP_S390_LOADARG:
6241 case OP_S390_ARGREG:
6242 case OP_S390_ARGPTR:
6243 printf ("[0x%lx(%s)]", tree->inst_offset,
6244 mono_arch_regname (tree->inst_basereg));
6247 case OP_S390_STKARG:
6248 printf ("[0x%lx(previous_frame)]",
6253 printf ("[0x%lx(%d,%s),0x%lx(%s)]",
6254 tree->inst_offset, tree->backend.size,
6255 mono_arch_regname(tree->dreg),
6257 mono_arch_regname(tree->sreg1));
6260 case OP_S390_SETF4RET:
6261 printf ("[f%s,f%s]",
6262 mono_arch_regname (tree->dreg),
6263 mono_arch_regname (tree->sreg1));
6267 printf ("[0x%lx(0x%lx,%s)]", tree->inst_offset,
6269 mono_arch_regname (tree->sreg1));
6273 printf ("[0x%lx(0x%lx,%s)]", tree->inst_offset,
6275 mono_arch_regname (tree->sreg1));
6278 case OP_S390_BKCHAIN:
6279 printf ("[previous_frame(%s)]",
6280 mono_arch_regname (tree->sreg1));
6288 /*========================= End of Function ========================*/
6290 /*------------------------------------------------------------------*/
6292 /* Name - mono_arch_regalloc_cost */
6294 /* Function - Determine the cost, in the number of memory */
6295 /* references, of the action of allocating the var- */
6296 /* iable VMV into a register during global register */
6299 /* Returns - Cost */
6301 /*------------------------------------------------------------------*/
6304 mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
6310 /*========================= End of Function ========================*/
6312 /*------------------------------------------------------------------*/
6314 /* Name - mono_arch_flush_register_windows */
6320 /*------------------------------------------------------------------*/
6323 mono_arch_flush_register_windows (void)
6327 /*========================= End of Function ========================*/
6329 /*------------------------------------------------------------------*/
6331 /* Name - mono_arch_is_inst_imm */
6333 /* Function - Determine if operand qualifies as an immediate */
6334 /* value. For s390 this is a value -32768-32768 */
6336 /* Returns - True|False - is [not] immediate value. */
6338 /*------------------------------------------------------------------*/
6341 mono_arch_is_inst_imm (gint64 imm)
6343 return s390_is_imm32 (imm);
6346 /*========================= End of Function ========================*/
6348 /*------------------------------------------------------------------*/
6350 /* Name - mono_arch_get_patch_offset */
6352 /* Function - Dummy entry point until s390x supports aot. */
6354 /* Returns - Offset for patch. */
6356 /*------------------------------------------------------------------*/
6359 mono_arch_get_patch_offset (guint8 *code)
6364 /*========================= End of Function ========================*/
6366 /*------------------------------------------------------------------*/
6368 /* Name - mono_arch_context_get_int_reg. */
6372 /* Returns - Return a register from the context. */
6374 /*------------------------------------------------------------------*/
6377 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
6379 return ((mgreg_t) ctx->uc_mcontext.gregs[reg]);
6382 /*========================= End of Function ========================*/
6384 /*------------------------------------------------------------------*/
6386 /* Name - mono_arch_context_set_int_reg. */
6388 /* Function - Set a value in a specified register. */
6390 /*------------------------------------------------------------------*/
6393 mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val)
6395 ctx->uc_mcontext.gregs[reg] = val;
6398 /*========================= End of Function ========================*/
6400 /*------------------------------------------------------------------*/
6402 /* Name - mono_arch_get_this_arg_from_call. */
6406 /*------------------------------------------------------------------*/
6409 mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
6411 return (gpointer) regs [s390_r2];
6414 /*========================= End of Function ========================*/
6416 /*------------------------------------------------------------------*/
6418 /* Name - mono_arch_install_handler_block_guard */
6422 /*------------------------------------------------------------------*/
6425 mono_arch_install_handler_block_guard (MonoJitInfo *ji, MonoJitExceptionInfo *clause,
6426 MonoContext *ctx, gpointer new_value)
6429 gpointer *sp, old_value;
6432 offset = clause->exvar_offset;
6435 bp = MONO_CONTEXT_GET_BP (ctx);
6436 sp = *(gpointer*)(bp + offset);
6439 if (old_value < ji->code_start || (char*)old_value > ((char*)ji->code_start + ji->code_size))
6447 /*========================= End of Function ========================*/
6449 /*------------------------------------------------------------------*/
6451 /* Name - get_delegate_invoke_impl. */
6455 /*------------------------------------------------------------------*/
6458 get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 param_count, gboolean aot)
6460 guint8 *code, *start;
6465 start = code = mono_global_codeman_reserve (size);
6467 /* Replace the this argument with the target */
6468 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6469 s390_lg (code, s390_r2, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, target));
6470 s390_br (code, s390_r1);
6471 g_assert ((code - start) <= size);
6473 mono_arch_flush_icache (start, size);
6477 size = 32 + param_count * 8;
6478 start = code = mono_global_codeman_reserve (size);
6480 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6481 /* slide down the arguments */
6482 for (i = 0; i < param_count; ++i) {
6483 s390_lgr (code, (s390_r2 + i), (s390_r2 + i + 1));
6485 s390_br (code, s390_r1);
6487 g_assert ((code - start) <= size);
6489 mono_arch_flush_icache (start, size);
6492 MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL));
6495 *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
6497 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
6498 *info = mono_tramp_info_create (name, start, code - start, NULL, NULL);
6505 /*========================= End of Function ========================*/
6507 /*------------------------------------------------------------------*/
6509 /* Name - mono_arch_get_delegate_invoke_impls. */
6513 /*------------------------------------------------------------------*/
6516 mono_arch_get_delegate_invoke_impls (void)
6519 MonoTrampInfo *info;
6522 get_delegate_invoke_impl (&info, TRUE, 0, TRUE);
6523 res = g_slist_prepend (res, info);
6525 for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
6526 get_delegate_invoke_impl (&info, FALSE, i, TRUE);
6527 res = g_slist_prepend (res, info);
6533 /*========================= End of Function ========================*/
6535 /*------------------------------------------------------------------*/
6537 /* Name - mono_arch_get_delegate_invoke_impl. */
6541 /*------------------------------------------------------------------*/
6544 mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target)
6546 guint8 *code, *start;
6548 /* FIXME: Support more cases */
6549 if (MONO_TYPE_ISSTRUCT (sig->ret))
6553 static guint8* cached = NULL;
6558 if (mono_aot_only) {
6559 start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
6561 MonoTrampInfo *info;
6562 start = get_delegate_invoke_impl (&info, TRUE, 0, FALSE);
6563 mono_tramp_info_register (info, NULL);
6566 mono_memory_barrier ();
6570 static guint8* cache [MAX_ARCH_DELEGATE_PARAMS + 1] = {NULL};
6573 if (sig->param_count > MAX_ARCH_DELEGATE_PARAMS)
6575 for (i = 0; i < sig->param_count; ++i)
6576 if (!mono_is_regsize_var (sig->params [i]))
6580 code = cache [sig->param_count];
6584 if (mono_aot_only) {
6585 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", sig->param_count);
6586 start = mono_aot_get_trampoline (name);
6589 MonoTrampInfo *info;
6590 start = get_delegate_invoke_impl (&info, FALSE, sig->param_count, FALSE);
6591 mono_tramp_info_register (info, NULL);
6594 mono_memory_barrier ();
6596 cache [sig->param_count] = start;
6601 /*========================= End of Function ========================*/
6603 /*------------------------------------------------------------------*/
6605 /* Name - mono_arch_get_delegate_virtual_invoke_impl. */
6609 /*------------------------------------------------------------------*/
6612 mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method,
6613 int offset, gboolean load_imt_reg)
6615 guint8 *code, *start;
6618 start = code = mono_global_codeman_reserve (size);
6621 * Replace the "this" argument with the target
6623 s390_lgr (code, s390_r1, s390_r2);
6624 s390_lg (code, s390_r2, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, target));
6627 * Load the IMT register, if needed
6630 s390_lg (code, MONO_ARCH_IMT_REG, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, method));
6636 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET(MonoObject, vtable));
6638 s390_agfi(code, s390_r1, offset);
6640 s390_lg (code, s390_r1, 0, s390_r1, 0);
6641 s390_br (code, s390_r1);
6646 /*========================= End of Function ========================*/
6648 /*------------------------------------------------------------------*/
6650 /* Name - mono_arch_build_imt_trampoline. */
6654 /*------------------------------------------------------------------*/
6657 mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain,
6658 MonoIMTCheckItem **imt_entries, int count,
6659 gpointer fail_tramp)
6663 guchar *code, *start;
6666 for (i = 0; i < count; ++i) {
6667 MonoIMTCheckItem *item = imt_entries [i];
6668 if (item->is_equals) {
6669 if (item->check_target_idx) {
6670 if (!item->compare_done)
6671 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6672 if (item->has_target_code)
6673 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE;
6675 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE +
6679 item->chunk_size += CMP_SIZE + 2 * BR_SIZE + JUMP_SIZE +
6681 if (!item->has_target_code)
6682 item->chunk_size += LOAD_SIZE;
6684 item->chunk_size += LOADCON_SIZE + LOAD_SIZE + BR_SIZE;
6685 #if ENABLE_WRONG_METHOD_CHECK
6686 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6691 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6692 imt_entries [item->check_target_idx]->compare_done = TRUE;
6694 size += item->chunk_size;
6698 code = mono_method_alloc_generic_virtual_trampoline (domain, size);
6700 code = mono_domain_code_reserve (domain, size);
6704 for (i = 0; i < count; ++i) {
6705 MonoIMTCheckItem *item = imt_entries [i];
6706 item->code_target = (guint8 *) code;
6707 if (item->is_equals) {
6708 if (item->check_target_idx) {
6709 if (!item->compare_done) {
6710 S390_SET (code, s390_r0, item->key);
6711 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
6713 item->jmp_code = (guint8*) code;
6714 s390_jcl (code, S390_CC_NE, 0);
6716 if (item->has_target_code) {
6717 S390_SET (code, s390_r1, item->value.target_code);
6719 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6720 s390_lg (code, s390_r1, 0, s390_r1, 0);
6722 s390_br (code, s390_r1);
6727 S390_SET (code, s390_r0, item->key);
6728 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
6729 item->jmp_code = (guint8*) code;
6730 s390_jcl (code, S390_CC_NE, 0);
6731 if (item->has_target_code) {
6732 S390_SET (code, s390_r1, item->value.target_code);
6735 S390_SET (code, s390_r1,
6736 (&(vtable->vtable [item->value.vtable_slot])));
6737 s390_lg (code, s390_r1, 0, s390_r1, 0);
6739 s390_br (code, s390_r1);
6740 target = (gint64) S390_RELATIVE(code, item->jmp_code);
6741 s390_patch_rel(item->jmp_code+2, target);
6742 S390_SET (code, s390_r1, fail_tramp);
6743 s390_br (code, s390_r1);
6744 item->jmp_code = NULL;
6746 /* enable the commented code to assert on wrong method */
6747 #if ENABLE_WRONG_METHOD_CHECK
6748 g_assert_not_reached ();
6750 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6751 s390_lg (code, s390_r1, 0, s390_r1, 0);
6752 s390_br (code, s390_r1);
6756 S390_SET (code, s390_r0, item->key);
6757 s390_cgr (code, MONO_ARCH_IMT_REG, s390_r0);
6758 item->jmp_code = (guint8 *) code;
6759 s390_jcl (code, S390_CC_GE, 0);
6763 * patch the branches to get to the target items
6765 for (i = 0; i < count; ++i) {
6766 MonoIMTCheckItem *item = imt_entries [i];
6767 if (item->jmp_code) {
6768 if (item->check_target_idx) {
6770 offset = (gint64) S390_RELATIVE(imt_entries [item->check_target_idx]->code_target,
6772 s390_patch_rel ((guchar *) item->jmp_code + 2, (guint64) offset);
6777 mono_arch_flush_icache ((guint8*)start, (code - start));
6778 MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL));
6781 mono_stats.imt_trampolines_size += (code - start);
6783 g_assert (code - start <= size);
6785 snprintf(trampName, sizeof(trampName), "%d_imt_trampoline", domain->domain_id);
6786 mono_tramp_info_register (mono_tramp_info_create (trampName, start, code - start, NULL, NULL), domain);
6791 /*========================= End of Function ========================*/
6793 /*------------------------------------------------------------------*/
6795 /* Name - mono_arch_find_imt_method. */
6797 /* Function - Get the method address from MONO_ARCH_IMT_REG */
6798 /* found in the save area. */
6800 /*------------------------------------------------------------------*/
6803 mono_arch_find_imt_method (mgreg_t *regs, guint8 *code)
6805 return ((MonoMethod *) regs [MONO_ARCH_IMT_REG]);
6808 /*========================= End of Function ========================*/
6810 /*------------------------------------------------------------------*/
6812 /* Name - mono_arch_find_static_call_vtable */
6814 /* Function - Find the static call vtable. */
6816 /*------------------------------------------------------------------*/
6819 mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
6821 mgreg_t *r = (mgreg_t*)regs;
6823 return (MonoVTable*)(gsize) r [MONO_ARCH_RGCTX_REG];
6826 /*========================= End of Function ========================*/
6828 /*------------------------------------------------------------------*/
6830 /* Name - mono_arch_get_cie_program */
6832 /* Function - Find the static call vtable. */
6834 /*------------------------------------------------------------------*/
6837 mono_arch_get_cie_program (void)
6841 mono_add_unwind_op_def_cfa (l, 0, 0, STK_BASE, 0);
6846 /*========================= End of Function ========================*/
6848 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
6850 /*------------------------------------------------------------------*/
6852 /* Name - mono_arch_set_breakpoint. */
6854 /* Function - Set a breakpoint at the native code corresponding */
6855 /* to JI at NATIVE_OFFSET. The location should */
6856 /* contain code emitted by OP_SEQ_POINT. */
6858 /*------------------------------------------------------------------*/
6861 mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
6865 breakpointCode.pTrigger = bp_trigger_page;
6866 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
6867 code += BREAKPOINT_SIZE;
6870 /*========================= End of Function ========================*/
6872 /*------------------------------------------------------------------*/
6874 /* Name - mono_arch_clear_breakpoint. */
6876 /* Function - Clear the breakpoint at IP. */
6878 /*------------------------------------------------------------------*/
6881 mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
6886 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); i++)
6890 /*========================= End of Function ========================*/
6892 /*------------------------------------------------------------------*/
6894 /* Name - mono_arch_is_breakpoint_event. */
6898 /*------------------------------------------------------------------*/
6901 mono_arch_is_breakpoint_event (void *info, void *sigctx)
6903 siginfo_t* sinfo = (siginfo_t*) info;
6906 * Sometimes the address is off by 4
6908 if (sinfo->si_addr >= bp_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)bp_trigger_page + 128)
6914 /*========================= End of Function ========================*/
6916 /*------------------------------------------------------------------*/
6918 /* Name - mono_arch_skip_breakpoint. */
6920 /* Function - Modify the CTX so the IP is placed after the */
6921 /* breakpoint instruction, so when we resume, the */
6922 /* instruction is not executed again. */
6924 /*------------------------------------------------------------------*/
6927 mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
6929 MONO_CONTEXT_SET_IP (ctx, ((guint8*)MONO_CONTEXT_GET_IP (ctx) + sizeof(RXY_Format)));
6932 /*========================= End of Function ========================*/
6934 /*------------------------------------------------------------------*/
6936 /* Name - mono_arch_start_single_stepping. */
6938 /* Function - Start single stepping. */
6940 /*------------------------------------------------------------------*/
6943 mono_arch_start_single_stepping (void)
6945 mono_mprotect (ss_trigger_page, mono_pagesize (), 0);
6948 /*========================= End of Function ========================*/
6950 /*------------------------------------------------------------------*/
6952 /* Name - mono_arch_stop_single_stepping. */
6954 /* Function - Stop single stepping. */
6956 /*------------------------------------------------------------------*/
6959 mono_arch_stop_single_stepping (void)
6961 mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ);
6964 /*========================= End of Function ========================*/
6966 /*------------------------------------------------------------------*/
6968 /* Name - mono_arch_is_single_step_event. */
6970 /* Function - Return whether the machine state in sigctx cor- */
6971 /* responds to a single step event. */
6973 /*------------------------------------------------------------------*/
6976 mono_arch_is_single_step_event (void *info, void *sigctx)
6978 siginfo_t* sinfo = (siginfo_t*) info;
6981 * Sometimes the address is off by 4
6983 if (sinfo->si_addr >= ss_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)ss_trigger_page + 128)
6989 /*========================= End of Function ========================*/
6991 /*------------------------------------------------------------------*/
6993 /* Name - mono_arch_skip_single_step. */
6995 /* Function - Modify the ctx so the IP is placed after the */
6996 /* single step trigger instruction, so that the */
6997 /* instruction is not executed again. */
6999 /*------------------------------------------------------------------*/
7002 mono_arch_skip_single_step (MonoContext *ctx)
7004 MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + BREAKPOINT_SIZE);
7007 /*========================= End of Function ========================*/
7009 /*------------------------------------------------------------------*/
7011 /* Name - mono_arch_create_seq_point_info. */
7013 /* Function - Return a pointer to a data struction which is */
7014 /* used by the sequence point implementation in */
7017 /*------------------------------------------------------------------*/
7020 mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code)
7026 /*========================= End of Function ========================*/
7028 /*------------------------------------------------------------------*/
7030 /* Name - mono_arch_init_lmf_ext. */
7034 /*------------------------------------------------------------------*/
7037 mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
7039 ext->lmf.previous_lmf = prev_lmf;
7040 /* Mark that this is a MonoLMFExt */
7041 ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
7042 ext->lmf.ebp = (gssize)ext;
7045 /*========================= End of Function ========================*/
7049 /*------------------------------------------------------------------*/
7051 /* Name - mono_arch_cpu_enumerate_simd_versions. */
7053 /* Function - If this CPU supports vector operations then it */
7054 /* supports the equivalent of SSE1-4. */
7056 /*------------------------------------------------------------------*/
7059 mono_arch_cpu_enumerate_simd_versions (void)
7061 guint32 sseOpts = 0;
7063 if (mono_hwcap_s390x_has_vec)
7064 sseOpts = (SIMD_VERSION_SSE1 | SIMD_VERSION_SSE2 |
7065 SIMD_VERSION_SSE3 | SIMD_VERSION_SSSE3 |
7066 SIMD_VERSION_SSE41 | SIMD_VERSION_SSE42 |
7067 SIMD_VERSION_SSE4a);
7072 /*========================= End of Function ========================*/
7074 /*------------------------------------------------------------------*/
7076 /* Name - mono_arch_opcode_supported. */
7078 /* Function - Check if a given return code is supported. */
7080 /*------------------------------------------------------------------*/
7083 mono_arch_opcode_supported (int opcode)
7086 case OP_ATOMIC_ADD_I4:
7087 case OP_ATOMIC_ADD_I8:
7088 case OP_ATOMIC_EXCHANGE_I4:
7089 case OP_ATOMIC_EXCHANGE_I8:
7096 /*========================= End of Function ========================*/