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 || (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE))
2187 offset += S390_TRACE_STACK_SIZE;
2189 /*------------------------------------------------------*/
2190 /* Reserve space to save LMF and caller saved registers */
2191 /*------------------------------------------------------*/
2192 if (cfg->method->save_lmf)
2193 offset += sizeof (MonoLMF);
2195 /*------------------------------------------------------*/
2196 /* align the offset */
2197 /*------------------------------------------------------*/
2198 cfg->stack_offset = S390_ALIGN(offset, S390_STACK_ALIGNMENT);
2200 /*------------------------------------------------------*/
2201 /* Fix offsets for args whose value is in parent frame */
2202 /*------------------------------------------------------*/
2203 for (iParm = sArg; iParm < eArg; ++iParm) {
2204 inst = cfg->args [iParm];
2206 if (inst->opcode == OP_S390_STKARG) {
2207 inst->opcode = OP_REGOFFSET;
2208 inst->inst_offset += cfg->stack_offset;
2213 /*========================= End of Function ========================*/
2215 /*------------------------------------------------------------------*/
2217 /* Name - mono_arch_create_vars */
2219 /*------------------------------------------------------------------*/
2222 mono_arch_create_vars (MonoCompile *cfg)
2224 MonoMethodSignature *sig;
2227 sig = mono_method_signature (cfg->method);
2229 cinfo = get_call_info (cfg, cfg->mempool, sig);
2231 if (cinfo->struct_ret) {
2232 cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG);
2233 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2234 printf ("vret_addr = ");
2235 mono_print_ins (cfg->vret_addr);
2240 /*========================= End of Function ========================*/
2242 /*------------------------------------------------------------------*/
2244 /* Name - add_outarg_reg2. */
2246 /*------------------------------------------------------------------*/
2249 add_outarg_reg2 (MonoCompile *cfg, MonoCallInst *call, ArgStorage storage, int reg, MonoInst *tree)
2254 case RegTypeGeneral:
2255 MONO_INST_NEW (cfg, ins, OP_MOVE);
2256 ins->dreg = mono_alloc_ireg (cfg);
2257 ins->sreg1 = tree->dreg;
2258 MONO_ADD_INS (cfg->cbb, ins);
2259 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, FALSE);
2262 MONO_INST_NEW (cfg, ins, OP_FMOVE);
2263 ins->dreg = mono_alloc_freg (cfg);
2264 ins->sreg1 = tree->dreg;
2265 MONO_ADD_INS (cfg->cbb, ins);
2266 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2269 MONO_INST_NEW (cfg, ins, OP_S390_SETF4RET);
2270 ins->dreg = mono_alloc_freg (cfg);
2271 ins->sreg1 = tree->dreg;
2272 MONO_ADD_INS (cfg->cbb, ins);
2273 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2276 g_assert_not_reached ();
2280 /*========================= End of Function ========================*/
2282 /*------------------------------------------------------------------*/
2284 /* Name - emit_sig_cookie. */
2286 /*------------------------------------------------------------------*/
2289 emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo)
2291 MonoMethodSignature *tmpSig;
2294 cfg->disable_aot = TRUE;
2296 /*----------------------------------------------------------*/
2297 /* mono_ArgIterator_Setup assumes the signature cookie is */
2298 /* passed first and all the arguments which were before it */
2299 /* passed on the stack after the signature. So compensate */
2300 /* by passing a different signature. */
2301 /*----------------------------------------------------------*/
2302 tmpSig = mono_metadata_signature_dup (call->signature);
2303 tmpSig->param_count -= call->signature->sentinelpos;
2304 tmpSig->sentinelpos = 0;
2305 if (tmpSig->param_count > 0)
2306 memcpy (tmpSig->params,
2307 call->signature->params + call->signature->sentinelpos,
2308 tmpSig->param_count * sizeof(MonoType *));
2310 MONO_INST_NEW (cfg, sig_arg, OP_ICONST);
2311 sig_arg->dreg = mono_alloc_ireg (cfg);
2312 sig_arg->inst_p0 = tmpSig;
2313 MONO_ADD_INS (cfg->cbb, sig_arg);
2315 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, STK_BASE,
2316 cinfo->sigCookie.offset, sig_arg->dreg);
2319 /*========================= End of Function ========================*/
2321 /*------------------------------------------------------------------*/
2323 /* Name - mono_arch_emit_call */
2325 /*------------------------------------------------------------------*/
2328 mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
2331 MonoMethodSignature *sig;
2333 int i, n, lParamArea;
2335 ArgInfo *ainfo = NULL;
2337 MonoMethodHeader *header;
2340 sig = call->signature;
2341 n = sig->param_count + sig->hasthis;
2342 DEBUG (g_print ("Call requires: %d parameters\n",n));
2344 cinfo = get_call_info (cfg, cfg->mempool, sig);
2346 stackSize = cinfo->sz.stack_size + cinfo->sz.local_size +
2347 cinfo->sz.parm_size + cinfo->sz.offset;
2348 call->stack_usage = MAX(stackSize, call->stack_usage);
2349 lParamArea = MAX((call->stack_usage-S390_MINIMAL_STACK_SIZE-cinfo->sz.parm_size), 0);
2350 cfg->param_area = MAX(((signed) cfg->param_area), lParamArea);
2351 cfg->flags |= MONO_CFG_HAS_CALLS;
2353 if (cinfo->struct_ret) {
2354 MONO_INST_NEW (cfg, ins, OP_MOVE);
2355 ins->sreg1 = call->vret_var->dreg;
2356 ins->dreg = mono_alloc_preg (cfg);
2357 MONO_ADD_INS (cfg->cbb, ins);
2358 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, cinfo->ret.reg, FALSE);
2361 header = cfg->header;
2362 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2367 for (i = 0; i < n; ++i) {
2370 ainfo = cinfo->args + i;
2371 if (i >= sig->hasthis)
2372 t = sig->params [i - sig->hasthis];
2374 t = &mono_defaults.int_class->byval_arg;
2375 t = mini_get_underlying_type (t);
2377 in = call->args [i];
2379 if ((sig->call_convention == MONO_CALL_VARARG) &&
2381 (i == sig->sentinelpos)) {
2382 emit_sig_cookie (cfg, call, cinfo);
2385 switch (ainfo->regtype) {
2386 case RegTypeGeneral:
2387 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2390 if (MONO_TYPE_ISSTRUCT (t)) {
2391 /* Valuetype passed in one fp register */
2392 ainfo->regtype = RegTypeStructByValInFP;
2395 if (ainfo->size == 4)
2396 ainfo->regtype = RegTypeFPR4;
2397 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2400 case RegTypeStructByVal:
2401 case RegTypeStructByAddr:
2402 case RegTypeStructByAddrOnStack: {
2406 if (sig->params [i - sig->hasthis]->type == MONO_TYPE_TYPEDBYREF) {
2407 size = sizeof (MonoTypedRef);
2408 align = sizeof (gpointer);
2412 size = mono_type_native_stack_size (&in->klass->byval_arg, &align);
2415 * Other backends use mono_type_stack_size (), but that
2416 * aligns the size to 8, which is larger than the size of
2417 * the source, leading to reads of invalid memory if the
2418 * source is at the end of address space.
2420 size = mono_class_value_size (in->klass, &align);
2423 g_assert (in->klass);
2425 ainfo->offparm += cinfo->sz.offStruct;
2427 MONO_INST_NEW (cfg, ins, OP_OUTARG_VT);
2428 ins->sreg1 = in->dreg;
2429 ins->klass = in->klass;
2430 ins->backend.size = ainfo->size;
2431 ins->inst_p0 = call;
2432 ins->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
2433 memcpy (ins->inst_p1, ainfo, sizeof (ArgInfo));
2435 MONO_ADD_INS (cfg->cbb, ins);
2437 if (ainfo->regtype == RegTypeStructByAddr) {
2439 * We use OP_OUTARG_VT to copy the valuetype to a stack location, then
2440 * use the normal OUTARG opcodes to pass the address of the location to
2443 int treg = mono_alloc_preg (cfg);
2444 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2445 frmReg, ainfo->offparm);
2446 mono_call_inst_add_outarg_reg (cfg, call, treg, ainfo->reg, FALSE);
2447 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
2448 /* The address of the valuetype is passed on the stack */
2449 int treg = mono_alloc_preg (cfg);
2450 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2451 frmReg, ainfo->offparm);
2452 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG,
2453 ainfo->reg, ainfo->offset, treg);
2455 if (cfg->compute_gc_maps) {
2458 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, t);
2464 if (!t->byref && t->type == MONO_TYPE_R4) {
2465 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG,
2466 STK_BASE, ainfo->offset + 4,
2468 } else if (!t->byref && (t->type == MONO_TYPE_R8)) {
2469 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG,
2470 STK_BASE, ainfo->offset,
2473 MONO_INST_NEW (cfg, ins, OP_STORE_MEMBASE_REG);
2474 ins->inst_destbasereg = STK_BASE;
2475 ins->inst_offset = ainfo->offset;
2476 ins->sreg1 = in->dreg;
2479 /* This is needed by MonoTypedRef->value to point to the correct data */
2480 if ((sig->call_convention == MONO_CALL_VARARG) &&
2481 (i >= sig->sentinelpos)) {
2482 switch (ainfo->size) {
2484 ins->opcode = OP_STOREI1_MEMBASE_REG;
2487 ins->opcode = OP_STOREI2_MEMBASE_REG;
2490 ins->opcode = OP_STOREI4_MEMBASE_REG;
2498 MONO_ADD_INS (cfg->cbb, ins);
2502 g_assert_not_reached ();
2508 * Handle the case where there are no implicit arguments
2510 if ((sig->call_convention == MONO_CALL_VARARG) &&
2512 (i == sig->sentinelpos)) {
2513 emit_sig_cookie (cfg, call, cinfo);
2517 /*========================= End of Function ========================*/
2519 /*------------------------------------------------------------------*/
2521 /* Name - mono_arch_emit_outarg_vt */
2523 /*------------------------------------------------------------------*/
2526 mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
2528 MonoCallInst *call = (MonoCallInst*)ins->inst_p0;
2529 ArgInfo *ainfo = (ArgInfo*)ins->inst_p1;
2530 int size = ins->backend.size;
2532 if (ainfo->regtype == RegTypeStructByVal) {
2534 arg->ins.sreg1 = ainfo->reg;
2535 arg->ins.opcode = OP_OUTARG_VT;
2536 arg->size = ainfo->size;
2537 arg->offset = ainfo->offset;
2538 arg->offPrm = ainfo->offparm + cinfo->sz.offStruct;
2540 if (ainfo->reg != STK_BASE) {
2541 MONO_OUTPUT_VTR (cfg, size, ainfo->reg, src->dreg, 0);
2543 MONO_OUTPUT_VTS (cfg, size, ainfo->reg, ainfo->offset,
2546 } else if (ainfo->regtype == RegTypeStructByValInFP) {
2547 int dreg = mono_alloc_freg (cfg);
2549 if (ainfo->size == 4) {
2550 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR4_MEMBASE, dreg, src->dreg, 0);
2551 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, dreg, dreg);
2553 g_assert (ainfo->size == 8);
2555 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR8_MEMBASE, dreg, src->dreg, 0);
2558 mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg, TRUE);
2561 MonoMethodHeader *header;
2564 header = mono_method_get_header_checked (cfg->method, &error);
2565 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
2566 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2571 MONO_EMIT_NEW_MOVE (cfg, srcReg, ainfo->offparm,
2572 src->dreg, 0, size);
2574 if (cfg->compute_gc_maps) {
2577 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, &ins->klass->byval_arg);
2582 /*========================= End of Function ========================*/
2584 /*------------------------------------------------------------------*/
2586 /* Name - mono_arch_emit_setret */
2588 /*------------------------------------------------------------------*/
2591 mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
2593 MonoType *ret = mini_get_underlying_type (mono_method_signature (method)->ret);
2596 if (ret->type == MONO_TYPE_R4) {
2597 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, s390_f0, val->dreg);
2599 } else if (ret->type == MONO_TYPE_R8) {
2600 MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, s390_f0, val->dreg);
2605 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg);
2608 /*========================= End of Function ========================*/
2610 /*------------------------------------------------------------------*/
2612 /* Name - mono_arch_instrument_mem_needs */
2614 /* Function - Allow tracing to work with this interface (with */
2615 /* an optional argument). */
2617 /*------------------------------------------------------------------*/
2620 mono_arch_instrument_mem_needs (MonoMethod *method, int *stack, int *code)
2622 /* no stack room needed now (may be needed for FASTCALL-trace support) */
2624 /* split prolog-epilog requirements? */
2625 *code = 50; /* max bytes needed: check this number */
2628 /*========================= End of Function ========================*/
2630 /*------------------------------------------------------------------*/
2632 /* Name - mono_arch_instrument_prolog */
2634 /* Function - Create an "instrumented" prolog. */
2636 /*------------------------------------------------------------------*/
2639 mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p,
2640 gboolean enable_arguments)
2647 parmOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2648 if (cfg->method->save_lmf)
2649 parmOffset -= sizeof(MonoLMF);
2650 fpOffset = parmOffset + (5*sizeof(gpointer));
2653 s390_stmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2654 s390_stdy (code, s390_f0, 0, STK_BASE, fpOffset);
2655 s390_stdy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2656 s390_stdy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2657 s390_stdy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2658 S390_SET (code, s390_r1, func);
2659 S390_SET (code, s390_r2, cfg->method);
2660 s390_lay (code, s390_r3, 0, STK_BASE, parmOffset);
2661 s390_lgr (code, s390_r4, STK_BASE);
2662 s390_aghi (code, s390_r4, cfg->stack_usage);
2663 s390_basr (code, s390_r14, s390_r1);
2664 s390_ldy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2665 s390_ldy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2666 s390_ldy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2667 s390_ldy (code, s390_f0, 0, STK_BASE, fpOffset);
2668 s390_lmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2673 /*========================= End of Function ========================*/
2675 /*------------------------------------------------------------------*/
2677 /* Name - mono_arch_instrument_epilog */
2679 /* Function - Create an epilog that will handle the returned */
2680 /* values used in instrumentation. */
2682 /*------------------------------------------------------------------*/
2685 mono_arch_instrument_epilog_full (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments, gboolean preserve_argument_registers)
2688 int save_mode = SAVE_NONE,
2691 MonoMethod *method = cfg->method;
2692 int rtype = mini_get_underlying_type (mono_method_signature (method)->ret)->type;
2694 offset = code - cfg->native_code;
2695 /*-----------------------------------------*/
2696 /* We need about 128 bytes of instructions */
2697 /*-----------------------------------------*/
2698 if (offset > (cfg->code_size - 128)) {
2699 cfg->code_size *= 2;
2700 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
2701 code = cfg->native_code + offset;
2704 saveOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2705 if (method->save_lmf)
2706 saveOffset -= sizeof(MonoLMF);
2710 case MONO_TYPE_VOID:
2711 /* special case string .ctor icall */
2712 if (strcmp (".ctor", method->name) && method->klass == mono_defaults.string_class)
2713 save_mode = SAVE_ONE;
2715 save_mode = SAVE_NONE;
2719 save_mode = SAVE_ONE;
2722 save_mode = SAVE_R4;
2725 save_mode = SAVE_R8;
2727 case MONO_TYPE_VALUETYPE:
2728 if (mono_method_signature (method)->ret->data.klass->enumtype) {
2729 rtype = mono_class_enum_basetype (mono_method_signature (method)->ret->data.klass)->type;
2732 save_mode = SAVE_STRUCT;
2735 save_mode = SAVE_ONE;
2739 switch (save_mode) {
2741 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2742 if (enable_arguments) {
2743 s390_lgr (code, s390_r3, s390_r2);
2747 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2748 if (enable_arguments) {
2749 s390_ldebr (code, s390_f0, s390_f0);
2753 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2756 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2757 if (enable_arguments) {
2758 s390_lg (code, s390_r3, 0, cfg->frame_reg,
2759 S390_MINIMAL_STACK_SIZE+cfg->param_area);
2767 S390_SET (code, s390_r1, func);
2768 S390_SET (code, s390_r2, cfg->method);
2769 s390_basr (code, s390_r14, s390_r1);
2771 switch (save_mode) {
2773 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2777 s390_ld (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2780 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2790 /*========================= End of Function ========================*/
2792 /*------------------------------------------------------------------*/
2794 /* Name - mono_arch_peephole_pass_1 */
2796 /* Function - Form a peephole pass at the code looking for */
2797 /* simple optimizations. */
2799 /*------------------------------------------------------------------*/
2802 mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
2806 /*========================= End of Function ========================*/
2808 /*------------------------------------------------------------------*/
2810 /* Name - mono_arch_peephole_pass_2 */
2812 /* Function - Form a peephole pass at the code looking for */
2813 /* simple optimizations. */
2815 /*------------------------------------------------------------------*/
2818 mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
2822 MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
2823 mono_peephole_ins (bb, ins);
2827 /*========================= End of Function ========================*/
2829 /*------------------------------------------------------------------*/
2831 /* Name - mono_arch_lowering_pass. */
2833 /*------------------------------------------------------------------*/
2836 mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
2838 MonoInst *ins, *next;
2840 MONO_BB_FOR_EACH_INS_SAFE (bb, next, ins) {
2841 switch (ins->opcode) {
2846 case OP_IDIV_UN_IMM:
2847 case OP_IREM_UN_IMM:
2852 case OP_LOCALLOC_IMM:
2853 mono_decompose_op_imm (cfg, bb, ins);
2856 if (!s390_is_imm16 (ins->inst_imm))
2857 /* This is created by the memcpy code which ignores is_inst_imm */
2858 mono_decompose_op_imm (cfg, bb, ins);
2865 bb->max_vreg = cfg->next_vreg;
2868 /*========================= End of Function ========================*/
2870 /*------------------------------------------------------------------*/
2872 /* Name - emit_float_to_int */
2874 /* Function - Create instructions which will convert a floating */
2875 /* point value to integer. */
2877 /*------------------------------------------------------------------*/
2880 emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size, gboolean is_signed)
2882 /* sreg is a float, dreg is an integer reg. */
2884 s390_cgdbr (code, dreg, 5, sreg);
2887 s390_ltgr (code, dreg, dreg);
2889 s390_oill (code, dreg, 0x80);
2890 s390_lghi (code, s390_r0, 0xff);
2891 s390_ngr (code, dreg, s390_r0);
2894 s390_ltgr (code, dreg, dreg);
2896 s390_oill (code, dreg, 0x8000);
2897 s390_llill(code, s390_r0, 0xffff);
2898 s390_ngr (code, dreg, s390_r0);
2903 S390_SET (code, s390_r13, 0x41e0000000000000llu);
2904 s390_ldgr (code, s390_f14, s390_r13);
2905 s390_ldr (code, s390_f15, sreg);
2906 s390_cdbr (code, s390_f15, s390_f14);
2907 s390_jl (code, 0); CODEPTR (code, o[0]);
2908 S390_SET (code, s390_r13, 0x41f0000000000000llu);
2909 s390_ldgr (code, s390_f14, s390_r13);
2910 s390_sdbr (code, s390_f15, s390_f14);
2911 s390_cfdbr (code, dreg, 7, s390_f15);
2913 PTRSLOT (code, o[0]);
2914 s390_cfdbr (code, dreg, 5, sreg);
2917 s390_lghi (code, s390_r0, 0xff);
2918 s390_ngr (code, dreg, s390_r0);
2921 s390_llill(code, s390_r0, 0xffff);
2922 s390_ngr (code, dreg, s390_r0);
2929 /*========================= End of Function ========================*/
2931 /*------------------------------------------------------------------*/
2933 /* Name - gboolean_is_unsigned. */
2935 /* Function - Return TRUE if next opcode is checking for un- */
2938 /*------------------------------------------------------------------*/
2941 gboolean is_unsigned (MonoInst *next)
2944 (((next->opcode >= OP_IBNE_UN) &&
2945 (next->opcode <= OP_IBLT_UN)) ||
2946 ((next->opcode >= OP_LBNE_UN) &&
2947 (next->opcode <= OP_LBLT_UN)) ||
2948 ((next->opcode >= OP_COND_EXC_NE_UN) &&
2949 (next->opcode <= OP_COND_EXC_LT_UN)) ||
2950 ((next->opcode >= OP_COND_EXC_INE_UN) &&
2951 (next->opcode <= OP_COND_EXC_ILT_UN)) ||
2952 ((next->opcode == OP_CLT_UN) ||
2953 (next->opcode == OP_CGT_UN)) ||
2954 ((next->opcode == OP_ICLT_UN) ||
2955 (next->opcode == OP_ICGT_UN) ||
2956 (next->opcode == OP_LCLT_UN) ||
2957 (next->opcode == OP_LCGT_UN))))
2963 /*========================= End of Function ========================*/
2965 /*------------------------------------------------------------------*/
2967 /* Name - mono_arch_output_basic_block */
2969 /* Function - Perform the "real" work of emitting instructions */
2970 /* that will do the work of in the basic block. */
2972 /*------------------------------------------------------------------*/
2975 mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
2980 guint8 *code = cfg->native_code + cfg->code_len;
2981 guint last_offset = 0;
2984 /* we don't align basic blocks of loops on s390 */
2986 if (cfg->verbose_level > 2)
2987 g_print ("Basic block %d starting at offset 0x%x\n", bb->block_num, bb->native_offset);
2989 if ((cfg->prof_options & MONO_PROFILE_COVERAGE) && cfg->coverage_info) {
2990 MonoProfileCoverageInfo *cov = cfg->coverage_info;
2991 g_assert (!mono_compile_aot);
2992 cov->data [bb->dfn].cil_code = bb->cil_code;
2993 /* This is not thread save, but good enough */
2994 S390_SET (code, s390_r1, &cov->data [bb->dfn].count);
2995 s390_alsi (code, 0, s390_r1, 1);
2998 MONO_BB_FOR_EACH_INS (bb, ins) {
2999 offset = code - cfg->native_code;
3001 max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
3003 if (offset > (cfg->code_size - max_len - 16)) {
3004 cfg->code_size *= 2;
3005 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
3006 code = cfg->native_code + offset;
3009 mono_debug_record_line_number (cfg, ins, offset);
3011 switch (ins->opcode) {
3012 case OP_STOREI1_MEMBASE_IMM: {
3013 s390_lghi (code, s390_r0, ins->inst_imm);
3014 S390_LONG (code, stcy, stc, s390_r0, 0,
3015 ins->inst_destbasereg, ins->inst_offset);
3018 case OP_STOREI2_MEMBASE_IMM: {
3019 s390_lghi (code, s390_r0, ins->inst_imm);
3020 S390_LONG (code, sthy, sth, s390_r0, 0,
3021 ins->inst_destbasereg, ins->inst_offset);
3024 case OP_STOREI4_MEMBASE_IMM: {
3025 s390_lgfi (code, s390_r0, ins->inst_imm);
3026 S390_LONG (code, sty, st, s390_r0, 0,
3027 ins->inst_destbasereg, ins->inst_offset);
3030 case OP_STORE_MEMBASE_IMM:
3031 case OP_STOREI8_MEMBASE_IMM: {
3032 S390_SET (code, s390_r0, ins->inst_imm);
3033 S390_LONG (code, stg, stg, s390_r0, 0,
3034 ins->inst_destbasereg, ins->inst_offset);
3037 case OP_STOREI1_MEMBASE_REG: {
3038 S390_LONG (code, stcy, stc, ins->sreg1, 0,
3039 ins->inst_destbasereg, ins->inst_offset);
3042 case OP_STOREI2_MEMBASE_REG: {
3043 S390_LONG (code, sthy, sth, ins->sreg1, 0,
3044 ins->inst_destbasereg, ins->inst_offset);
3047 case OP_STOREI4_MEMBASE_REG: {
3048 S390_LONG (code, sty, st, ins->sreg1, 0,
3049 ins->inst_destbasereg, ins->inst_offset);
3052 case OP_STORE_MEMBASE_REG:
3053 case OP_STOREI8_MEMBASE_REG: {
3054 S390_LONG (code, stg, stg, ins->sreg1, 0,
3055 ins->inst_destbasereg, ins->inst_offset);
3059 g_assert_not_reached ();
3061 case OP_LOAD_MEMBASE:
3062 case OP_LOADI8_MEMBASE: {
3063 S390_LONG (code, lg, lg, ins->dreg, 0,
3064 ins->inst_basereg, ins->inst_offset);
3067 case OP_LOADI4_MEMBASE: {
3068 S390_LONG (code, lgf, lgf, ins->dreg, 0,
3069 ins->inst_basereg, ins->inst_offset);
3072 case OP_LOADU4_MEMBASE: {
3073 S390_LONG (code, llgf, llgf, ins->dreg, 0,
3074 ins->inst_basereg, ins->inst_offset);
3077 case OP_LOADU1_MEMBASE: {
3078 S390_LONG (code, llgc, llgc, ins->dreg, 0,
3079 ins->inst_basereg, ins->inst_offset);
3082 case OP_LOADI1_MEMBASE: {
3083 S390_LONG (code, lgb, lgb, ins->dreg, 0,
3084 ins->inst_basereg, ins->inst_offset);
3087 case OP_LOADU2_MEMBASE: {
3088 S390_LONG (code, llgh, llgh, ins->dreg, 0,
3089 ins->inst_basereg, ins->inst_offset);
3092 case OP_LOADI2_MEMBASE: {
3093 S390_LONG (code, lgh, lgh, ins->dreg, 0,
3094 ins->inst_basereg, ins->inst_offset);
3097 case OP_LCONV_TO_I1: {
3098 s390_lgbr (code, ins->dreg, ins->sreg1);
3101 case OP_LCONV_TO_I2: {
3102 s390_lghr (code, ins->dreg, ins->sreg1);
3105 case OP_LCONV_TO_U1: {
3106 s390_llgcr (code, ins->dreg, ins->sreg1);
3109 case OP_LCONV_TO_U2: {
3110 s390_llghr (code, ins->dreg, ins->sreg1);
3113 case OP_ICONV_TO_I1: {
3114 s390_lgbr (code, ins->dreg, ins->sreg1);
3117 case OP_ICONV_TO_I2: {
3118 s390_lghr (code, ins->dreg, ins->sreg1);
3121 case OP_ICONV_TO_U1: {
3122 s390_llgcr (code, ins->dreg, ins->sreg1);
3125 case OP_ICONV_TO_U2: {
3126 s390_llghr (code, ins->dreg, ins->sreg1);
3131 if (is_unsigned (ins->next))
3132 s390_clgr (code, ins->sreg1, ins->sreg2);
3134 s390_cgr (code, ins->sreg1, ins->sreg2);
3138 if (is_unsigned (ins->next))
3139 s390_clr (code, ins->sreg1, ins->sreg2);
3141 s390_cr (code, ins->sreg1, ins->sreg2);
3144 case OP_COMPARE_IMM:
3145 case OP_LCOMPARE_IMM: {
3146 S390_SET (code, s390_r0, ins->inst_imm);
3147 if (is_unsigned (ins->next))
3148 s390_clgr (code, ins->sreg1, s390_r0);
3150 s390_cgr (code, ins->sreg1, s390_r0);
3153 case OP_ICOMPARE_IMM: {
3154 S390_SET (code, s390_r0, ins->inst_imm);
3155 if (is_unsigned (ins->next))
3156 s390_clr (code, ins->sreg1, s390_r0);
3158 s390_cr (code, ins->sreg1, s390_r0);
3162 mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_ABS,
3164 S390_CALL_TEMPLATE (code, s390_r14);
3169 s390_agr (code, ins->dreg, src2);
3174 s390_agr (code, ins->dreg, src2);
3179 s390_alcgr (code, ins->dreg, src2);
3183 if (ins->dreg != ins->sreg1) {
3184 s390_lgr (code, ins->dreg, ins->sreg1);
3186 if (s390_is_imm16 (ins->inst_imm)) {
3187 s390_aghi (code, ins->dreg, ins->inst_imm);
3188 } else if (s390_is_imm32 (ins->inst_imm)) {
3189 s390_agfi (code, ins->dreg, ins->inst_imm);
3191 S390_SET (code, s390_r0, ins->inst_imm);
3192 s390_agr (code, ins->dreg, s390_r0);
3197 if (ins->dreg != ins->sreg1) {
3198 s390_lgr (code, ins->dreg, ins->sreg1);
3200 g_assert (s390_is_imm16 (ins->inst_imm));
3201 s390_aghi (code, ins->dreg, ins->inst_imm);
3205 if (ins->dreg != ins->sreg1) {
3206 s390_lgr (code, ins->dreg, ins->sreg1);
3208 if (s390_is_imm16 (ins->inst_imm)) {
3209 s390_lghi (code, s390_r0, ins->inst_imm);
3210 s390_alcgr (code, ins->dreg, s390_r0);
3212 S390_SET (code, s390_r0, ins->inst_imm);
3213 s390_alcgr (code, ins->dreg, s390_r0);
3218 case OP_S390_IADD_OVF: {
3220 s390_ar (code, ins->dreg, src2);
3221 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3222 s390_lgfr (code, ins->dreg, ins->dreg);
3225 case OP_IADD_OVF_UN:
3226 case OP_S390_IADD_OVF_UN: {
3228 s390_algr (code, ins->dreg, src2);
3229 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3230 s390_llgfr (code, ins->dreg, ins->dreg);
3233 case OP_ADD_OVF_CARRY: {
3235 s390_lghi (code, s390_r0, 0);
3236 s390_lgr (code, s390_r1, s390_r0);
3237 s390_alcgr (code, s390_r0, s390_r1);
3238 s390_agr (code, ins->dreg, src2);
3239 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3240 s390_agr (code, ins->dreg, s390_r0);
3241 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3244 case OP_ADD_OVF_UN_CARRY: {
3246 s390_alcgr (code, ins->dreg, src2);
3247 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3252 s390_sgr (code, ins->dreg, src2);
3257 s390_sgr (code, ins->dreg, src2);
3262 s390_slbgr(code, ins->dreg, src2);
3266 if (ins->dreg != ins->sreg1) {
3267 s390_lgr (code, ins->dreg, ins->sreg1);
3269 if (s390_is_imm16 (-ins->inst_imm)) {
3270 s390_aghi (code, ins->dreg, -ins->inst_imm);
3271 } else if (s390_is_imm32 (-ins->inst_imm)) {
3272 s390_slgfi (code, ins->dreg, ins->inst_imm);
3274 S390_SET (code, s390_r0, ins->inst_imm);
3275 s390_slgr (code, ins->dreg, s390_r0);
3280 if (ins->dreg != ins->sreg1) {
3281 s390_lgr (code, ins->dreg, ins->sreg1);
3283 if (s390_is_imm16 (-ins->inst_imm)) {
3284 s390_aghi (code, ins->dreg, -ins->inst_imm);
3285 } else if (s390_is_imm32 (-ins->inst_imm)) {
3286 s390_slgfi (code, ins->dreg, ins->inst_imm);
3288 S390_SET (code, s390_r0, ins->inst_imm);
3289 s390_slgr (code, ins->dreg, s390_r0);
3294 if (ins->dreg != ins->sreg1) {
3295 s390_lgr (code, ins->dreg, ins->sreg1);
3297 if (s390_is_imm16 (-ins->inst_imm)) {
3298 s390_lghi (code, s390_r0, ins->inst_imm);
3299 s390_slbgr (code, ins->dreg, s390_r0);
3301 S390_SET (code, s390_r0, ins->inst_imm);
3302 s390_slbgr(code, ins->dreg, s390_r0);
3306 case OP_SUB_OVF_CARRY: {
3308 s390_lghi (code, s390_r0, 0);
3309 s390_lgr (code, s390_r1, s390_r0);
3310 s390_slbgr (code, s390_r0, s390_r1);
3311 s390_sgr (code, ins->dreg, src2);
3312 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3313 s390_agr (code, ins->dreg, s390_r0);
3314 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3317 case OP_SUB_OVF_UN_CARRY: {
3319 s390_slbgr (code, ins->dreg, src2);
3320 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3324 if (ins->sreg1 == ins->dreg) {
3325 s390_ngr (code, ins->dreg, ins->sreg2);
3328 if (ins->sreg2 == ins->dreg) {
3329 s390_ngr (code, ins->dreg, ins->sreg1);
3332 s390_lgr (code, ins->dreg, ins->sreg1);
3333 s390_ngr (code, ins->dreg, ins->sreg2);
3339 if (ins->dreg != ins->sreg1) {
3340 s390_lgr (code, ins->dreg, ins->sreg1);
3342 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3343 s390_ngr (code, ins->dreg, s390_r0);
3347 s390_lgr (code, s390_r1, ins->sreg1);
3348 s390_dsgr (code, s390_r0, ins->sreg2);
3349 s390_lgr (code, ins->dreg, s390_r1);
3353 s390_lgr (code, s390_r1, ins->sreg1);
3354 s390_lghi (code, s390_r0, 0);
3355 s390_dlgr (code, s390_r0, ins->sreg2);
3356 s390_lgr (code, ins->dreg, s390_r1);
3360 s390_lgr (code, s390_r1, ins->sreg1);
3361 s390_dsgr (code, s390_r0, ins->sreg2);
3362 s390_lgr (code, ins->dreg, s390_r0);
3366 if (s390_is_imm16 (ins->inst_imm)) {
3367 s390_lghi (code, s390_r13, ins->inst_imm);
3369 s390_lgfi (code, s390_r13, ins->inst_imm);
3371 s390_lgr (code, s390_r0, ins->sreg1);
3372 s390_dsgr (code, s390_r0, s390_r13);
3373 s390_lgfr (code, ins->dreg, s390_r0);
3377 s390_lgr (code, s390_r1, ins->sreg1);
3378 s390_lghi (code, s390_r0, 0);
3379 s390_dlgr (code, s390_r0, ins->sreg2);
3380 s390_lgr (code, ins->dreg, s390_r0);
3384 if (ins->sreg1 == ins->dreg) {
3385 s390_ogr (code, ins->dreg, ins->sreg2);
3388 if (ins->sreg2 == ins->dreg) {
3389 s390_ogr (code, ins->dreg, ins->sreg1);
3392 s390_lgr (code, ins->dreg, ins->sreg1);
3393 s390_ogr (code, ins->dreg, ins->sreg2);
3399 if (ins->dreg != ins->sreg1) {
3400 s390_lgr (code, ins->dreg, ins->sreg1);
3402 S390_SET_MASK(code, s390_r0, ins->inst_imm);
3403 s390_ogr (code, ins->dreg, s390_r0);
3407 if (ins->sreg1 == ins->dreg) {
3408 s390_xgr (code, ins->dreg, ins->sreg2);
3411 if (ins->sreg2 == ins->dreg) {
3412 s390_xgr (code, ins->dreg, ins->sreg1);
3415 s390_lgr (code, ins->dreg, ins->sreg1);
3416 s390_xgr (code, ins->dreg, ins->sreg2);
3422 if (ins->dreg != ins->sreg1) {
3423 s390_lgr (code, ins->dreg, ins->sreg1);
3425 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3426 s390_xgr (code, ins->dreg, s390_r0);
3431 s390_sllg (code, ins->dreg, ins->dreg, src2, 0);
3436 if (ins->sreg1 != ins->dreg) {
3437 s390_lgr (code, ins->dreg, ins->sreg1);
3439 s390_sllg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3444 s390_srag (code, ins->dreg, ins->dreg, src2, 0);
3449 if (ins->sreg1 != ins->dreg) {
3450 s390_lgr (code, ins->dreg, ins->sreg1);
3452 s390_srag (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3456 case OP_LSHR_UN_IMM: {
3457 if (ins->sreg1 != ins->dreg) {
3458 s390_lgr (code, ins->dreg, ins->sreg1);
3460 s390_srlg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3465 s390_srlg (code, ins->dreg, ins->dreg, src2, 0);
3469 if (ins->sreg1 != ins->dreg) {
3470 s390_lgr (code, ins->dreg, ins->sreg1);
3472 s390_lghi (code, s390_r0, -1);
3473 s390_xgr (code, ins->dreg, s390_r0);
3477 s390_lcgr (code, ins->dreg, ins->sreg1);
3482 s390_msgr (code, ins->dreg, src2);
3487 if (ins->dreg != ins->sreg1) {
3488 s390_lgr (code, ins->dreg, ins->sreg1);
3490 if (s390_is_imm16 (ins->inst_imm)) {
3491 s390_lghi (code, s390_r13, ins->inst_imm);
3492 } else if (s390_is_imm32 (ins->inst_imm)) {
3493 s390_lgfi (code, s390_r13, ins->inst_imm);
3495 S390_SET (code, s390_r13, ins->inst_imm);
3497 s390_msgr (code, ins->dreg, s390_r13);
3502 s390_ltgr (code, s390_r1, ins->sreg1);
3503 s390_jz (code, 0); CODEPTR(code, o[0]);
3504 s390_ltgr (code, s390_r0, ins->sreg2);
3506 s390_lghi (code, s390_r1, 0);
3507 s390_j (code, 0); CODEPTR(code, o[1]);
3508 s390_xgr (code, s390_r0, s390_r1);
3509 s390_msgr (code, s390_r1, ins->sreg2);
3510 s390_xgr (code, s390_r0, s390_r1);
3511 s390_srlg (code, s390_r0, s390_r0, 0, 63);
3512 s390_ltgr (code, s390_r0, s390_r0);
3513 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3514 PTRSLOT (code, o[0]);
3515 PTRSLOT (code, o[1]);
3516 s390_lgr (code, ins->dreg, s390_r1);
3519 case OP_LMUL_OVF_UN: {
3520 s390_lghi (code, s390_r0, 0);
3521 s390_lgr (code, s390_r1, ins->sreg1);
3522 s390_mlgr (code, s390_r0, ins->sreg2);
3523 s390_ltgr (code, s390_r0, s390_r0);
3524 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3525 s390_lgr (code, ins->dreg, s390_r1);
3529 g_assert_not_reached ();
3531 s390_algr (code, ins->dreg, src2);
3536 s390_agr (code, ins->dreg, src2);
3540 g_assert_not_reached ();
3542 s390_alcgr (code, ins->dreg, src2);
3546 if (ins->dreg != ins->sreg1) {
3547 s390_lgfr (code, ins->dreg, ins->sreg1);
3549 if (s390_is_imm16 (ins->inst_imm)) {
3550 s390_aghi (code, ins->dreg, ins->inst_imm);
3552 s390_afi (code, ins->dreg, ins->inst_imm);
3557 if (ins->dreg != ins->sreg1) {
3558 s390_lgfr (code, ins->dreg, ins->sreg1);
3560 if (s390_is_imm16 (ins->inst_imm)) {
3561 s390_lghi (code, s390_r0, ins->inst_imm);
3562 s390_alcgr (code, ins->dreg, s390_r0);
3564 S390_SET (code, s390_r0, ins->inst_imm);
3565 s390_alcgr (code, ins->dreg, s390_r0);
3570 case OP_S390_LADD_OVF: {
3572 s390_agr (code, ins->dreg, src2);
3573 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3576 case OP_LADD_OVF_UN:
3577 case OP_S390_LADD_OVF_UN: {
3579 s390_algr (code, ins->dreg, src2);
3580 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3584 CHECK_SRCDST_NCOM_I;
3585 s390_slgr (code, ins->dreg, src2);
3589 CHECK_SRCDST_NCOM_I;
3590 s390_sgr (code, ins->dreg, src2);
3594 CHECK_SRCDST_NCOM_I;
3595 s390_slbgr (code, ins->dreg, src2);
3599 if (ins->dreg != ins->sreg1) {
3600 s390_lgfr (code, ins->dreg, ins->sreg1);
3602 if (s390_is_imm16 (-ins->inst_imm)) {
3603 s390_aghi (code, ins->dreg, -ins->inst_imm);
3605 s390_agfi (code, ins->dreg, -ins->inst_imm);
3610 S390_SET (code, s390_r0, ins->inst_imm);
3611 s390_slgfr (code, ins->dreg, s390_r0);
3615 case OP_S390_ISUB_OVF: {
3617 s390_sr (code, ins->dreg, src2);
3618 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3619 s390_lgfr (code, ins->dreg, ins->dreg);
3622 case OP_ISUB_OVF_UN:
3623 case OP_S390_ISUB_OVF_UN: {
3625 s390_slr (code, ins->dreg, src2);
3626 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3627 s390_llgfr(code, ins->dreg, ins->dreg);
3631 case OP_S390_LSUB_OVF: {
3633 s390_sgr (code, ins->dreg, src2);
3634 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3637 case OP_LSUB_OVF_UN:
3638 case OP_S390_LSUB_OVF_UN: {
3640 s390_slgr (code, ins->dreg, src2);
3641 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3645 CHECK_SRCDST_NCOM_I;
3646 s390_ngr (code, ins->dreg, src2);
3650 if (ins->dreg != ins->sreg1) {
3651 s390_lgfr (code, ins->dreg, ins->sreg1);
3653 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3654 s390_ngr (code, ins->dreg, s390_r0);
3658 s390_lgfr (code, s390_r0, ins->sreg1);
3659 s390_srda (code, s390_r0, 0, 32);
3660 s390_dr (code, s390_r0, ins->sreg2);
3661 s390_lgfr (code, ins->dreg, s390_r1);
3665 s390_lgfr (code, s390_r0, ins->sreg1);
3666 s390_srdl (code, s390_r0, 0, 32);
3667 s390_dlr (code, s390_r0, ins->sreg2);
3668 s390_lgfr (code, ins->dreg, s390_r1);
3672 if (s390_is_imm16 (ins->inst_imm)) {
3673 s390_lghi (code, s390_r13, ins->inst_imm);
3675 s390_lgfi (code, s390_r13, ins->inst_imm);
3677 s390_lgfr (code, s390_r0, ins->sreg1);
3678 s390_srda (code, s390_r0, 0, 32);
3679 s390_dr (code, s390_r0, ins->sreg2);
3680 s390_lgfr (code, ins->dreg, s390_r1);
3684 s390_lgfr (code, s390_r0, ins->sreg1);
3685 s390_srda (code, s390_r0, 0, 32);
3686 s390_dr (code, s390_r0, ins->sreg2);
3687 s390_lgfr (code, ins->dreg, s390_r0);
3690 s390_lgfr (code, s390_r0, ins->sreg1);
3691 s390_srdl (code, s390_r0, 0, 32);
3692 s390_dlr (code, s390_r0, ins->sreg2);
3693 s390_lgfr (code, ins->dreg, s390_r0);
3697 if (s390_is_imm16 (ins->inst_imm)) {
3698 s390_lghi (code, s390_r13, ins->inst_imm);
3700 s390_lgfi (code, s390_r13, ins->inst_imm);
3702 s390_lgfr (code, s390_r0, ins->sreg1);
3703 s390_srda (code, s390_r0, 0, 32);
3704 s390_dr (code, s390_r0, ins->sreg2);
3705 s390_lgfr (code, ins->dreg, s390_r0);
3710 s390_ogr (code, ins->dreg, src2);
3714 if (ins->dreg != ins->sreg1) {
3715 s390_lgfr (code, ins->dreg, ins->sreg1);
3717 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3718 s390_ogr (code, ins->dreg, s390_r0);
3723 s390_xgr (code, ins->dreg, src2);
3727 if (ins->dreg != ins->sreg1) {
3728 s390_lgfr (code, ins->dreg, ins->sreg1);
3730 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3731 s390_xgr (code, ins->dreg, s390_r0);
3736 s390_sll (code, ins->dreg, src2, 0);
3740 if (ins->sreg1 != ins->dreg) {
3741 s390_lgfr (code, ins->dreg, ins->sreg1);
3743 s390_sll (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3748 s390_sra (code, ins->dreg, src2, 0);
3752 if (ins->sreg1 != ins->dreg) {
3753 s390_lgfr (code, ins->dreg, ins->sreg1);
3755 s390_sra (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3758 case OP_ISHR_UN_IMM: {
3759 if (ins->sreg1 != ins->dreg) {
3760 s390_lgfr (code, ins->dreg, ins->sreg1);
3762 s390_srl (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3767 s390_srl (code, ins->dreg, src2, 0);
3771 if (ins->sreg1 != ins->dreg) {
3772 s390_lgfr (code, ins->dreg, ins->sreg1);
3774 s390_lghi (code, s390_r0, -1);
3775 s390_xgr (code, ins->dreg, s390_r0);
3779 s390_lcgr (code, ins->dreg, ins->sreg1);
3784 s390_msr (code, ins->dreg, src2);
3788 if (ins->dreg != ins->sreg1) {
3789 s390_lgfr (code, ins->dreg, ins->sreg1);
3791 if (s390_is_imm16 (ins->inst_imm)) {
3792 s390_lghi (code, s390_r0, ins->inst_imm);
3794 s390_lgfi (code, s390_r0, ins->inst_imm);
3796 s390_msr (code, ins->dreg, s390_r0);
3801 s390_ltr (code, s390_r1, ins->sreg1);
3802 s390_jz (code, 0); CODEPTR(code, o[0]);
3803 s390_ltr (code, s390_r0, ins->sreg2);
3805 s390_lhi (code, s390_r1, 0);
3806 s390_j (code, 0); CODEPTR(code, o[1]);
3807 s390_xr (code, s390_r0, s390_r1);
3808 s390_msr (code, s390_r1, ins->sreg2);
3809 s390_xr (code, s390_r0, s390_r1);
3810 s390_srl (code, s390_r0, 0, 31);
3811 s390_ltr (code, s390_r0, s390_r0);
3812 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3813 PTRSLOT (code, o[0]);
3814 PTRSLOT (code, o[1]);
3815 s390_lgfr (code, ins->dreg, s390_r1);
3818 case OP_IMUL_OVF_UN: {
3819 s390_lhi (code, s390_r0, 0);
3820 s390_lr (code, s390_r1, ins->sreg1);
3821 s390_mlr (code, s390_r0, ins->sreg2);
3822 s390_ltr (code, s390_r0, s390_r0);
3823 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3824 s390_lgfr (code, ins->dreg, s390_r1);
3829 S390_SET (code, ins->dreg, ins->inst_c0);
3833 mono_add_patch_info (cfg, code - cfg->native_code,
3834 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3835 S390_LOAD_TEMPLATE (code, ins->dreg);
3838 case OP_JUMP_TABLE: {
3839 mono_add_patch_info (cfg, code - cfg->native_code,
3840 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3841 S390_LOAD_TEMPLATE (code, ins->dreg);
3845 if (ins->dreg != ins->sreg1) {
3846 s390_lgr (code, ins->dreg, ins->sreg1);
3850 case OP_LCONV_TO_I8:
3852 s390_lgfr (code, ins->dreg, ins->sreg1);
3854 case OP_LCONV_TO_I4:
3855 s390_lgfr (code, ins->dreg, ins->sreg1);
3858 case OP_LCONV_TO_U8:
3859 case OP_LCONV_TO_U4:
3861 s390_llgfr (code, ins->dreg, ins->sreg1);
3863 case OP_LCONV_TO_OVF_U4:
3864 S390_SET (code, s390_r0, 4294967295);
3865 s390_clgr (code, ins->sreg1, s390_r0);
3866 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3867 s390_ltgr (code, ins->sreg1, ins->sreg1);
3868 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3869 s390_llgfr(code, ins->dreg, ins->sreg1);
3871 case OP_LCONV_TO_OVF_I4_UN:
3872 S390_SET (code, s390_r0, 2147483647);
3873 s390_cgr (code, ins->sreg1, s390_r0);
3874 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3875 s390_ltgr (code, ins->sreg1, ins->sreg1);
3876 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3877 s390_lgfr (code, ins->dreg, ins->sreg1);
3880 if (ins->dreg != ins->sreg1) {
3881 s390_ldr (code, ins->dreg, ins->sreg1);
3884 case OP_MOVE_F_TO_I8:
3885 s390_lgdr (code, ins->dreg, ins->sreg1);
3887 case OP_MOVE_I8_TO_F:
3888 s390_ldgr (code, ins->dreg, ins->sreg1);
3890 case OP_MOVE_F_TO_I4:
3891 s390_ledbr (code, s390_f0, ins->sreg1);
3892 s390_lgdr (code, ins->dreg, s390_f0);
3893 s390_srag (code, ins->dreg, ins->dreg, 0, 32);
3895 case OP_MOVE_I4_TO_F:
3896 s390_slag (code, s390_r0, ins->sreg1, 0, 32);
3897 s390_ldgr (code, ins->dreg, s390_r0);
3898 s390_ldebr (code, ins->dreg, ins->dreg);
3900 case OP_FCONV_TO_R4:
3901 s390_ledbr (code, ins->dreg, ins->sreg1);
3902 s390_ldebr (code, ins->dreg, ins->dreg);
3904 case OP_S390_SETF4RET:
3905 s390_ledbr (code, ins->dreg, ins->sreg1);
3908 if (s390_is_imm16 (ins->inst_offset)) {
3909 s390_lghi (code, s390_r13, ins->inst_offset);
3910 } else if (s390_is_imm32 (ins->inst_offset)) {
3911 s390_lgfi (code, s390_r13, ins->inst_offset);
3913 S390_SET (code, s390_r13, ins->inst_offset);
3915 s390_ear (code, s390_r1, 0);
3916 s390_sllg(code, s390_r1, s390_r1, 0, 32);
3917 s390_ear (code, s390_r1, 1);
3918 s390_lg (code, ins->dreg, s390_r13, s390_r1, 0);
3922 if (s390_is_imm16 (ins->inst_offset)) {
3923 s390_lghi (code, s390_r13, ins->inst_offset);
3924 } else if (s390_is_imm32 (ins->inst_offset)) {
3925 s390_lgfi (code, s390_r13, ins->inst_offset);
3927 S390_SET (code, s390_r13, ins->inst_offset);
3929 s390_ear (code, s390_r1, 0);
3930 s390_sllg(code, s390_r1, s390_r1, 0, 32);
3931 s390_ear (code, s390_r1, 1);
3932 s390_stg (code, ins->sreg1, s390_r13, s390_r1, 0);
3936 if (cfg->method->save_lmf)
3937 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
3939 if (cfg->flags & MONO_CFG_HAS_TAIL) {
3940 code = emit_load_volatile_arguments (code, cfg);
3943 code = backUpStackPtr(cfg, code);
3944 s390_lg (code, s390_r14, 0, cfg->frame_reg, S390_RET_ADDR_OFFSET);
3945 mono_add_patch_info (cfg, code - cfg->native_code,
3946 MONO_PATCH_INFO_METHOD_JUMP,
3948 s390_jcl (code, S390_CC_UN, 0);
3951 case OP_CHECK_THIS: {
3952 /* ensure ins->sreg1 is not NULL */
3953 s390_lg (code, s390_r0, 0, ins->sreg1, 0);
3954 s390_ltgr (code, s390_r0, s390_r0);
3955 // EMIT_COND_SYSTEM_EXCEPTION (S390_CC_ZR, "NullReferenceException");
3959 int offset = cfg->sig_cookie + cfg->stack_usage;
3961 if (s390_is_imm16 (offset)) {
3962 s390_lghi (code, s390_r0, offset);
3963 } else if (s390_is_imm32 (offset)) {
3964 s390_lgfi (code, s390_r0, offset);
3966 S390_SET (code, s390_r0, offset);
3968 s390_agr (code, s390_r0, cfg->frame_reg);
3969 s390_stg (code, s390_r0, 0, ins->sreg1, 0);
3973 call = (MonoCallInst*)ins;
3974 if (ins->flags & MONO_INST_HAS_METHOD)
3975 mono_add_patch_info (cfg, code-cfg->native_code,
3976 MONO_PATCH_INFO_METHOD,
3979 mono_add_patch_info (cfg, code-cfg->native_code,
3980 MONO_PATCH_INFO_ABS,
3982 S390_CALL_TEMPLATE (code, s390_r14);
3983 if (call->signature->ret->type == MONO_TYPE_R4)
3984 s390_ldebr (code, s390_f0, s390_f0);
3992 call = (MonoCallInst*)ins;
3993 if (ins->flags & MONO_INST_HAS_METHOD)
3994 mono_add_patch_info (cfg, code-cfg->native_code,
3995 MONO_PATCH_INFO_METHOD,
3998 mono_add_patch_info (cfg, code-cfg->native_code,
3999 MONO_PATCH_INFO_ABS,
4001 S390_CALL_TEMPLATE (code, s390_r14);
4004 case OP_FCALL_REG: {
4005 call = (MonoCallInst*)ins;
4006 s390_lgr (code, s390_r1, ins->sreg1);
4007 s390_basr (code, s390_r14, s390_r1);
4008 if (call->signature->ret->type == MONO_TYPE_R4)
4009 s390_ldebr (code, s390_f0, s390_f0);
4015 case OP_VOIDCALL_REG:
4017 s390_lgr (code, s390_r1, ins->sreg1);
4018 s390_basr (code, s390_r14, s390_r1);
4021 case OP_FCALL_MEMBASE: {
4022 call = (MonoCallInst*)ins;
4023 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4024 s390_basr (code, s390_r14, s390_r1);
4025 if (call->signature->ret->type == MONO_TYPE_R4)
4026 s390_ldebr (code, s390_f0, s390_f0);
4029 case OP_LCALL_MEMBASE:
4030 case OP_VCALL_MEMBASE:
4031 case OP_VCALL2_MEMBASE:
4032 case OP_VOIDCALL_MEMBASE:
4033 case OP_CALL_MEMBASE: {
4034 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4035 s390_basr (code, s390_r14, s390_r1);
4042 if (cfg->param_area == 0)
4043 alloca_skip = S390_MINIMAL_STACK_SIZE;
4045 alloca_skip = cfg->param_area;
4047 area_offset = S390_ALIGN(alloca_skip, S390_STACK_ALIGNMENT);
4048 s390_lgr (code, s390_r1, ins->sreg1);
4049 if (ins->flags & MONO_INST_INIT)
4050 s390_lgr (code, s390_r0, ins->sreg1);
4051 s390_aghi (code, s390_r1, 14);
4052 s390_srlg (code, s390_r1, s390_r1, 0, 3);
4053 s390_sllg (code, s390_r1, s390_r1, 0, 3);
4054 if (cfg->method->save_lmf) {
4055 /*----------------------------------*/
4056 /* we have to adjust lmf ebp value */
4057 /*----------------------------------*/
4058 int lmfOffset = cfg->stack_usage - sizeof(MonoLMF);
4060 s390_lgr (code, s390_r13, cfg->frame_reg);
4061 if (s390_is_imm16(lmfOffset)) {
4062 s390_aghi (code, s390_r13, lmfOffset);
4063 } else if (s390_is_imm32(lmfOffset)) {
4064 s390_agfi (code, s390_r13, lmfOffset);
4066 S390_SET (code, s390_r13, lmfOffset);
4068 s390_lgr (code, s390_r14, STK_BASE);
4069 s390_sgr (code, s390_r14, s390_r1);
4070 s390_stg (code, s390_r14, 0, s390_r13,
4071 G_STRUCT_OFFSET(MonoLMF, ebp));
4073 s390_lg (code, s390_r13, 0, STK_BASE, 0);
4074 s390_sgr (code, STK_BASE, s390_r1);
4075 s390_stg (code, s390_r13, 0, STK_BASE, 0);
4076 s390_la (code, ins->dreg, 0, STK_BASE, area_offset);
4077 s390_srlg (code, ins->dreg, ins->dreg, 0, 3);
4078 s390_sllg (code, ins->dreg, ins->dreg, 0, 3);
4079 if (ins->flags & MONO_INST_INIT) {
4080 s390_lgr (code, s390_r1, s390_r0);
4081 s390_lgr (code, s390_r0, ins->dreg);
4082 s390_lgr (code, s390_r14, s390_r12);
4083 s390_lghi (code, s390_r13, 0);
4084 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4086 s390_lgr (code, s390_r12, s390_r14);
4091 s390_lgr (code, s390_r2, ins->sreg1);
4092 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4093 (gpointer) "mono_arch_throw_exception");
4094 S390_CALL_TEMPLATE(code, s390_r14);
4098 s390_lgr (code, s390_r2, ins->sreg1);
4099 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4100 (gpointer) "mono_arch_rethrow_exception");
4101 S390_CALL_TEMPLATE(code, s390_r14);
4104 case OP_START_HANDLER: {
4105 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4107 S390_LONG (code, stg, stg, s390_r14, 0,
4108 spvar->inst_basereg,
4109 spvar->inst_offset);
4112 case OP_ENDFILTER: {
4113 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4115 if (ins->sreg1 != s390_r2)
4116 s390_lgr(code, s390_r2, ins->sreg1);
4117 S390_LONG (code, lg, lg, s390_r14, 0,
4118 spvar->inst_basereg,
4119 spvar->inst_offset);
4120 s390_br (code, s390_r14);
4123 case OP_ENDFINALLY: {
4124 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4126 S390_LONG (code, lg, lg, s390_r14, 0,
4127 spvar->inst_basereg,
4128 spvar->inst_offset);
4129 s390_br (code, s390_r14);
4132 case OP_CALL_HANDLER: {
4133 mono_add_patch_info (cfg, code-cfg->native_code,
4134 MONO_PATCH_INFO_BB, ins->inst_target_bb);
4135 s390_brasl (code, s390_r14, 0);
4136 mono_cfg_add_try_hole (cfg, ins->inst_eh_block, code, bb);
4140 ins->inst_c0 = code - cfg->native_code;
4143 case OP_RELAXED_NOP:
4146 case OP_DUMMY_STORE:
4147 case OP_NOT_REACHED:
4151 case OP_IL_SEQ_POINT:
4152 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4154 case OP_SEQ_POINT: {
4157 if (cfg->compile_aot)
4161 * Read from the single stepping trigger page. This will cause a
4162 * SIGSEGV when single stepping is enabled.
4163 * We do this _before_ the breakpoint, so single stepping after
4164 * a breakpoint is hit will step to the next IL offset.
4166 if (ins->flags & MONO_INST_SINGLE_STEP_LOC) {
4167 breakpointCode.pTrigger = ss_trigger_page;
4168 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
4169 code += BREAKPOINT_SIZE;
4172 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4175 * A placeholder for a possible breakpoint inserted by
4176 * mono_arch_set_breakpoint ().
4178 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); ++i)
4182 * Add an additional nop so skipping the bp doesn't cause the ip to point
4183 * to another IL offset.
4189 case OP_GENERIC_CLASS_INIT: {
4190 static int byte_offset = -1;
4191 static guint8 bitmask;
4194 g_assert (ins->sreg1 == S390_FIRST_ARG_REG);
4196 if (byte_offset < 0)
4197 mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);
4199 s390_tm (code, ins->sreg1, byte_offset, bitmask);
4200 s390_jo (code, 0); CODEPTR(code, jump);
4202 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4203 "mono_generic_class_init");
4204 S390_CALL_TEMPLATE(code, s390_r14);
4206 PTRSLOT (code, jump);
4208 ins->flags |= MONO_INST_GC_CALLSITE;
4209 ins->backend.pc_offset = code - cfg->native_code;
4213 EMIT_UNCOND_BRANCH(ins);
4216 s390_br (code, ins->sreg1);
4222 s390_lghi(code, ins->dreg, 1);
4224 s390_lghi(code, ins->dreg, 0);
4230 s390_lghi(code, ins->dreg, 1);
4232 s390_lghi(code, ins->dreg, 0);
4238 s390_lghi(code, ins->dreg, 1);
4240 s390_lghi(code, ins->dreg, 0);
4246 s390_lghi(code, ins->dreg, 1);
4248 s390_lghi(code, ins->dreg, 0);
4254 s390_lghi(code, ins->dreg, 1);
4256 s390_lghi(code, ins->dreg, 0);
4259 case OP_COND_EXC_EQ:
4260 case OP_COND_EXC_IEQ:
4261 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_EQ, ins->inst_p1);
4263 case OP_COND_EXC_NE_UN:
4264 case OP_COND_EXC_INE_UN:
4265 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NE, ins->inst_p1);
4267 case OP_COND_EXC_LT:
4268 case OP_COND_EXC_ILT:
4269 case OP_COND_EXC_LT_UN:
4270 case OP_COND_EXC_ILT_UN:
4271 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, ins->inst_p1);
4273 case OP_COND_EXC_GT:
4274 case OP_COND_EXC_IGT:
4275 case OP_COND_EXC_GT_UN:
4276 case OP_COND_EXC_IGT_UN:
4277 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, ins->inst_p1);
4279 case OP_COND_EXC_GE:
4280 case OP_COND_EXC_IGE:
4281 case OP_COND_EXC_GE_UN:
4282 case OP_COND_EXC_IGE_UN:
4283 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GE, ins->inst_p1);
4285 case OP_COND_EXC_LE:
4286 case OP_COND_EXC_ILE:
4287 case OP_COND_EXC_LE_UN:
4288 case OP_COND_EXC_ILE_UN:
4289 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LE, ins->inst_p1);
4291 case OP_COND_EXC_OV:
4292 case OP_COND_EXC_IOV:
4293 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, ins->inst_p1);
4295 case OP_COND_EXC_NO:
4296 case OP_COND_EXC_INO:
4297 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NO, ins->inst_p1);
4300 case OP_COND_EXC_IC:
4301 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, ins->inst_p1);
4303 case OP_COND_EXC_NC:
4304 case OP_COND_EXC_INC:
4305 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, ins->inst_p1);
4309 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4313 EMIT_COND_BRANCH (ins, S390_CC_NE);
4319 EMIT_COND_BRANCH (ins, S390_CC_LT);
4325 EMIT_COND_BRANCH (ins, S390_CC_GT);
4331 EMIT_COND_BRANCH (ins, S390_CC_GE);
4337 EMIT_COND_BRANCH (ins, S390_CC_LE);
4340 /* floating point opcodes */
4342 if (*((double *) ins->inst_p0) == 0) {
4343 s390_lzdr (code, ins->dreg);
4345 S390_SET (code, s390_r13, ins->inst_p0);
4346 s390_ld (code, ins->dreg, 0, s390_r13, 0);
4351 if (*((float *) ins->inst_p0) == 0) {
4352 s390_lzdr (code, ins->dreg);
4354 S390_SET (code, s390_r13, ins->inst_p0);
4355 s390_ldeb (code, ins->dreg, 0, s390_r13, 0);
4359 case OP_STORER8_MEMBASE_REG: {
4360 S390_LONG (code, stdy, std, ins->sreg1, 0,
4361 ins->inst_destbasereg, ins->inst_offset);
4364 case OP_LOADR8_MEMBASE: {
4365 S390_LONG (code, ldy, ld, ins->dreg, 0,
4366 ins->inst_basereg, ins->inst_offset);
4369 case OP_STORER4_MEMBASE_REG: {
4370 s390_ledbr (code, s390_f15, ins->sreg1);
4371 S390_LONG (code, stey, ste, s390_f15, 0,
4372 ins->inst_destbasereg, ins->inst_offset);
4375 case OP_LOADR4_MEMBASE: {
4376 S390_LONG (code, ley, le, s390_f15, 0,
4377 ins->inst_basereg, ins->inst_offset);
4378 s390_ldebr (code, ins->dreg, s390_f15);
4381 case OP_ICONV_TO_R_UN: {
4382 if (mono_hwcap_s390x_has_fpe) {
4383 s390_cdlfbr (code, ins->dreg, 5, ins->sreg1, 0);
4385 s390_llgfr (code, s390_r0, ins->sreg1);
4386 s390_cdgbr (code, ins->dreg, s390_r0);
4390 case OP_LCONV_TO_R_UN: {
4391 if (mono_hwcap_s390x_has_fpe) {
4392 s390_cdlgbr (code, ins->dreg, 5, ins->sreg1, 0);
4395 s390_cxgbr (code, s390_f12, ins->sreg1);
4396 s390_ltgr (code, ins->sreg1, ins->sreg1);
4397 s390_jnl (code, 0); CODEPTR(code, jump);
4398 S390_SET (code, s390_r13, 0x403f000000000000llu);
4399 s390_lgdr (code, s390_f13, s390_r13);
4400 s390_lzdr (code, s390_f15);
4401 s390_axbr (code, s390_f12, s390_f13);
4402 PTRSLOT(code, jump);
4403 s390_ldxbr (code, s390_f13, s390_f12);
4404 s390_ldr (code, ins->dreg, s390_f13);
4408 case OP_LCONV_TO_R4:
4409 case OP_ICONV_TO_R4: {
4410 s390_cegbr (code, ins->dreg, ins->sreg1);
4411 s390_ldebr (code, ins->dreg, ins->dreg);
4414 case OP_LCONV_TO_R8:
4415 case OP_ICONV_TO_R8: {
4416 s390_cdgbr (code, ins->dreg, ins->sreg1);
4419 case OP_FCONV_TO_I1:
4420 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4421 s390_ltgr (code, ins->dreg, ins->dreg);
4423 s390_oill (code, ins->dreg, 0x80);
4424 s390_lghi (code, s390_r0, 0xff);
4425 s390_ngr (code, ins->dreg, s390_r0);
4427 case OP_FCONV_TO_U1:
4428 if (mono_hwcap_s390x_has_fpe) {
4429 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4430 s390_lghi (code, s390_r0, 0xff);
4431 s390_ngr (code, ins->dreg, s390_r0);
4433 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 1, FALSE);
4436 case OP_FCONV_TO_I2:
4437 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4438 s390_ltgr (code, ins->dreg, ins->dreg);
4440 s390_oill (code, ins->dreg, 0x8000);
4441 s390_llill (code, s390_r0, 0xffff);
4442 s390_ngr (code, ins->dreg, s390_r0);
4444 case OP_FCONV_TO_U2:
4445 if (mono_hwcap_s390x_has_fpe) {
4446 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4447 s390_llill (code, s390_r0, 0xffff);
4448 s390_ngr (code, ins->dreg, s390_r0);
4450 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 2, FALSE);
4453 case OP_FCONV_TO_I4:
4455 s390_cfdbr (code, ins->dreg, 5, ins->sreg1);
4457 case OP_FCONV_TO_U4:
4459 if (mono_hwcap_s390x_has_fpe) {
4460 s390_clfdbr (code, ins->dreg, 5, ins->sreg1, 0);
4462 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE);
4465 case OP_FCONV_TO_I8:
4466 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4468 case OP_FCONV_TO_U8:
4469 if (mono_hwcap_s390x_has_fpe) {
4470 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4472 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 8, FALSE);
4475 case OP_LCONV_TO_OVF_I: {
4476 /* Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000 */
4478 s390_ltgr (code, ins->sreg2, ins->sreg2);
4479 s390_jnl (code, 0); CODEPTR(code, o[0]);
4480 s390_ltgr (code, ins->sreg1, ins->sreg1);
4481 s390_jnl (code, 0); CODEPTR(code, o[1]);
4482 s390_lhi (code, s390_r13, -1);
4483 s390_cgr (code, ins->sreg1, s390_r13);
4484 s390_jnz (code, 0); CODEPTR(code, o[2]);
4485 if (ins->dreg != ins->sreg2)
4486 s390_lgr (code, ins->dreg, ins->sreg2);
4487 s390_j (code, 0); CODEPTR(code, o[3]);
4488 PTRSLOT(code, o[0]);
4489 s390_jz (code, 0); CODEPTR(code, o[4]);
4490 PTRSLOT(code, o[1]);
4491 PTRSLOT(code, o[2]);
4492 mono_add_patch_info (cfg, code - cfg->native_code,
4493 MONO_PATCH_INFO_EXC, "OverflowException");
4494 s390_brasl (code, s390_r14, 0);
4495 PTRSLOT(code, o[3]);
4496 PTRSLOT(code, o[4]);
4500 s390_lpdbr (code, ins->dreg, ins->sreg1);
4504 s390_sqdbr (code, ins->dreg, ins->sreg1);
4509 s390_adbr (code, ins->dreg, src2);
4513 CHECK_SRCDST_NCOM_F;
4514 s390_sdbr (code, ins->dreg, src2);
4519 s390_mdbr (code, ins->dreg, src2);
4523 CHECK_SRCDST_NCOM_F;
4524 s390_ddbr (code, ins->dreg, src2);
4528 s390_lcdbr (code, ins->dreg, ins->sreg1);
4532 CHECK_SRCDST_NCOM_F;
4533 s390_didbr (code, ins->dreg, src2, 5, s390_f15);
4537 s390_cdbr (code, ins->sreg1, ins->sreg2);
4541 s390_cdbr (code, ins->sreg1, ins->sreg2);
4542 s390_lghi (code, ins->dreg, 1);
4544 s390_lghi (code, ins->dreg, 0);
4548 s390_cdbr (code, ins->sreg1, ins->sreg2);
4549 s390_lghi (code, ins->dreg, 1);
4551 s390_lghi (code, ins->dreg, 0);
4555 s390_cdbr (code, ins->sreg1, ins->sreg2);
4556 s390_lghi (code, ins->dreg, 1);
4558 s390_lghi (code, ins->dreg, 0);
4562 s390_cdbr (code, ins->sreg1, ins->sreg2);
4563 s390_lghi (code, ins->dreg, 1);
4565 s390_lghi (code, ins->dreg, 0);
4569 s390_cdbr (code, ins->sreg1, ins->sreg2);
4570 s390_lghi (code, ins->dreg, 1);
4572 s390_lghi (code, ins->dreg, 0);
4577 s390_jo (code, 0); CODEPTR(code, o);
4578 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4583 EMIT_COND_BRANCH (ins, S390_CC_NE|S390_CC_OV);
4587 s390_jo (code, 0); CODEPTR(code, o);
4588 EMIT_COND_BRANCH (ins, S390_CC_LT);
4593 EMIT_COND_BRANCH (ins, S390_CC_LT|S390_CC_OV);
4597 s390_jo (code, 0); CODEPTR(code, o);
4598 EMIT_COND_BRANCH (ins, S390_CC_GT);
4603 EMIT_COND_BRANCH (ins, S390_CC_GT|S390_CC_OV);
4607 s390_jo (code, 0); CODEPTR(code, o);
4608 EMIT_COND_BRANCH (ins, S390_CC_GE);
4613 EMIT_COND_BRANCH (ins, S390_CC_GE|S390_CC_OV);
4617 s390_jo (code, 0); CODEPTR(code, o);
4618 EMIT_COND_BRANCH (ins, S390_CC_LE);
4623 EMIT_COND_BRANCH (ins, S390_CC_LE|S390_CC_OV);
4627 s390_lhi (code, s390_r13, 0x7f);
4628 s390_tcdb (code, ins->sreg1, 0, s390_r13, 0);
4629 s390_jz (code, 0); CODEPTR(code, o);
4630 mono_add_patch_info (cfg, code - cfg->native_code,
4631 MONO_PATCH_INFO_EXC, "OverflowException");
4632 s390_brasl (code, s390_r14,0);
4636 case OP_S390_MOVE: {
4637 if (ins->backend.size > 0) {
4638 if (ins->backend.size <= 256) {
4639 s390_mvc (code, ins->backend.size, ins->dreg,
4640 ins->inst_offset, ins->sreg1, ins->inst_imm);
4642 s390_lgr (code, s390_r0, ins->dreg);
4643 if (ins->inst_offset > 0) {
4644 if (s390_is_imm16 (ins->inst_offset)) {
4645 s390_aghi (code, s390_r0, ins->inst_offset);
4646 } else if (s390_is_imm32 (ins->inst_offset)) {
4647 s390_agfi (code, s390_r0, ins->inst_offset);
4649 S390_SET (code, s390_r13, ins->inst_offset);
4650 s390_agr (code, s390_r0, s390_r13);
4653 s390_lgr (code, s390_r12, ins->sreg1);
4654 if (ins->inst_imm > 0) {
4655 if (s390_is_imm16 (ins->inst_imm)) {
4656 s390_aghi (code, s390_r12, ins->inst_imm);
4657 } else if (s390_is_imm32 (ins->inst_imm)) {
4658 s390_agfi (code, s390_r12, ins->inst_imm);
4660 S390_SET (code, s390_r13, ins->inst_imm);
4661 s390_agr (code, s390_r12, s390_r13);
4664 if (s390_is_imm16 (ins->backend.size)) {
4665 s390_lghi (code, s390_r1, ins->backend.size);
4666 } else if (s390_is_imm32 (ins->inst_offset)) {
4667 s390_agfi (code, s390_r1, ins->backend.size);
4669 S390_SET (code, s390_r13, ins->backend.size);
4670 s390_agr (code, s390_r1, s390_r13);
4672 s390_lgr (code, s390_r13, s390_r1);
4673 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4679 case OP_ATOMIC_ADD_I8: {
4680 s390_lgr (code, s390_r1, ins->sreg2);
4681 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4682 s390_agr (code, s390_r1, s390_r0);
4683 s390_csg (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4684 s390_jnz (code, -10);
4685 s390_lgr (code, ins->dreg, s390_r1);
4688 case OP_ATOMIC_EXCHANGE_I8: {
4689 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4690 s390_csg (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
4691 s390_jnz (code, -6);
4692 s390_lgr (code, ins->dreg, s390_r0);
4695 case OP_ATOMIC_ADD_I4: {
4696 s390_lgfr(code, s390_r1, ins->sreg2);
4697 s390_lgf (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4698 s390_agr (code, s390_r1, s390_r0);
4699 s390_cs (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4700 s390_jnz (code, -9);
4701 s390_lgfr(code, ins->dreg, s390_r1);
4704 case OP_ATOMIC_EXCHANGE_I4: {
4705 s390_l (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4706 s390_cs (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
4707 s390_jnz (code, -4);
4708 s390_lgfr(code, ins->dreg, s390_r0);
4711 case OP_S390_BKCHAIN: {
4712 s390_lgr (code, ins->dreg, ins->sreg1);
4713 if (s390_is_imm16 (cfg->stack_offset)) {
4714 s390_aghi (code, ins->dreg, cfg->stack_offset);
4715 } else if (s390_is_imm32 (cfg->stack_offset)) {
4716 s390_agfi (code, ins->dreg, cfg->stack_offset);
4718 S390_SET (code, s390_r13, cfg->stack_offset);
4719 s390_agr (code, ins->dreg, s390_r13);
4723 case OP_MEMORY_BARRIER:
4726 case OP_GC_SAFE_POINT: {
4729 g_assert (mono_threads_is_coop_enabled ());
4731 s390_chi (code, ins->sreg1, 1);
4732 s390_je (code, 0); CODEPTR(code, br);
4733 mono_add_patch_info (cfg, code- cfg->native_code, MONO_PATCH_INFO_ABS,
4734 mono_threads_state_poll);
4735 S390_CALL_TEMPLATE (code, s390_r14);
4739 case OP_GC_LIVENESS_DEF:
4740 case OP_GC_LIVENESS_USE:
4741 case OP_GC_PARAM_SLOT_LIVENESS_DEF:
4742 ins->backend.pc_offset = code - cfg->native_code;
4744 case OP_GC_SPILL_SLOT_LIVENESS_DEF:
4745 ins->backend.pc_offset = code - cfg->native_code;
4746 bb->spill_slot_defs = g_slist_prepend_mempool (cfg->mempool, bb->spill_slot_defs, ins);
4748 #ifdef MONO_ARCH_SIMD_INTRINSICS
4750 s390x_addps (code, ins->sreg1, ins->sreg2);
4753 s390x_divps (code, ins->sreg1, ins->sreg2);
4756 s390x_mulps (code, ins->sreg1, ins->sreg2);
4759 s390x_subps (code, ins->sreg1, ins->sreg2);
4762 s390x_maxps (code, ins->sreg1, ins->sreg2);
4765 s390x_minps (code, ins->sreg1, ins->sreg2);
4768 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
4769 s390x_cmpps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4772 s390x_andps (code, ins->sreg1, ins->sreg2);
4775 s390x_andnps (code, ins->sreg1, ins->sreg2);
4778 s390x_orps (code, ins->sreg1, ins->sreg2);
4781 s390x_xorps (code, ins->sreg1, ins->sreg2);
4784 s390x_sqrtps (code, ins->dreg, ins->sreg1);
4787 s390x_rsqrtps (code, ins->dreg, ins->sreg1);
4790 s390x_rcpps (code, ins->dreg, ins->sreg1);
4793 s390x_addsubps (code, ins->sreg1, ins->sreg2);
4796 s390x_haddps (code, ins->sreg1, ins->sreg2);
4799 s390x_hsubps (code, ins->sreg1, ins->sreg2);
4802 s390x_movshdup (code, ins->dreg, ins->sreg1);
4805 s390x_movsldup (code, ins->dreg, ins->sreg1);
4808 case OP_PSHUFLEW_HIGH:
4809 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4810 s390x_pshufhw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4812 case OP_PSHUFLEW_LOW:
4813 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4814 s390x_pshuflw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4817 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4818 s390x_pshufd_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4821 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4822 s390x_shufps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4825 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0x3);
4826 s390x_shufpd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4830 s390x_addpd (code, ins->sreg1, ins->sreg2);
4833 s390x_divpd (code, ins->sreg1, ins->sreg2);
4836 s390x_mulpd (code, ins->sreg1, ins->sreg2);
4839 s390x_subpd (code, ins->sreg1, ins->sreg2);
4842 s390x_maxpd (code, ins->sreg1, ins->sreg2);
4845 s390x_minpd (code, ins->sreg1, ins->sreg2);
4848 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
4849 s390x_cmppd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4852 s390x_andpd (code, ins->sreg1, ins->sreg2);
4855 s390x_andnpd (code, ins->sreg1, ins->sreg2);
4858 s390x_orpd (code, ins->sreg1, ins->sreg2);
4861 s390x_xorpd (code, ins->sreg1, ins->sreg2);
4864 s390x_sqrtpd (code, ins->dreg, ins->sreg1);
4867 s390x_addsubpd (code, ins->sreg1, ins->sreg2);
4870 s390x_haddpd (code, ins->sreg1, ins->sreg2);
4873 s390x_hsubpd (code, ins->sreg1, ins->sreg2);
4876 s390x_movddup (code, ins->dreg, ins->sreg1);
4879 case OP_EXTRACT_MASK:
4880 s390x_pmovmskb (code, ins->dreg, ins->sreg1);
4884 s390x_pand (code, ins->sreg1, ins->sreg2);
4887 s390x_por (code, ins->sreg1, ins->sreg2);
4890 s390x_pxor (code, ins->sreg1, ins->sreg2);
4894 s390x_paddb (code, ins->sreg1, ins->sreg2);
4897 s390x_paddw (code, ins->sreg1, ins->sreg2);
4900 s390x_paddd (code, ins->sreg1, ins->sreg2);
4903 s390x_paddq (code, ins->sreg1, ins->sreg2);
4907 s390x_psubb (code, ins->sreg1, ins->sreg2);
4910 s390x_psubw (code, ins->sreg1, ins->sreg2);
4913 s390x_psubd (code, ins->sreg1, ins->sreg2);
4916 s390x_psubq (code, ins->sreg1, ins->sreg2);
4920 s390x_pmaxub (code, ins->sreg1, ins->sreg2);
4923 s390x_pmaxuw (code, ins->sreg1, ins->sreg2);
4926 s390x_pmaxud (code, ins->sreg1, ins->sreg2);
4930 s390x_pmaxsb (code, ins->sreg1, ins->sreg2);
4933 s390x_pmaxsw (code, ins->sreg1, ins->sreg2);
4936 s390x_pmaxsd (code, ins->sreg1, ins->sreg2);
4940 s390x_pavgb (code, ins->sreg1, ins->sreg2);
4943 s390x_pavgw (code, ins->sreg1, ins->sreg2);
4947 s390x_pminub (code, ins->sreg1, ins->sreg2);
4950 s390x_pminuw (code, ins->sreg1, ins->sreg2);
4953 s390x_pminud (code, ins->sreg1, ins->sreg2);
4957 s390x_pminsb (code, ins->sreg1, ins->sreg2);
4960 s390x_pminsw (code, ins->sreg1, ins->sreg2);
4963 s390x_pminsd (code, ins->sreg1, ins->sreg2);
4967 s390x_pcmpeqb (code, ins->sreg1, ins->sreg2);
4970 s390x_pcmpeqw (code, ins->sreg1, ins->sreg2);
4973 s390x_pcmpeqd (code, ins->sreg1, ins->sreg2);
4976 s390x_pcmpeqq (code, ins->sreg1, ins->sreg2);
4980 s390x_pcmpgtb (code, ins->sreg1, ins->sreg2);
4983 s390x_pcmpgtw (code, ins->sreg1, ins->sreg2);
4986 s390x_pcmpgtd (code, ins->sreg1, ins->sreg2);
4989 s390x_pcmpgtq (code, ins->sreg1, ins->sreg2);
4992 case OP_PSUM_ABS_DIFF:
4993 s390x_psadbw (code, ins->sreg1, ins->sreg2);
4996 case OP_UNPACK_LOWB:
4997 s390x_punpcklbw (code, ins->sreg1, ins->sreg2);
4999 case OP_UNPACK_LOWW:
5000 s390x_punpcklwd (code, ins->sreg1, ins->sreg2);
5002 case OP_UNPACK_LOWD:
5003 s390x_punpckldq (code, ins->sreg1, ins->sreg2);
5005 case OP_UNPACK_LOWQ:
5006 s390x_punpcklqdq (code, ins->sreg1, ins->sreg2);
5008 case OP_UNPACK_LOWPS:
5009 s390x_unpcklps (code, ins->sreg1, ins->sreg2);
5011 case OP_UNPACK_LOWPD:
5012 s390x_unpcklpd (code, ins->sreg1, ins->sreg2);
5015 case OP_UNPACK_HIGHB:
5016 s390x_punpckhbw (code, ins->sreg1, ins->sreg2);
5018 case OP_UNPACK_HIGHW:
5019 s390x_punpckhwd (code, ins->sreg1, ins->sreg2);
5021 case OP_UNPACK_HIGHD:
5022 s390x_punpckhdq (code, ins->sreg1, ins->sreg2);
5024 case OP_UNPACK_HIGHQ:
5025 s390x_punpckhqdq (code, ins->sreg1, ins->sreg2);
5027 case OP_UNPACK_HIGHPS:
5028 s390x_unpckhps (code, ins->sreg1, ins->sreg2);
5030 case OP_UNPACK_HIGHPD:
5031 s390x_unpckhpd (code, ins->sreg1, ins->sreg2);
5035 s390x_packsswb (code, ins->sreg1, ins->sreg2);
5038 s390x_packssdw (code, ins->sreg1, ins->sreg2);
5041 s390x_packuswb (code, ins->sreg1, ins->sreg2);
5044 s390x_packusdw (code, ins->sreg1, ins->sreg2);
5047 case OP_PADDB_SAT_UN:
5048 s390x_paddusb (code, ins->sreg1, ins->sreg2);
5050 case OP_PSUBB_SAT_UN:
5051 s390x_psubusb (code, ins->sreg1, ins->sreg2);
5053 case OP_PADDW_SAT_UN:
5054 s390x_paddusw (code, ins->sreg1, ins->sreg2);
5056 case OP_PSUBW_SAT_UN:
5057 s390x_psubusw (code, ins->sreg1, ins->sreg2);
5061 s390x_paddsb (code, ins->sreg1, ins->sreg2);
5064 s390x_psubsb (code, ins->sreg1, ins->sreg2);
5067 s390x_paddsw (code, ins->sreg1, ins->sreg2);
5070 s390x_psubsw (code, ins->sreg1, ins->sreg2);
5074 s390x_pmullw (code, ins->sreg1, ins->sreg2);
5077 s390x_pmulld (code, ins->sreg1, ins->sreg2);
5080 s390x_pmuludq (code, ins->sreg1, ins->sreg2);
5082 case OP_PMULW_HIGH_UN:
5083 s390x_pmulhuw (code, ins->sreg1, ins->sreg2);
5086 s390x_pmulhw (code, ins->sreg1, ins->sreg2);
5090 s390x_psrlw_reg_imm (code, ins->dreg, ins->inst_imm);
5093 s390x_psrlw (code, ins->dreg, ins->sreg2);
5097 s390x_psraw_reg_imm (code, ins->dreg, ins->inst_imm);
5100 s390x_psraw (code, ins->dreg, ins->sreg2);
5104 s390x_psllw_reg_imm (code, ins->dreg, ins->inst_imm);
5107 s390x_psllw (code, ins->dreg, ins->sreg2);
5111 s390x_psrld_reg_imm (code, ins->dreg, ins->inst_imm);
5114 s390x_psrld (code, ins->dreg, ins->sreg2);
5118 s390x_psrad_reg_imm (code, ins->dreg, ins->inst_imm);
5121 s390x_psrad (code, ins->dreg, ins->sreg2);
5125 s390x_pslld_reg_imm (code, ins->dreg, ins->inst_imm);
5128 s390x_pslld (code, ins->dreg, ins->sreg2);
5132 s390x_psrlq_reg_imm (code, ins->dreg, ins->inst_imm);
5135 s390x_psrlq (code, ins->dreg, ins->sreg2);
5138 /*TODO: This is appart of the sse spec but not added
5140 s390x_psraq_reg_imm (code, ins->dreg, ins->inst_imm);
5143 s390x_psraq (code, ins->dreg, ins->sreg2);
5148 s390x_psllq_reg_imm (code, ins->dreg, ins->inst_imm);
5151 s390x_psllq (code, ins->dreg, ins->sreg2);
5154 s390x_cvtdq2pd (code, ins->dreg, ins->sreg1);
5157 s390x_cvtdq2ps (code, ins->dreg, ins->sreg1);
5160 s390x_cvtpd2dq (code, ins->dreg, ins->sreg1);
5163 s390x_cvtpd2ps (code, ins->dreg, ins->sreg1);
5166 s390x_cvtps2dq (code, ins->dreg, ins->sreg1);
5169 s390x_cvtps2pd (code, ins->dreg, ins->sreg1);
5172 s390x_cvttpd2dq (code, ins->dreg, ins->sreg1);
5175 s390x_cvttps2dq (code, ins->dreg, ins->sreg1);
5179 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5182 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5186 amd64_movhlps (code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg1);
5187 amd64_movd_reg_xreg_size (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG, 8);
5189 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 8);
5194 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5196 amd64_shift_reg_imm (code, X86_SHR, ins->dreg, ins->inst_c0 * 8);
5197 amd64_widen_reg (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I1, FALSE);
5201 /*amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5203 amd64_shift_reg_imm_size (code, X86_SHR, ins->dreg, 16, 4);*/
5204 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5205 amd64_widen_reg_size (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I2, TRUE, 4);
5209 amd64_movhlps (code, ins->dreg, ins->sreg1);
5211 s390x_movsd (code, ins->dreg, ins->sreg1);
5214 s390x_pinsrw_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5216 case OP_EXTRACTX_U2:
5217 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5219 case OP_INSERTX_U1_SLOW:
5220 /*sreg1 is the extracted ireg (scratch)
5221 /sreg2 is the to be inserted ireg (scratch)
5222 /dreg is the xreg to receive the value*/
5224 /*clear the bits from the extracted word*/
5225 amd64_alu_reg_imm (code, X86_AND, ins->sreg1, ins->inst_c0 & 1 ? 0x00FF : 0xFF00);
5226 /*shift the value to insert if needed*/
5227 if (ins->inst_c0 & 1)
5228 amd64_shift_reg_imm_size (code, X86_SHL, ins->sreg2, 8, 4);
5229 /*join them together*/
5230 amd64_alu (code, X86_OR, ins->sreg1, ins->sreg2);
5231 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0 / 2);
5233 case OP_INSERTX_I4_SLOW:
5234 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2);
5235 amd64_shift_reg_imm (code, X86_SHR, ins->sreg2, 16);
5236 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2 + 1);
5238 case OP_INSERTX_I8_SLOW:
5239 amd64_movd_xreg_reg_size(code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg2, 8);
5241 amd64_movlhps (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5243 s390x_movsd (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5246 case OP_INSERTX_R4_SLOW:
5247 switch (ins->inst_c0) {
5250 s390x_movss (code, ins->dreg, ins->sreg2);
5252 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5255 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5257 s390x_movss (code, ins->dreg, ins->sreg2);
5259 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5260 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5263 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5265 s390x_movss (code, ins->dreg, ins->sreg2);
5267 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5268 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5271 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5273 s390x_movss (code, ins->dreg, ins->sreg2);
5275 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5276 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5280 case OP_INSERTX_R8_SLOW:
5282 amd64_movlhps (code, ins->dreg, ins->sreg2);
5284 s390x_movsd (code, ins->dreg, ins->sreg2);
5286 case OP_STOREX_MEMBASE_REG:
5287 case OP_STOREX_MEMBASE:
5288 s390x_movups_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5290 case OP_LOADX_MEMBASE:
5291 s390x_movups_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5293 case OP_LOADX_ALIGNED_MEMBASE:
5294 s390x_movaps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5296 case OP_STOREX_ALIGNED_MEMBASE_REG:
5297 s390x_movaps_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5299 case OP_STOREX_NTA_MEMBASE_REG:
5300 s390x_movntps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5302 case OP_PREFETCH_MEMBASE:
5303 s390x_prefetch_reg_membase (code, ins->backend.arg_info, ins->sreg1, ins->inst_offset);
5307 /*FIXME the peephole pass should have killed this*/
5308 if (ins->dreg != ins->sreg1)
5309 s390x_movaps (code, ins->dreg, ins->sreg1);
5312 s390x_pxor (code, ins->dreg, ins->dreg);
5314 case OP_ICONV_TO_R4_RAW:
5315 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5318 case OP_FCONV_TO_R8_X:
5319 s390x_movsd (code, ins->dreg, ins->sreg1);
5322 case OP_XCONV_R8_TO_I4:
5323 s390x_cvttsd2si_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5324 switch (ins->backend.source_opcode) {
5325 case OP_FCONV_TO_I1:
5326 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, FALSE);
5328 case OP_FCONV_TO_U1:
5329 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, FALSE);
5331 case OP_FCONV_TO_I2:
5332 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, TRUE);
5334 case OP_FCONV_TO_U2:
5335 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, TRUE);
5341 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 0);
5342 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 1);
5343 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5346 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5347 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5350 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 8);
5351 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5355 s390x_movsd (code, ins->dreg, ins->sreg1);
5357 s390x_movsd (code, ins->dreg, ins->sreg1);
5358 s390x_cvtsd2ss (code, ins->dreg, ins->dreg);
5360 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5363 s390x_movsd (code, ins->dreg, ins->sreg1);
5364 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5368 g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
5369 g_assert_not_reached ();
5372 if ((cfg->opt & MONO_OPT_BRANCH) && ((code - cfg->native_code - offset) > max_len)) {
5373 g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %ld)",
5374 mono_inst_name (ins->opcode), max_len, code - cfg->native_code - offset);
5375 g_assert_not_reached ();
5378 last_offset = offset;
5381 cfg->code_len = code - cfg->native_code;
5384 /*========================= End of Function ========================*/
5386 /*------------------------------------------------------------------*/
5388 /* Name - mono_arch_register_lowlevel_calls */
5390 /* Function - Register routines to help with --trace operation. */
5392 /*------------------------------------------------------------------*/
5395 mono_arch_register_lowlevel_calls (void)
5399 /*========================= End of Function ========================*/
5401 /*------------------------------------------------------------------*/
5403 /* Name - mono_arch_patch_code */
5405 /* Function - Process the patch data created during the */
5406 /* instruction build process. This resolves jumps, */
5407 /* calls, variables etc. */
5409 /*------------------------------------------------------------------*/
5412 mono_arch_patch_code (MonoCompile *cfg, MonoMethod *method, MonoDomain *domain,
5413 guint8 *code, MonoJumpInfo *ji, gboolean run_cctors,
5416 MonoJumpInfo *patch_info;
5420 for (patch_info = ji; patch_info; patch_info = patch_info->next) {
5421 unsigned char *ip = patch_info->ip.i + code;
5422 gconstpointer target = NULL;
5424 target = mono_resolve_patch_target (method, domain, code,
5425 patch_info, run_cctors, error);
5426 return_if_nok (error);
5428 switch (patch_info->type) {
5429 case MONO_PATCH_INFO_IP:
5430 case MONO_PATCH_INFO_LDSTR:
5431 case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
5432 case MONO_PATCH_INFO_LDTOKEN:
5433 case MONO_PATCH_INFO_EXC:
5434 s390_patch_addr (ip, (guint64) target);
5436 case MONO_PATCH_INFO_METHOD:
5437 case MONO_PATCH_INFO_INTERNAL_METHOD:
5438 case MONO_PATCH_INFO_JIT_ICALL_ADDR:
5439 case MONO_PATCH_INFO_RGCTX_FETCH:
5440 case MONO_PATCH_INFO_ABS: {
5441 S390_EMIT_CALL (ip, target);
5444 case MONO_PATCH_INFO_SWITCH:
5445 /*----------------------------------*/
5446 /* ip points at the basr r13,0/j +4 */
5447 /* instruction the vtable value */
5448 /* follows this (i.e. ip+6) */
5449 /*----------------------------------*/
5450 S390_EMIT_LOAD (ip, target);
5452 case MONO_PATCH_INFO_METHODCONST:
5453 case MONO_PATCH_INFO_CLASS:
5454 case MONO_PATCH_INFO_IMAGE:
5455 case MONO_PATCH_INFO_FIELD:
5456 case MONO_PATCH_INFO_IID:
5457 case MONO_PATCH_INFO_EXC_NAME:
5458 target = S390_RELATIVE(target, ip);
5459 s390_patch_rel (ip, (guint64) target);
5461 case MONO_PATCH_INFO_R4:
5462 case MONO_PATCH_INFO_R8:
5463 case MONO_PATCH_INFO_METHOD_REL:
5464 g_assert_not_reached ();
5467 target = S390_RELATIVE(target, ip);
5469 s390_patch_rel (ip, (guint64) target);
5474 /*========================= End of Function ========================*/
5476 /*------------------------------------------------------------------*/
5478 /* Name - emit_load_volatile_arguments */
5480 /* Function - Emit the instructions to reload parameter regist- */
5481 /* registers for use with "tail" operations. */
5483 /* The register loading operations performed here */
5484 /* are the mirror of the store operations performed */
5485 /* in mono_arch_emit_prolog and need to be kept in */
5486 /* synchronization with it. */
5488 /*------------------------------------------------------------------*/
5491 emit_load_volatile_arguments (guint8 *code, MonoCompile *cfg)
5494 MonoMethod *method = cfg->method;
5495 MonoMethodSignature *sig = mono_method_signature(method);
5499 cinfo = get_call_info (NULL, NULL, sig);
5501 if (cinfo->struct_ret) {
5502 ArgInfo *ainfo = &cinfo->ret;
5503 inst = cfg->vret_addr;
5504 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5507 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5508 ArgInfo *ainfo = cinfo->args + i;
5509 inst = cfg->args [pos];
5511 if (inst->opcode == OP_REGVAR) {
5512 if (ainfo->regtype == RegTypeGeneral)
5513 s390_lgr (code, ainfo->reg, inst->dreg);
5514 else if (ainfo->regtype == RegTypeFP) {
5515 if (inst->dreg != ainfo->reg) {
5516 if (ainfo->size == 4) {
5517 s390_ldebr (code, ainfo->reg, inst->dreg);
5519 s390_ldr (code, ainfo->reg, inst->dreg);
5523 else if (ainfo->regtype == RegTypeBase) {
5525 g_assert_not_reached ();
5527 if (ainfo->regtype == RegTypeGeneral) {
5528 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5529 g_assert_not_reached();
5530 switch (ainfo->size) {
5532 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5535 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5538 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5541 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5544 } else if (ainfo->regtype == RegTypeBase) {
5545 } else if (ainfo->regtype == RegTypeFP) {
5546 if (ainfo->size == 8)
5547 s390_ld (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5548 else if (ainfo->size == 4)
5549 s390_le (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5551 g_assert_not_reached ();
5552 } else if (ainfo->regtype == RegTypeStructByVal) {
5553 if (ainfo->reg != STK_BASE) {
5554 switch (ainfo->size) {
5556 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5559 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5562 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5565 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5569 } else if (ainfo->regtype == RegTypeStructByAddr) {
5570 if (ainfo->reg != STK_BASE) {
5571 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5574 g_assert_not_reached ();
5582 /*========================= End of Function ========================*/
5584 /*------------------------------------------------------------------*/
5586 /* Name - mono_arch_emit_prolog */
5588 /* Function - Create the instruction sequence for a function */
5591 /*------------------------------------------------------------------*/
5594 mono_arch_emit_prolog (MonoCompile *cfg)
5596 MonoMethod *method = cfg->method;
5598 MonoMethodSignature *sig;
5600 long alloc_size, pos, max_offset, i, cfa_offset = 0;
5609 cfg->code_size = 512;
5611 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
5613 cfg->code_size += 256;
5614 } else if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
5615 cfg->code_size += 256;
5617 if (method->save_lmf)
5618 cfg->code_size += 200;
5620 cfg->native_code = code = g_malloc (cfg->code_size);
5622 mono_emit_unwind_op_def_cfa (cfg, code, STK_BASE, 0);
5623 emit_unwind_regs(cfg, code, s390_r6, s390_r14, S390_REG_SAVE_OFFSET);
5624 s390_stmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
5625 mono_emit_unwind_op_offset (cfg, code, s390_r14, S390_RET_ADDR_OFFSET);
5626 mini_gc_set_slot_type_from_cfa (cfg, S390_RET_ADDR_OFFSET, SLOT_NOREF);
5628 if (cfg->arch.bkchain_reg != -1)
5629 s390_lgr (code, cfg->arch.bkchain_reg, STK_BASE);
5631 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
5632 cfg->used_int_regs |= 1 << 11;
5635 alloc_size = cfg->stack_offset;
5637 cfg->stack_usage = cfa_offset = alloc_size;
5638 mono_emit_unwind_op_def_cfa_offset (cfg, code, alloc_size);
5639 s390_lgr (code, s390_r11, STK_BASE);
5640 if (s390_is_imm16 (alloc_size)) {
5641 s390_aghi (code, STK_BASE, -alloc_size);
5642 } else if (s390_is_imm32 (alloc_size)) {
5643 s390_agfi (code, STK_BASE, -alloc_size);
5645 int stackSize = alloc_size;
5646 while (stackSize > INT_MAX) {
5647 s390_agfi (code, STK_BASE, -INT_MAX);
5648 stackSize -= INT_MAX;
5650 s390_agfi (code, STK_BASE, -stackSize);
5652 s390_stg (code, s390_r11, 0, STK_BASE, 0);
5654 if (cfg->frame_reg != STK_BASE)
5655 s390_lgr (code, s390_r11, STK_BASE);
5657 mono_emit_unwind_op_def_cfa_reg (cfg, code, cfg->frame_reg);
5659 /* store runtime generic context */
5660 if (cfg->rgctx_var) {
5661 g_assert (cfg->rgctx_var->opcode == OP_REGOFFSET);
5663 s390_stg (code, MONO_ARCH_RGCTX_REG, 0,
5664 cfg->rgctx_var->inst_basereg,
5665 cfg->rgctx_var->inst_offset);
5668 /* compute max_offset in order to use short forward jumps
5669 * we always do it on s390 because the immediate displacement
5670 * for jumps is too small
5673 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
5675 bb->max_offset = max_offset;
5677 if (cfg->prof_options & MONO_PROFILE_COVERAGE)
5680 MONO_BB_FOR_EACH_INS (bb, ins)
5681 max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
5684 /* load arguments allocated to register from the stack */
5685 sig = mono_method_signature (method);
5688 cinfo = get_call_info (cfg, cfg->mempool, sig);
5690 if (cinfo->struct_ret) {
5691 ArgInfo *ainfo = &cinfo->ret;
5692 inst = cfg->vret_addr;
5693 inst->backend.size = ainfo->vtsize;
5694 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5697 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5698 ArgInfo *ainfo = cinfo->args + i;
5699 inst = cfg->args [pos];
5701 if (inst->opcode == OP_VTARG_ADDR)
5702 inst = inst->inst_left;
5704 if (inst->opcode == OP_REGVAR) {
5705 if (ainfo->regtype == RegTypeGeneral)
5706 s390_lgr (code, inst->dreg, ainfo->reg);
5707 else if (ainfo->regtype == RegTypeFP) {
5708 if (inst->dreg != ainfo->reg) {
5709 if (ainfo->size == 4) {
5710 s390_ledbr (code, inst->dreg, ainfo->reg);
5712 s390_ldr (code, inst->dreg, ainfo->reg);
5716 else if (ainfo->regtype == RegTypeBase) {
5717 s390_lgr (code, s390_r13, STK_BASE);
5718 s390_aghi (code, s390_r13, alloc_size);
5719 s390_lg (code, inst->dreg, 0, s390_r13, ainfo->offset);
5721 g_assert_not_reached ();
5723 if (cfg->verbose_level > 2)
5724 g_print ("Argument %d assigned to register %s\n",
5725 pos, mono_arch_regname (inst->dreg));
5727 if (ainfo->regtype == RegTypeGeneral) {
5728 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5729 g_assert_not_reached();
5730 switch (ainfo->size) {
5732 s390_stc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5735 s390_sth (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5738 s390_st (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5741 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5744 } else if (ainfo->regtype == RegTypeBase) {
5745 } else if (ainfo->regtype == RegTypeFP) {
5746 if (ainfo->size == 8)
5747 s390_std (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5748 else if (ainfo->size == 4)
5749 s390_ste (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5751 g_assert_not_reached ();
5752 } else if (ainfo->regtype == RegTypeStructByVal) {
5753 int doffset = inst->inst_offset;
5755 if (ainfo->reg != STK_BASE)
5759 s390_lgr (code, s390_r13, STK_BASE);
5760 s390_aghi (code, s390_r13, alloc_size);
5763 size = (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE
5764 ? mono_class_native_size(mono_class_from_mono_type(inst->inst_vtype), NULL)
5769 if (ainfo->reg == STK_BASE)
5770 s390_ic (code, reg, 0, s390_r13, ainfo->offset+7);
5771 s390_stc (code, reg, 0, inst->inst_basereg, doffset);
5774 if (ainfo->reg == STK_BASE)
5775 s390_lh (code, reg, 0, s390_r13, ainfo->offset+6);
5776 s390_sth (code, reg, 0, inst->inst_basereg, doffset);
5779 if (ainfo->reg == STK_BASE)
5780 s390_l (code, reg, 0, s390_r13, ainfo->offset+4);
5781 s390_st (code, reg, 0, inst->inst_basereg, doffset);
5784 if (ainfo->reg == STK_BASE)
5785 s390_lg (code, reg, 0, s390_r13, ainfo->offset);
5786 s390_stg (code, reg, 0, inst->inst_basereg, doffset);
5789 } else if (ainfo->regtype == RegTypeStructByAddr) {
5790 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5791 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
5793 g_assert_not_reached ();
5798 if (method->save_lmf) {
5799 /*---------------------------------------------------------------*/
5800 /* build the MonoLMF structure on the stack - see mini-s390x.h */
5801 /*---------------------------------------------------------------*/
5802 lmfOffset = alloc_size - sizeof(MonoLMF);
5804 s390_lgr (code, s390_r13, cfg->frame_reg);
5805 s390_aghi (code, s390_r13, lmfOffset);
5807 /*---------------------------------------------------------------*/
5808 /* Preserve the parameter registers while we fix up the lmf */
5809 /*---------------------------------------------------------------*/
5810 s390_stmg (code, s390_r2, s390_r6, s390_r13,
5811 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
5813 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[0]), SLOT_NOREF);
5814 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[1]), SLOT_NOREF);
5815 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[2]), SLOT_NOREF);
5816 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[3]), SLOT_NOREF);
5817 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[4]), SLOT_NOREF);
5819 /*---------------------------------------------------------------*/
5820 /* On return from this call r2 have the address of the &lmf */
5821 /*---------------------------------------------------------------*/
5822 mono_add_patch_info (cfg, code - cfg->native_code,
5823 MONO_PATCH_INFO_INTERNAL_METHOD,
5824 (gpointer)"mono_tls_get_lmf_addr");
5825 S390_CALL_TEMPLATE(code, s390_r1);
5827 /*---------------------------------------------------------------*/
5828 /* Set lmf.lmf_addr = jit_tls->lmf */
5829 /*---------------------------------------------------------------*/
5830 s390_stg (code, s390_r2, 0, s390_r13,
5831 G_STRUCT_OFFSET(MonoLMF, lmf_addr));
5832 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, lmf_addr), SLOT_NOREF);
5834 /*---------------------------------------------------------------*/
5835 /* Get current lmf */
5836 /*---------------------------------------------------------------*/
5837 s390_lg (code, s390_r0, 0, s390_r2, 0);
5839 /*---------------------------------------------------------------*/
5840 /* Set our lmf as the current lmf */
5841 /*---------------------------------------------------------------*/
5842 s390_stg (code, s390_r13, 0, s390_r2, 0);
5844 /*---------------------------------------------------------------*/
5845 /* Have our lmf.previous_lmf point to the last lmf */
5846 /*---------------------------------------------------------------*/
5847 s390_stg (code, s390_r0, 0, s390_r13,
5848 G_STRUCT_OFFSET(MonoLMF, previous_lmf));
5849 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), SLOT_NOREF);
5851 /*---------------------------------------------------------------*/
5852 /* save method info */
5853 /*---------------------------------------------------------------*/
5854 S390_SET (code, s390_r1, method);
5855 s390_stg (code, s390_r1, 0, s390_r13,
5856 G_STRUCT_OFFSET(MonoLMF, method));
5857 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, method), SLOT_NOREF);
5859 /*---------------------------------------------------------------*/
5860 /* save the current IP */
5861 /*---------------------------------------------------------------*/
5862 s390_stg (code, STK_BASE, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp));
5863 s390_basr (code, s390_r1, 0);
5864 s390_stg (code, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip));
5865 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, ebp), SLOT_NOREF);
5866 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, eip), SLOT_NOREF);
5868 /*---------------------------------------------------------------*/
5869 /* Save general and floating point registers */
5870 /*---------------------------------------------------------------*/
5871 s390_stmg (code, s390_r2, s390_r12, s390_r13,
5872 G_STRUCT_OFFSET(MonoLMF, gregs[2]));
5873 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[0]), SLOT_NOREF);
5874 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[1]), SLOT_NOREF);
5875 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[2]), SLOT_NOREF);
5876 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[3]), SLOT_NOREF);
5877 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[4]), SLOT_NOREF);
5878 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[5]), SLOT_NOREF);
5879 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[6]), SLOT_NOREF);
5880 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[7]), SLOT_NOREF);
5881 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[8]), SLOT_NOREF);
5882 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[9]), SLOT_NOREF);
5883 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[10]), SLOT_NOREF);
5885 fpOffset = lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, fregs[0]);
5886 for (i = 0; i < 16; i++) {
5887 s390_std (code, i, 0, s390_r13,
5888 G_STRUCT_OFFSET(MonoLMF, fregs[i]));
5889 mini_gc_set_slot_type_from_fp (cfg, fpOffset, SLOT_NOREF);
5890 fpOffset += sizeof(double);
5893 /*---------------------------------------------------------------*/
5894 /* Restore the parameter registers now that we've set up the lmf */
5895 /*---------------------------------------------------------------*/
5896 s390_lmg (code, s390_r2, s390_r6, s390_r13,
5897 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
5900 if (cfg->method->save_lmf)
5901 argsClobbered = TRUE;
5904 argsClobbered = TRUE;
5905 code = mono_arch_instrument_prolog (cfg, enter_method, code, TRUE);
5908 if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
5909 argsClobbered = TRUE;
5912 * Optimize the common case of the first bblock making a call with the same
5913 * arguments as the method. This works because the arguments are still in their
5914 * original argument registers.
5916 if (!argsClobbered) {
5917 MonoBasicBlock *first_bb = cfg->bb_entry;
5919 int filter = FILTER_IL_SEQ_POINT;
5921 next = mono_bb_first_inst (first_bb, filter);
5922 if (!next && first_bb->next_bb) {
5923 first_bb = first_bb->next_bb;
5924 next = mono_bb_first_inst (first_bb, filter);
5927 if (first_bb->in_count > 1)
5930 for (i = 0; next && i < sig->param_count + sig->hasthis; ++i) {
5931 ArgInfo *ainfo = cinfo->args + i;
5932 gboolean match = FALSE;
5934 inst = cfg->args [i];
5935 if (inst->opcode != OP_REGVAR) {
5936 switch (ainfo->regtype) {
5937 case RegTypeGeneral: {
5938 if (((next->opcode == OP_LOAD_MEMBASE) ||
5939 (next->opcode == OP_LOADI4_MEMBASE)) &&
5940 next->inst_basereg == inst->inst_basereg &&
5941 next->inst_offset == inst->inst_offset) {
5942 if (next->dreg == ainfo->reg) {
5946 next->opcode = OP_MOVE;
5947 next->sreg1 = ainfo->reg;
5948 /* Only continue if the instruction doesn't change argument regs */
5949 if (next->dreg == ainfo->reg)
5959 /* Argument allocated to (non-volatile) register */
5960 switch (ainfo->regtype) {
5961 case RegTypeGeneral:
5962 if (next->opcode == OP_MOVE &&
5963 next->sreg1 == inst->dreg &&
5964 next->dreg == ainfo->reg) {
5975 next = mono_inst_next (next, filter);
5982 cfg->code_len = code - cfg->native_code;
5983 g_assert (cfg->code_len < cfg->code_size);
5988 /*========================= End of Function ========================*/
5990 /*------------------------------------------------------------------*/
5992 /* Name - mono_arch_emit_epilog */
5994 /* Function - Emit the instructions for a function epilog. */
5996 /*------------------------------------------------------------------*/
5999 mono_arch_emit_epilog (MonoCompile *cfg)
6001 MonoMethod *method = cfg->method;
6004 int max_epilog_size = 96;
6006 if (cfg->method->save_lmf)
6007 max_epilog_size += 128;
6009 if (mono_jit_trace_calls != NULL)
6010 max_epilog_size += 128;
6011 else if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
6012 max_epilog_size += 128;
6014 while ((cfg->code_len + max_epilog_size) > (cfg->code_size - 16)) {
6015 cfg->code_size *= 2;
6016 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6017 cfg->stat_code_reallocs++;
6020 code = cfg->native_code + cfg->code_len;
6022 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
6023 code = mono_arch_instrument_epilog (cfg, leave_method, code, TRUE);
6027 if (method->save_lmf)
6028 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
6030 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
6031 s390_lg (code, STK_BASE, 0, STK_BASE, 0);
6033 code = backUpStackPtr(cfg, code);
6035 s390_lmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
6036 s390_br (code, s390_r14);
6038 cfg->code_len = code - cfg->native_code;
6040 g_assert (cfg->code_len < cfg->code_size);
6044 /*========================= End of Function ========================*/
6046 /*------------------------------------------------------------------*/
6048 /* Name - mono_arch_emit_exceptions */
6050 /* Function - Emit the blocks to handle exception conditions. */
6052 /*------------------------------------------------------------------*/
6055 mono_arch_emit_exceptions (MonoCompile *cfg)
6057 MonoJumpInfo *patch_info;
6063 MonoClass *exc_classes [MAX_EXC];
6064 guint8 *exc_throw_start [MAX_EXC];
6066 for (patch_info = cfg->patch_info;
6068 patch_info = patch_info->next) {
6069 if (patch_info->type == MONO_PATCH_INFO_EXC)
6073 code_size = exc_count * 48;
6075 while ((cfg->code_len + code_size) > (cfg->code_size - 16)) {
6076 cfg->code_size *= 2;
6077 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6078 cfg->stat_code_reallocs++;
6081 code = cfg->native_code + cfg->code_len;
6083 /*---------------------------------------------------------------------*/
6084 /* Add code to raise exceptions */
6085 /*---------------------------------------------------------------------*/
6086 for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
6087 switch (patch_info->type) {
6088 case MONO_PATCH_INFO_EXC: {
6089 guint8 *ip = patch_info->ip.i + cfg->native_code;
6090 MonoClass *exc_class;
6093 /*-----------------------------------------------------*/
6094 /* Patch the branch in epilog to come here */
6095 /*-----------------------------------------------------*/
6096 s390_patch_rel (ip + 2, (guint64) S390_RELATIVE(code,ip));
6098 exc_class = mono_class_load_from_name (mono_defaults.corlib,
6100 patch_info->data.name);
6101 throw_ip = patch_info->ip.i;
6103 for (iExc = 0; iExc < nThrows; ++iExc)
6104 if (exc_classes [iExc] == exc_class)
6107 if (iExc < nThrows) {
6108 s390_jcl (code, S390_CC_UN,
6109 (guint64) exc_throw_start [iExc]);
6110 patch_info->type = MONO_PATCH_INFO_NONE;
6113 if (nThrows < MAX_EXC) {
6114 exc_classes [nThrows] = exc_class;
6115 exc_throw_start [nThrows] = code;
6118 /*---------------------------------------------*/
6119 /* Patch the parameter passed to the handler */
6120 /*---------------------------------------------*/
6121 S390_SET (code, s390_r2, exc_class->type_token);
6122 /*---------------------------------------------*/
6123 /* Load return address & parameter register */
6124 /*---------------------------------------------*/
6125 s390_larl (code, s390_r14, (guint64)S390_RELATIVE((patch_info->ip.i +
6126 cfg->native_code + 8), code));
6127 /*---------------------------------------------*/
6128 /* Reuse the current patch to set the jump */
6129 /*---------------------------------------------*/
6130 patch_info->type = MONO_PATCH_INFO_INTERNAL_METHOD;
6131 patch_info->data.name = "mono_arch_throw_corlib_exception";
6132 patch_info->ip.i = code - cfg->native_code;
6133 S390_BR_TEMPLATE (code, s390_r1);
6143 cfg->code_len = code - cfg->native_code;
6145 g_assert (cfg->code_len < cfg->code_size);
6149 /*========================= End of Function ========================*/
6151 /*------------------------------------------------------------------*/
6153 /* Name - mono_arch_finish_init */
6155 /* Function - Setup the JIT's Thread Level Specific Data. */
6157 /*------------------------------------------------------------------*/
6160 mono_arch_finish_init (void)
6164 /*========================= End of Function ========================*/
6166 /*------------------------------------------------------------------*/
6168 /* Name - mono_arch_free_jit_tls_data */
6170 /* Function - Free tls data. */
6172 /*------------------------------------------------------------------*/
6175 mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
6179 /*========================= End of Function ========================*/
6181 /*------------------------------------------------------------------*/
6183 /* Name - mono_arch_emit_inst_for_method */
6185 /*------------------------------------------------------------------*/
6188 mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
6193 /*========================= End of Function ========================*/
6195 /*------------------------------------------------------------------*/
6197 /* Name - mono_arch_decompose_opts */
6199 /* Function - Decompose opcode into a System z opcode. */
6201 /*------------------------------------------------------------------*/
6204 mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
6207 * Have to rename these to avoid being decomposed normally, since the normal
6208 * decomposition does not work on S390.
6210 switch (ins->opcode) {
6212 ins->opcode = OP_S390_ISUB_OVF;
6214 case OP_ISUB_OVF_UN:
6215 ins->opcode = OP_S390_ISUB_OVF_UN;
6218 ins->opcode = OP_S390_IADD_OVF;
6220 case OP_IADD_OVF_UN:
6221 ins->opcode = OP_S390_IADD_OVF_UN;
6224 ins->opcode = OP_S390_LADD_OVF;
6226 case OP_LADD_OVF_UN:
6227 ins->opcode = OP_S390_LADD_OVF_UN;
6230 ins->opcode = OP_S390_LSUB_OVF;
6232 case OP_LSUB_OVF_UN:
6233 ins->opcode = OP_S390_LSUB_OVF_UN;
6240 /*========================= End of Function ========================*/
6242 /*------------------------------------------------------------------*/
6244 /* Name - mono_arch_print_tree */
6246 /* Function - Print platform-specific opcode details. */
6248 /* Returns - 1 - opcode details have been printed */
6249 /* 0 - opcode details have not been printed */
6251 /*------------------------------------------------------------------*/
6254 mono_arch_print_tree (MonoInst *tree, int arity)
6258 switch (tree->opcode) {
6259 case OP_S390_LOADARG:
6260 case OP_S390_ARGREG:
6261 case OP_S390_ARGPTR:
6262 printf ("[0x%lx(%s)]", tree->inst_offset,
6263 mono_arch_regname (tree->inst_basereg));
6266 case OP_S390_STKARG:
6267 printf ("[0x%lx(previous_frame)]",
6272 printf ("[0x%lx(%d,%s),0x%lx(%s)]",
6273 tree->inst_offset, tree->backend.size,
6274 mono_arch_regname(tree->dreg),
6276 mono_arch_regname(tree->sreg1));
6279 case OP_S390_SETF4RET:
6280 printf ("[f%s,f%s]",
6281 mono_arch_regname (tree->dreg),
6282 mono_arch_regname (tree->sreg1));
6286 printf ("[0x%lx(0x%lx,%s)]", tree->inst_offset,
6288 mono_arch_regname (tree->sreg1));
6292 printf ("[0x%lx(0x%lx,%s)]", tree->inst_offset,
6294 mono_arch_regname (tree->sreg1));
6297 case OP_S390_BKCHAIN:
6298 printf ("[previous_frame(%s)]",
6299 mono_arch_regname (tree->sreg1));
6307 /*========================= End of Function ========================*/
6309 /*------------------------------------------------------------------*/
6311 /* Name - mono_arch_regalloc_cost */
6313 /* Function - Determine the cost, in the number of memory */
6314 /* references, of the action of allocating the var- */
6315 /* iable VMV into a register during global register */
6318 /* Returns - Cost */
6320 /*------------------------------------------------------------------*/
6323 mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
6329 /*========================= End of Function ========================*/
6331 /*------------------------------------------------------------------*/
6333 /* Name - mono_arch_flush_register_windows */
6339 /*------------------------------------------------------------------*/
6342 mono_arch_flush_register_windows (void)
6346 /*========================= End of Function ========================*/
6348 /*------------------------------------------------------------------*/
6350 /* Name - mono_arch_is_inst_imm */
6352 /* Function - Determine if operand qualifies as an immediate */
6353 /* value. For s390 this is a value -32768-32768 */
6355 /* Returns - True|False - is [not] immediate value. */
6357 /*------------------------------------------------------------------*/
6360 mono_arch_is_inst_imm (gint64 imm)
6362 return s390_is_imm32 (imm);
6365 /*========================= End of Function ========================*/
6367 /*------------------------------------------------------------------*/
6369 /* Name - mono_arch_get_patch_offset */
6371 /* Function - Dummy entry point until s390x supports aot. */
6373 /* Returns - Offset for patch. */
6375 /*------------------------------------------------------------------*/
6378 mono_arch_get_patch_offset (guint8 *code)
6383 /*========================= End of Function ========================*/
6385 /*------------------------------------------------------------------*/
6387 /* Name - mono_arch_context_get_int_reg. */
6391 /* Returns - Return a register from the context. */
6393 /*------------------------------------------------------------------*/
6396 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
6398 return ((mgreg_t) ctx->uc_mcontext.gregs[reg]);
6401 /*========================= End of Function ========================*/
6403 /*------------------------------------------------------------------*/
6405 /* Name - mono_arch_context_set_int_reg. */
6407 /* Function - Set a value in a specified register. */
6409 /*------------------------------------------------------------------*/
6412 mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val)
6414 ctx->uc_mcontext.gregs[reg] = val;
6417 /*========================= End of Function ========================*/
6419 /*------------------------------------------------------------------*/
6421 /* Name - mono_arch_get_this_arg_from_call. */
6425 /*------------------------------------------------------------------*/
6428 mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
6430 return (gpointer) regs [s390_r2];
6433 /*========================= End of Function ========================*/
6435 /*------------------------------------------------------------------*/
6437 /* Name - mono_arch_install_handler_block_guard */
6441 /*------------------------------------------------------------------*/
6444 mono_arch_install_handler_block_guard (MonoJitInfo *ji, MonoJitExceptionInfo *clause,
6445 MonoContext *ctx, gpointer new_value)
6448 gpointer *sp, old_value;
6451 offset = clause->exvar_offset;
6454 bp = MONO_CONTEXT_GET_BP (ctx);
6455 sp = *(gpointer*)(bp + offset);
6458 if (old_value < ji->code_start || (char*)old_value > ((char*)ji->code_start + ji->code_size))
6466 /*========================= End of Function ========================*/
6468 /*------------------------------------------------------------------*/
6470 /* Name - get_delegate_invoke_impl. */
6474 /*------------------------------------------------------------------*/
6477 get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 param_count, gboolean aot)
6479 guint8 *code, *start;
6484 start = code = mono_global_codeman_reserve (size);
6486 /* Replace the this argument with the target */
6487 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6488 s390_lg (code, s390_r2, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, target));
6489 s390_br (code, s390_r1);
6490 g_assert ((code - start) <= size);
6492 mono_arch_flush_icache (start, size);
6496 size = 32 + param_count * 8;
6497 start = code = mono_global_codeman_reserve (size);
6499 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6500 /* slide down the arguments */
6501 for (i = 0; i < param_count; ++i) {
6502 s390_lgr (code, (s390_r2 + i), (s390_r2 + i + 1));
6504 s390_br (code, s390_r1);
6506 g_assert ((code - start) <= size);
6508 mono_arch_flush_icache (start, size);
6511 mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
6514 *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
6516 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
6517 *info = mono_tramp_info_create (name, start, code - start, NULL, NULL);
6524 /*========================= End of Function ========================*/
6526 /*------------------------------------------------------------------*/
6528 /* Name - mono_arch_get_delegate_invoke_impls. */
6532 /*------------------------------------------------------------------*/
6535 mono_arch_get_delegate_invoke_impls (void)
6538 MonoTrampInfo *info;
6541 get_delegate_invoke_impl (&info, TRUE, 0, TRUE);
6542 res = g_slist_prepend (res, info);
6544 for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
6545 get_delegate_invoke_impl (&info, FALSE, i, TRUE);
6546 res = g_slist_prepend (res, info);
6552 /*========================= End of Function ========================*/
6554 /*------------------------------------------------------------------*/
6556 /* Name - mono_arch_get_delegate_invoke_impl. */
6560 /*------------------------------------------------------------------*/
6563 mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target)
6565 guint8 *code, *start;
6567 /* FIXME: Support more cases */
6568 if (MONO_TYPE_ISSTRUCT (sig->ret))
6572 static guint8* cached = NULL;
6577 if (mono_aot_only) {
6578 start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
6580 MonoTrampInfo *info;
6581 start = get_delegate_invoke_impl (&info, TRUE, 0, FALSE);
6582 mono_tramp_info_register (info, NULL);
6585 mono_memory_barrier ();
6589 static guint8* cache [MAX_ARCH_DELEGATE_PARAMS + 1] = {NULL};
6592 if (sig->param_count > MAX_ARCH_DELEGATE_PARAMS)
6594 for (i = 0; i < sig->param_count; ++i)
6595 if (!mono_is_regsize_var (sig->params [i]))
6599 code = cache [sig->param_count];
6603 if (mono_aot_only) {
6604 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", sig->param_count);
6605 start = mono_aot_get_trampoline (name);
6608 MonoTrampInfo *info;
6609 start = get_delegate_invoke_impl (&info, FALSE, sig->param_count, FALSE);
6610 mono_tramp_info_register (info, NULL);
6613 mono_memory_barrier ();
6615 cache [sig->param_count] = start;
6620 /*========================= End of Function ========================*/
6622 /*------------------------------------------------------------------*/
6624 /* Name - mono_arch_get_delegate_virtual_invoke_impl. */
6628 /*------------------------------------------------------------------*/
6631 mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method,
6632 int offset, gboolean load_imt_reg)
6634 guint8 *code, *start;
6637 start = code = mono_global_codeman_reserve (size);
6640 * Replace the "this" argument with the target
6642 s390_lgr (code, s390_r1, s390_r2);
6643 s390_lg (code, s390_r2, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, target));
6646 * Load the IMT register, if needed
6649 s390_lg (code, MONO_ARCH_IMT_REG, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, method));
6655 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET(MonoObject, vtable));
6657 s390_agfi(code, s390_r1, offset);
6659 s390_lg (code, s390_r1, 0, s390_r1, 0);
6660 s390_br (code, s390_r1);
6665 /*========================= End of Function ========================*/
6667 /*------------------------------------------------------------------*/
6669 /* Name - mono_arch_build_imt_trampoline. */
6673 /*------------------------------------------------------------------*/
6676 mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain,
6677 MonoIMTCheckItem **imt_entries, int count,
6678 gpointer fail_tramp)
6682 guchar *code, *start;
6685 for (i = 0; i < count; ++i) {
6686 MonoIMTCheckItem *item = imt_entries [i];
6687 if (item->is_equals) {
6688 if (item->check_target_idx) {
6689 if (!item->compare_done)
6690 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6691 if (item->has_target_code)
6692 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE;
6694 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE +
6698 item->chunk_size += CMP_SIZE + 2 * BR_SIZE + JUMP_SIZE +
6700 if (!item->has_target_code)
6701 item->chunk_size += LOAD_SIZE;
6703 item->chunk_size += LOADCON_SIZE + LOAD_SIZE + BR_SIZE;
6704 #if ENABLE_WRONG_METHOD_CHECK
6705 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6710 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6711 imt_entries [item->check_target_idx]->compare_done = TRUE;
6713 size += item->chunk_size;
6717 code = mono_method_alloc_generic_virtual_trampoline (domain, size);
6719 code = mono_domain_code_reserve (domain, size);
6723 for (i = 0; i < count; ++i) {
6724 MonoIMTCheckItem *item = imt_entries [i];
6725 item->code_target = (guint8 *) code;
6726 if (item->is_equals) {
6727 if (item->check_target_idx) {
6728 if (!item->compare_done) {
6729 S390_SET (code, s390_r0, item->key);
6730 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
6732 item->jmp_code = (guint8*) code;
6733 s390_jcl (code, S390_CC_NE, 0);
6735 if (item->has_target_code) {
6736 S390_SET (code, s390_r1, item->value.target_code);
6738 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6739 s390_lg (code, s390_r1, 0, s390_r1, 0);
6741 s390_br (code, s390_r1);
6746 S390_SET (code, s390_r0, item->key);
6747 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
6748 item->jmp_code = (guint8*) code;
6749 s390_jcl (code, S390_CC_NE, 0);
6750 if (item->has_target_code) {
6751 S390_SET (code, s390_r1, item->value.target_code);
6754 S390_SET (code, s390_r1,
6755 (&(vtable->vtable [item->value.vtable_slot])));
6756 s390_lg (code, s390_r1, 0, s390_r1, 0);
6758 s390_br (code, s390_r1);
6759 target = (gint64) S390_RELATIVE(code, item->jmp_code);
6760 s390_patch_rel(item->jmp_code+2, target);
6761 S390_SET (code, s390_r1, fail_tramp);
6762 s390_br (code, s390_r1);
6763 item->jmp_code = NULL;
6765 /* enable the commented code to assert on wrong method */
6766 #if ENABLE_WRONG_METHOD_CHECK
6767 g_assert_not_reached ();
6769 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6770 s390_lg (code, s390_r1, 0, s390_r1, 0);
6771 s390_br (code, s390_r1);
6775 S390_SET (code, s390_r0, item->key);
6776 s390_cgr (code, MONO_ARCH_IMT_REG, s390_r0);
6777 item->jmp_code = (guint8 *) code;
6778 s390_jcl (code, S390_CC_GE, 0);
6782 * patch the branches to get to the target items
6784 for (i = 0; i < count; ++i) {
6785 MonoIMTCheckItem *item = imt_entries [i];
6786 if (item->jmp_code) {
6787 if (item->check_target_idx) {
6789 offset = (gint64) S390_RELATIVE(imt_entries [item->check_target_idx]->code_target,
6791 s390_patch_rel ((guchar *) item->jmp_code + 2, (guint64) offset);
6796 mono_arch_flush_icache ((guint8*)start, (code - start));
6797 mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL);
6800 mono_stats.imt_trampolines_size += (code - start);
6802 g_assert (code - start <= size);
6804 snprintf(trampName, sizeof(trampName), "%d_imt_trampoline", domain->domain_id);
6805 mono_tramp_info_register (mono_tramp_info_create (trampName, start, code - start, NULL, NULL), domain);
6810 /*========================= End of Function ========================*/
6812 /*------------------------------------------------------------------*/
6814 /* Name - mono_arch_find_imt_method. */
6816 /* Function - Get the method address from MONO_ARCH_IMT_REG */
6817 /* found in the save area. */
6819 /*------------------------------------------------------------------*/
6822 mono_arch_find_imt_method (mgreg_t *regs, guint8 *code)
6824 return ((MonoMethod *) regs [MONO_ARCH_IMT_REG]);
6827 /*========================= End of Function ========================*/
6829 /*------------------------------------------------------------------*/
6831 /* Name - mono_arch_find_static_call_vtable */
6833 /* Function - Find the static call vtable. */
6835 /*------------------------------------------------------------------*/
6838 mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
6840 mgreg_t *r = (mgreg_t*)regs;
6842 return (MonoVTable*)(gsize) r [MONO_ARCH_RGCTX_REG];
6845 /*========================= End of Function ========================*/
6847 /*------------------------------------------------------------------*/
6849 /* Name - mono_arch_get_cie_program */
6851 /* Function - Find the static call vtable. */
6853 /*------------------------------------------------------------------*/
6856 mono_arch_get_cie_program (void)
6860 mono_add_unwind_op_def_cfa (l, 0, 0, STK_BASE, 0);
6865 /*========================= End of Function ========================*/
6867 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
6869 /*------------------------------------------------------------------*/
6871 /* Name - mono_arch_set_breakpoint. */
6873 /* Function - Set a breakpoint at the native code corresponding */
6874 /* to JI at NATIVE_OFFSET. The location should */
6875 /* contain code emitted by OP_SEQ_POINT. */
6877 /*------------------------------------------------------------------*/
6880 mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
6884 breakpointCode.pTrigger = bp_trigger_page;
6885 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
6886 code += BREAKPOINT_SIZE;
6889 /*========================= End of Function ========================*/
6891 /*------------------------------------------------------------------*/
6893 /* Name - mono_arch_clear_breakpoint. */
6895 /* Function - Clear the breakpoint at IP. */
6897 /*------------------------------------------------------------------*/
6900 mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
6905 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); i++)
6909 /*========================= End of Function ========================*/
6911 /*------------------------------------------------------------------*/
6913 /* Name - mono_arch_is_breakpoint_event. */
6917 /*------------------------------------------------------------------*/
6920 mono_arch_is_breakpoint_event (void *info, void *sigctx)
6922 siginfo_t* sinfo = (siginfo_t*) info;
6925 * Sometimes the address is off by 4
6927 if (sinfo->si_addr >= bp_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)bp_trigger_page + 128)
6933 /*========================= End of Function ========================*/
6935 /*------------------------------------------------------------------*/
6937 /* Name - mono_arch_skip_breakpoint. */
6939 /* Function - Modify the CTX so the IP is placed after the */
6940 /* breakpoint instruction, so when we resume, the */
6941 /* instruction is not executed again. */
6943 /*------------------------------------------------------------------*/
6946 mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
6948 MONO_CONTEXT_SET_IP (ctx, ((guint8*)MONO_CONTEXT_GET_IP (ctx) + sizeof(RXY_Format)));
6951 /*========================= End of Function ========================*/
6953 /*------------------------------------------------------------------*/
6955 /* Name - mono_arch_start_single_stepping. */
6957 /* Function - Start single stepping. */
6959 /*------------------------------------------------------------------*/
6962 mono_arch_start_single_stepping (void)
6964 mono_mprotect (ss_trigger_page, mono_pagesize (), 0);
6967 /*========================= End of Function ========================*/
6969 /*------------------------------------------------------------------*/
6971 /* Name - mono_arch_stop_single_stepping. */
6973 /* Function - Stop single stepping. */
6975 /*------------------------------------------------------------------*/
6978 mono_arch_stop_single_stepping (void)
6980 mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ);
6983 /*========================= End of Function ========================*/
6985 /*------------------------------------------------------------------*/
6987 /* Name - mono_arch_is_single_step_event. */
6989 /* Function - Return whether the machine state in sigctx cor- */
6990 /* responds to a single step event. */
6992 /*------------------------------------------------------------------*/
6995 mono_arch_is_single_step_event (void *info, void *sigctx)
6997 siginfo_t* sinfo = (siginfo_t*) info;
7000 * Sometimes the address is off by 4
7002 if (sinfo->si_addr >= ss_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)ss_trigger_page + 128)
7008 /*========================= End of Function ========================*/
7010 /*------------------------------------------------------------------*/
7012 /* Name - mono_arch_skip_single_step. */
7014 /* Function - Modify the ctx so the IP is placed after the */
7015 /* single step trigger instruction, so that the */
7016 /* instruction is not executed again. */
7018 /*------------------------------------------------------------------*/
7021 mono_arch_skip_single_step (MonoContext *ctx)
7023 MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + BREAKPOINT_SIZE);
7026 /*========================= End of Function ========================*/
7028 /*------------------------------------------------------------------*/
7030 /* Name - mono_arch_create_seq_point_info. */
7032 /* Function - Return a pointer to a data struction which is */
7033 /* used by the sequence point implementation in */
7036 /*------------------------------------------------------------------*/
7039 mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code)
7045 /*========================= End of Function ========================*/
7047 /*------------------------------------------------------------------*/
7049 /* Name - mono_arch_init_lmf_ext. */
7053 /*------------------------------------------------------------------*/
7056 mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
7058 ext->lmf.previous_lmf = prev_lmf;
7059 /* Mark that this is a MonoLMFExt */
7060 ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
7061 ext->lmf.ebp = (gssize)ext;
7064 /*========================= End of Function ========================*/
7068 /*------------------------------------------------------------------*/
7070 /* Name - mono_arch_cpu_enumerate_simd_versions. */
7072 /* Function - If this CPU supports vector operations then it */
7073 /* supports the equivalent of SSE1-4. */
7075 /*------------------------------------------------------------------*/
7078 mono_arch_cpu_enumerate_simd_versions (void)
7080 guint32 sseOpts = 0;
7082 if (mono_hwcap_s390x_has_vec)
7083 sseOpts = (SIMD_VERSION_SSE1 | SIMD_VERSION_SSE2 |
7084 SIMD_VERSION_SSE3 | SIMD_VERSION_SSSE3 |
7085 SIMD_VERSION_SSE41 | SIMD_VERSION_SSE42 |
7086 SIMD_VERSION_SSE4a);
7091 /*========================= End of Function ========================*/
7093 /*------------------------------------------------------------------*/
7095 /* Name - mono_arch_opcode_supported. */
7097 /* Function - Check if a given return code is supported. */
7099 /*------------------------------------------------------------------*/
7102 mono_arch_opcode_supported (int opcode)
7105 case OP_ATOMIC_ADD_I4:
7106 case OP_ATOMIC_ADD_I8:
7107 case OP_ATOMIC_EXCHANGE_I4:
7108 case OP_ATOMIC_EXCHANGE_I8:
7115 /*========================= End of Function ========================*/