1 /*------------------------------------------------------------------*/
3 /* Name - mini-s390.c */
5 /* Function - S/390 backend for the Mono code generator. */
7 /* Name - Neale Ferguson (Neale.Ferguson@SoftwareAG-usa.com) */
9 /* Date - January, 2004 */
11 /* Derivation - From mini-x86 & mini-ppc by - */
12 /* Paolo Molaro (lupus@ximian.com) */
13 /* Dietmar Maurer (dietmar@ximian.com) */
15 /*------------------------------------------------------------------*/
17 /*------------------------------------------------------------------*/
19 /*------------------------------------------------------------------*/
21 #define MAX_ARCH_DELEGATE_PARAMS 7
23 #define EMIT_COND_BRANCH(ins,cond) \
25 if (ins->inst_true_bb->native_offset) { \
27 displace = ((cfg->native_code + \
28 ins->inst_true_bb->native_offset) - code) / 2; \
29 if (s390_is_imm16(displace)) { \
30 s390_brc (code, cond, displace); \
32 s390_jcl (code, cond, displace); \
35 mono_add_patch_info (cfg, code - cfg->native_code, \
36 MONO_PATCH_INFO_BB, ins->inst_true_bb); \
37 s390_jcl (code, cond, 0); \
41 #define EMIT_UNCOND_BRANCH(ins) \
43 if (ins->inst_target_bb->native_offset) { \
45 displace = ((cfg->native_code + \
46 ins->inst_target_bb->native_offset) - code) / 2; \
47 if (s390_is_imm16(displace)) { \
48 s390_brc (code, S390_CC_UN, displace); \
50 s390_jcl (code, S390_CC_UN, displace); \
53 mono_add_patch_info (cfg, code - cfg->native_code, \
54 MONO_PATCH_INFO_BB, ins->inst_target_bb); \
55 s390_jcl (code, S390_CC_UN, 0); \
59 #define EMIT_COND_SYSTEM_EXCEPTION(cond,exc_name) \
61 mono_add_patch_info (cfg, code - cfg->native_code, \
62 MONO_PATCH_INFO_EXC, exc_name); \
63 s390_jcl (code, cond, 0); \
66 #define CHECK_SRCDST_COM \
67 if (ins->dreg == ins->sreg2) { \
71 if (ins->dreg != ins->sreg1) { \
72 s390_lgr (code, ins->dreg, ins->sreg1); \
76 #define CHECK_SRCDST_NCOM \
77 if (ins->dreg == ins->sreg2) { \
79 s390_lgr (code, s390_r13, ins->sreg2); \
83 if (ins->dreg != ins->sreg1) { \
84 s390_lgr (code, ins->dreg, ins->sreg1); \
87 #define CHECK_SRCDST_COM_I \
88 if (ins->dreg == ins->sreg2) { \
92 if (ins->dreg != ins->sreg1) { \
93 s390_lgfr (code, ins->dreg, ins->sreg1); \
97 #define CHECK_SRCDST_NCOM_I \
98 if (ins->dreg == ins->sreg2) { \
100 s390_lgfr (code, s390_r13, ins->sreg2); \
104 if (ins->dreg != ins->sreg1) { \
105 s390_lgfr (code, ins->dreg, ins->sreg1); \
108 #define CHECK_SRCDST_COM_F \
109 if (ins->dreg == ins->sreg2) { \
113 if (ins->dreg != ins->sreg1) { \
114 s390_ldr (code, ins->dreg, ins->sreg1); \
118 #define CHECK_SRCDST_NCOM_F \
119 if (ins->dreg == ins->sreg2) { \
121 s390_ldr (code, s390_r13, ins->sreg2); \
125 if (ins->dreg != ins->sreg1) { \
126 s390_ldr (code, ins->dreg, ins->sreg1); \
129 #define MONO_EMIT_NEW_MOVE(cfg,dest,offset,src,imm,size) do { \
132 MONO_INST_NEW (cfg, inst, OP_NOP); \
135 inst->inst_offset = offset; \
137 inst->inst_imm = imm; \
139 if (s390_is_uimm12(offset)) { \
141 inst->inst_offset = offset; \
143 dReg = mono_alloc_preg (cfg); \
144 MONO_EMIT_NEW_BIALU_IMM(cfg, OP_ADD_IMM, \
145 dReg, dest, offset); \
147 inst->inst_offset = 0; \
149 if (s390_is_uimm12(imm)) { \
151 inst->inst_imm = imm; \
153 sReg = mono_alloc_preg (cfg); \
154 MONO_EMIT_NEW_BIALU_IMM(cfg, OP_ADD_IMM, \
156 inst->sreg1 = sReg; \
157 inst->inst_imm = 0; \
160 inst->opcode = OP_S390_MOVE; \
161 inst->backend.size = size; \
162 MONO_ADD_INS (cfg->cbb, inst); \
165 #define MONO_OUTPUT_VTR(cfg, size, dr, sr, so) do { \
166 int reg = mono_alloc_preg (cfg); \
169 MONO_EMIT_NEW_ICONST(cfg, reg, 0); \
172 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU1_MEMBASE, \
176 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU2_MEMBASE, \
180 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI4_MEMBASE, \
184 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI8_MEMBASE, \
188 mono_call_inst_add_outarg_reg(cfg, call, reg, dr, FALSE); \
191 #define MONO_OUTPUT_VTS(cfg, size, dr, dx, sr, so) do { \
195 tmpr = mono_alloc_preg (cfg); \
196 MONO_EMIT_NEW_ICONST(cfg, tmpr, 0); \
197 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
201 tmpr = mono_alloc_preg (cfg); \
202 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU1_MEMBASE, \
204 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
208 tmpr = mono_alloc_preg (cfg); \
209 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU2_MEMBASE, \
211 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
215 tmpr = mono_alloc_preg (cfg); \
216 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI4_MEMBASE, \
218 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
222 MONO_EMIT_NEW_MOVE (cfg, dr, dx, sr, so, size); \
228 #define DEBUG(a) if (cfg->verbose_level > 1) a
232 #define S390_TRACE_STACK_SIZE (5*sizeof(gpointer)+4*sizeof(gdouble))
234 #define BREAKPOINT_SIZE sizeof(breakpoint_t)
235 #define S390X_NOP_SIZE sizeof(RR_Format)
237 #define MAX(a, b) ((a) > (b) ? (a) : (b))
240 * imt thunking size values
243 #define LOADCON_SIZE 20
247 #define ENABLE_WRONG_METHOD_CHECK 0
249 #define mono_mini_arch_lock() mono_mutex_lock (&mini_arch_mutex)
250 #define mono_mini_arch_unlock() mono_mutex_unlock (&mini_arch_mutex)
252 /*========================= End of Defines =========================*/
254 /*------------------------------------------------------------------*/
255 /* I n c l u d e s */
256 /*------------------------------------------------------------------*/
260 #include <sys/types.h>
263 #include <mono/metadata/abi-details.h>
264 #include <mono/metadata/appdomain.h>
265 #include <mono/metadata/debug-helpers.h>
266 #include <mono/metadata/profiler-private.h>
267 #include <mono/utils/mono-math.h>
268 #include <mono/utils/mono-mmap.h>
269 #include <mono/utils/mono-hwcap-s390x.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"
279 /*========================= End of Includes ========================*/
281 /*------------------------------------------------------------------*/
282 /* T y p e d e f s */
283 /*------------------------------------------------------------------*/
295 /*------------------------------------------------------------------*/
296 /* Used by the instrument_emit_epilog */
297 /*------------------------------------------------------------------*/
308 typedef struct InstList InstList;
322 RegTypeStructByValInFP,
324 RegTypeStructByAddrOnStack
328 gint32 offset; /* offset from caller's stack */
329 gint32 offparm; /* offset from callee's stack */
330 guint16 vtsize; /* in param area */
333 guint32 size; /* Size of structure used by RegTypeStructByVal */
334 gint32 type; /* Data type of argument */
350 gint64 gr[5]; /* R2-R6 */
351 gdouble fp[3]; /* F0-F2 */
352 } __attribute__ ((packed)) RegParm;
360 } __attribute__ ((packed)) breakpoint_t;
362 /*========================= End of Typedefs ========================*/
364 /*------------------------------------------------------------------*/
365 /* P r o t o t y p e s */
366 /*------------------------------------------------------------------*/
368 static void indent (int);
369 static guint8 * backUpStackPtr(MonoCompile *, guint8 *);
370 static void decodeParm (MonoType *, void *, int);
371 static void enter_method (MonoMethod *, RegParm *, char *);
372 static void leave_method (MonoMethod *, ...);
373 static inline void add_general (guint *, size_data *, ArgInfo *);
374 static inline void add_stackParm (guint *, size_data *, ArgInfo *, gint);
375 static inline void add_float (guint *, size_data *, ArgInfo *);
376 static CallInfo * get_call_info (MonoCompile *, MonoMemPool *, MonoMethodSignature *);
377 static guchar * emit_float_to_int (MonoCompile *, guchar *, int, int, int, gboolean);
378 static guint8 * emit_load_volatile_arguments (guint8 *, MonoCompile *);
379 static __inline__ void emit_unwind_regs(MonoCompile *, guint8 *, int, int, long);
381 /*========================= End of Prototypes ======================*/
383 /*------------------------------------------------------------------*/
384 /* G l o b a l V a r i a b l e s */
385 /*------------------------------------------------------------------*/
387 int mono_exc_esp_offset = 0;
389 __thread int indent_level = 0;
391 static gint appdomain_tls_offset = -1,
393 lmf_addr_tls_offset = -1;
395 pthread_key_t lmf_addr_key;
397 gboolean lmf_addr_key_inited = FALSE;
402 * The code generated for sequence points reads from this location,
403 * which is made read-only when single stepping is enabled.
405 static gpointer ss_trigger_page;
408 * Enabled breakpoints read from this trigger page
410 static gpointer bp_trigger_page;
412 breakpoint_t breakpointCode;
414 static mono_mutex_t mini_arch_mutex;
416 static const char * grNames[] = {
417 "s390_r0", "s390_sp", "s390_r2", "s390_r3", "s390_r4",
418 "s390_r5", "s390_r6", "s390_r7", "s390_r8", "s390_r9",
419 "s390_r10", "s390_r11", "s390_r12", "s390_r13", "s390_r14",
423 static const char * fpNames[] = {
424 "s390_f0", "s390_f1", "s390_f2", "s390_f3", "s390_f4",
425 "s390_f5", "s390_f6", "s390_f7", "s390_f8", "s390_f9",
426 "s390_f10", "s390_f11", "s390_f12", "s390_f13", "s390_f14",
430 static const char * vrNames[] = {
431 "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7",
432 "vr8", "vr9", "vr10", "vr11", "vr12", "vr13", "vr14", "vr15",
433 "vr16", "vr17", "vr18", "vr19", "vr20", "vr21", "vr22", "vr23",
434 "vr24", "vr25", "vr26", "vr27", "vr28", "vr29", "vr30", "vr31"
437 /*====================== End of Global Variables ===================*/
439 /*------------------------------------------------------------------*/
441 /* Name - mono_arch_regname */
443 /* Function - Returns the name of the register specified by */
444 /* the input parameter. */
446 /*------------------------------------------------------------------*/
449 mono_arch_regname (int reg)
451 if (reg >= 0 && reg < 16)
452 return grNames [reg];
457 /*========================= End of Function ========================*/
459 /*------------------------------------------------------------------*/
461 /* Name - mono_arch_fregname */
463 /* Function - Returns the name of the register specified by */
464 /* the input parameter. */
466 /*------------------------------------------------------------------*/
469 mono_arch_fregname (int reg)
471 if (reg >= 0 && reg < 16)
472 return fpNames [reg];
477 /*========================= End of Function ========================*/
479 /*------------------------------------------------------------------*/
481 /* Name - mono_arch_xregname */
483 /* Function - Returns the name of the register specified by */
484 /* the input parameter. */
486 /*------------------------------------------------------------------*/
489 mono_arch_xregname (int reg)
491 if (reg < s390_VR_NREG)
492 return vrNames [reg];
497 /*========================= End of Function ========================*/
499 /*------------------------------------------------------------------*/
501 /* Name - arch_get_argument_info */
503 /* Function - Gathers information on parameters such as size, */
504 /* alignment, and padding. arg_info should be large */
505 /* enough to hold param_count + 1 entries. */
507 /* Parameters - @csig - Method signature */
508 /* @param_count - No. of parameters to consider */
509 /* @arg_info - An array to store the result info */
511 /* Returns - Size of the activation frame */
513 /*------------------------------------------------------------------*/
516 mono_arch_get_argument_info (MonoMethodSignature *csig,
518 MonoJitArgumentInfo *arg_info)
520 int k, frame_size = 0;
521 int size, align, pad;
524 if (MONO_TYPE_ISSTRUCT (csig->ret)) {
525 frame_size += sizeof (gpointer);
529 arg_info [0].offset = offset;
532 frame_size += sizeof (gpointer);
536 arg_info [0].size = frame_size;
538 for (k = 0; k < param_count; k++) {
541 size = mono_type_native_stack_size (csig->params [k], (guint32 *) &align);
543 size = mini_type_stack_size (csig->params [k], &align);
545 frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
546 arg_info [k].pad = pad;
548 arg_info [k + 1].pad = 0;
549 arg_info [k + 1].size = size;
551 arg_info [k + 1].offset = offset;
555 align = MONO_ARCH_FRAME_ALIGNMENT;
556 frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
557 arg_info [k].pad = pad;
562 /*========================= End of Function ========================*/
564 /*------------------------------------------------------------------*/
566 /* Name - emit_unwind_regs. */
568 /* Function - Determines if a value can be returned in one or */
571 /*------------------------------------------------------------------*/
573 static void __inline__
574 emit_unwind_regs(MonoCompile *cfg, guint8 *code, int start, int end, long offset)
578 for (i = start; i < end; i++) {
579 mono_emit_unwind_op_offset (cfg, code, i, offset);
580 offset += sizeof(gulong);
584 /*========================= End of Function ========================*/
586 /*------------------------------------------------------------------*/
588 /* Name - retFitsInReg. */
590 /* Function - Determines if a value can be returned in one or */
593 /*------------------------------------------------------------------*/
595 static inline gboolean
596 retFitsInReg(guint32 size)
611 /*========================= End of Function ========================*/
613 /*------------------------------------------------------------------*/
615 /* Name - backStackPtr. */
617 /* Function - Restore Stack Pointer to previous frame. */
619 /*------------------------------------------------------------------*/
621 static inline guint8 *
622 backUpStackPtr(MonoCompile *cfg, guint8 *code)
624 int stackSize = cfg->stack_usage;
626 if (cfg->frame_reg != STK_BASE)
627 s390_lgr (code, STK_BASE, cfg->frame_reg);
629 if (s390_is_imm16 (stackSize)) {
630 s390_aghi (code, STK_BASE, stackSize);
632 while (stackSize > 32767) {
633 s390_aghi (code, STK_BASE, 32767);
636 s390_aghi (code, STK_BASE, stackSize);
641 /*========================= End of Function ========================*/
643 /*------------------------------------------------------------------*/
647 /* Function - Perform nice indenting to current level */
649 /*------------------------------------------------------------------*/
655 indent_level += diff;
657 printf("%p [%3d] ",(void *)pthread_self(),v);
662 indent_level += diff;
665 /*========================= End of Function ========================*/
667 /*------------------------------------------------------------------*/
669 /* Name - cvtMonoType */
671 /* Function - Convert a mono-type to a string. */
673 /*------------------------------------------------------------------*/
676 cvtMonoType(MonoTypeEnum t)
681 return "MONO_TYPE_END";
683 return "MONO_TYPE_VOID";
684 case MONO_TYPE_BOOLEAN:
685 return "MONO_TYPE_BOOLEAN";
687 return "MONO_TYPE_CHAR";
689 return "MONO_TYPE_I1";
691 return "MONO_TYPE_U1";
693 return "MONO_TYPE_I2";
695 return "MONO_TYPE_U2";
697 return "MONO_TYPE_I4";
699 return "MONO_TYPE_U4";
701 return "MONO_TYPE_I8";
703 return "MONO_TYPE_U8";
705 return "MONO_TYPE_R4";
707 return "MONO_TYPE_R8";
708 case MONO_TYPE_STRING:
709 return "MONO_TYPE_STRING";
711 return "MONO_TYPE_PTR";
712 case MONO_TYPE_BYREF:
713 return "MONO_TYPE_BYREF";
714 case MONO_TYPE_VALUETYPE:
715 return "MONO_TYPE_VALUETYPE";
716 case MONO_TYPE_CLASS:
717 return "MONO_TYPE_CLASS";
719 return "MONO_TYPE_VAR";
720 case MONO_TYPE_ARRAY:
721 return "MONO_TYPE_ARRAY";
722 case MONO_TYPE_GENERICINST:
723 return "MONO_TYPE_GENERICINST";
724 case MONO_TYPE_TYPEDBYREF:
725 return "MONO_TYPE_TYPEDBYREF";
727 return "MONO_TYPE_I";
729 return "MONO_TYPE_U";
730 case MONO_TYPE_FNPTR:
731 return "MONO_TYPE_FNPTR";
732 case MONO_TYPE_OBJECT:
733 return "MONO_TYPE_OBJECT";
734 case MONO_TYPE_SZARRAY:
735 return "MONO_TYPE_SZARRAY";
737 return "MONO_TYPE_MVAR";
738 case MONO_TYPE_CMOD_REQD:
739 return "MONO_TYPE_CMOD_REQD";
740 case MONO_TYPE_CMOD_OPT:
741 return "MONO_TYPE_CMOD_OPT";
742 case MONO_TYPE_INTERNAL:
743 return "MONO_TYPE_INTERNAL";
744 case MONO_TYPE_MODIFIER:
745 return "MONO_TYPE_MODIFIER";
746 case MONO_TYPE_SENTINEL:
747 return "MONO_TYPE_SENTINEL";
748 case MONO_TYPE_PINNED:
749 return "MONO_TYPE_PINNED";
756 /*========================= End of Function ========================*/
758 /*------------------------------------------------------------------*/
760 /* Name - decodeParm */
762 /* Function - Decode a parameter for the trace. */
764 /*------------------------------------------------------------------*/
767 decodeParm(MonoType *type, void *curParm, int size)
772 printf("[BYREF:%p], ", *((char **) curParm));
774 simpleType = mini_get_underlying_type(type)->type;
776 switch (simpleType) {
778 printf ("[INTPTR:%p], ", *((int **) curParm));
781 printf ("[UINTPTR:%p], ", *((int **) curParm));
783 case MONO_TYPE_BOOLEAN :
784 printf ("[BOOL:%ld], ", *((gint64 *) curParm));
786 case MONO_TYPE_CHAR :
787 printf ("[CHAR:%c], ", *((int *) curParm));
790 printf ("[INT1:%ld], ", *((gint64 *) curParm));
793 printf ("[INT2:%ld], ", *((gint64 *) curParm));
796 printf ("[INT4:%ld], ", *((gint64 *) curParm));
799 printf ("[UINT1:%lu], ", *((guint64 *) curParm));
802 printf ("[UINT2:%lu], ", *((guint64 *) curParm));
805 printf ("[UINT4:%lu], ", *((guint64 *) curParm));
808 printf ("[UINT8:%lu], ", *((guint64 *) curParm));
810 case MONO_TYPE_STRING : {
811 MonoString *s = *((MonoString **) curParm);
813 g_assert (((MonoObject *) s)->vtable->klass == mono_defaults.string_class);
814 printf("[STRING:%p:%s], ", s, mono_string_to_utf8(s));
816 printf("[STRING:null], ");
820 case MONO_TYPE_CLASS :
821 case MONO_TYPE_OBJECT : {
822 MonoObject *obj = *((MonoObject **) curParm);
824 if ((obj) && (obj->vtable)) {
825 printf("[CLASS/OBJ:");
826 klass = obj->vtable->klass;
827 printf("%p [%p] ",obj,curParm);
828 if (klass == mono_defaults.string_class) {
829 printf("[STRING:%p:%s]",
830 obj, mono_string_to_utf8 ((MonoString *) obj));
831 } else if (klass == mono_defaults.int32_class) {
832 printf("[INT32:%p:%d]",
833 obj, *(gint32 *)((char *)obj + sizeof (MonoObject)));
836 klass->name_space, klass->name, obj);
839 printf("[OBJECT:null], ");
844 printf("[PTR:%p], ", *((gpointer **) (curParm)));
846 case MONO_TYPE_FNPTR :
847 printf("[FNPTR:%p], ", *((gpointer **) (curParm)));
849 case MONO_TYPE_ARRAY :
850 printf("[ARRAY:%p], ", *((gpointer **) (curParm)));
852 case MONO_TYPE_SZARRAY :
853 printf("[SZARRAY:%p], ", *((gpointer **) (curParm)));
856 printf("[INT8:%ld], ", *((gint64 *) (curParm)));
859 printf("[FLOAT4:%g], ", *((float *) (curParm)));
862 printf("[FLOAT8:%g], ", *((double *) (curParm)));
864 case MONO_TYPE_VALUETYPE : {
866 MonoMarshalType *info;
868 if (type->data.klass->enumtype) {
869 simpleType = mono_class_enum_basetype (type->data.klass)->type;
870 printf("{VALUETYPE} - ");
874 info = mono_marshal_load_type_info (type->data.klass);
876 if ((info->native_size == sizeof(float)) &&
877 (info->num_fields == 1) &&
878 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
879 printf("[FLOAT4:%f], ", *((float *) (curParm)));
883 if ((info->native_size == sizeof(double)) &&
884 (info->num_fields == 1) &&
885 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
886 printf("[FLOAT8:%g], ", *((double *) (curParm)));
890 printf("[VALUETYPE:");
891 for (i = 0; i < size; i++)
892 printf("%02x,", *((guint8 *)curParm+i));
896 case MONO_TYPE_TYPEDBYREF: {
898 printf("[TYPEDBYREF:");
899 for (i = 0; i < size; i++)
900 printf("%02x,", *((guint8 *)curParm+i));
905 printf("[%s], ",cvtMonoType(simpleType));
910 /*========================= End of Function ========================*/
912 /*------------------------------------------------------------------*/
914 /* Name - enter_method */
916 /* Function - Perform tracing of the entry to the current */
919 /*------------------------------------------------------------------*/
922 enter_method (MonoMethod *method, RegParm *rParm, char *sp)
924 int i, oParm = 0, iParm = 0;
927 MonoMethodSignature *sig;
934 fname = mono_method_full_name (method, TRUE);
936 printf ("ENTER: %s ", fname);
939 ip = (*(guint64 *) (sp+S390_RET_ADDR_OFFSET));
940 printf ("ip: %p sp: %p - ", (gpointer) ip, sp);
945 sig = mono_method_signature (method);
947 cinfo = get_call_info (NULL, NULL, sig);
949 if (cinfo->struct_ret) {
950 printf ("[STRUCTRET:%p], ", (gpointer) rParm->gr[0]);
955 gpointer *this_arg = (gpointer *) rParm->gr[iParm];
956 obj = (MonoObject *) this_arg;
957 switch(method->klass->this_arg.type) {
958 case MONO_TYPE_VALUETYPE:
960 guint64 *value = (guint64 *) ((uintptr_t)this_arg + sizeof(MonoObject));
961 printf("this:[value:%p:%016lx], ", this_arg, *value);
963 printf ("this:[NULL], ");
965 case MONO_TYPE_STRING:
968 klass = obj->vtable->klass;
969 if (klass == mono_defaults.string_class) {
970 printf ("this:[STRING:%p:%s], ",
971 obj, mono_string_to_utf8 ((MonoString *)obj));
973 printf ("this:%p[%s.%s], ",
974 obj, klass->name_space, klass->name);
977 printf("vtable:[NULL], ");
979 printf ("this:[NULL], ");
982 printf("this[%s]: %p, ",cvtMonoType(method->klass->this_arg.type),this_arg);
987 for (i = 0; i < sig->param_count; ++i) {
988 ainfo = &cinfo->args[i + oParm];
989 switch (ainfo->regtype) {
990 case RegTypeGeneral :
991 decodeParm(sig->params[i], &(rParm->gr[ainfo->reg-2]), ainfo->size);
994 decodeParm(sig->params[i], &(rParm->fp[ainfo->reg]), ainfo->size);
997 decodeParm(sig->params[i], sp+ainfo->offset, ainfo->size);
999 case RegTypeStructByVal :
1000 if (ainfo->reg != STK_BASE) {
1001 int offset = sizeof(glong) - ainfo->size;
1002 curParm = &(rParm->gr[ainfo->reg-2])+offset;
1005 curParm = sp+ainfo->offset;
1007 if (retFitsInReg (ainfo->vtsize))
1008 decodeParm(sig->params[i],
1012 decodeParm(sig->params[i],
1013 *((char **) curParm),
1016 case RegTypeStructByAddr :
1017 if (ainfo->reg != STK_BASE)
1018 curParm = &(rParm->gr[ainfo->reg-2]);
1020 curParm = sp+ainfo->offset;
1022 decodeParm(sig->params[i],
1023 *((char **) curParm),
1035 /*========================= End of Function ========================*/
1037 /*------------------------------------------------------------------*/
1039 /* Name - leave_method */
1043 /*------------------------------------------------------------------*/
1046 leave_method (MonoMethod *method, ...)
1053 va_start(ap, method);
1055 fname = mono_method_full_name (method, TRUE);
1057 printf ("LEAVE: %s", fname);
1060 type = mono_method_signature (method)->ret;
1063 switch (type->type) {
1064 case MONO_TYPE_VOID:
1066 case MONO_TYPE_BOOLEAN: {
1067 int val = va_arg (ap, int);
1069 printf ("[TRUE:%d]", val);
1075 case MONO_TYPE_CHAR: {
1076 int val = va_arg (ap, int);
1077 printf ("[CHAR:%d]", val);
1080 case MONO_TYPE_I1: {
1081 int val = va_arg (ap, int);
1082 printf ("[INT1:%d]", val);
1085 case MONO_TYPE_U1: {
1086 int val = va_arg (ap, int);
1087 printf ("[UINT1:%d]", val);
1090 case MONO_TYPE_I2: {
1091 int val = va_arg (ap, int);
1092 printf ("[INT2:%d]", val);
1095 case MONO_TYPE_U2: {
1096 int val = va_arg (ap, int);
1097 printf ("[UINT2:%d]", val);
1100 case MONO_TYPE_I4: {
1101 int val = va_arg (ap, int);
1102 printf ("[INT4:%d]", val);
1105 case MONO_TYPE_U4: {
1106 int val = va_arg (ap, int);
1107 printf ("[UINT4:%d]", val);
1111 gint64 val = va_arg (ap, gint64);
1112 printf ("[INT:%ld]", val);
1117 gint64 val = va_arg (ap, gint64);
1118 printf ("[UINT:%lu]", val);
1122 case MONO_TYPE_STRING: {
1123 MonoString *s = va_arg (ap, MonoString *);
1126 g_assert (((MonoObject *)s)->vtable->klass == mono_defaults.string_class);
1127 printf ("[STRING:%p:%s]", s, mono_string_to_utf8 (s));
1129 printf ("[STRING:null], ");
1132 case MONO_TYPE_CLASS:
1133 case MONO_TYPE_OBJECT: {
1134 MonoObject *o = va_arg (ap, MonoObject *);
1136 if ((o) && (o->vtable)) {
1137 if (o->vtable->klass == mono_defaults.boolean_class) {
1138 printf ("[BOOLEAN:%p:%d]", o, *((guint8 *)o + sizeof (MonoObject)));
1139 } else if (o->vtable->klass == mono_defaults.int32_class) {
1140 printf ("[INT32:%p:%d]", o, *((gint32 *)((char *)o + sizeof (MonoObject))));
1141 } else if (o->vtable->klass == mono_defaults.int64_class) {
1142 printf ("[INT64:%p:%ld]", o, *((gint64 *)((char *)o + sizeof (MonoObject))));
1144 printf ("[%s.%s:%p]", o->vtable->klass->name_space, o->vtable->klass->name, o);
1146 printf ("[OBJECT:%p]", o);
1151 case MONO_TYPE_FNPTR:
1152 case MONO_TYPE_ARRAY:
1153 case MONO_TYPE_SZARRAY: {
1154 gpointer p = va_arg (ap, gpointer);
1155 printf ("[result=%p]", p);
1158 case MONO_TYPE_I8: {
1159 gint64 l = va_arg (ap, gint64);
1160 printf ("[LONG:%ld]", l);
1163 case MONO_TYPE_U8: {
1164 guint64 l = va_arg (ap, guint64);
1165 printf ("[ULONG:%lu]", l);
1168 case MONO_TYPE_R4: {
1169 double f = va_arg (ap, double);
1170 printf ("[FLOAT4:%g]\n", f);
1173 case MONO_TYPE_R8: {
1174 double f = va_arg (ap, double);
1175 printf ("[FLOAT8:%g]\n", f);
1178 case MONO_TYPE_VALUETYPE: {
1179 MonoMarshalType *info;
1180 if (type->data.klass->enumtype) {
1181 type = mono_class_enum_basetype (type->data.klass);
1186 info = mono_marshal_load_type_info (type->data.klass);
1188 if ((info->native_size == sizeof(float)) &&
1189 (info->num_fields == 1) &&
1190 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1191 double f = va_arg (ap, double);
1192 printf("[FLOAT4:%g]\n", (double) f);
1196 if ((info->native_size == sizeof(double)) &&
1197 (info->num_fields == 1) &&
1198 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1199 double f = va_arg (ap, double);
1200 printf("[FLOAT8:%g]\n", f);
1204 size = mono_type_size (type, &align);
1207 guint32 p = va_arg (ap, guint32);
1208 printf ("[%02x]\n",p);
1212 guint32 p = va_arg (ap, guint32);
1213 printf ("[%04x]\n",p);
1217 guint32 p = va_arg (ap, guint32);
1218 printf ("[%08x]\n",p);
1222 guint64 p = va_arg (ap, guint64);
1223 printf ("[%016lx]\n",p);
1227 gpointer p = va_arg (ap, gpointer);
1228 printf ("[VALUETYPE] %p\n",p);
1234 case MONO_TYPE_TYPEDBYREF: {
1235 guint8 *p = va_arg (ap, gpointer);
1237 size = mono_type_size (type, &align);
1244 for (j = 0; p && j < size; j++)
1245 printf ("%02x,", p [j]);
1249 printf ("[TYPEDBYREF]\n");
1253 case MONO_TYPE_GENERICINST: {
1254 printf("[GENERICINST]\n");
1257 case MONO_TYPE_MVAR: {
1261 case MONO_TYPE_CMOD_REQD: {
1262 printf("[CMOD_REQD]\n");
1265 case MONO_TYPE_CMOD_OPT: {
1266 printf("[CMOD_OPT]\n");
1269 case MONO_TYPE_INTERNAL: {
1270 printf("[INTERNAL]\n");
1274 printf ("(unknown return type %x)",
1275 mono_method_signature (method)->ret->type);
1278 ip = ((gint64) __builtin_extract_return_addr (__builtin_return_address (0)));
1279 printf (" ip: %p\n", (gpointer) ip);
1282 /*========================= End of Function ========================*/
1284 /*------------------------------------------------------------------*/
1286 /* Name - mono_arch_cpu_init */
1288 /* Function - Perform CPU specific initialization to execute */
1291 /*------------------------------------------------------------------*/
1294 mono_arch_cpu_init (void)
1298 /*========================= End of Function ========================*/
1300 /*------------------------------------------------------------------*/
1302 /* Name - mono_arch_init. */
1304 /* Function - Initialize architecture specific code. */
1306 /*------------------------------------------------------------------*/
1309 mono_arch_init (void)
1313 mono_mutex_init_recursive (&mini_arch_mutex);
1315 ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ);
1316 bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ);
1317 mono_mprotect (bp_trigger_page, mono_pagesize (), 0);
1319 code = (guint8 *) &breakpointCode;
1320 s390_basr(code, s390_r13, 0);
1322 s390_llong(code, 0);
1323 s390_lg(code, s390_r13, 0, s390_r13, 4);
1324 s390_lg(code, s390_r0, 0, s390_r13, 0);
1327 /*========================= End of Function ========================*/
1329 /*------------------------------------------------------------------*/
1331 /* Name - mono_arch_cleanup. */
1333 /* Function - Cleanup architecture specific code . */
1335 /*------------------------------------------------------------------*/
1338 mono_arch_cleanup (void)
1340 if (ss_trigger_page)
1341 mono_vfree (ss_trigger_page, mono_pagesize ());
1342 if (bp_trigger_page)
1343 mono_vfree (bp_trigger_page, mono_pagesize ());
1344 mono_mutex_destroy (&mini_arch_mutex);
1347 /*========================= End of Function ========================*/
1349 /*------------------------------------------------------------------*/
1351 /* Name - mono_arch_cpu_optimizations */
1353 /* Function - Returns the optimizations supported on this CPU */
1355 /*------------------------------------------------------------------*/
1358 mono_arch_cpu_optimizations (guint32 *exclude_mask)
1362 /*----------------------------------------------------------*/
1363 /* No s390-specific optimizations yet */
1364 /*----------------------------------------------------------*/
1365 *exclude_mask = MONO_OPT_LINEARS;
1369 /*========================= End of Function ========================*/
1371 /*------------------------------------------------------------------*/
1373 /* Name - mono_arch_get_allocatable_int_vars */
1377 /*------------------------------------------------------------------*/
1380 mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
1385 for (i = 0; i < cfg->num_varinfo; i++) {
1386 MonoInst *ins = cfg->varinfo [i];
1387 MonoMethodVar *vmv = MONO_VARINFO (cfg, i);
1390 if (vmv->range.first_use.abs_pos >= vmv->range.last_use.abs_pos)
1393 if (ins->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) ||
1394 (ins->opcode != OP_LOCAL && ins->opcode != OP_ARG))
1397 /* we can only allocate 32 bit values */
1398 if (mono_is_regsize_var(ins->inst_vtype)) {
1399 g_assert (MONO_VARINFO (cfg, i)->reg == -1);
1400 g_assert (i == vmv->idx);
1401 vars = mono_varlist_insert_sorted (cfg, vars, vmv, FALSE);
1408 /*========================= End of Function ========================*/
1410 /*------------------------------------------------------------------*/
1412 /* Name - mono_arch_global_int_regs */
1414 /* Function - Return a list of usable integer registers. */
1416 /*------------------------------------------------------------------*/
1419 mono_arch_get_global_int_regs (MonoCompile *cfg)
1422 MonoMethodHeader *header;
1425 header = cfg->header;
1426 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
1427 cfg->frame_reg = s390_r11;
1430 /* FIXME: s390_r12 is reserved for bkchain_reg. Only reserve it if needed */
1432 for (i = 8; i < top; ++i) {
1433 if (cfg->frame_reg != i)
1434 regs = g_list_prepend (regs, GUINT_TO_POINTER (i));
1440 /*========================= End of Function ========================*/
1442 /*------------------------------------------------------------------*/
1444 /* Name - mono_arch_flush_icache */
1446 /* Function - Flush the CPU icache. */
1448 /*------------------------------------------------------------------*/
1451 mono_arch_flush_icache (guint8 *code, gint size)
1455 /*========================= End of Function ========================*/
1457 /*------------------------------------------------------------------*/
1459 /* Name - add_general */
1461 /* Function - Determine code and stack size incremements for a */
1464 /*------------------------------------------------------------------*/
1467 add_general (guint *gr, size_data *sz, ArgInfo *ainfo)
1469 if (*gr > S390_LAST_ARG_REG) {
1470 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1471 ainfo->offset = sz->stack_size;
1472 ainfo->reg = STK_BASE;
1473 ainfo->regtype = RegTypeBase;
1474 sz->stack_size += sizeof(long);
1475 sz->local_size += sizeof(long);
1476 sz->offStruct += sizeof(long);
1477 sz->code_size += 12;
1485 /*========================= End of Function ========================*/
1487 /*------------------------------------------------------------------*/
1489 /* Name - add_stackParm */
1491 /* Function - Determine code and stack size incremements for a */
1494 /*------------------------------------------------------------------*/
1497 add_stackParm (guint *gr, size_data *sz, ArgInfo *ainfo, gint size)
1499 if (*gr > S390_LAST_ARG_REG) {
1500 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1501 ainfo->reg = STK_BASE;
1502 ainfo->offset = sz->stack_size;
1503 ainfo->regtype = RegTypeStructByAddrOnStack;
1504 sz->stack_size += sizeof (gpointer);
1505 sz->parm_size += sizeof(gpointer);
1506 sz->offStruct += sizeof(gpointer);
1509 ainfo->offset = sz->stack_size;
1510 ainfo->regtype = RegTypeStructByAddr;
1513 ainfo->offparm = sz->offset;
1514 sz->offset = S390_ALIGN(sz->offset+size, sizeof(long));
1516 ainfo->vtsize = size;
1517 sz->parm_size += size;
1520 /*========================= End of Function ========================*/
1522 /*------------------------------------------------------------------*/
1524 /* Name - add_float */
1526 /* Function - Determine code and stack size incremements for a */
1527 /* float parameter. */
1529 /*------------------------------------------------------------------*/
1532 add_float (guint *fr, size_data *sz, ArgInfo *ainfo)
1534 if ((*fr) <= S390_LAST_FPARG_REG) {
1535 ainfo->regtype = RegTypeFP;
1541 ainfo->offset = sz->stack_size;
1542 ainfo->reg = STK_BASE;
1543 ainfo->regtype = RegTypeBase;
1545 sz->stack_size += sizeof(double);
1546 sz->local_size += sizeof(double);
1547 sz->offStruct += sizeof(double);
1551 /*========================= End of Function ========================*/
1553 /*------------------------------------------------------------------*/
1555 /* Name - get_call_info */
1557 /* Function - Determine the amount of space required for code */
1558 /* and stack. In addition determine starting points */
1559 /* for stack-based parameters, and area for struct- */
1560 /* ures being returned on the stack. */
1562 /*------------------------------------------------------------------*/
1565 get_call_info (MonoCompile *cfg, MonoMemPool *mp, MonoMethodSignature *sig)
1567 guint i, fr, gr, size, pstart;
1568 int nParm = sig->hasthis + sig->param_count;
1570 guint32 simpleType, align;
1571 gboolean is_pinvoke = sig->pinvoke;
1576 cinfo = mono_mempool_alloc0 (mp, sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1578 cinfo = g_malloc0 (sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1583 cinfo->struct_ret = 0;
1587 sz->offStruct = S390_MINIMAL_STACK_SIZE;
1588 sz->stack_size = S390_MINIMAL_STACK_SIZE;
1595 /*----------------------------------------------------------*/
1596 /* We determine the size of the return code/stack in case we*/
1597 /* need to reserve a register to be used to address a stack */
1598 /* area that the callee will use. */
1599 /*----------------------------------------------------------*/
1601 ret_type = mini_get_underlying_type (sig->ret);
1602 simpleType = ret_type->type;
1604 switch (simpleType) {
1605 case MONO_TYPE_BOOLEAN:
1610 case MONO_TYPE_CHAR:
1615 case MONO_TYPE_CLASS:
1616 case MONO_TYPE_OBJECT:
1617 case MONO_TYPE_SZARRAY:
1618 case MONO_TYPE_ARRAY:
1620 case MONO_TYPE_FNPTR:
1621 case MONO_TYPE_STRING:
1622 cinfo->ret.reg = s390_r2;
1627 cinfo->ret.reg = s390_f0;
1632 cinfo->ret.reg = s390_r2;
1635 case MONO_TYPE_GENERICINST:
1636 if (!mono_type_generic_inst_is_valuetype (sig->ret)) {
1637 cinfo->ret.reg = s390_r2;
1642 case MONO_TYPE_VALUETYPE: {
1643 MonoClass *klass = mono_class_from_mono_type (sig->ret);
1644 if (klass->enumtype) {
1645 simpleType = mono_class_enum_basetype (klass)->type;
1648 size = mini_type_stack_size_full (&klass->byval_arg, NULL, sig->pinvoke);
1650 cinfo->struct_ret = 1;
1651 cinfo->ret.size = size;
1652 cinfo->ret.vtsize = size;
1655 case MONO_TYPE_TYPEDBYREF:
1656 size = sizeof (MonoTypedRef);
1657 cinfo->struct_ret = 1;
1658 cinfo->ret.size = size;
1659 cinfo->ret.vtsize = size;
1661 case MONO_TYPE_VOID:
1664 g_error ("Can't handle as return value 0x%x", sig->ret->type);
1670 * To simplify get_this_arg_reg () and LLVM integration, emit the vret arg after
1671 * the first argument, allowing 'this' to be always passed in the first arg reg.
1672 * Also do this if the first argument is a reference type, since virtual calls
1673 * are sometimes made using calli without sig->hasthis set, like in the delegate
1676 if (cinfo->struct_ret && !is_pinvoke &&
1678 (sig->param_count > 0 &&
1679 MONO_TYPE_IS_REFERENCE (mini_get_underlying_type (sig->params [0]))))) {
1681 cinfo->args[nParm].size = sizeof (gpointer);
1682 add_general (&gr, sz, cinfo->args + nParm);
1684 cinfo->args[nParm].size = sizeof (gpointer);
1685 add_general (&gr, sz, &cinfo->args [sig->hasthis + nParm]);
1689 cinfo->vret_arg_index = 1;
1690 cinfo->ret.reg = gr;
1695 cinfo->args[nParm].size = sizeof (gpointer);
1696 add_general (&gr, sz, cinfo->args + nParm);
1700 if (cinfo->struct_ret) {
1701 cinfo->ret.reg = gr;
1706 if ((sig->call_convention == MONO_CALL_VARARG) && (sig->param_count == 0)) {
1707 gr = S390_LAST_ARG_REG + 1;
1708 fr = S390_LAST_FPARG_REG + 1;
1710 /* Emit the signature cookie just before the implicit arguments */
1711 add_general (&gr, sz, &cinfo->sigCookie);
1714 /*----------------------------------------------------------*/
1715 /* We determine the size of the parameter code and stack */
1716 /* requirements by checking the types and sizes of the */
1718 /*----------------------------------------------------------*/
1720 for (i = pstart; i < sig->param_count; ++i) {
1723 /*--------------------------------------------------*/
1724 /* Handle vararg type calls. All args are put on */
1726 /*--------------------------------------------------*/
1727 if ((sig->call_convention == MONO_CALL_VARARG) &&
1728 (i == sig->sentinelpos)) {
1729 gr = S390_LAST_ARG_REG + 1;
1730 fr = S390_LAST_FPARG_REG + 1;
1731 add_general (&gr, sz, &cinfo->sigCookie);
1734 if (sig->params [i]->byref) {
1735 add_general (&gr, sz, cinfo->args+nParm);
1736 cinfo->args[nParm].size = sizeof(gpointer);
1741 ptype = mini_get_underlying_type (sig->params [i]);
1742 simpleType = ptype->type;
1743 cinfo->args[nParm].type = simpleType;
1744 switch (simpleType) {
1745 case MONO_TYPE_BOOLEAN:
1748 cinfo->args[nParm].size = sizeof(char);
1749 add_general (&gr, sz, cinfo->args+nParm);
1754 case MONO_TYPE_CHAR:
1755 cinfo->args[nParm].size = sizeof(short);
1756 add_general (&gr, sz, cinfo->args+nParm);
1761 cinfo->args[nParm].size = sizeof(int);
1762 add_general (&gr, sz, cinfo->args+nParm);
1768 case MONO_TYPE_FNPTR:
1769 case MONO_TYPE_CLASS:
1770 case MONO_TYPE_OBJECT:
1771 case MONO_TYPE_STRING:
1772 case MONO_TYPE_SZARRAY:
1773 case MONO_TYPE_ARRAY:
1774 cinfo->args[nParm].size = sizeof(gpointer);
1775 add_general (&gr, sz, cinfo->args+nParm);
1780 cinfo->args[nParm].size = sizeof(long long);
1781 add_general (&gr, sz, cinfo->args+nParm);
1785 cinfo->args[nParm].size = sizeof(float);
1786 add_float (&fr, sz, cinfo->args+nParm);
1790 cinfo->args[nParm].size = sizeof(double);
1791 add_float (&fr, sz, cinfo->args+nParm);
1794 case MONO_TYPE_GENERICINST:
1795 if (!mono_type_generic_inst_is_valuetype (ptype)) {
1796 cinfo->args[nParm].size = sizeof(gpointer);
1797 add_general (&gr, sz, cinfo->args+nParm);
1802 case MONO_TYPE_VALUETYPE: {
1803 MonoMarshalType *info;
1804 MonoClass *klass = mono_class_from_mono_type (ptype);
1807 size = mono_class_native_size(klass, NULL);
1809 size = mono_class_value_size(klass, NULL);
1811 if (simpleType != MONO_TYPE_GENERICINST) {
1812 info = mono_marshal_load_type_info(klass);
1814 if ((info->native_size == sizeof(float)) &&
1815 (info->num_fields == 1) &&
1816 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1817 cinfo->args[nParm].size = sizeof(float);
1818 add_float(&fr, sz, cinfo->args+nParm);
1823 if ((info->native_size == sizeof(double)) &&
1824 (info->num_fields == 1) &&
1825 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1826 cinfo->args[nParm].size = sizeof(double);
1827 add_float(&fr, sz, cinfo->args+nParm);
1833 cinfo->args[nParm].vtsize = 0;
1834 cinfo->args[nParm].size = 0;
1837 /*----------------------------------*/
1838 /* On S/390, structures of size 1, */
1839 /* 2, 4, and 8 bytes are passed in */
1840 /* (a) register(s). */
1841 /*----------------------------------*/
1847 add_general(&gr, sz, cinfo->args+nParm);
1848 cinfo->args[nParm].size = size;
1849 cinfo->args[nParm].regtype = RegTypeStructByVal;
1851 sz->local_size += sizeof(long);
1854 add_stackParm(&gr, sz, cinfo->args+nParm, size);
1859 case MONO_TYPE_TYPEDBYREF: {
1860 int size = sizeof (MonoTypedRef);
1862 cinfo->args[nParm].vtsize = 0;
1863 cinfo->args[nParm].size = 0;
1866 /*----------------------------------*/
1867 /* On S/390, structures of size 1, */
1868 /* 2, 4, and 8 bytes are passed in */
1869 /* (a) register(s). */
1870 /*----------------------------------*/
1876 add_general(&gr, sz, cinfo->args+nParm);
1877 cinfo->args[nParm].size = size;
1878 cinfo->args[nParm].regtype = RegTypeStructByVal;
1880 sz->local_size += sizeof(long);
1883 add_stackParm(&gr, sz, cinfo->args+nParm, size);
1889 g_error ("Can't trampoline 0x%x", ptype);
1893 /*----------------------------------------------------------*/
1894 /* Handle the case where there are no implicit arguments */
1895 /*----------------------------------------------------------*/
1896 if ((sig->call_convention == MONO_CALL_VARARG) &&
1899 (sig->param_count == sig->sentinelpos)) {
1900 gr = S390_LAST_ARG_REG + 1;
1901 fr = S390_LAST_FPARG_REG + 1;
1902 add_general (&gr, sz, &cinfo->sigCookie);
1905 /*----------------------------------------------------------*/
1906 /* If we are passing a structure back then if it won't be */
1907 /* in a register(s) then we make room at the end of the */
1908 /* parameters that may have been placed on the stack */
1909 /*----------------------------------------------------------*/
1910 if (cinfo->struct_ret) {
1911 cinfo->ret.offset = sz->stack_size;
1912 switch (cinfo->ret.size) {
1920 sz->stack_size += S390_ALIGN(cinfo->ret.size, align);
1925 sz->stack_size = sz->stack_size + sz->local_size + sz->parm_size +
1927 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1932 /*========================= End of Function ========================*/
1934 /*------------------------------------------------------------------*/
1936 /* Name - mono_arch_allocate_vars */
1938 /* Function - Set var information according to the calling */
1939 /* convention for S/390. The local var stuff should */
1940 /* most likely be split in another method. */
1942 /* Parameter - @m - Compile unit. */
1944 /*------------------------------------------------------------------*/
1947 mono_arch_allocate_vars (MonoCompile *cfg)
1949 MonoMethodSignature *sig;
1950 MonoMethodHeader *header;
1953 int iParm, iVar, offset, align, size, curinst;
1954 int frame_reg = STK_BASE;
1957 header = cfg->header;
1959 cfg->flags |= MONO_CFG_HAS_SPILLUP;
1961 /*---------------------------------------------------------*/
1962 /* We use the frame register also for any method that has */
1963 /* filter clauses. This way, when the handlers are called, */
1964 /* the code will reference local variables using the frame */
1965 /* reg instead of the stack pointer: if we had to restore */
1966 /* the stack pointer, we'd corrupt the method frames that */
1967 /* are already on the stack (since filters get called */
1968 /* before stack unwinding happens) when the filter code */
1969 /* would call any method. */
1970 /*---------------------------------------------------------*/
1971 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
1972 frame_reg = s390_r11;
1974 cfg->frame_reg = frame_reg;
1976 cfg->arch.bkchain_reg = -1;
1978 if (frame_reg != STK_BASE)
1979 cfg->used_int_regs |= (1 << frame_reg);
1981 if (cfg->uses_rgctx_reg)
1982 cfg->used_int_regs |= (1 << MONO_ARCH_IMT_REG);
1984 sig = mono_method_signature (cfg->method);
1986 cinfo = get_call_info (cfg, cfg->mempool, sig);
1988 if (!cinfo->struct_ret) {
1989 switch (mini_get_underlying_type (sig->ret)->type) {
1990 case MONO_TYPE_VOID:
1993 cfg->ret->opcode = OP_REGVAR;
1994 cfg->ret->dreg = s390_r2;
1999 /*--------------------------------------------------------------*/
2000 /* local vars are at a positive offset from the stack pointer */
2001 /* also note that if the function uses alloca, we use s390_r11 */
2002 /* to point at the local variables. */
2003 /* add parameter area size for called functions */
2004 /*--------------------------------------------------------------*/
2005 if (cfg->param_area == 0)
2006 offset = S390_MINIMAL_STACK_SIZE;
2008 offset = cfg->param_area;
2010 cfg->sig_cookie = 0;
2012 if (cinfo->struct_ret) {
2013 inst = cfg->vret_addr;
2014 offset = S390_ALIGN(offset, sizeof(gpointer));
2015 inst->inst_offset = offset;
2016 inst->opcode = OP_REGOFFSET;
2017 inst->inst_basereg = frame_reg;
2018 offset += sizeof(gpointer);
2019 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2020 printf ("vret_addr =");
2021 mono_print_ins (cfg->vret_addr);
2026 inst = cfg->args [0];
2027 if (inst->opcode != OP_REGVAR) {
2028 inst->opcode = OP_REGOFFSET;
2029 inst->inst_basereg = frame_reg;
2030 offset = S390_ALIGN(offset, sizeof(gpointer));
2031 inst->inst_offset = offset;
2032 offset += sizeof (gpointer);
2039 eArg = sig->param_count + sArg;
2041 if (sig->call_convention == MONO_CALL_VARARG)
2042 cfg->sig_cookie += S390_MINIMAL_STACK_SIZE;
2044 for (iParm = sArg; iParm < eArg; ++iParm) {
2045 inst = cfg->args [curinst];
2046 if (inst->opcode != OP_REGVAR) {
2047 switch (cinfo->args[iParm].regtype) {
2048 case RegTypeStructByAddr : {
2051 size = sizeof (gpointer);
2053 inst->opcode = OP_REGOFFSET;
2054 inst->inst_basereg = frame_reg;
2055 offset = S390_ALIGN (offset, sizeof (gpointer));
2056 inst->inst_offset = offset;
2058 /* Add a level of indirection */
2059 MONO_INST_NEW (cfg, indir, 0);
2061 inst->opcode = OP_VTARG_ADDR;
2062 inst->inst_left = indir;
2065 case RegTypeStructByAddrOnStack : {
2068 size = sizeof (gpointer);
2070 /* Similar to the == STK_BASE case below */
2071 cfg->arch.bkchain_reg = s390_r12;
2072 cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2074 inst->opcode = OP_REGOFFSET;
2075 inst->dreg = mono_alloc_preg (cfg);
2076 inst->inst_basereg = cfg->arch.bkchain_reg;
2077 inst->inst_offset = cinfo->args [iParm].offset;
2079 /* Add a level of indirection */
2080 MONO_INST_NEW (cfg, indir, 0);
2082 inst->opcode = OP_VTARG_ADDR;
2083 inst->inst_left = indir;
2086 case RegTypeStructByVal :
2087 size = cinfo->args[iParm].size;
2088 offset = S390_ALIGN(offset, size);
2089 inst->opcode = OP_REGOFFSET;
2090 inst->inst_basereg = frame_reg;
2091 inst->inst_offset = offset;
2094 if (cinfo->args [iParm].reg == STK_BASE) {
2096 * These arguments are in the previous frame, so we can't
2097 * compute their offset from the current frame pointer right
2098 * now, since cfg->stack_offset is not yet known, so dedicate a
2099 * register holding the previous frame pointer.
2101 cfg->arch.bkchain_reg = s390_r12;
2102 cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2104 inst->opcode = OP_REGOFFSET;
2105 inst->inst_basereg = cfg->arch.bkchain_reg;
2106 size = (cinfo->args[iParm].size < 8
2107 ? 8 - cinfo->args[iParm].size
2109 inst->inst_offset = cinfo->args [iParm].offset + size;
2110 size = sizeof (long);
2112 inst->opcode = OP_REGOFFSET;
2113 inst->inst_basereg = frame_reg;
2114 size = (cinfo->args[iParm].size < 8
2117 offset = S390_ALIGN(offset, size);
2118 if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
2119 inst->inst_offset = offset;
2121 inst->inst_offset = offset + (8 - size);
2126 if ((sig->call_convention == MONO_CALL_VARARG) &&
2127 (cinfo->args[iParm].regtype != RegTypeGeneral) &&
2128 (iParm < sig->sentinelpos))
2129 cfg->sig_cookie += size;
2130 printf("%s %4d cookine %x\n",__FUNCTION__,__LINE__,cfg->sig_cookie);
2133 offset += MAX(size, 8);
2138 cfg->locals_min_stack_offset = offset;
2140 curinst = cfg->locals_start;
2141 for (iVar = curinst; iVar < cfg->num_varinfo; ++iVar) {
2142 inst = cfg->varinfo [iVar];
2143 if ((inst->flags & MONO_INST_IS_DEAD) ||
2144 (inst->opcode == OP_REGVAR))
2147 /*--------------------------------------------------*/
2148 /* inst->backend.is_pinvoke indicates native sized */
2149 /* value typs this is used by the pinvoke wrappers */
2150 /* when they call functions returning structure */
2151 /*--------------------------------------------------*/
2152 if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype))
2153 size = mono_class_native_size (mono_class_from_mono_type(inst->inst_vtype),
2154 (guint32 *) &align);
2156 size = mono_type_size (inst->inst_vtype, &align);
2158 offset = S390_ALIGN(offset, align);
2159 inst->inst_offset = offset;
2160 inst->opcode = OP_REGOFFSET;
2161 inst->inst_basereg = frame_reg;
2163 DEBUG (g_print("allocating local %d to %ld, size: %d\n",
2164 iVar, inst->inst_offset, size));
2167 cfg->locals_max_stack_offset = offset;
2169 /*------------------------------------------------------*/
2170 /* Allow space for the trace method stack area if needed*/
2171 /*------------------------------------------------------*/
2172 if ((mono_jit_trace_calls != NULL && mono_trace_eval (cfg->method))
2173 || (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE))
2174 offset += S390_TRACE_STACK_SIZE;
2176 /*------------------------------------------------------*/
2177 /* Reserve space to save LMF and caller saved registers */
2178 /*------------------------------------------------------*/
2179 if (cfg->method->save_lmf)
2180 offset += sizeof (MonoLMF);
2182 /*------------------------------------------------------*/
2183 /* align the offset */
2184 /*------------------------------------------------------*/
2185 cfg->stack_offset = S390_ALIGN(offset, S390_STACK_ALIGNMENT);
2187 /*------------------------------------------------------*/
2188 /* Fix offsets for args whose value is in parent frame */
2189 /*------------------------------------------------------*/
2190 for (iParm = sArg; iParm < eArg; ++iParm) {
2191 inst = cfg->args [iParm];
2193 if (inst->opcode == OP_S390_STKARG) {
2194 inst->opcode = OP_REGOFFSET;
2195 inst->inst_offset += cfg->stack_offset;
2200 /*========================= End of Function ========================*/
2202 /*------------------------------------------------------------------*/
2204 /* Name - mono_arch_create_vars */
2206 /*------------------------------------------------------------------*/
2209 mono_arch_create_vars (MonoCompile *cfg)
2211 MonoMethodSignature *sig;
2214 sig = mono_method_signature (cfg->method);
2216 cinfo = get_call_info (cfg, cfg->mempool, sig);
2218 if (cinfo->struct_ret) {
2219 cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG);
2220 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2221 printf ("vret_addr = ");
2222 mono_print_ins (cfg->vret_addr);
2227 /*========================= End of Function ========================*/
2229 /*------------------------------------------------------------------*/
2231 /* Name - add_outarg_reg2. */
2233 /*------------------------------------------------------------------*/
2236 add_outarg_reg2 (MonoCompile *cfg, MonoCallInst *call, ArgStorage storage, int reg, MonoInst *tree)
2241 case RegTypeGeneral:
2242 MONO_INST_NEW (cfg, ins, OP_MOVE);
2243 ins->dreg = mono_alloc_ireg (cfg);
2244 ins->sreg1 = tree->dreg;
2245 MONO_ADD_INS (cfg->cbb, ins);
2246 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, FALSE);
2249 MONO_INST_NEW (cfg, ins, OP_FMOVE);
2250 ins->dreg = mono_alloc_freg (cfg);
2251 ins->sreg1 = tree->dreg;
2252 MONO_ADD_INS (cfg->cbb, ins);
2253 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2256 MONO_INST_NEW (cfg, ins, OP_S390_SETF4RET);
2257 ins->dreg = mono_alloc_freg (cfg);
2258 ins->sreg1 = tree->dreg;
2259 MONO_ADD_INS (cfg->cbb, ins);
2260 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2263 g_assert_not_reached ();
2267 /*========================= End of Function ========================*/
2269 /*------------------------------------------------------------------*/
2271 /* Name - emit_sig_cookie. */
2273 /*------------------------------------------------------------------*/
2276 emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo)
2278 MonoMethodSignature *tmpSig;
2281 cfg->disable_aot = TRUE;
2283 /*----------------------------------------------------------*/
2284 /* mono_ArgIterator_Setup assumes the signature cookie is */
2285 /* passed first and all the arguments which were before it */
2286 /* passed on the stack after the signature. So compensate */
2287 /* by passing a different signature. */
2288 /*----------------------------------------------------------*/
2289 tmpSig = mono_metadata_signature_dup (call->signature);
2290 tmpSig->param_count -= call->signature->sentinelpos;
2291 tmpSig->sentinelpos = 0;
2292 if (tmpSig->param_count > 0)
2293 memcpy (tmpSig->params,
2294 call->signature->params + call->signature->sentinelpos,
2295 tmpSig->param_count * sizeof(MonoType *));
2297 MONO_INST_NEW (cfg, sig_arg, OP_ICONST);
2298 sig_arg->dreg = mono_alloc_ireg (cfg);
2299 sig_arg->inst_p0 = tmpSig;
2300 MONO_ADD_INS (cfg->cbb, sig_arg);
2302 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, STK_BASE,
2303 cinfo->sigCookie.offset, sig_arg->dreg);
2306 /*========================= End of Function ========================*/
2308 /*------------------------------------------------------------------*/
2310 /* Name - mono_arch_emit_call */
2312 /*------------------------------------------------------------------*/
2315 mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
2318 MonoMethodSignature *sig;
2320 int i, n, lParamArea;
2322 ArgInfo *ainfo = NULL;
2324 MonoMethodHeader *header;
2327 sig = call->signature;
2328 n = sig->param_count + sig->hasthis;
2329 DEBUG (g_print ("Call requires: %d parameters\n",n));
2331 cinfo = get_call_info (cfg, cfg->mempool, sig);
2333 stackSize = cinfo->sz.stack_size + cinfo->sz.local_size +
2334 cinfo->sz.parm_size + cinfo->sz.offset;
2335 call->stack_usage = MAX(stackSize, call->stack_usage);
2336 lParamArea = MAX((call->stack_usage-S390_MINIMAL_STACK_SIZE-cinfo->sz.parm_size), 0);
2337 cfg->param_area = MAX(((signed) cfg->param_area), lParamArea);
2338 cfg->flags |= MONO_CFG_HAS_CALLS;
2340 if (cinfo->struct_ret) {
2341 MONO_INST_NEW (cfg, ins, OP_MOVE);
2342 ins->sreg1 = call->vret_var->dreg;
2343 ins->dreg = mono_alloc_preg (cfg);
2344 MONO_ADD_INS (cfg->cbb, ins);
2345 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, cinfo->ret.reg, FALSE);
2348 header = cfg->header;
2349 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2354 for (i = 0; i < n; ++i) {
2357 ainfo = cinfo->args + i;
2358 if (i >= sig->hasthis)
2359 t = sig->params [i - sig->hasthis];
2361 t = &mono_defaults.int_class->byval_arg;
2362 t = mini_get_underlying_type (t);
2364 in = call->args [i];
2366 if ((sig->call_convention == MONO_CALL_VARARG) &&
2368 (i == sig->sentinelpos)) {
2369 emit_sig_cookie (cfg, call, cinfo);
2372 switch (ainfo->regtype) {
2373 case RegTypeGeneral:
2374 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2377 if (MONO_TYPE_ISSTRUCT (t)) {
2378 /* Valuetype passed in one fp register */
2379 ainfo->regtype = RegTypeStructByValInFP;
2382 if (ainfo->size == 4)
2383 ainfo->regtype = RegTypeFPR4;
2384 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2387 case RegTypeStructByVal:
2388 case RegTypeStructByAddr:
2389 case RegTypeStructByAddrOnStack: {
2393 if (sig->params [i - sig->hasthis]->type == MONO_TYPE_TYPEDBYREF) {
2394 size = sizeof (MonoTypedRef);
2395 align = sizeof (gpointer);
2399 size = mono_type_native_stack_size (&in->klass->byval_arg, &align);
2402 * Other backends use mono_type_stack_size (), but that
2403 * aligns the size to 8, which is larger than the size of
2404 * the source, leading to reads of invalid memory if the
2405 * source is at the end of address space.
2407 size = mono_class_value_size (in->klass, &align);
2410 g_assert (in->klass);
2412 ainfo->offparm += cinfo->sz.offStruct;
2414 MONO_INST_NEW (cfg, ins, OP_OUTARG_VT);
2415 ins->sreg1 = in->dreg;
2416 ins->klass = in->klass;
2417 ins->backend.size = ainfo->size;
2418 ins->inst_p0 = call;
2419 ins->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
2420 memcpy (ins->inst_p1, ainfo, sizeof (ArgInfo));
2422 MONO_ADD_INS (cfg->cbb, ins);
2424 if (ainfo->regtype == RegTypeStructByAddr) {
2426 * We use OP_OUTARG_VT to copy the valuetype to a stack location, then
2427 * use the normal OUTARG opcodes to pass the address of the location to
2430 int treg = mono_alloc_preg (cfg);
2431 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2432 frmReg, ainfo->offparm);
2433 mono_call_inst_add_outarg_reg (cfg, call, treg, ainfo->reg, FALSE);
2434 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
2435 /* The address of the valuetype is passed on the stack */
2436 int treg = mono_alloc_preg (cfg);
2437 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2438 frmReg, ainfo->offparm);
2439 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG,
2440 ainfo->reg, ainfo->offset, treg);
2442 if (cfg->compute_gc_maps) {
2445 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, t);
2451 if (!t->byref && t->type == MONO_TYPE_R4) {
2452 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG,
2453 STK_BASE, ainfo->offset + 4,
2455 } else if (!t->byref && (t->type == MONO_TYPE_R8)) {
2456 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG,
2457 STK_BASE, ainfo->offset,
2460 MONO_INST_NEW (cfg, ins, OP_STORE_MEMBASE_REG);
2461 ins->inst_destbasereg = STK_BASE;
2462 ins->inst_offset = ainfo->offset;
2463 ins->sreg1 = in->dreg;
2466 /* This is needed by MonoTypedRef->value to point to the correct data */
2467 if ((sig->call_convention == MONO_CALL_VARARG) &&
2468 (i >= sig->sentinelpos)) {
2469 switch (ainfo->size) {
2471 ins->opcode = OP_STOREI1_MEMBASE_REG;
2474 ins->opcode = OP_STOREI2_MEMBASE_REG;
2477 ins->opcode = OP_STOREI4_MEMBASE_REG;
2485 MONO_ADD_INS (cfg->cbb, ins);
2489 g_assert_not_reached ();
2495 * Handle the case where there are no implicit arguments
2497 if ((sig->call_convention == MONO_CALL_VARARG) &&
2499 (i == sig->sentinelpos)) {
2500 emit_sig_cookie (cfg, call, cinfo);
2504 /*========================= End of Function ========================*/
2506 /*------------------------------------------------------------------*/
2508 /* Name - mono_arch_emit_outarg_vt */
2510 /*------------------------------------------------------------------*/
2513 mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
2515 MonoCallInst *call = (MonoCallInst*)ins->inst_p0;
2516 ArgInfo *ainfo = (ArgInfo*)ins->inst_p1;
2517 int size = ins->backend.size;
2519 if (ainfo->regtype == RegTypeStructByVal) {
2521 arg->ins.sreg1 = ainfo->reg;
2522 arg->ins.opcode = OP_OUTARG_VT;
2523 arg->size = ainfo->size;
2524 arg->offset = ainfo->offset;
2525 arg->offPrm = ainfo->offparm + cinfo->sz.offStruct;
2527 if (ainfo->reg != STK_BASE) {
2528 MONO_OUTPUT_VTR (cfg, size, ainfo->reg, src->dreg, 0);
2530 MONO_OUTPUT_VTS (cfg, size, ainfo->reg, ainfo->offset,
2533 } else if (ainfo->regtype == RegTypeStructByValInFP) {
2534 int dreg = mono_alloc_freg (cfg);
2536 if (ainfo->size == 4) {
2537 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR4_MEMBASE, dreg, src->dreg, 0);
2538 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, dreg, dreg);
2540 g_assert (ainfo->size == 8);
2542 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR8_MEMBASE, dreg, src->dreg, 0);
2545 mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg, TRUE);
2547 MonoMethodHeader *header;
2550 header = mono_method_get_header (cfg->method);
2551 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2556 MONO_EMIT_NEW_MOVE (cfg, srcReg, ainfo->offparm,
2557 src->dreg, 0, size);
2559 if (cfg->compute_gc_maps) {
2562 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, &ins->klass->byval_arg);
2567 /*========================= End of Function ========================*/
2569 /*------------------------------------------------------------------*/
2571 /* Name - mono_arch_emit_setret */
2573 /*------------------------------------------------------------------*/
2576 mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
2578 MonoType *ret = mini_get_underlying_type (mono_method_signature (method)->ret);
2581 if (ret->type == MONO_TYPE_R4) {
2582 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, s390_f0, val->dreg);
2584 } else if (ret->type == MONO_TYPE_R8) {
2585 MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, s390_f0, val->dreg);
2590 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg);
2593 /*========================= End of Function ========================*/
2595 /*------------------------------------------------------------------*/
2597 /* Name - mono_arch_instrument_mem_needs */
2599 /* Function - Allow tracing to work with this interface (with */
2600 /* an optional argument). */
2602 /*------------------------------------------------------------------*/
2605 mono_arch_instrument_mem_needs (MonoMethod *method, int *stack, int *code)
2607 /* no stack room needed now (may be needed for FASTCALL-trace support) */
2609 /* split prolog-epilog requirements? */
2610 *code = 50; /* max bytes needed: check this number */
2613 /*========================= End of Function ========================*/
2615 /*------------------------------------------------------------------*/
2617 /* Name - mono_arch_instrument_prolog */
2619 /* Function - Create an "instrumented" prolog. */
2621 /*------------------------------------------------------------------*/
2624 mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p,
2625 gboolean enable_arguments)
2632 parmOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2633 if (cfg->method->save_lmf)
2634 parmOffset -= sizeof(MonoLMF);
2635 fpOffset = parmOffset + (5*sizeof(gpointer));
2638 s390_stmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2639 s390_stdy (code, s390_f0, 0, STK_BASE, fpOffset);
2640 s390_stdy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2641 s390_stdy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2642 s390_stdy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2643 S390_SET (code, s390_r1, func);
2644 S390_SET (code, s390_r2, cfg->method);
2645 s390_lay (code, s390_r3, 0, STK_BASE, parmOffset);
2646 s390_lgr (code, s390_r4, STK_BASE);
2647 s390_aghi (code, s390_r4, cfg->stack_usage);
2648 s390_basr (code, s390_r14, s390_r1);
2649 s390_ldy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2650 s390_ldy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2651 s390_ldy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2652 s390_ldy (code, s390_f0, 0, STK_BASE, fpOffset);
2653 s390_lmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2658 /*========================= End of Function ========================*/
2660 /*------------------------------------------------------------------*/
2662 /* Name - mono_arch_instrument_epilog */
2664 /* Function - Create an epilog that will handle the returned */
2665 /* values used in instrumentation. */
2667 /*------------------------------------------------------------------*/
2670 mono_arch_instrument_epilog_full (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments, gboolean preserve_argument_registers)
2673 int save_mode = SAVE_NONE,
2676 MonoMethod *method = cfg->method;
2677 int rtype = mini_get_underlying_type (mono_method_signature (method)->ret)->type;
2679 offset = code - cfg->native_code;
2680 /*-----------------------------------------*/
2681 /* We need about 128 bytes of instructions */
2682 /*-----------------------------------------*/
2683 if (offset > (cfg->code_size - 128)) {
2684 cfg->code_size *= 2;
2685 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
2686 code = cfg->native_code + offset;
2689 saveOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2690 if (method->save_lmf)
2691 saveOffset -= sizeof(MonoLMF);
2695 case MONO_TYPE_VOID:
2696 /* special case string .ctor icall */
2697 if (strcmp (".ctor", method->name) && method->klass == mono_defaults.string_class)
2698 save_mode = SAVE_ONE;
2700 save_mode = SAVE_NONE;
2704 save_mode = SAVE_ONE;
2707 save_mode = SAVE_R4;
2710 save_mode = SAVE_R8;
2712 case MONO_TYPE_VALUETYPE:
2713 if (mono_method_signature (method)->ret->data.klass->enumtype) {
2714 rtype = mono_class_enum_basetype (mono_method_signature (method)->ret->data.klass)->type;
2717 save_mode = SAVE_STRUCT;
2720 save_mode = SAVE_ONE;
2724 switch (save_mode) {
2726 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2727 if (enable_arguments) {
2728 s390_lgr (code, s390_r3, s390_r2);
2732 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2733 if (enable_arguments) {
2734 s390_ldebr (code, s390_f0, s390_f0);
2738 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2741 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2742 if (enable_arguments) {
2743 s390_lg (code, s390_r3, 0, cfg->frame_reg,
2744 S390_MINIMAL_STACK_SIZE+cfg->param_area);
2752 S390_SET (code, s390_r1, func);
2753 S390_SET (code, s390_r2, cfg->method);
2754 s390_basr (code, s390_r14, s390_r1);
2756 switch (save_mode) {
2758 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2762 s390_ld (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2765 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2775 /*========================= End of Function ========================*/
2777 /*------------------------------------------------------------------*/
2779 /* Name - mono_arch_peephole_pass_1 */
2781 /* Function - Form a peephole pass at the code looking for */
2782 /* simple optimizations. */
2784 /*------------------------------------------------------------------*/
2787 mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
2791 /*========================= End of Function ========================*/
2793 /*------------------------------------------------------------------*/
2795 /* Name - mono_arch_peephole_pass_2 */
2797 /* Function - Form a peephole pass at the code looking for */
2798 /* simple optimizations. */
2800 /*------------------------------------------------------------------*/
2803 mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
2807 MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
2808 mono_peephole_ins (bb, ins);
2812 /*========================= End of Function ========================*/
2814 /*------------------------------------------------------------------*/
2816 /* Name - mono_arch_lowering_pass. */
2818 /*------------------------------------------------------------------*/
2821 mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
2823 MonoInst *ins, *next;
2825 MONO_BB_FOR_EACH_INS_SAFE (bb, next, ins) {
2826 switch (ins->opcode) {
2831 case OP_IDIV_UN_IMM:
2832 case OP_IREM_UN_IMM:
2837 case OP_LOCALLOC_IMM:
2838 mono_decompose_op_imm (cfg, bb, ins);
2841 if (!s390_is_imm16 (ins->inst_imm))
2842 /* This is created by the memcpy code which ignores is_inst_imm */
2843 mono_decompose_op_imm (cfg, bb, ins);
2850 bb->max_vreg = cfg->next_vreg;
2853 /*========================= End of Function ========================*/
2855 /*------------------------------------------------------------------*/
2857 /* Name - emit_float_to_int */
2859 /* Function - Create instructions which will convert a floating */
2860 /* point value to integer. */
2862 /*------------------------------------------------------------------*/
2865 emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size, gboolean is_signed)
2867 /* sreg is a float, dreg is an integer reg. */
2869 s390_cgdbr (code, dreg, 5, sreg);
2872 s390_ltgr (code, dreg, dreg);
2874 s390_oill (code, dreg, 0x80);
2875 s390_lghi (code, s390_r0, 0xff);
2876 s390_ngr (code, dreg, s390_r0);
2879 s390_ltgr (code, dreg, dreg);
2881 s390_oill (code, dreg, 0x8000);
2882 s390_llill(code, s390_r0, 0xffff);
2883 s390_ngr (code, dreg, s390_r0);
2888 S390_SET (code, s390_r13, 0x41e0000000000000llu);
2889 s390_ldgr (code, s390_f14, s390_r13);
2890 s390_ldr (code, s390_f15, sreg);
2891 s390_cdbr (code, s390_f15, s390_f14);
2892 s390_jl (code, 0); CODEPTR (code, o[0]);
2893 S390_SET (code, s390_r13, 0x41f0000000000000llu);
2894 s390_ldgr (code, s390_f14, s390_r13);
2895 s390_sdbr (code, s390_f15, s390_f14);
2896 s390_cfdbr (code, dreg, 7, s390_f15);
2898 PTRSLOT (code, o[0]);
2899 s390_cfdbr (code, dreg, 5, sreg);
2902 s390_lghi (code, s390_r0, 0xff);
2903 s390_ngr (code, dreg, s390_r0);
2906 s390_llill(code, s390_r0, 0xffff);
2907 s390_ngr (code, dreg, s390_r0);
2914 /*========================= End of Function ========================*/
2916 /*------------------------------------------------------------------*/
2918 /* Name - gboolean_is_unsigned. */
2920 /* Function - Return TRUE if next opcode is checking for un- */
2923 /*------------------------------------------------------------------*/
2926 gboolean is_unsigned (MonoInst *next)
2929 (((next->opcode >= OP_IBNE_UN) &&
2930 (next->opcode <= OP_IBLT_UN)) ||
2931 ((next->opcode >= OP_LBNE_UN) &&
2932 (next->opcode <= OP_LBLT_UN)) ||
2933 ((next->opcode >= OP_COND_EXC_NE_UN) &&
2934 (next->opcode <= OP_COND_EXC_LT_UN)) ||
2935 ((next->opcode >= OP_COND_EXC_INE_UN) &&
2936 (next->opcode <= OP_COND_EXC_ILT_UN)) ||
2937 ((next->opcode == OP_CLT_UN) ||
2938 (next->opcode == OP_CGT_UN)) ||
2939 ((next->opcode == OP_ICLT_UN) ||
2940 (next->opcode == OP_ICGT_UN) ||
2941 (next->opcode == OP_LCLT_UN) ||
2942 (next->opcode == OP_LCGT_UN))))
2948 /*========================= End of Function ========================*/
2950 /*------------------------------------------------------------------*/
2952 /* Name - mono_arch_output_basic_block */
2954 /* Function - Perform the "real" work of emitting instructions */
2955 /* that will do the work of in the basic block. */
2957 /*------------------------------------------------------------------*/
2960 mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
2965 guint8 *code = cfg->native_code + cfg->code_len;
2966 guint last_offset = 0;
2969 /* we don't align basic blocks of loops on s390 */
2971 if (cfg->verbose_level > 2)
2972 g_print ("Basic block %d starting at offset 0x%x\n", bb->block_num, bb->native_offset);
2974 if ((cfg->prof_options & MONO_PROFILE_COVERAGE) && cfg->coverage_info) {
2975 MonoProfileCoverageInfo *cov = cfg->coverage_info;
2976 g_assert (!mono_compile_aot);
2977 cov->data [bb->dfn].cil_code = bb->cil_code;
2978 /* This is not thread save, but good enough */
2979 S390_SET (code, s390_r1, &cov->data [bb->dfn].count);
2980 s390_alsi (code, 0, s390_r1, 1);
2983 MONO_BB_FOR_EACH_INS (bb, ins) {
2984 offset = code - cfg->native_code;
2986 max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
2988 if (offset > (cfg->code_size - max_len - 16)) {
2989 cfg->code_size *= 2;
2990 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
2991 code = cfg->native_code + offset;
2994 mono_debug_record_line_number (cfg, ins, offset);
2996 switch (ins->opcode) {
2997 case OP_STOREI1_MEMBASE_IMM: {
2998 s390_lghi (code, s390_r0, ins->inst_imm);
2999 S390_LONG (code, stcy, stc, s390_r0, 0,
3000 ins->inst_destbasereg, ins->inst_offset);
3003 case OP_STOREI2_MEMBASE_IMM: {
3004 s390_lghi (code, s390_r0, ins->inst_imm);
3005 S390_LONG (code, sthy, sth, s390_r0, 0,
3006 ins->inst_destbasereg, ins->inst_offset);
3009 case OP_STOREI4_MEMBASE_IMM: {
3010 s390_lgfi (code, s390_r0, ins->inst_imm);
3011 S390_LONG (code, sty, st, s390_r0, 0,
3012 ins->inst_destbasereg, ins->inst_offset);
3015 case OP_STORE_MEMBASE_IMM:
3016 case OP_STOREI8_MEMBASE_IMM: {
3017 S390_SET (code, s390_r0, ins->inst_imm);
3018 S390_LONG (code, stg, stg, s390_r0, 0,
3019 ins->inst_destbasereg, ins->inst_offset);
3022 case OP_STOREI1_MEMBASE_REG: {
3023 S390_LONG (code, stcy, stc, ins->sreg1, 0,
3024 ins->inst_destbasereg, ins->inst_offset);
3027 case OP_STOREI2_MEMBASE_REG: {
3028 S390_LONG (code, sthy, sth, ins->sreg1, 0,
3029 ins->inst_destbasereg, ins->inst_offset);
3032 case OP_STOREI4_MEMBASE_REG: {
3033 S390_LONG (code, sty, st, ins->sreg1, 0,
3034 ins->inst_destbasereg, ins->inst_offset);
3037 case OP_STORE_MEMBASE_REG:
3038 case OP_STOREI8_MEMBASE_REG: {
3039 S390_LONG (code, stg, stg, ins->sreg1, 0,
3040 ins->inst_destbasereg, ins->inst_offset);
3044 g_assert_not_reached ();
3046 case OP_LOAD_MEMBASE:
3047 case OP_LOADI8_MEMBASE: {
3048 S390_LONG (code, lg, lg, ins->dreg, 0,
3049 ins->inst_basereg, ins->inst_offset);
3052 case OP_LOADI4_MEMBASE: {
3053 S390_LONG (code, lgf, lgf, ins->dreg, 0,
3054 ins->inst_basereg, ins->inst_offset);
3057 case OP_LOADU4_MEMBASE: {
3058 S390_LONG (code, llgf, llgf, ins->dreg, 0,
3059 ins->inst_basereg, ins->inst_offset);
3062 case OP_LOADU1_MEMBASE: {
3063 S390_LONG (code, llgc, llgc, ins->dreg, 0,
3064 ins->inst_basereg, ins->inst_offset);
3067 case OP_LOADI1_MEMBASE: {
3068 S390_LONG (code, lgb, lgb, ins->dreg, 0,
3069 ins->inst_basereg, ins->inst_offset);
3072 case OP_LOADU2_MEMBASE: {
3073 S390_LONG (code, llgh, llgh, ins->dreg, 0,
3074 ins->inst_basereg, ins->inst_offset);
3077 case OP_LOADI2_MEMBASE: {
3078 S390_LONG (code, lgh, lgh, ins->dreg, 0,
3079 ins->inst_basereg, ins->inst_offset);
3082 case OP_LCONV_TO_I1: {
3083 s390_lgbr (code, ins->dreg, ins->sreg1);
3086 case OP_LCONV_TO_I2: {
3087 s390_lghr (code, ins->dreg, ins->sreg1);
3090 case OP_LCONV_TO_U1: {
3091 s390_llgcr (code, ins->dreg, ins->sreg1);
3094 case OP_LCONV_TO_U2: {
3095 s390_llghr (code, ins->dreg, ins->sreg1);
3098 case OP_ICONV_TO_I1: {
3099 s390_lgbr (code, ins->dreg, ins->sreg1);
3102 case OP_ICONV_TO_I2: {
3103 s390_lghr (code, ins->dreg, ins->sreg1);
3106 case OP_ICONV_TO_U1: {
3107 s390_llgcr (code, ins->dreg, ins->sreg1);
3110 case OP_ICONV_TO_U2: {
3111 s390_llghr (code, ins->dreg, ins->sreg1);
3116 if (is_unsigned (ins->next))
3117 s390_clgr (code, ins->sreg1, ins->sreg2);
3119 s390_cgr (code, ins->sreg1, ins->sreg2);
3123 if (is_unsigned (ins->next))
3124 s390_clr (code, ins->sreg1, ins->sreg2);
3126 s390_cr (code, ins->sreg1, ins->sreg2);
3129 case OP_COMPARE_IMM:
3130 case OP_LCOMPARE_IMM: {
3131 S390_SET (code, s390_r0, ins->inst_imm);
3132 if (is_unsigned (ins->next))
3133 s390_clgr (code, ins->sreg1, s390_r0);
3135 s390_cgr (code, ins->sreg1, s390_r0);
3138 case OP_ICOMPARE_IMM: {
3139 S390_SET (code, s390_r0, ins->inst_imm);
3140 if (is_unsigned (ins->next))
3141 s390_clr (code, ins->sreg1, s390_r0);
3143 s390_cr (code, ins->sreg1, s390_r0);
3147 mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_ABS,
3149 S390_CALL_TEMPLATE (code, s390_r14);
3154 s390_agr (code, ins->dreg, src2);
3159 s390_agr (code, ins->dreg, src2);
3164 s390_alcgr (code, ins->dreg, src2);
3168 if (ins->dreg != ins->sreg1) {
3169 s390_lgr (code, ins->dreg, ins->sreg1);
3171 if (s390_is_imm16 (ins->inst_imm)) {
3172 s390_aghi (code, ins->dreg, ins->inst_imm);
3173 } else if (s390_is_imm32 (ins->inst_imm)) {
3174 s390_agfi (code, ins->dreg, ins->inst_imm);
3176 S390_SET (code, s390_r0, ins->inst_imm);
3177 s390_agr (code, ins->dreg, s390_r0);
3182 if (ins->dreg != ins->sreg1) {
3183 s390_lgr (code, ins->dreg, ins->sreg1);
3185 g_assert (s390_is_imm16 (ins->inst_imm));
3186 s390_aghi (code, ins->dreg, ins->inst_imm);
3190 if (ins->dreg != ins->sreg1) {
3191 s390_lgr (code, ins->dreg, ins->sreg1);
3193 if (s390_is_imm16 (ins->inst_imm)) {
3194 s390_lghi (code, s390_r0, ins->inst_imm);
3195 s390_alcgr (code, ins->dreg, s390_r0);
3197 S390_SET (code, s390_r0, ins->inst_imm);
3198 s390_alcgr (code, ins->dreg, s390_r0);
3203 case OP_S390_IADD_OVF: {
3205 s390_ar (code, ins->dreg, src2);
3206 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3207 s390_lgfr (code, ins->dreg, ins->dreg);
3210 case OP_IADD_OVF_UN:
3211 case OP_S390_IADD_OVF_UN: {
3213 s390_algr (code, ins->dreg, src2);
3214 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3215 s390_llgfr (code, ins->dreg, ins->dreg);
3218 case OP_ADD_OVF_CARRY: {
3220 s390_lghi (code, s390_r0, 0);
3221 s390_lgr (code, s390_r1, s390_r0);
3222 s390_alcgr (code, s390_r0, s390_r1);
3223 s390_agr (code, ins->dreg, src2);
3224 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3225 s390_agr (code, ins->dreg, s390_r0);
3226 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3229 case OP_ADD_OVF_UN_CARRY: {
3231 s390_alcgr (code, ins->dreg, src2);
3232 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3237 s390_sgr (code, ins->dreg, src2);
3242 s390_sgr (code, ins->dreg, src2);
3247 s390_slbgr(code, ins->dreg, src2);
3251 if (ins->dreg != ins->sreg1) {
3252 s390_lgr (code, ins->dreg, ins->sreg1);
3254 if (s390_is_imm16 (-ins->inst_imm)) {
3255 s390_aghi (code, ins->dreg, -ins->inst_imm);
3256 } else if (s390_is_imm32 (-ins->inst_imm)) {
3257 s390_slgfi (code, ins->dreg, ins->inst_imm);
3259 S390_SET (code, s390_r0, ins->inst_imm);
3260 s390_slgr (code, ins->dreg, s390_r0);
3265 if (ins->dreg != ins->sreg1) {
3266 s390_lgr (code, ins->dreg, ins->sreg1);
3268 if (s390_is_imm16 (-ins->inst_imm)) {
3269 s390_aghi (code, ins->dreg, -ins->inst_imm);
3270 } else if (s390_is_imm32 (-ins->inst_imm)) {
3271 s390_slgfi (code, ins->dreg, ins->inst_imm);
3273 S390_SET (code, s390_r0, ins->inst_imm);
3274 s390_slgr (code, ins->dreg, s390_r0);
3279 if (ins->dreg != ins->sreg1) {
3280 s390_lgr (code, ins->dreg, ins->sreg1);
3282 if (s390_is_imm16 (-ins->inst_imm)) {
3283 s390_lghi (code, s390_r0, ins->inst_imm);
3284 s390_slbgr (code, ins->dreg, s390_r0);
3286 S390_SET (code, s390_r0, ins->inst_imm);
3287 s390_slbgr(code, ins->dreg, s390_r0);
3291 case OP_SUB_OVF_CARRY: {
3293 s390_lghi (code, s390_r0, 0);
3294 s390_lgr (code, s390_r1, s390_r0);
3295 s390_slbgr (code, s390_r0, s390_r1);
3296 s390_sgr (code, ins->dreg, src2);
3297 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3298 s390_agr (code, ins->dreg, s390_r0);
3299 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3302 case OP_SUB_OVF_UN_CARRY: {
3304 s390_slbgr (code, ins->dreg, src2);
3305 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3309 if (ins->sreg1 == ins->dreg) {
3310 s390_ngr (code, ins->dreg, ins->sreg2);
3313 if (ins->sreg2 == ins->dreg) {
3314 s390_ngr (code, ins->dreg, ins->sreg1);
3317 s390_lgr (code, ins->dreg, ins->sreg1);
3318 s390_ngr (code, ins->dreg, ins->sreg2);
3324 if (ins->dreg != ins->sreg1) {
3325 s390_lgr (code, ins->dreg, ins->sreg1);
3327 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3328 s390_ngr (code, ins->dreg, s390_r0);
3332 s390_lgr (code, s390_r1, ins->sreg1);
3333 s390_dsgr (code, s390_r0, ins->sreg2);
3334 s390_lgr (code, ins->dreg, s390_r1);
3338 s390_lgr (code, s390_r1, ins->sreg1);
3339 s390_lghi (code, s390_r0, 0);
3340 s390_dlgr (code, s390_r0, ins->sreg2);
3341 s390_lgr (code, ins->dreg, s390_r1);
3345 s390_lgr (code, s390_r1, ins->sreg1);
3346 s390_dsgr (code, s390_r0, ins->sreg2);
3347 s390_lgr (code, ins->dreg, s390_r0);
3351 if (s390_is_imm16 (ins->inst_imm)) {
3352 s390_lghi (code, s390_r13, ins->inst_imm);
3354 s390_lgfi (code, s390_r13, ins->inst_imm);
3356 s390_lgr (code, s390_r0, ins->sreg1);
3357 s390_dsgr (code, s390_r0, s390_r13);
3358 s390_lgfr (code, ins->dreg, s390_r0);
3362 s390_lgr (code, s390_r1, ins->sreg1);
3363 s390_lghi (code, s390_r0, 0);
3364 s390_dlgr (code, s390_r0, ins->sreg2);
3365 s390_lgr (code, ins->dreg, s390_r0);
3369 if (ins->sreg1 == ins->dreg) {
3370 s390_ogr (code, ins->dreg, ins->sreg2);
3373 if (ins->sreg2 == ins->dreg) {
3374 s390_ogr (code, ins->dreg, ins->sreg1);
3377 s390_lgr (code, ins->dreg, ins->sreg1);
3378 s390_ogr (code, ins->dreg, ins->sreg2);
3384 if (ins->dreg != ins->sreg1) {
3385 s390_lgr (code, ins->dreg, ins->sreg1);
3387 S390_SET_MASK(code, s390_r0, ins->inst_imm);
3388 s390_ogr (code, ins->dreg, s390_r0);
3392 if (ins->sreg1 == ins->dreg) {
3393 s390_xgr (code, ins->dreg, ins->sreg2);
3396 if (ins->sreg2 == ins->dreg) {
3397 s390_xgr (code, ins->dreg, ins->sreg1);
3400 s390_lgr (code, ins->dreg, ins->sreg1);
3401 s390_xgr (code, ins->dreg, ins->sreg2);
3407 if (ins->dreg != ins->sreg1) {
3408 s390_lgr (code, ins->dreg, ins->sreg1);
3410 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3411 s390_xgr (code, ins->dreg, s390_r0);
3416 s390_sllg (code, ins->dreg, ins->dreg, src2, 0);
3421 if (ins->sreg1 != ins->dreg) {
3422 s390_lgr (code, ins->dreg, ins->sreg1);
3424 s390_sllg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3429 s390_srag (code, ins->dreg, ins->dreg, src2, 0);
3434 if (ins->sreg1 != ins->dreg) {
3435 s390_lgr (code, ins->dreg, ins->sreg1);
3437 s390_srag (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3441 case OP_LSHR_UN_IMM: {
3442 if (ins->sreg1 != ins->dreg) {
3443 s390_lgr (code, ins->dreg, ins->sreg1);
3445 s390_srlg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3450 s390_srlg (code, ins->dreg, ins->dreg, src2, 0);
3454 if (ins->sreg1 != ins->dreg) {
3455 s390_lgr (code, ins->dreg, ins->sreg1);
3457 s390_lghi (code, s390_r0, -1);
3458 s390_xgr (code, ins->dreg, s390_r0);
3462 s390_lcgr (code, ins->dreg, ins->sreg1);
3467 s390_msgr (code, ins->dreg, src2);
3472 if (ins->dreg != ins->sreg1) {
3473 s390_lgr (code, ins->dreg, ins->sreg1);
3475 if (s390_is_imm16 (ins->inst_imm)) {
3476 s390_lghi (code, s390_r13, ins->inst_imm);
3477 } else if (s390_is_imm32 (ins->inst_imm)) {
3478 s390_lgfi (code, s390_r13, ins->inst_imm);
3480 S390_SET (code, s390_r13, ins->inst_imm);
3482 s390_msgr (code, ins->dreg, s390_r13);
3487 s390_ltgr (code, s390_r1, ins->sreg1);
3488 s390_jz (code, 0); CODEPTR(code, o[0]);
3489 s390_ltgr (code, s390_r0, ins->sreg2);
3491 s390_lghi (code, s390_r1, 0);
3492 s390_j (code, 0); CODEPTR(code, o[1]);
3493 s390_xgr (code, s390_r0, s390_r1);
3494 s390_msgr (code, s390_r1, ins->sreg2);
3495 s390_xgr (code, s390_r0, s390_r1);
3496 s390_srlg (code, s390_r0, s390_r0, 0, 63);
3497 s390_ltgr (code, s390_r0, s390_r0);
3498 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3499 PTRSLOT (code, o[0]);
3500 PTRSLOT (code, o[1]);
3501 s390_lgr (code, ins->dreg, s390_r1);
3504 case OP_LMUL_OVF_UN: {
3505 s390_lghi (code, s390_r0, 0);
3506 s390_lgr (code, s390_r1, ins->sreg1);
3507 s390_mlgr (code, s390_r0, ins->sreg2);
3508 s390_ltgr (code, s390_r0, s390_r0);
3509 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3510 s390_lgr (code, ins->dreg, s390_r1);
3514 g_assert_not_reached ();
3516 s390_algr (code, ins->dreg, src2);
3521 s390_agr (code, ins->dreg, src2);
3525 g_assert_not_reached ();
3527 s390_alcgr (code, ins->dreg, src2);
3531 if (ins->dreg != ins->sreg1) {
3532 s390_lgfr (code, ins->dreg, ins->sreg1);
3534 if (s390_is_imm16 (ins->inst_imm)) {
3535 s390_aghi (code, ins->dreg, ins->inst_imm);
3537 s390_afi (code, ins->dreg, ins->inst_imm);
3542 if (ins->dreg != ins->sreg1) {
3543 s390_lgfr (code, ins->dreg, ins->sreg1);
3545 if (s390_is_imm16 (ins->inst_imm)) {
3546 s390_lghi (code, s390_r0, ins->inst_imm);
3547 s390_alcgr (code, ins->dreg, s390_r0);
3549 S390_SET (code, s390_r0, ins->inst_imm);
3550 s390_alcgr (code, ins->dreg, s390_r0);
3555 case OP_S390_LADD_OVF: {
3557 s390_agr (code, ins->dreg, src2);
3558 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3561 case OP_LADD_OVF_UN:
3562 case OP_S390_LADD_OVF_UN: {
3564 s390_algr (code, ins->dreg, src2);
3565 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3569 CHECK_SRCDST_NCOM_I;
3570 s390_slgr (code, ins->dreg, src2);
3574 CHECK_SRCDST_NCOM_I;
3575 s390_sgr (code, ins->dreg, src2);
3579 CHECK_SRCDST_NCOM_I;
3580 s390_slbgr (code, ins->dreg, src2);
3584 if (ins->dreg != ins->sreg1) {
3585 s390_lgfr (code, ins->dreg, ins->sreg1);
3587 if (s390_is_imm16 (-ins->inst_imm)) {
3588 s390_aghi (code, ins->dreg, -ins->inst_imm);
3590 s390_agfi (code, ins->dreg, -ins->inst_imm);
3595 S390_SET (code, s390_r0, ins->inst_imm);
3596 s390_slgfr (code, ins->dreg, s390_r0);
3600 case OP_S390_ISUB_OVF: {
3602 s390_sr (code, ins->dreg, src2);
3603 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3604 s390_lgfr (code, ins->dreg, ins->dreg);
3607 case OP_ISUB_OVF_UN:
3608 case OP_S390_ISUB_OVF_UN: {
3610 s390_slr (code, ins->dreg, src2);
3611 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3612 s390_llgfr(code, ins->dreg, ins->dreg);
3616 case OP_S390_LSUB_OVF: {
3618 s390_sgr (code, ins->dreg, src2);
3619 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3622 case OP_LSUB_OVF_UN:
3623 case OP_S390_LSUB_OVF_UN: {
3625 s390_slgr (code, ins->dreg, src2);
3626 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3630 CHECK_SRCDST_NCOM_I;
3631 s390_ngr (code, ins->dreg, src2);
3635 if (ins->dreg != ins->sreg1) {
3636 s390_lgfr (code, ins->dreg, ins->sreg1);
3638 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3639 s390_ngr (code, ins->dreg, s390_r0);
3643 s390_lgfr (code, s390_r0, ins->sreg1);
3644 s390_srda (code, s390_r0, 0, 32);
3645 s390_dr (code, s390_r0, ins->sreg2);
3646 s390_lgfr (code, ins->dreg, s390_r1);
3650 s390_lgfr (code, s390_r0, ins->sreg1);
3651 s390_srdl (code, s390_r0, 0, 32);
3652 s390_dlr (code, s390_r0, ins->sreg2);
3653 s390_lgfr (code, ins->dreg, s390_r1);
3657 if (s390_is_imm16 (ins->inst_imm)) {
3658 s390_lghi (code, s390_r13, ins->inst_imm);
3660 s390_lgfi (code, s390_r13, ins->inst_imm);
3662 s390_lgfr (code, s390_r0, ins->sreg1);
3663 s390_srda (code, s390_r0, 0, 32);
3664 s390_dr (code, s390_r0, ins->sreg2);
3665 s390_lgfr (code, ins->dreg, s390_r1);
3669 s390_lgfr (code, s390_r0, ins->sreg1);
3670 s390_srda (code, s390_r0, 0, 32);
3671 s390_dr (code, s390_r0, ins->sreg2);
3672 s390_lgfr (code, ins->dreg, s390_r0);
3675 s390_lgfr (code, s390_r0, ins->sreg1);
3676 s390_srdl (code, s390_r0, 0, 32);
3677 s390_dlr (code, s390_r0, ins->sreg2);
3678 s390_lgfr (code, ins->dreg, s390_r0);
3682 if (s390_is_imm16 (ins->inst_imm)) {
3683 s390_lghi (code, s390_r13, ins->inst_imm);
3685 s390_lgfi (code, s390_r13, ins->inst_imm);
3687 s390_lgfr (code, s390_r0, ins->sreg1);
3688 s390_srda (code, s390_r0, 0, 32);
3689 s390_dr (code, s390_r0, ins->sreg2);
3690 s390_lgfr (code, ins->dreg, s390_r0);
3695 s390_ogr (code, ins->dreg, src2);
3699 if (ins->dreg != ins->sreg1) {
3700 s390_lgfr (code, ins->dreg, ins->sreg1);
3702 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3703 s390_ogr (code, ins->dreg, s390_r0);
3708 s390_xgr (code, ins->dreg, src2);
3712 if (ins->dreg != ins->sreg1) {
3713 s390_lgfr (code, ins->dreg, ins->sreg1);
3715 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3716 s390_xgr (code, ins->dreg, s390_r0);
3721 s390_sll (code, ins->dreg, src2, 0);
3725 if (ins->sreg1 != ins->dreg) {
3726 s390_lgfr (code, ins->dreg, ins->sreg1);
3728 s390_sll (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3733 s390_sra (code, ins->dreg, src2, 0);
3737 if (ins->sreg1 != ins->dreg) {
3738 s390_lgfr (code, ins->dreg, ins->sreg1);
3740 s390_sra (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3743 case OP_ISHR_UN_IMM: {
3744 if (ins->sreg1 != ins->dreg) {
3745 s390_lgfr (code, ins->dreg, ins->sreg1);
3747 s390_srl (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3752 s390_srl (code, ins->dreg, src2, 0);
3756 if (ins->sreg1 != ins->dreg) {
3757 s390_lgfr (code, ins->dreg, ins->sreg1);
3759 s390_lghi (code, s390_r0, -1);
3760 s390_xgr (code, ins->dreg, s390_r0);
3764 s390_lcgr (code, ins->dreg, ins->sreg1);
3769 s390_msr (code, ins->dreg, src2);
3773 if (ins->dreg != ins->sreg1) {
3774 s390_lgfr (code, ins->dreg, ins->sreg1);
3776 if (s390_is_imm16 (ins->inst_imm)) {
3777 s390_lghi (code, s390_r0, ins->inst_imm);
3779 s390_lgfi (code, s390_r0, ins->inst_imm);
3781 s390_msr (code, ins->dreg, s390_r0);
3786 s390_ltr (code, s390_r1, ins->sreg1);
3787 s390_jz (code, 0); CODEPTR(code, o[0]);
3788 s390_ltr (code, s390_r0, ins->sreg2);
3790 s390_lhi (code, s390_r1, 0);
3791 s390_j (code, 0); CODEPTR(code, o[1]);
3792 s390_xr (code, s390_r0, s390_r1);
3793 s390_msr (code, s390_r1, ins->sreg2);
3794 s390_xr (code, s390_r0, s390_r1);
3795 s390_srl (code, s390_r0, 0, 31);
3796 s390_ltr (code, s390_r0, s390_r0);
3797 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3798 PTRSLOT (code, o[0]);
3799 PTRSLOT (code, o[1]);
3800 s390_lgfr (code, ins->dreg, s390_r1);
3803 case OP_IMUL_OVF_UN: {
3804 s390_lhi (code, s390_r0, 0);
3805 s390_lr (code, s390_r1, ins->sreg1);
3806 s390_mlr (code, s390_r0, ins->sreg2);
3807 s390_ltr (code, s390_r0, s390_r0);
3808 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3809 s390_lgfr (code, ins->dreg, s390_r1);
3814 S390_SET (code, ins->dreg, ins->inst_c0);
3818 mono_add_patch_info (cfg, code - cfg->native_code,
3819 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3820 S390_LOAD_TEMPLATE (code, ins->dreg);
3823 case OP_JUMP_TABLE: {
3824 mono_add_patch_info (cfg, code - cfg->native_code,
3825 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3826 S390_LOAD_TEMPLATE (code, ins->dreg);
3830 if (ins->dreg != ins->sreg1) {
3831 s390_lgr (code, ins->dreg, ins->sreg1);
3835 case OP_LCONV_TO_I8:
3837 s390_lgfr (code, ins->dreg, ins->sreg1);
3839 case OP_LCONV_TO_I4:
3840 s390_lgfr (code, ins->dreg, ins->sreg1);
3843 case OP_LCONV_TO_U8:
3844 case OP_LCONV_TO_U4:
3846 s390_llgfr (code, ins->dreg, ins->sreg1);
3848 case OP_LCONV_TO_OVF_U4:
3849 S390_SET (code, s390_r0, 4294967295);
3850 s390_clgr (code, ins->sreg1, s390_r0);
3851 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3852 s390_ltgr (code, ins->sreg1, ins->sreg1);
3853 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3854 s390_llgfr(code, ins->dreg, ins->sreg1);
3856 case OP_LCONV_TO_OVF_I4_UN:
3857 S390_SET (code, s390_r0, 2147483647);
3858 s390_cgr (code, ins->sreg1, s390_r0);
3859 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3860 s390_ltgr (code, ins->sreg1, ins->sreg1);
3861 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3862 s390_lgfr (code, ins->dreg, ins->sreg1);
3865 if (ins->dreg != ins->sreg1) {
3866 s390_ldr (code, ins->dreg, ins->sreg1);
3869 case OP_MOVE_F_TO_I8:
3870 s390_lgdr (code, ins->dreg, ins->sreg1);
3872 case OP_MOVE_I8_TO_F:
3873 s390_ldgr (code, ins->dreg, ins->sreg1);
3875 case OP_MOVE_F_TO_I4:
3876 s390_ledbr (code, s390_f0, ins->sreg1);
3877 s390_lgdr (code, ins->dreg, s390_f0);
3878 s390_srag (code, ins->dreg, ins->dreg, 0, 32);
3880 case OP_MOVE_I4_TO_F:
3881 s390_slag (code, s390_r0, ins->sreg1, 0, 32);
3882 s390_ldgr (code, ins->dreg, s390_r0);
3883 s390_ldebr (code, ins->dreg, ins->dreg);
3885 case OP_FCONV_TO_R4:
3886 s390_ledbr (code, ins->dreg, ins->sreg1);
3887 s390_ldebr (code, ins->dreg, ins->dreg);
3889 case OP_S390_SETF4RET:
3890 s390_ledbr (code, ins->dreg, ins->sreg1);
3893 if (s390_is_imm16 (ins->inst_offset)) {
3894 s390_lghi (code, s390_r13, ins->inst_offset);
3895 } else if (s390_is_imm32 (ins->inst_offset)) {
3896 s390_lgfi (code, s390_r13, ins->inst_offset);
3898 S390_SET (code, s390_r13, ins->inst_offset);
3900 s390_ear (code, s390_r1, 0);
3901 s390_sllg(code, s390_r1, s390_r1, 0, 32);
3902 s390_ear (code, s390_r1, 1);
3903 s390_lg (code, ins->dreg, s390_r13, s390_r1, 0);
3907 if (cfg->method->save_lmf)
3908 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
3910 if (cfg->flags & MONO_CFG_HAS_TAIL) {
3911 code = emit_load_volatile_arguments (code, cfg);
3914 code = backUpStackPtr(cfg, code);
3915 s390_lg (code, s390_r14, 0, cfg->frame_reg, S390_RET_ADDR_OFFSET);
3916 mono_add_patch_info (cfg, code - cfg->native_code,
3917 MONO_PATCH_INFO_METHOD_JUMP,
3919 s390_jcl (code, S390_CC_UN, 0);
3922 case OP_CHECK_THIS: {
3923 /* ensure ins->sreg1 is not NULL */
3924 s390_lg (code, s390_r0, 0, ins->sreg1, 0);
3925 s390_ltgr (code, s390_r0, s390_r0);
3926 // EMIT_COND_SYSTEM_EXCEPTION (S390_CC_ZR, "NullReferenceException");
3930 int offset = cfg->sig_cookie + cfg->stack_usage;
3932 if (s390_is_imm16 (offset)) {
3933 s390_lghi (code, s390_r0, offset);
3934 } else if (s390_is_imm32 (offset)) {
3935 s390_lgfi (code, s390_r0, offset);
3937 S390_SET (code, s390_r0, offset);
3939 s390_agr (code, s390_r0, cfg->frame_reg);
3940 s390_stg (code, s390_r0, 0, ins->sreg1, 0);
3944 call = (MonoCallInst*)ins;
3945 if (ins->flags & MONO_INST_HAS_METHOD)
3946 mono_add_patch_info (cfg, code-cfg->native_code,
3947 MONO_PATCH_INFO_METHOD,
3950 mono_add_patch_info (cfg, code-cfg->native_code,
3951 MONO_PATCH_INFO_ABS,
3953 S390_CALL_TEMPLATE (code, s390_r14);
3954 if (call->signature->ret->type == MONO_TYPE_R4)
3955 s390_ldebr (code, s390_f0, s390_f0);
3963 call = (MonoCallInst*)ins;
3964 if (ins->flags & MONO_INST_HAS_METHOD)
3965 mono_add_patch_info (cfg, code-cfg->native_code,
3966 MONO_PATCH_INFO_METHOD,
3969 mono_add_patch_info (cfg, code-cfg->native_code,
3970 MONO_PATCH_INFO_ABS,
3972 S390_CALL_TEMPLATE (code, s390_r14);
3975 case OP_FCALL_REG: {
3976 call = (MonoCallInst*)ins;
3977 s390_lgr (code, s390_r1, ins->sreg1);
3978 s390_basr (code, s390_r14, s390_r1);
3979 if (call->signature->ret->type == MONO_TYPE_R4)
3980 s390_ldebr (code, s390_f0, s390_f0);
3986 case OP_VOIDCALL_REG:
3988 s390_lgr (code, s390_r1, ins->sreg1);
3989 s390_basr (code, s390_r14, s390_r1);
3992 case OP_FCALL_MEMBASE: {
3993 call = (MonoCallInst*)ins;
3994 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
3995 s390_basr (code, s390_r14, s390_r1);
3996 if (call->signature->ret->type == MONO_TYPE_R4)
3997 s390_ldebr (code, s390_f0, s390_f0);
4000 case OP_LCALL_MEMBASE:
4001 case OP_VCALL_MEMBASE:
4002 case OP_VCALL2_MEMBASE:
4003 case OP_VOIDCALL_MEMBASE:
4004 case OP_CALL_MEMBASE: {
4005 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4006 s390_basr (code, s390_r14, s390_r1);
4013 if (cfg->param_area == 0)
4014 alloca_skip = S390_MINIMAL_STACK_SIZE;
4016 alloca_skip = cfg->param_area;
4018 area_offset = S390_ALIGN(alloca_skip, S390_STACK_ALIGNMENT);
4019 s390_lgr (code, s390_r1, ins->sreg1);
4020 if (ins->flags & MONO_INST_INIT)
4021 s390_lgr (code, s390_r0, ins->sreg1);
4022 s390_aghi (code, s390_r1, 14);
4023 s390_srlg (code, s390_r1, s390_r1, 0, 3);
4024 s390_sllg (code, s390_r1, s390_r1, 0, 3);
4025 if (cfg->method->save_lmf) {
4026 /*----------------------------------*/
4027 /* we have to adjust lmf ebp value */
4028 /*----------------------------------*/
4029 int lmfOffset = cfg->stack_usage - sizeof(MonoLMF);
4031 s390_lgr (code, s390_r13, cfg->frame_reg);
4032 if (s390_is_imm16(lmfOffset)) {
4033 s390_aghi (code, s390_r13, lmfOffset);
4034 } else if (s390_is_imm32(lmfOffset)) {
4035 s390_agfi (code, s390_r13, lmfOffset);
4037 S390_SET (code, s390_r13, lmfOffset);
4039 s390_lgr (code, s390_r14, STK_BASE);
4040 s390_sgr (code, s390_r14, s390_r1);
4041 s390_stg (code, s390_r14, 0, s390_r13,
4042 G_STRUCT_OFFSET(MonoLMF, ebp));
4044 s390_lg (code, s390_r13, 0, STK_BASE, 0);
4045 s390_sgr (code, STK_BASE, s390_r1);
4046 s390_stg (code, s390_r13, 0, STK_BASE, 0);
4047 s390_la (code, ins->dreg, 0, STK_BASE, area_offset);
4048 s390_srlg (code, ins->dreg, ins->dreg, 0, 3);
4049 s390_sllg (code, ins->dreg, ins->dreg, 0, 3);
4050 if (ins->flags & MONO_INST_INIT) {
4051 s390_lgr (code, s390_r1, s390_r0);
4052 s390_lgr (code, s390_r0, ins->dreg);
4053 s390_lgr (code, s390_r14, s390_r12);
4054 s390_lghi (code, s390_r13, 0);
4055 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4057 s390_lgr (code, s390_r12, s390_r14);
4062 s390_lgr (code, s390_r2, ins->sreg1);
4063 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4064 (gpointer) "mono_arch_throw_exception");
4065 S390_CALL_TEMPLATE(code, s390_r14);
4069 s390_lgr (code, s390_r2, ins->sreg1);
4070 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4071 (gpointer) "mono_arch_rethrow_exception");
4072 S390_CALL_TEMPLATE(code, s390_r14);
4075 case OP_START_HANDLER: {
4076 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4078 S390_LONG (code, stg, stg, s390_r14, 0,
4079 spvar->inst_basereg,
4080 spvar->inst_offset);
4083 case OP_ENDFILTER: {
4084 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4086 if (ins->sreg1 != s390_r2)
4087 s390_lgr(code, s390_r2, ins->sreg1);
4088 S390_LONG (code, lg, lg, s390_r14, 0,
4089 spvar->inst_basereg,
4090 spvar->inst_offset);
4091 s390_br (code, s390_r14);
4094 case OP_ENDFINALLY: {
4095 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4097 S390_LONG (code, lg, lg, s390_r14, 0,
4098 spvar->inst_basereg,
4099 spvar->inst_offset);
4100 s390_br (code, s390_r14);
4103 case OP_CALL_HANDLER: {
4104 mono_add_patch_info (cfg, code-cfg->native_code,
4105 MONO_PATCH_INFO_BB, ins->inst_target_bb);
4106 s390_brasl (code, s390_r14, 0);
4107 mono_cfg_add_try_hole (cfg, ins->inst_eh_block, code, bb);
4111 ins->inst_c0 = code - cfg->native_code;
4114 case OP_RELAXED_NOP:
4117 case OP_DUMMY_STORE:
4118 case OP_NOT_REACHED:
4122 case OP_IL_SEQ_POINT:
4123 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4125 case OP_SEQ_POINT: {
4128 if (cfg->compile_aot)
4132 * Read from the single stepping trigger page. This will cause a
4133 * SIGSEGV when single stepping is enabled.
4134 * We do this _before_ the breakpoint, so single stepping after
4135 * a breakpoint is hit will step to the next IL offset.
4137 if (ins->flags & MONO_INST_SINGLE_STEP_LOC) {
4138 breakpointCode.pTrigger = ss_trigger_page;
4139 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
4140 code += BREAKPOINT_SIZE;
4143 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4146 * A placeholder for a possible breakpoint inserted by
4147 * mono_arch_set_breakpoint ().
4149 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); ++i)
4153 * Add an additional nop so skipping the bp doesn't cause the ip to point
4154 * to another IL offset.
4160 case OP_GENERIC_CLASS_INIT: {
4161 static int byte_offset = -1;
4162 static guint8 bitmask;
4165 g_assert (ins->sreg1 == S390_FIRST_ARG_REG);
4167 if (byte_offset < 0)
4168 mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);
4170 s390_tm (code, ins->sreg1, byte_offset, bitmask);
4171 s390_jo (code, 0); CODEPTR(code, jump);
4173 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4174 "mono_generic_class_init");
4175 S390_CALL_TEMPLATE(code, s390_r14);
4177 PTRSLOT (code, jump);
4179 ins->flags |= MONO_INST_GC_CALLSITE;
4180 ins->backend.pc_offset = code - cfg->native_code;
4184 EMIT_UNCOND_BRANCH(ins);
4187 s390_br (code, ins->sreg1);
4193 s390_lghi(code, ins->dreg, 1);
4195 s390_lghi(code, ins->dreg, 0);
4201 s390_lghi(code, ins->dreg, 1);
4203 s390_lghi(code, ins->dreg, 0);
4209 s390_lghi(code, ins->dreg, 1);
4211 s390_lghi(code, ins->dreg, 0);
4217 s390_lghi(code, ins->dreg, 1);
4219 s390_lghi(code, ins->dreg, 0);
4225 s390_lghi(code, ins->dreg, 1);
4227 s390_lghi(code, ins->dreg, 0);
4230 case OP_COND_EXC_EQ:
4231 case OP_COND_EXC_IEQ:
4232 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_EQ, ins->inst_p1);
4234 case OP_COND_EXC_NE_UN:
4235 case OP_COND_EXC_INE_UN:
4236 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NE, ins->inst_p1);
4238 case OP_COND_EXC_LT:
4239 case OP_COND_EXC_ILT:
4240 case OP_COND_EXC_LT_UN:
4241 case OP_COND_EXC_ILT_UN:
4242 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, ins->inst_p1);
4244 case OP_COND_EXC_GT:
4245 case OP_COND_EXC_IGT:
4246 case OP_COND_EXC_GT_UN:
4247 case OP_COND_EXC_IGT_UN:
4248 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, ins->inst_p1);
4250 case OP_COND_EXC_GE:
4251 case OP_COND_EXC_IGE:
4252 case OP_COND_EXC_GE_UN:
4253 case OP_COND_EXC_IGE_UN:
4254 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GE, ins->inst_p1);
4256 case OP_COND_EXC_LE:
4257 case OP_COND_EXC_ILE:
4258 case OP_COND_EXC_LE_UN:
4259 case OP_COND_EXC_ILE_UN:
4260 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LE, ins->inst_p1);
4262 case OP_COND_EXC_OV:
4263 case OP_COND_EXC_IOV:
4264 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, ins->inst_p1);
4266 case OP_COND_EXC_NO:
4267 case OP_COND_EXC_INO:
4268 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NO, ins->inst_p1);
4271 case OP_COND_EXC_IC:
4272 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, ins->inst_p1);
4274 case OP_COND_EXC_NC:
4275 case OP_COND_EXC_INC:
4276 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, ins->inst_p1);
4280 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4284 EMIT_COND_BRANCH (ins, S390_CC_NE);
4290 EMIT_COND_BRANCH (ins, S390_CC_LT);
4296 EMIT_COND_BRANCH (ins, S390_CC_GT);
4302 EMIT_COND_BRANCH (ins, S390_CC_GE);
4308 EMIT_COND_BRANCH (ins, S390_CC_LE);
4311 /* floating point opcodes */
4313 if (*((double *) ins->inst_p0) == 0) {
4314 s390_lzdr (code, ins->dreg);
4316 S390_SET (code, s390_r13, ins->inst_p0);
4317 s390_ld (code, ins->dreg, 0, s390_r13, 0);
4322 if (*((float *) ins->inst_p0) == 0) {
4323 s390_lzdr (code, ins->dreg);
4325 S390_SET (code, s390_r13, ins->inst_p0);
4326 s390_ldeb (code, ins->dreg, 0, s390_r13, 0);
4330 case OP_STORER8_MEMBASE_REG: {
4331 S390_LONG (code, stdy, std, ins->sreg1, 0,
4332 ins->inst_destbasereg, ins->inst_offset);
4335 case OP_LOADR8_MEMBASE: {
4336 S390_LONG (code, ldy, ld, ins->dreg, 0,
4337 ins->inst_basereg, ins->inst_offset);
4340 case OP_STORER4_MEMBASE_REG: {
4341 s390_ledbr (code, s390_f15, ins->sreg1);
4342 S390_LONG (code, stey, ste, s390_f15, 0,
4343 ins->inst_destbasereg, ins->inst_offset);
4346 case OP_LOADR4_MEMBASE: {
4347 S390_LONG (code, ley, le, s390_f15, 0,
4348 ins->inst_basereg, ins->inst_offset);
4349 s390_ldebr (code, ins->dreg, s390_f15);
4352 case OP_ICONV_TO_R_UN: {
4354 s390_cdlfbr (code, ins->dreg, 5, ins->sreg1, 0);
4356 s390_llgfr (code, s390_r0, ins->sreg1);
4357 s390_cdgbr (code, ins->dreg, s390_r0);
4361 case OP_LCONV_TO_R_UN: {
4363 s390_cdlgbr (code, ins->dreg, 5, ins->sreg1, 0);
4366 s390_cxgbr (code, s390_f12, ins->sreg1);
4367 s390_ltgr (code, ins->sreg1, ins->sreg1);
4368 s390_jnl (code, 0); CODEPTR(code, jump);
4369 S390_SET (code, s390_r13, 0x403f000000000000llu);
4370 s390_lgdr (code, s390_f13, s390_r13);
4371 s390_lzdr (code, s390_f15);
4372 s390_axbr (code, s390_f12, s390_f13);
4373 PTRSLOT(code, jump);
4374 s390_ldxbr (code, s390_f13, s390_f12);
4375 s390_ldr (code, ins->dreg, s390_f13);
4379 case OP_LCONV_TO_R4:
4380 case OP_ICONV_TO_R4: {
4381 s390_cegbr (code, ins->dreg, ins->sreg1);
4382 s390_ldebr (code, ins->dreg, ins->dreg);
4385 case OP_LCONV_TO_R8:
4386 case OP_ICONV_TO_R8: {
4387 s390_cdgbr (code, ins->dreg, ins->sreg1);
4390 case OP_FCONV_TO_I1:
4391 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4392 s390_ltgr (code, ins->dreg, ins->dreg);
4394 s390_oill (code, ins->dreg, 0x80);
4395 s390_lghi (code, s390_r0, 0xff);
4396 s390_ngr (code, ins->dreg, s390_r0);
4398 case OP_FCONV_TO_U1:
4400 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4401 s390_lghi (code, s390_r0, 0xff);
4402 s390_ngr (code, ins->dreg, s390_r0);
4404 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 1, FALSE);
4407 case OP_FCONV_TO_I2:
4408 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4409 s390_ltgr (code, ins->dreg, ins->dreg);
4411 s390_oill (code, ins->dreg, 0x8000);
4412 s390_llill (code, s390_r0, 0xffff);
4413 s390_ngr (code, ins->dreg, s390_r0);
4415 case OP_FCONV_TO_U2:
4417 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4418 s390_llill (code, s390_r0, 0xffff);
4419 s390_ngr (code, ins->dreg, s390_r0);
4421 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 2, FALSE);
4424 case OP_FCONV_TO_I4:
4426 s390_cfdbr (code, ins->dreg, 5, ins->sreg1);
4428 case OP_FCONV_TO_U4:
4431 s390_clfdbr (code, ins->dreg, 5, ins->sreg1, 0);
4433 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE);
4436 case OP_FCONV_TO_I8:
4437 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4439 case OP_FCONV_TO_U8:
4441 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4443 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 8, FALSE);
4446 case OP_LCONV_TO_OVF_I: {
4447 /* Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000 */
4449 s390_ltgr (code, ins->sreg2, ins->sreg2);
4450 s390_jnl (code, 0); CODEPTR(code, o[0]);
4451 s390_ltgr (code, ins->sreg1, ins->sreg1);
4452 s390_jnl (code, 0); CODEPTR(code, o[1]);
4453 s390_lhi (code, s390_r13, -1);
4454 s390_cgr (code, ins->sreg1, s390_r13);
4455 s390_jnz (code, 0); CODEPTR(code, o[2]);
4456 if (ins->dreg != ins->sreg2)
4457 s390_lgr (code, ins->dreg, ins->sreg2);
4458 s390_j (code, 0); CODEPTR(code, o[3]);
4459 PTRSLOT(code, o[0]);
4460 s390_jz (code, 0); CODEPTR(code, o[4]);
4461 PTRSLOT(code, o[1]);
4462 PTRSLOT(code, o[2]);
4463 mono_add_patch_info (cfg, code - cfg->native_code,
4464 MONO_PATCH_INFO_EXC, "OverflowException");
4465 s390_brasl (code, s390_r14, 0);
4466 PTRSLOT(code, o[3]);
4467 PTRSLOT(code, o[4]);
4471 s390_lpdbr (code, ins->dreg, ins->sreg1);
4475 s390_sqdbr (code, ins->dreg, ins->sreg1);
4480 s390_adbr (code, ins->dreg, src2);
4484 CHECK_SRCDST_NCOM_F;
4485 s390_sdbr (code, ins->dreg, src2);
4490 s390_mdbr (code, ins->dreg, src2);
4494 CHECK_SRCDST_NCOM_F;
4495 s390_ddbr (code, ins->dreg, src2);
4499 s390_lcdbr (code, ins->dreg, ins->sreg1);
4503 CHECK_SRCDST_NCOM_F;
4504 s390_didbr (code, ins->dreg, src2, 5, s390_f15);
4508 s390_cdbr (code, ins->sreg1, ins->sreg2);
4512 s390_cdbr (code, ins->sreg1, ins->sreg2);
4513 s390_lghi (code, ins->dreg, 1);
4515 s390_lghi (code, ins->dreg, 0);
4519 s390_cdbr (code, ins->sreg1, ins->sreg2);
4520 s390_lghi (code, ins->dreg, 1);
4522 s390_lghi (code, ins->dreg, 0);
4526 s390_cdbr (code, ins->sreg1, ins->sreg2);
4527 s390_lghi (code, ins->dreg, 1);
4529 s390_lghi (code, ins->dreg, 0);
4533 s390_cdbr (code, ins->sreg1, ins->sreg2);
4534 s390_lghi (code, ins->dreg, 1);
4536 s390_lghi (code, ins->dreg, 0);
4540 s390_cdbr (code, ins->sreg1, ins->sreg2);
4541 s390_lghi (code, ins->dreg, 1);
4543 s390_lghi (code, ins->dreg, 0);
4548 s390_jo (code, 0); CODEPTR(code, o);
4549 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4554 EMIT_COND_BRANCH (ins, S390_CC_NE|S390_CC_OV);
4558 s390_jo (code, 0); CODEPTR(code, o);
4559 EMIT_COND_BRANCH (ins, S390_CC_LT);
4564 EMIT_COND_BRANCH (ins, S390_CC_LT|S390_CC_OV);
4568 s390_jo (code, 0); CODEPTR(code, o);
4569 EMIT_COND_BRANCH (ins, S390_CC_GT);
4574 EMIT_COND_BRANCH (ins, S390_CC_GT|S390_CC_OV);
4578 s390_jo (code, 0); CODEPTR(code, o);
4579 EMIT_COND_BRANCH (ins, S390_CC_GE);
4584 EMIT_COND_BRANCH (ins, S390_CC_GE|S390_CC_OV);
4588 s390_jo (code, 0); CODEPTR(code, o);
4589 EMIT_COND_BRANCH (ins, S390_CC_LE);
4594 EMIT_COND_BRANCH (ins, S390_CC_LE|S390_CC_OV);
4598 s390_lhi (code, s390_r13, 0x7f);
4599 s390_tcdb (code, ins->sreg1, 0, s390_r13, 0);
4600 s390_jz (code, 0); CODEPTR(code, o);
4601 mono_add_patch_info (cfg, code - cfg->native_code,
4602 MONO_PATCH_INFO_EXC, "ArithmeticException");
4603 s390_brasl (code, s390_r14,0);
4607 case OP_S390_MOVE: {
4608 if (ins->backend.size > 0) {
4609 if (ins->backend.size <= 256) {
4610 s390_mvc (code, ins->backend.size, ins->dreg,
4611 ins->inst_offset, ins->sreg1, ins->inst_imm);
4613 s390_lgr (code, s390_r0, ins->dreg);
4614 if (ins->inst_offset > 0) {
4615 if (s390_is_imm16 (ins->inst_offset)) {
4616 s390_aghi (code, s390_r0, ins->inst_offset);
4617 } else if (s390_is_imm32 (ins->inst_offset)) {
4618 s390_agfi (code, s390_r0, ins->inst_offset);
4620 S390_SET (code, s390_r13, ins->inst_offset);
4621 s390_agr (code, s390_r0, s390_r13);
4624 s390_lgr (code, s390_r12, ins->sreg1);
4625 if (ins->inst_imm > 0) {
4626 if (s390_is_imm16 (ins->inst_imm)) {
4627 s390_aghi (code, s390_r12, ins->inst_imm);
4628 } else if (s390_is_imm32 (ins->inst_imm)) {
4629 s390_agfi (code, s390_r12, ins->inst_imm);
4631 S390_SET (code, s390_r13, ins->inst_imm);
4632 s390_agr (code, s390_r12, s390_r13);
4635 if (s390_is_imm16 (ins->backend.size)) {
4636 s390_lghi (code, s390_r1, ins->backend.size);
4637 } else if (s390_is_imm32 (ins->inst_offset)) {
4638 s390_agfi (code, s390_r1, ins->backend.size);
4640 S390_SET (code, s390_r13, ins->backend.size);
4641 s390_agr (code, s390_r1, s390_r13);
4643 s390_lgr (code, s390_r13, s390_r1);
4644 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4650 case OP_ATOMIC_ADD_I8: {
4651 s390_lgr (code, s390_r1, ins->sreg2);
4652 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4653 s390_agr (code, s390_r1, s390_r0);
4654 s390_csg (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4655 s390_jnz (code, -10);
4656 s390_lgr (code, ins->dreg, s390_r1);
4659 case OP_ATOMIC_EXCHANGE_I8: {
4660 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4661 s390_csg (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
4662 s390_jnz (code, -6);
4663 s390_lgr (code, ins->dreg, s390_r0);
4666 case OP_ATOMIC_ADD_I4: {
4667 s390_lgfr(code, s390_r1, ins->sreg2);
4668 s390_lgf (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4669 s390_agr (code, s390_r1, s390_r0);
4670 s390_cs (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4671 s390_jnz (code, -9);
4672 s390_lgfr(code, ins->dreg, s390_r1);
4675 case OP_ATOMIC_EXCHANGE_I4: {
4676 s390_l (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4677 s390_cs (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
4678 s390_jnz (code, -4);
4679 s390_lgfr(code, ins->dreg, s390_r0);
4682 case OP_S390_BKCHAIN: {
4683 s390_lgr (code, ins->dreg, ins->sreg1);
4684 if (s390_is_imm16 (cfg->stack_offset)) {
4685 s390_aghi (code, ins->dreg, cfg->stack_offset);
4686 } else if (s390_is_imm32 (cfg->stack_offset)) {
4687 s390_agfi (code, ins->dreg, cfg->stack_offset);
4689 S390_SET (code, s390_r13, cfg->stack_offset);
4690 s390_agr (code, ins->dreg, s390_r13);
4694 case OP_MEMORY_BARRIER:
4697 case OP_GC_SAFE_POINT: {
4700 g_assert (mono_threads_is_coop_enabled ());
4702 s390_chi (code, ins->sreg1, 1);
4703 s390_je (code, 0); CODEPTR(code, br);
4704 mono_add_patch_info (cfg, code- cfg->native_code, MONO_PATCH_INFO_ABS,
4705 mono_threads_state_poll);
4706 S390_CALL_TEMPLATE (code, s390_r14);
4710 case OP_GC_LIVENESS_DEF:
4711 case OP_GC_LIVENESS_USE:
4712 case OP_GC_PARAM_SLOT_LIVENESS_DEF:
4713 ins->backend.pc_offset = code - cfg->native_code;
4715 case OP_GC_SPILL_SLOT_LIVENESS_DEF:
4716 ins->backend.pc_offset = code - cfg->native_code;
4717 bb->spill_slot_defs = g_slist_prepend_mempool (cfg->mempool, bb->spill_slot_defs, ins);
4719 #ifdef MONO_ARCH_SIMD_INTRINSICS
4721 s390x_addps (code, ins->sreg1, ins->sreg2);
4724 s390x_divps (code, ins->sreg1, ins->sreg2);
4727 s390x_mulps (code, ins->sreg1, ins->sreg2);
4730 s390x_subps (code, ins->sreg1, ins->sreg2);
4733 s390x_maxps (code, ins->sreg1, ins->sreg2);
4736 s390x_minps (code, ins->sreg1, ins->sreg2);
4739 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
4740 s390x_cmpps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4743 s390x_andps (code, ins->sreg1, ins->sreg2);
4746 s390x_andnps (code, ins->sreg1, ins->sreg2);
4749 s390x_orps (code, ins->sreg1, ins->sreg2);
4752 s390x_xorps (code, ins->sreg1, ins->sreg2);
4755 s390x_sqrtps (code, ins->dreg, ins->sreg1);
4758 s390x_rsqrtps (code, ins->dreg, ins->sreg1);
4761 s390x_rcpps (code, ins->dreg, ins->sreg1);
4764 s390x_addsubps (code, ins->sreg1, ins->sreg2);
4767 s390x_haddps (code, ins->sreg1, ins->sreg2);
4770 s390x_hsubps (code, ins->sreg1, ins->sreg2);
4773 s390x_movshdup (code, ins->dreg, ins->sreg1);
4776 s390x_movsldup (code, ins->dreg, ins->sreg1);
4779 case OP_PSHUFLEW_HIGH:
4780 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4781 s390x_pshufhw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4783 case OP_PSHUFLEW_LOW:
4784 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4785 s390x_pshuflw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4788 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4789 s390x_pshufd_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4792 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4793 s390x_shufps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4796 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0x3);
4797 s390x_shufpd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4801 s390x_addpd (code, ins->sreg1, ins->sreg2);
4804 s390x_divpd (code, ins->sreg1, ins->sreg2);
4807 s390x_mulpd (code, ins->sreg1, ins->sreg2);
4810 s390x_subpd (code, ins->sreg1, ins->sreg2);
4813 s390x_maxpd (code, ins->sreg1, ins->sreg2);
4816 s390x_minpd (code, ins->sreg1, ins->sreg2);
4819 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
4820 s390x_cmppd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4823 s390x_andpd (code, ins->sreg1, ins->sreg2);
4826 s390x_andnpd (code, ins->sreg1, ins->sreg2);
4829 s390x_orpd (code, ins->sreg1, ins->sreg2);
4832 s390x_xorpd (code, ins->sreg1, ins->sreg2);
4835 s390x_sqrtpd (code, ins->dreg, ins->sreg1);
4838 s390x_addsubpd (code, ins->sreg1, ins->sreg2);
4841 s390x_haddpd (code, ins->sreg1, ins->sreg2);
4844 s390x_hsubpd (code, ins->sreg1, ins->sreg2);
4847 s390x_movddup (code, ins->dreg, ins->sreg1);
4850 case OP_EXTRACT_MASK:
4851 s390x_pmovmskb (code, ins->dreg, ins->sreg1);
4855 s390x_pand (code, ins->sreg1, ins->sreg2);
4858 s390x_por (code, ins->sreg1, ins->sreg2);
4861 s390x_pxor (code, ins->sreg1, ins->sreg2);
4865 s390x_paddb (code, ins->sreg1, ins->sreg2);
4868 s390x_paddw (code, ins->sreg1, ins->sreg2);
4871 s390x_paddd (code, ins->sreg1, ins->sreg2);
4874 s390x_paddq (code, ins->sreg1, ins->sreg2);
4878 s390x_psubb (code, ins->sreg1, ins->sreg2);
4881 s390x_psubw (code, ins->sreg1, ins->sreg2);
4884 s390x_psubd (code, ins->sreg1, ins->sreg2);
4887 s390x_psubq (code, ins->sreg1, ins->sreg2);
4891 s390x_pmaxub (code, ins->sreg1, ins->sreg2);
4894 s390x_pmaxuw (code, ins->sreg1, ins->sreg2);
4897 s390x_pmaxud (code, ins->sreg1, ins->sreg2);
4901 s390x_pmaxsb (code, ins->sreg1, ins->sreg2);
4904 s390x_pmaxsw (code, ins->sreg1, ins->sreg2);
4907 s390x_pmaxsd (code, ins->sreg1, ins->sreg2);
4911 s390x_pavgb (code, ins->sreg1, ins->sreg2);
4914 s390x_pavgw (code, ins->sreg1, ins->sreg2);
4918 s390x_pminub (code, ins->sreg1, ins->sreg2);
4921 s390x_pminuw (code, ins->sreg1, ins->sreg2);
4924 s390x_pminud (code, ins->sreg1, ins->sreg2);
4928 s390x_pminsb (code, ins->sreg1, ins->sreg2);
4931 s390x_pminsw (code, ins->sreg1, ins->sreg2);
4934 s390x_pminsd (code, ins->sreg1, ins->sreg2);
4938 s390x_pcmpeqb (code, ins->sreg1, ins->sreg2);
4941 s390x_pcmpeqw (code, ins->sreg1, ins->sreg2);
4944 s390x_pcmpeqd (code, ins->sreg1, ins->sreg2);
4947 s390x_pcmpeqq (code, ins->sreg1, ins->sreg2);
4951 s390x_pcmpgtb (code, ins->sreg1, ins->sreg2);
4954 s390x_pcmpgtw (code, ins->sreg1, ins->sreg2);
4957 s390x_pcmpgtd (code, ins->sreg1, ins->sreg2);
4960 s390x_pcmpgtq (code, ins->sreg1, ins->sreg2);
4963 case OP_PSUM_ABS_DIFF:
4964 s390x_psadbw (code, ins->sreg1, ins->sreg2);
4967 case OP_UNPACK_LOWB:
4968 s390x_punpcklbw (code, ins->sreg1, ins->sreg2);
4970 case OP_UNPACK_LOWW:
4971 s390x_punpcklwd (code, ins->sreg1, ins->sreg2);
4973 case OP_UNPACK_LOWD:
4974 s390x_punpckldq (code, ins->sreg1, ins->sreg2);
4976 case OP_UNPACK_LOWQ:
4977 s390x_punpcklqdq (code, ins->sreg1, ins->sreg2);
4979 case OP_UNPACK_LOWPS:
4980 s390x_unpcklps (code, ins->sreg1, ins->sreg2);
4982 case OP_UNPACK_LOWPD:
4983 s390x_unpcklpd (code, ins->sreg1, ins->sreg2);
4986 case OP_UNPACK_HIGHB:
4987 s390x_punpckhbw (code, ins->sreg1, ins->sreg2);
4989 case OP_UNPACK_HIGHW:
4990 s390x_punpckhwd (code, ins->sreg1, ins->sreg2);
4992 case OP_UNPACK_HIGHD:
4993 s390x_punpckhdq (code, ins->sreg1, ins->sreg2);
4995 case OP_UNPACK_HIGHQ:
4996 s390x_punpckhqdq (code, ins->sreg1, ins->sreg2);
4998 case OP_UNPACK_HIGHPS:
4999 s390x_unpckhps (code, ins->sreg1, ins->sreg2);
5001 case OP_UNPACK_HIGHPD:
5002 s390x_unpckhpd (code, ins->sreg1, ins->sreg2);
5006 s390x_packsswb (code, ins->sreg1, ins->sreg2);
5009 s390x_packssdw (code, ins->sreg1, ins->sreg2);
5012 s390x_packuswb (code, ins->sreg1, ins->sreg2);
5015 s390x_packusdw (code, ins->sreg1, ins->sreg2);
5018 case OP_PADDB_SAT_UN:
5019 s390x_paddusb (code, ins->sreg1, ins->sreg2);
5021 case OP_PSUBB_SAT_UN:
5022 s390x_psubusb (code, ins->sreg1, ins->sreg2);
5024 case OP_PADDW_SAT_UN:
5025 s390x_paddusw (code, ins->sreg1, ins->sreg2);
5027 case OP_PSUBW_SAT_UN:
5028 s390x_psubusw (code, ins->sreg1, ins->sreg2);
5032 s390x_paddsb (code, ins->sreg1, ins->sreg2);
5035 s390x_psubsb (code, ins->sreg1, ins->sreg2);
5038 s390x_paddsw (code, ins->sreg1, ins->sreg2);
5041 s390x_psubsw (code, ins->sreg1, ins->sreg2);
5045 s390x_pmullw (code, ins->sreg1, ins->sreg2);
5048 s390x_pmulld (code, ins->sreg1, ins->sreg2);
5051 s390x_pmuludq (code, ins->sreg1, ins->sreg2);
5053 case OP_PMULW_HIGH_UN:
5054 s390x_pmulhuw (code, ins->sreg1, ins->sreg2);
5057 s390x_pmulhw (code, ins->sreg1, ins->sreg2);
5061 s390x_psrlw_reg_imm (code, ins->dreg, ins->inst_imm);
5064 s390x_psrlw (code, ins->dreg, ins->sreg2);
5068 s390x_psraw_reg_imm (code, ins->dreg, ins->inst_imm);
5071 s390x_psraw (code, ins->dreg, ins->sreg2);
5075 s390x_psllw_reg_imm (code, ins->dreg, ins->inst_imm);
5078 s390x_psllw (code, ins->dreg, ins->sreg2);
5082 s390x_psrld_reg_imm (code, ins->dreg, ins->inst_imm);
5085 s390x_psrld (code, ins->dreg, ins->sreg2);
5089 s390x_psrad_reg_imm (code, ins->dreg, ins->inst_imm);
5092 s390x_psrad (code, ins->dreg, ins->sreg2);
5096 s390x_pslld_reg_imm (code, ins->dreg, ins->inst_imm);
5099 s390x_pslld (code, ins->dreg, ins->sreg2);
5103 s390x_psrlq_reg_imm (code, ins->dreg, ins->inst_imm);
5106 s390x_psrlq (code, ins->dreg, ins->sreg2);
5109 /*TODO: This is appart of the sse spec but not added
5111 s390x_psraq_reg_imm (code, ins->dreg, ins->inst_imm);
5114 s390x_psraq (code, ins->dreg, ins->sreg2);
5119 s390x_psllq_reg_imm (code, ins->dreg, ins->inst_imm);
5122 s390x_psllq (code, ins->dreg, ins->sreg2);
5125 s390x_cvtdq2pd (code, ins->dreg, ins->sreg1);
5128 s390x_cvtdq2ps (code, ins->dreg, ins->sreg1);
5131 s390x_cvtpd2dq (code, ins->dreg, ins->sreg1);
5134 s390x_cvtpd2ps (code, ins->dreg, ins->sreg1);
5137 s390x_cvtps2dq (code, ins->dreg, ins->sreg1);
5140 s390x_cvtps2pd (code, ins->dreg, ins->sreg1);
5143 s390x_cvttpd2dq (code, ins->dreg, ins->sreg1);
5146 s390x_cvttps2dq (code, ins->dreg, ins->sreg1);
5150 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5153 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5157 amd64_movhlps (code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg1);
5158 amd64_movd_reg_xreg_size (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG, 8);
5160 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 8);
5165 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5167 amd64_shift_reg_imm (code, X86_SHR, ins->dreg, ins->inst_c0 * 8);
5168 amd64_widen_reg (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I1, FALSE);
5172 /*amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5174 amd64_shift_reg_imm_size (code, X86_SHR, ins->dreg, 16, 4);*/
5175 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5176 amd64_widen_reg_size (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I2, TRUE, 4);
5180 amd64_movhlps (code, ins->dreg, ins->sreg1);
5182 s390x_movsd (code, ins->dreg, ins->sreg1);
5185 s390x_pinsrw_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5187 case OP_EXTRACTX_U2:
5188 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5190 case OP_INSERTX_U1_SLOW:
5191 /*sreg1 is the extracted ireg (scratch)
5192 /sreg2 is the to be inserted ireg (scratch)
5193 /dreg is the xreg to receive the value*/
5195 /*clear the bits from the extracted word*/
5196 amd64_alu_reg_imm (code, X86_AND, ins->sreg1, ins->inst_c0 & 1 ? 0x00FF : 0xFF00);
5197 /*shift the value to insert if needed*/
5198 if (ins->inst_c0 & 1)
5199 amd64_shift_reg_imm_size (code, X86_SHL, ins->sreg2, 8, 4);
5200 /*join them together*/
5201 amd64_alu (code, X86_OR, ins->sreg1, ins->sreg2);
5202 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0 / 2);
5204 case OP_INSERTX_I4_SLOW:
5205 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2);
5206 amd64_shift_reg_imm (code, X86_SHR, ins->sreg2, 16);
5207 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2 + 1);
5209 case OP_INSERTX_I8_SLOW:
5210 amd64_movd_xreg_reg_size(code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg2, 8);
5212 amd64_movlhps (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5214 s390x_movsd (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5217 case OP_INSERTX_R4_SLOW:
5218 switch (ins->inst_c0) {
5221 s390x_movss (code, ins->dreg, ins->sreg2);
5223 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5226 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5228 s390x_movss (code, ins->dreg, ins->sreg2);
5230 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5231 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5234 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5236 s390x_movss (code, ins->dreg, ins->sreg2);
5238 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5239 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5242 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5244 s390x_movss (code, ins->dreg, ins->sreg2);
5246 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5247 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5251 case OP_INSERTX_R8_SLOW:
5253 amd64_movlhps (code, ins->dreg, ins->sreg2);
5255 s390x_movsd (code, ins->dreg, ins->sreg2);
5257 case OP_STOREX_MEMBASE_REG:
5258 case OP_STOREX_MEMBASE:
5259 s390x_movups_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5261 case OP_LOADX_MEMBASE:
5262 s390x_movups_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5264 case OP_LOADX_ALIGNED_MEMBASE:
5265 s390x_movaps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5267 case OP_STOREX_ALIGNED_MEMBASE_REG:
5268 s390x_movaps_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5270 case OP_STOREX_NTA_MEMBASE_REG:
5271 s390x_movntps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5273 case OP_PREFETCH_MEMBASE:
5274 s390x_prefetch_reg_membase (code, ins->backend.arg_info, ins->sreg1, ins->inst_offset);
5278 /*FIXME the peephole pass should have killed this*/
5279 if (ins->dreg != ins->sreg1)
5280 s390x_movaps (code, ins->dreg, ins->sreg1);
5283 s390x_pxor (code, ins->dreg, ins->dreg);
5285 case OP_ICONV_TO_R4_RAW:
5286 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5289 case OP_FCONV_TO_R8_X:
5290 s390x_movsd (code, ins->dreg, ins->sreg1);
5293 case OP_XCONV_R8_TO_I4:
5294 s390x_cvttsd2si_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5295 switch (ins->backend.source_opcode) {
5296 case OP_FCONV_TO_I1:
5297 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, FALSE);
5299 case OP_FCONV_TO_U1:
5300 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, FALSE);
5302 case OP_FCONV_TO_I2:
5303 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, TRUE);
5305 case OP_FCONV_TO_U2:
5306 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, TRUE);
5312 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 0);
5313 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 1);
5314 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5317 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5318 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5321 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 8);
5322 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5326 s390x_movsd (code, ins->dreg, ins->sreg1);
5328 s390x_movsd (code, ins->dreg, ins->sreg1);
5329 s390x_cvtsd2ss (code, ins->dreg, ins->dreg);
5331 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5334 s390x_movsd (code, ins->dreg, ins->sreg1);
5335 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5339 g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
5340 g_assert_not_reached ();
5343 if ((cfg->opt & MONO_OPT_BRANCH) && ((code - cfg->native_code - offset) > max_len)) {
5344 g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %ld)",
5345 mono_inst_name (ins->opcode), max_len, code - cfg->native_code - offset);
5346 g_assert_not_reached ();
5349 last_offset = offset;
5352 cfg->code_len = code - cfg->native_code;
5355 /*========================= End of Function ========================*/
5357 /*------------------------------------------------------------------*/
5359 /* Name - mono_arch_register_lowlevel_calls */
5361 /* Function - Register routines to help with --trace operation. */
5363 /*------------------------------------------------------------------*/
5366 mono_arch_register_lowlevel_calls (void)
5370 /*========================= End of Function ========================*/
5372 /*------------------------------------------------------------------*/
5374 /* Name - mono_arch_patch_code */
5376 /* Function - Process the patch data created during the */
5377 /* instruction build process. This resolves jumps, */
5378 /* calls, variables etc. */
5380 /*------------------------------------------------------------------*/
5383 mono_arch_patch_code (MonoCompile *cfg, MonoMethod *method, MonoDomain *domain,
5384 guint8 *code, MonoJumpInfo *ji, gboolean run_cctors)
5386 MonoJumpInfo *patch_info;
5388 for (patch_info = ji; patch_info; patch_info = patch_info->next) {
5389 unsigned char *ip = patch_info->ip.i + code;
5390 gconstpointer target = NULL;
5392 target = mono_resolve_patch_target (method, domain, code,
5393 patch_info, run_cctors);
5395 switch (patch_info->type) {
5396 case MONO_PATCH_INFO_IP:
5397 case MONO_PATCH_INFO_LDSTR:
5398 case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
5399 case MONO_PATCH_INFO_LDTOKEN:
5400 case MONO_PATCH_INFO_EXC:
5401 s390_patch_addr (ip, (guint64) target);
5403 case MONO_PATCH_INFO_METHOD:
5404 case MONO_PATCH_INFO_INTERNAL_METHOD:
5405 case MONO_PATCH_INFO_JIT_ICALL_ADDR:
5406 case MONO_PATCH_INFO_RGCTX_FETCH:
5407 case MONO_PATCH_INFO_MONITOR_ENTER:
5408 case MONO_PATCH_INFO_MONITOR_ENTER_V4:
5409 case MONO_PATCH_INFO_MONITOR_EXIT:
5410 case MONO_PATCH_INFO_ABS: {
5411 S390_EMIT_CALL (ip, target);
5414 case MONO_PATCH_INFO_SWITCH:
5415 /*----------------------------------*/
5416 /* ip points at the basr r13,0/j +4 */
5417 /* instruction the vtable value */
5418 /* follows this (i.e. ip+6) */
5419 /*----------------------------------*/
5420 S390_EMIT_LOAD (ip, target);
5422 case MONO_PATCH_INFO_METHODCONST:
5423 case MONO_PATCH_INFO_CLASS:
5424 case MONO_PATCH_INFO_IMAGE:
5425 case MONO_PATCH_INFO_FIELD:
5426 case MONO_PATCH_INFO_IID:
5427 case MONO_PATCH_INFO_EXC_NAME:
5428 target = S390_RELATIVE(target, ip);
5429 s390_patch_rel (ip, (guint64) target);
5431 case MONO_PATCH_INFO_R4:
5432 case MONO_PATCH_INFO_R8:
5433 case MONO_PATCH_INFO_METHOD_REL:
5434 g_assert_not_reached ();
5437 target = S390_RELATIVE(target, ip);
5439 s390_patch_rel (ip, (guint64) target);
5444 /*========================= End of Function ========================*/
5446 /*------------------------------------------------------------------*/
5448 /* Name - emit_load_volatile_arguments */
5450 /* Function - Emit the instructions to reload parameter regist- */
5451 /* registers for use with "tail" operations. */
5453 /* The register loading operations performed here */
5454 /* are the mirror of the store operations performed */
5455 /* in mono_arch_emit_prolog and need to be kept in */
5456 /* synchronization with it. */
5458 /*------------------------------------------------------------------*/
5461 emit_load_volatile_arguments (guint8 *code, MonoCompile *cfg)
5464 MonoMethod *method = cfg->method;
5465 MonoMethodSignature *sig = mono_method_signature(method);
5469 cinfo = get_call_info (NULL, NULL, sig);
5471 if (cinfo->struct_ret) {
5472 ArgInfo *ainfo = &cinfo->ret;
5473 inst = cfg->vret_addr;
5474 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5477 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5478 ArgInfo *ainfo = cinfo->args + i;
5479 inst = cfg->args [pos];
5481 if (inst->opcode == OP_REGVAR) {
5482 if (ainfo->regtype == RegTypeGeneral)
5483 s390_lgr (code, ainfo->reg, inst->dreg);
5484 else if (ainfo->regtype == RegTypeFP) {
5485 if (inst->dreg != ainfo->reg) {
5486 if (ainfo->size == 4) {
5487 s390_ldebr (code, ainfo->reg, inst->dreg);
5489 s390_ldr (code, ainfo->reg, inst->dreg);
5493 else if (ainfo->regtype == RegTypeBase) {
5495 g_assert_not_reached ();
5497 if (ainfo->regtype == RegTypeGeneral) {
5498 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5499 g_assert_not_reached();
5500 switch (ainfo->size) {
5502 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5505 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5508 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5511 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5514 } else if (ainfo->regtype == RegTypeBase) {
5515 } else if (ainfo->regtype == RegTypeFP) {
5516 if (ainfo->size == 8)
5517 s390_ld (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5518 else if (ainfo->size == 4)
5519 s390_le (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5521 g_assert_not_reached ();
5522 } else if (ainfo->regtype == RegTypeStructByVal) {
5523 if (ainfo->reg != STK_BASE) {
5524 switch (ainfo->size) {
5526 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5529 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5532 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5535 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5539 } else if (ainfo->regtype == RegTypeStructByAddr) {
5540 if (ainfo->reg != STK_BASE) {
5541 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5544 g_assert_not_reached ();
5552 /*========================= End of Function ========================*/
5554 /*------------------------------------------------------------------*/
5556 /* Name - mono_arch_emit_prolog */
5558 /* Function - Create the instruction sequence for a function */
5561 /*------------------------------------------------------------------*/
5564 mono_arch_emit_prolog (MonoCompile *cfg)
5566 MonoMethod *method = cfg->method;
5568 MonoMethodSignature *sig;
5570 long alloc_size, pos, max_offset, i, cfa_offset = 0;
5578 cfg->code_size = 512;
5580 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
5582 cfg->code_size += 256;
5583 } else if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
5584 cfg->code_size += 256;
5586 if (method->save_lmf)
5587 cfg->code_size += 200;
5589 cfg->native_code = code = g_malloc (cfg->code_size);
5591 mono_emit_unwind_op_def_cfa (cfg, code, STK_BASE, 0);
5592 emit_unwind_regs(cfg, code, s390_r6, s390_r14, S390_REG_SAVE_OFFSET);
5593 s390_stmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
5594 mono_emit_unwind_op_offset (cfg, code, s390_r14, S390_RET_ADDR_OFFSET);
5596 if (cfg->arch.bkchain_reg != -1)
5597 s390_lgr (code, cfg->arch.bkchain_reg, STK_BASE);
5599 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
5600 cfg->used_int_regs |= 1 << 11;
5603 alloc_size = cfg->stack_offset;
5605 cfg->stack_usage = cfa_offset = alloc_size;
5606 mono_emit_unwind_op_def_cfa_offset (cfg, code, alloc_size);
5607 s390_lgr (code, s390_r11, STK_BASE);
5608 if (s390_is_imm16 (alloc_size)) {
5609 s390_aghi (code, STK_BASE, -alloc_size);
5610 } else if (s390_is_imm32 (alloc_size)) {
5611 s390_agfi (code, STK_BASE, -alloc_size);
5613 int stackSize = alloc_size;
5614 while (stackSize > INT_MAX) {
5615 s390_agfi (code, STK_BASE, -INT_MAX);
5616 stackSize -= INT_MAX;
5618 s390_agfi (code, STK_BASE, -stackSize);
5620 s390_stg (code, s390_r11, 0, STK_BASE, 0);
5622 if (cfg->frame_reg != STK_BASE)
5623 s390_lgr (code, s390_r11, STK_BASE);
5625 mono_emit_unwind_op_def_cfa_reg (cfg, code, cfg->frame_reg);
5627 /* store runtime generic context */
5628 if (cfg->rgctx_var) {
5629 g_assert (cfg->rgctx_var->opcode == OP_REGOFFSET);
5631 s390_stg (code, MONO_ARCH_RGCTX_REG, 0,
5632 cfg->rgctx_var->inst_basereg,
5633 cfg->rgctx_var->inst_offset);
5636 /* compute max_offset in order to use short forward jumps
5637 * we always do it on s390 because the immediate displacement
5638 * for jumps is too small
5641 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
5643 bb->max_offset = max_offset;
5645 if (cfg->prof_options & MONO_PROFILE_COVERAGE)
5648 MONO_BB_FOR_EACH_INS (bb, ins)
5649 max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
5652 /* load arguments allocated to register from the stack */
5653 sig = mono_method_signature (method);
5656 cinfo = get_call_info (cfg, cfg->mempool, sig);
5658 if (cinfo->struct_ret) {
5659 ArgInfo *ainfo = &cinfo->ret;
5660 inst = cfg->vret_addr;
5661 inst->backend.size = ainfo->vtsize;
5662 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5665 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5666 ArgInfo *ainfo = cinfo->args + i;
5667 inst = cfg->args [pos];
5669 if (inst->opcode == OP_VTARG_ADDR)
5670 inst = inst->inst_left;
5672 if (inst->opcode == OP_REGVAR) {
5673 if (ainfo->regtype == RegTypeGeneral)
5674 s390_lgr (code, inst->dreg, ainfo->reg);
5675 else if (ainfo->regtype == RegTypeFP) {
5676 if (inst->dreg != ainfo->reg) {
5677 if (ainfo->size == 4) {
5678 s390_ledbr (code, inst->dreg, ainfo->reg);
5680 s390_ldr (code, inst->dreg, ainfo->reg);
5684 else if (ainfo->regtype == RegTypeBase) {
5685 s390_lgr (code, s390_r13, STK_BASE);
5686 s390_aghi (code, s390_r13, alloc_size);
5687 s390_lg (code, inst->dreg, 0, s390_r13, ainfo->offset);
5689 g_assert_not_reached ();
5691 if (cfg->verbose_level > 2)
5692 g_print ("Argument %d assigned to register %s\n",
5693 pos, mono_arch_regname (inst->dreg));
5695 if (ainfo->regtype == RegTypeGeneral) {
5696 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5697 g_assert_not_reached();
5698 switch (ainfo->size) {
5700 s390_stc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5703 s390_sth (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5706 s390_st (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5709 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5712 } else if (ainfo->regtype == RegTypeBase) {
5713 } else if (ainfo->regtype == RegTypeFP) {
5714 if (ainfo->size == 8)
5715 s390_std (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5716 else if (ainfo->size == 4)
5717 s390_ste (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5719 g_assert_not_reached ();
5720 } else if (ainfo->regtype == RegTypeStructByVal) {
5721 int doffset = inst->inst_offset;
5723 if (ainfo->reg != STK_BASE)
5727 s390_lgr (code, s390_r13, STK_BASE);
5728 s390_aghi (code, s390_r13, alloc_size);
5731 size = (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE
5732 ? mono_class_native_size(mono_class_from_mono_type(inst->inst_vtype), NULL)
5737 if (ainfo->reg == STK_BASE)
5738 s390_ic (code, reg, 0, s390_r13, ainfo->offset+7);
5739 s390_stc (code, reg, 0, inst->inst_basereg, doffset);
5742 if (ainfo->reg == STK_BASE)
5743 s390_lh (code, reg, 0, s390_r13, ainfo->offset+6);
5744 s390_sth (code, reg, 0, inst->inst_basereg, doffset);
5747 if (ainfo->reg == STK_BASE)
5748 s390_l (code, reg, 0, s390_r13, ainfo->offset+4);
5749 s390_st (code, reg, 0, inst->inst_basereg, doffset);
5752 if (ainfo->reg == STK_BASE)
5753 s390_lg (code, reg, 0, s390_r13, ainfo->offset);
5754 s390_stg (code, reg, 0, inst->inst_basereg, doffset);
5757 } else if (ainfo->regtype == RegTypeStructByAddr) {
5758 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5759 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
5761 g_assert_not_reached ();
5766 if (method->save_lmf) {
5767 /*---------------------------------------------------------------*/
5768 /* build the MonoLMF structure on the stack - see mini-s390x.h */
5769 /*---------------------------------------------------------------*/
5770 lmfOffset = alloc_size - sizeof(MonoLMF);
5772 s390_lgr (code, s390_r13, cfg->frame_reg);
5773 s390_aghi (code, s390_r13, lmfOffset);
5775 /*---------------------------------------------------------------*/
5776 /* Preserve the parameter registers while we fix up the lmf */
5777 /*---------------------------------------------------------------*/
5778 s390_stmg (code, s390_r2, s390_r6, s390_r13,
5779 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
5781 /*---------------------------------------------------------------*/
5782 /* On return from this call r2 have the address of the &lmf */
5783 /*---------------------------------------------------------------*/
5784 if (lmf_addr_tls_offset == -1) {
5785 mono_add_patch_info (cfg, code - cfg->native_code,
5786 MONO_PATCH_INFO_INTERNAL_METHOD,
5787 (gpointer)"mono_get_lmf_addr");
5788 S390_CALL_TEMPLATE(code, s390_r1);
5790 /*-------------------------------------------------------*/
5791 /* Get LMF by getting value from thread level storage */
5792 /*-------------------------------------------------------*/
5793 s390_ear (code, s390_r1, 0);
5794 s390_sllg(code, s390_r1, s390_r1, 0, 32);
5795 s390_ear (code, s390_r1, 1);
5796 s390_lg (code, s390_r2, 0, s390_r1, lmf_addr_tls_offset);
5799 /*---------------------------------------------------------------*/
5800 /* Set lmf.lmf_addr = jit_tls->lmf */
5801 /*---------------------------------------------------------------*/
5802 s390_stg (code, s390_r2, 0, s390_r13,
5803 G_STRUCT_OFFSET(MonoLMF, lmf_addr));
5805 /*---------------------------------------------------------------*/
5806 /* Get current lmf */
5807 /*---------------------------------------------------------------*/
5808 s390_lg (code, s390_r0, 0, s390_r2, 0);
5810 /*---------------------------------------------------------------*/
5811 /* Set our lmf as the current lmf */
5812 /*---------------------------------------------------------------*/
5813 s390_stg (code, s390_r13, 0, s390_r2, 0);
5815 /*---------------------------------------------------------------*/
5816 /* Have our lmf.previous_lmf point to the last lmf */
5817 /*---------------------------------------------------------------*/
5818 s390_stg (code, s390_r0, 0, s390_r13,
5819 G_STRUCT_OFFSET(MonoLMF, previous_lmf));
5821 /*---------------------------------------------------------------*/
5822 /* save method info */
5823 /*---------------------------------------------------------------*/
5824 S390_SET (code, s390_r1, method);
5825 s390_stg (code, s390_r1, 0, s390_r13,
5826 G_STRUCT_OFFSET(MonoLMF, method));
5828 /*---------------------------------------------------------------*/
5829 /* save the current IP */
5830 /*---------------------------------------------------------------*/
5831 s390_stg (code, STK_BASE, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp));
5832 s390_basr (code, s390_r1, 0);
5833 s390_stg (code, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip));
5835 /*---------------------------------------------------------------*/
5836 /* Save general and floating point registers */
5837 /*---------------------------------------------------------------*/
5838 s390_stmg (code, s390_r2, s390_r12, s390_r13,
5839 G_STRUCT_OFFSET(MonoLMF, gregs[2]));
5840 for (i = 0; i < 16; i++) {
5841 s390_std (code, i, 0, s390_r13,
5842 G_STRUCT_OFFSET(MonoLMF, fregs[i]));
5845 /*---------------------------------------------------------------*/
5846 /* Restore the parameter registers now that we've set up the lmf */
5847 /*---------------------------------------------------------------*/
5848 s390_lmg (code, s390_r2, s390_r6, s390_r13,
5849 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
5852 if (cfg->method->save_lmf)
5853 argsClobbered = TRUE;
5856 argsClobbered = TRUE;
5857 code = mono_arch_instrument_prolog (cfg, enter_method, code, TRUE);
5860 if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
5861 argsClobbered = TRUE;
5864 * Optimize the common case of the first bblock making a call with the same
5865 * arguments as the method. This works because the arguments are still in their
5866 * original argument registers.
5868 if (!argsClobbered) {
5869 MonoBasicBlock *first_bb = cfg->bb_entry;
5871 int filter = FILTER_IL_SEQ_POINT;
5873 next = mono_bb_first_inst (first_bb, filter);
5874 if (!next && first_bb->next_bb) {
5875 first_bb = first_bb->next_bb;
5876 next = mono_bb_first_inst (first_bb, filter);
5879 if (first_bb->in_count > 1)
5882 for (i = 0; next && i < sig->param_count + sig->hasthis; ++i) {
5883 ArgInfo *ainfo = cinfo->args + i;
5884 gboolean match = FALSE;
5886 inst = cfg->args [i];
5887 if (inst->opcode != OP_REGVAR) {
5888 switch (ainfo->regtype) {
5889 case RegTypeGeneral: {
5890 if (((next->opcode == OP_LOAD_MEMBASE) ||
5891 (next->opcode == OP_LOADI4_MEMBASE)) &&
5892 next->inst_basereg == inst->inst_basereg &&
5893 next->inst_offset == inst->inst_offset) {
5894 if (next->dreg == ainfo->reg) {
5898 next->opcode = OP_MOVE;
5899 next->sreg1 = ainfo->reg;
5900 /* Only continue if the instruction doesn't change argument regs */
5901 if (next->dreg == ainfo->reg)
5911 /* Argument allocated to (non-volatile) register */
5912 switch (ainfo->regtype) {
5913 case RegTypeGeneral:
5914 if (next->opcode == OP_MOVE &&
5915 next->sreg1 == inst->dreg &&
5916 next->dreg == ainfo->reg) {
5927 next = mono_inst_next (next, filter);
5934 cfg->code_len = code - cfg->native_code;
5935 g_assert (cfg->code_len < cfg->code_size);
5940 /*========================= End of Function ========================*/
5942 /*------------------------------------------------------------------*/
5944 /* Name - mono_arch_emit_epilog */
5946 /* Function - Emit the instructions for a function epilog. */
5948 /*------------------------------------------------------------------*/
5951 mono_arch_emit_epilog (MonoCompile *cfg)
5953 MonoMethod *method = cfg->method;
5956 int max_epilog_size = 96;
5958 if (cfg->method->save_lmf)
5959 max_epilog_size += 128;
5961 if (mono_jit_trace_calls != NULL)
5962 max_epilog_size += 128;
5963 else if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
5964 max_epilog_size += 128;
5966 while ((cfg->code_len + max_epilog_size) > (cfg->code_size - 16)) {
5967 cfg->code_size *= 2;
5968 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
5969 cfg->stat_code_reallocs++;
5972 code = cfg->native_code + cfg->code_len;
5974 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
5975 code = mono_arch_instrument_epilog (cfg, leave_method, code, TRUE);
5979 if (method->save_lmf)
5980 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
5982 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
5983 s390_lg (code, STK_BASE, 0, STK_BASE, 0);
5985 code = backUpStackPtr(cfg, code);
5987 s390_lmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
5988 s390_br (code, s390_r14);
5990 cfg->code_len = code - cfg->native_code;
5992 g_assert (cfg->code_len < cfg->code_size);
5996 /*========================= End of Function ========================*/
5998 /*------------------------------------------------------------------*/
6000 /* Name - mono_arch_emit_exceptions */
6002 /* Function - Emit the blocks to handle exception conditions. */
6004 /*------------------------------------------------------------------*/
6007 mono_arch_emit_exceptions (MonoCompile *cfg)
6009 MonoJumpInfo *patch_info;
6015 MonoClass *exc_classes [MAX_EXC];
6016 guint8 *exc_throw_start [MAX_EXC];
6018 for (patch_info = cfg->patch_info;
6020 patch_info = patch_info->next) {
6021 if (patch_info->type == MONO_PATCH_INFO_EXC)
6025 code_size = exc_count * 48;
6027 while ((cfg->code_len + code_size) > (cfg->code_size - 16)) {
6028 cfg->code_size *= 2;
6029 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6030 cfg->stat_code_reallocs++;
6033 code = cfg->native_code + cfg->code_len;
6035 /*---------------------------------------------------------------------*/
6036 /* Add code to raise exceptions */
6037 /*---------------------------------------------------------------------*/
6038 for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
6039 switch (patch_info->type) {
6040 case MONO_PATCH_INFO_EXC: {
6041 guint8 *ip = patch_info->ip.i + cfg->native_code;
6042 MonoClass *exc_class;
6045 /*-----------------------------------------------------*/
6046 /* Patch the branch in epilog to come here */
6047 /*-----------------------------------------------------*/
6048 s390_patch_rel (ip + 2, (guint64) S390_RELATIVE(code,ip));
6050 exc_class = mono_class_from_name (mono_defaults.corlib,
6052 patch_info->data.name);
6053 g_assert (exc_class);
6054 throw_ip = patch_info->ip.i;
6056 for (iExc = 0; iExc < nThrows; ++iExc)
6057 if (exc_classes [iExc] == exc_class)
6060 if (iExc < nThrows) {
6061 s390_jcl (code, S390_CC_UN,
6062 (guint64) exc_throw_start [iExc]);
6063 patch_info->type = MONO_PATCH_INFO_NONE;
6066 if (nThrows < MAX_EXC) {
6067 exc_classes [nThrows] = exc_class;
6068 exc_throw_start [nThrows] = code;
6071 /*---------------------------------------------*/
6072 /* Patch the parameter passed to the handler */
6073 /*---------------------------------------------*/
6074 S390_SET (code, s390_r2, exc_class->type_token);
6075 /*---------------------------------------------*/
6076 /* Load return address & parameter register */
6077 /*---------------------------------------------*/
6078 s390_larl (code, s390_r14, (guint64)S390_RELATIVE((patch_info->ip.i +
6079 cfg->native_code + 8), code));
6080 /*---------------------------------------------*/
6081 /* Reuse the current patch to set the jump */
6082 /*---------------------------------------------*/
6083 patch_info->type = MONO_PATCH_INFO_INTERNAL_METHOD;
6084 patch_info->data.name = "mono_arch_throw_corlib_exception";
6085 patch_info->ip.i = code - cfg->native_code;
6086 S390_BR_TEMPLATE (code, s390_r1);
6096 cfg->code_len = code - cfg->native_code;
6098 g_assert (cfg->code_len < cfg->code_size);
6102 /*========================= End of Function ========================*/
6104 /*------------------------------------------------------------------*/
6106 /* Name - mono_arch_finish_init */
6108 /* Function - Setup the JIT's Thread Level Specific Data. */
6110 /*------------------------------------------------------------------*/
6113 mono_arch_finish_init (void)
6115 appdomain_tls_offset = mono_domain_get_tls_offset();
6116 lmf_tls_offset = mono_get_lmf_tls_offset();
6117 lmf_addr_tls_offset = mono_get_lmf_addr_tls_offset();
6120 /*========================= End of Function ========================*/
6122 /*------------------------------------------------------------------*/
6124 /* Name - mono_arch_free_jit_tls_data */
6126 /* Function - Free tls data. */
6128 /*------------------------------------------------------------------*/
6131 mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
6135 /*========================= End of Function ========================*/
6137 /*------------------------------------------------------------------*/
6139 /* Name - mono_arch_emit_inst_for_method */
6141 /*------------------------------------------------------------------*/
6144 mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
6149 /*========================= End of Function ========================*/
6151 /*------------------------------------------------------------------*/
6153 /* Name - mono_arch_decompose_opts */
6155 /* Function - Decompose opcode into a System z opcode. */
6157 /*------------------------------------------------------------------*/
6160 mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
6163 * Have to rename these to avoid being decomposed normally, since the normal
6164 * decomposition does not work on S390.
6166 switch (ins->opcode) {
6168 ins->opcode = OP_S390_ISUB_OVF;
6170 case OP_ISUB_OVF_UN:
6171 ins->opcode = OP_S390_ISUB_OVF_UN;
6174 ins->opcode = OP_S390_IADD_OVF;
6176 case OP_IADD_OVF_UN:
6177 ins->opcode = OP_S390_IADD_OVF_UN;
6180 ins->opcode = OP_S390_LADD_OVF;
6182 case OP_LADD_OVF_UN:
6183 ins->opcode = OP_S390_LADD_OVF_UN;
6186 ins->opcode = OP_S390_LSUB_OVF;
6188 case OP_LSUB_OVF_UN:
6189 ins->opcode = OP_S390_LSUB_OVF_UN;
6196 /*========================= End of Function ========================*/
6198 /*------------------------------------------------------------------*/
6200 /* Name - mono_arch_print_tree */
6202 /* Function - Print platform-specific opcode details. */
6204 /* Returns - 1 - opcode details have been printed */
6205 /* 0 - opcode details have not been printed */
6207 /*------------------------------------------------------------------*/
6210 mono_arch_print_tree (MonoInst *tree, int arity)
6214 switch (tree->opcode) {
6215 case OP_S390_LOADARG:
6216 case OP_S390_ARGREG:
6217 case OP_S390_ARGPTR:
6218 printf ("[0x%lx(%s)]", tree->inst_offset,
6219 mono_arch_regname (tree->inst_basereg));
6222 case OP_S390_STKARG:
6223 printf ("[0x%lx(previous_frame)]",
6228 printf ("[0x%lx(%d,%s),0x%lx(%s)]",
6229 tree->inst_offset, tree->backend.size,
6230 mono_arch_regname(tree->dreg),
6232 mono_arch_regname(tree->sreg1));
6235 case OP_S390_SETF4RET:
6236 printf ("[f%s,f%s]",
6237 mono_arch_regname (tree->dreg),
6238 mono_arch_regname (tree->sreg1));
6242 printf ("[0x%lx(0x%lx,%s)]", tree->inst_offset,
6244 mono_arch_regname (tree->sreg1));
6247 case OP_S390_BKCHAIN:
6248 printf ("[previous_frame(%s)]",
6249 mono_arch_regname (tree->sreg1));
6257 /*========================= End of Function ========================*/
6259 /*------------------------------------------------------------------*/
6261 /* Name - mono_arch_regalloc_cost */
6263 /* Function - Determine the cost, in the number of memory */
6264 /* references, of the action of allocating the var- */
6265 /* iable VMV into a register during global register */
6268 /* Returns - Cost */
6270 /*------------------------------------------------------------------*/
6273 mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
6279 /*========================= End of Function ========================*/
6281 /*------------------------------------------------------------------*/
6283 /* Name - mono_arch_flush_register_windows */
6289 /*------------------------------------------------------------------*/
6292 mono_arch_flush_register_windows (void)
6296 /*========================= End of Function ========================*/
6298 /*------------------------------------------------------------------*/
6300 /* Name - mono_arch_is_inst_imm */
6302 /* Function - Determine if operand qualifies as an immediate */
6303 /* value. For s390 this is a value -32768-32768 */
6305 /* Returns - True|False - is [not] immediate value. */
6307 /*------------------------------------------------------------------*/
6310 mono_arch_is_inst_imm (gint64 imm)
6312 return s390_is_imm32 (imm);
6315 /*========================= End of Function ========================*/
6317 /*------------------------------------------------------------------*/
6319 /* Name - mono_arch_get_patch_offset */
6321 /* Function - Dummy entry point until s390x supports aot. */
6323 /* Returns - Offset for patch. */
6325 /*------------------------------------------------------------------*/
6328 mono_arch_get_patch_offset (guint8 *code)
6333 /*========================= End of Function ========================*/
6335 /*------------------------------------------------------------------*/
6337 /* Name - mono_arch_context_get_int_reg. */
6341 /* Returns - Return a register from the context. */
6343 /*------------------------------------------------------------------*/
6346 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
6348 return ((mgreg_t) ctx->uc_mcontext.gregs[reg]);
6351 /*========================= End of Function ========================*/
6353 /*------------------------------------------------------------------*/
6355 /* Name - mono_arch_context_set_int_reg. */
6357 /* Function - Set a value in a specified register. */
6359 /*------------------------------------------------------------------*/
6362 mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val)
6364 ctx->uc_mcontext.gregs[reg] = val;
6367 /*========================= End of Function ========================*/
6369 /*------------------------------------------------------------------*/
6371 /* Name - mono_arch_get_this_arg_from_call. */
6375 /*------------------------------------------------------------------*/
6378 mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
6380 return (gpointer) regs [s390_r2];
6383 /*========================= End of Function ========================*/
6385 /*------------------------------------------------------------------*/
6387 /* Name - mono_arch_install_handler_block_guard */
6391 /*------------------------------------------------------------------*/
6394 mono_arch_install_handler_block_guard (MonoJitInfo *ji, MonoJitExceptionInfo *clause,
6395 MonoContext *ctx, gpointer new_value)
6398 gpointer *sp, old_value;
6401 offset = clause->exvar_offset;
6404 bp = MONO_CONTEXT_GET_BP (ctx);
6405 sp = *(gpointer*)(bp + offset);
6408 if (old_value < ji->code_start || (char*)old_value > ((char*)ji->code_start + ji->code_size))
6416 /*========================= End of Function ========================*/
6418 /*------------------------------------------------------------------*/
6420 /* Name - get_delegate_invoke_impl. */
6424 /*------------------------------------------------------------------*/
6427 get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 param_count, gboolean aot)
6429 guint8 *code, *start;
6434 start = code = mono_global_codeman_reserve (size);
6436 /* Replace the this argument with the target */
6437 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6438 s390_lg (code, s390_r2, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, target));
6439 s390_br (code, s390_r1);
6440 g_assert ((code - start) <= size);
6442 mono_arch_flush_icache (start, size);
6446 size = 32 + param_count * 8;
6447 start = code = mono_global_codeman_reserve (size);
6449 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6450 /* slide down the arguments */
6451 for (i = 0; i < param_count; ++i) {
6452 s390_lgr (code, (s390_r2 + i), (s390_r2 + i + 1));
6454 s390_br (code, s390_r1);
6456 g_assert ((code - start) <= size);
6458 mono_arch_flush_icache (start, size);
6461 mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
6464 *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
6466 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
6467 *info = mono_tramp_info_create (name, start, code - start, NULL, NULL);
6474 /*========================= End of Function ========================*/
6476 /*------------------------------------------------------------------*/
6478 /* Name - mono_arch_get_delegate_invoke_impls. */
6482 /*------------------------------------------------------------------*/
6485 mono_arch_get_delegate_invoke_impls (void)
6488 MonoTrampInfo *info;
6491 get_delegate_invoke_impl (&info, TRUE, 0, TRUE);
6492 res = g_slist_prepend (res, info);
6494 for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
6495 get_delegate_invoke_impl (&info, FALSE, i, TRUE);
6496 res = g_slist_prepend (res, info);
6502 /*========================= End of Function ========================*/
6504 /*------------------------------------------------------------------*/
6506 /* Name - mono_arch_get_delegate_invoke_impl. */
6510 /*------------------------------------------------------------------*/
6513 mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target)
6515 guint8 *code, *start;
6517 /* FIXME: Support more cases */
6518 if (MONO_TYPE_ISSTRUCT (sig->ret))
6522 static guint8* cached = NULL;
6527 if (mono_aot_only) {
6528 start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
6530 MonoTrampInfo *info;
6531 start = get_delegate_invoke_impl (&info, TRUE, 0, FALSE);
6532 mono_tramp_info_register (info, NULL);
6535 mono_memory_barrier ();
6539 static guint8* cache [MAX_ARCH_DELEGATE_PARAMS + 1] = {NULL};
6542 if (sig->param_count > MAX_ARCH_DELEGATE_PARAMS)
6544 for (i = 0; i < sig->param_count; ++i)
6545 if (!mono_is_regsize_var (sig->params [i]))
6549 code = cache [sig->param_count];
6553 if (mono_aot_only) {
6554 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", sig->param_count);
6555 start = mono_aot_get_trampoline (name);
6558 MonoTrampInfo *info;
6559 start = get_delegate_invoke_impl (&info, FALSE, sig->param_count, FALSE);
6560 mono_tramp_info_register (info, NULL);
6563 mono_memory_barrier ();
6565 cache [sig->param_count] = start;
6570 /*========================= End of Function ========================*/
6572 /*------------------------------------------------------------------*/
6574 /* Name - mono_arch_get_delegate_virtual_invoke_impl. */
6578 /*------------------------------------------------------------------*/
6581 mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method,
6582 int offset, gboolean load_imt_reg)
6584 guint8 *code, *start;
6587 start = code = mono_global_codeman_reserve (size);
6590 * Replace the "this" argument with the target
6592 s390_lgr (code, s390_r1, s390_r2);
6593 s390_lg (code, s390_r2, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, target));
6596 * Load the IMT register, if needed
6599 s390_lg (code, MONO_ARCH_IMT_REG, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, method));
6605 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET(MonoObject, vtable));
6607 s390_agfi(code, s390_r1, offset);
6609 s390_lg (code, s390_r1, 0, s390_r1, 0);
6610 s390_br (code, s390_r1);
6615 /*========================= End of Function ========================*/
6617 /*------------------------------------------------------------------*/
6619 /* Name - mono_arch_build_imt_thunk. */
6623 /*------------------------------------------------------------------*/
6626 mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain,
6627 MonoIMTCheckItem **imt_entries, int count,
6628 gpointer fail_tramp)
6632 guchar *code, *start;
6635 for (i = 0; i < count; ++i) {
6636 MonoIMTCheckItem *item = imt_entries [i];
6637 if (item->is_equals) {
6638 if (item->check_target_idx) {
6639 if (!item->compare_done)
6640 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6641 if (item->has_target_code)
6642 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE;
6644 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE +
6648 item->chunk_size += CMP_SIZE + 2 * BR_SIZE + JUMP_SIZE +
6650 if (!item->has_target_code)
6651 item->chunk_size += LOAD_SIZE;
6653 item->chunk_size += LOADCON_SIZE + LOAD_SIZE + BR_SIZE;
6654 #if ENABLE_WRONG_METHOD_CHECK
6655 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6660 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6661 imt_entries [item->check_target_idx]->compare_done = TRUE;
6663 size += item->chunk_size;
6667 code = mono_method_alloc_generic_virtual_thunk (domain, size);
6669 code = mono_domain_code_reserve (domain, size);
6673 for (i = 0; i < count; ++i) {
6674 MonoIMTCheckItem *item = imt_entries [i];
6675 item->code_target = (guint8 *) code;
6676 if (item->is_equals) {
6677 if (item->check_target_idx) {
6678 if (!item->compare_done) {
6679 S390_SET (code, s390_r0, item->key);
6680 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
6682 item->jmp_code = (guint8*) code;
6683 s390_jcl (code, S390_CC_NE, 0);
6685 if (item->has_target_code) {
6686 S390_SET (code, s390_r1, item->value.target_code);
6688 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6689 s390_lg (code, s390_r1, 0, s390_r1, 0);
6691 s390_br (code, s390_r1);
6696 S390_SET (code, s390_r0, item->key);
6697 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
6698 item->jmp_code = (guint8*) code;
6699 s390_jcl (code, S390_CC_NE, 0);
6700 if (item->has_target_code) {
6701 S390_SET (code, s390_r1, item->value.target_code);
6704 S390_SET (code, s390_r1,
6705 (&(vtable->vtable [item->value.vtable_slot])));
6706 s390_lg (code, s390_r1, 0, s390_r1, 0);
6708 s390_br (code, s390_r1);
6709 target = (gint64) S390_RELATIVE(code, item->jmp_code);
6710 s390_patch_rel(item->jmp_code+2, target);
6711 S390_SET (code, s390_r1, fail_tramp);
6712 s390_br (code, s390_r1);
6713 item->jmp_code = NULL;
6715 /* enable the commented code to assert on wrong method */
6716 #if ENABLE_WRONG_METHOD_CHECK
6717 g_assert_not_reached ();
6719 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6720 s390_lg (code, s390_r1, 0, s390_r1, 0);
6721 s390_br (code, s390_r1);
6725 S390_SET (code, s390_r0, item->key);
6726 s390_cgr (code, MONO_ARCH_IMT_REG, s390_r0);
6727 item->jmp_code = (guint8 *) code;
6728 s390_jcl (code, S390_CC_GE, 0);
6732 * patch the branches to get to the target items
6734 for (i = 0; i < count; ++i) {
6735 MonoIMTCheckItem *item = imt_entries [i];
6736 if (item->jmp_code) {
6737 if (item->check_target_idx) {
6739 offset = (gint64) S390_RELATIVE(imt_entries [item->check_target_idx]->code_target,
6741 s390_patch_rel ((guchar *) item->jmp_code + 2, (guint64) offset);
6746 mono_arch_flush_icache ((guint8*)start, (code - start));
6747 mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL);
6750 mono_stats.imt_thunks_size += (code - start);
6752 g_assert (code - start <= size);
6754 snprintf(trampName, sizeof(trampName), "%d_imt_thunk_trampoline", domain->domain_id);
6755 mono_tramp_info_register (mono_tramp_info_create (trampName, start, code - start, NULL, NULL), domain);
6760 /*========================= End of Function ========================*/
6762 /*------------------------------------------------------------------*/
6764 /* Name - mono_arch_find_imt_method. */
6766 /* Function - Get the method address from MONO_ARCH_IMT_REG */
6767 /* found in the save area. */
6769 /*------------------------------------------------------------------*/
6772 mono_arch_find_imt_method (mgreg_t *regs, guint8 *code)
6774 return ((MonoMethod *) regs [MONO_ARCH_IMT_REG]);
6777 /*========================= End of Function ========================*/
6779 /*------------------------------------------------------------------*/
6781 /* Name - mono_arch_find_static_call_vtable */
6783 /* Function - Find the static call vtable. */
6785 /*------------------------------------------------------------------*/
6788 mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
6790 mgreg_t *r = (mgreg_t*)regs;
6792 return (MonoVTable*)(gsize) r [MONO_ARCH_RGCTX_REG];
6795 /*========================= End of Function ========================*/
6797 /*------------------------------------------------------------------*/
6799 /* Name - mono_arch_get_cie_program */
6801 /* Function - Find the static call vtable. */
6803 /*------------------------------------------------------------------*/
6806 mono_arch_get_cie_program (void)
6810 mono_add_unwind_op_def_cfa (l, 0, 0, STK_BASE, 0);
6815 /*========================= End of Function ========================*/
6817 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
6819 /*------------------------------------------------------------------*/
6821 /* Name - mono_arch_set_breakpoint. */
6823 /* Function - Set a breakpoint at the native code corresponding */
6824 /* to JI at NATIVE_OFFSET. The location should */
6825 /* contain code emitted by OP_SEQ_POINT. */
6827 /*------------------------------------------------------------------*/
6830 mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
6834 breakpointCode.pTrigger = bp_trigger_page;
6835 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
6836 code += BREAKPOINT_SIZE;
6839 /*========================= End of Function ========================*/
6841 /*------------------------------------------------------------------*/
6843 /* Name - mono_arch_clear_breakpoint. */
6845 /* Function - Clear the breakpoint at IP. */
6847 /*------------------------------------------------------------------*/
6850 mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
6855 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); i++)
6859 /*========================= End of Function ========================*/
6861 /*------------------------------------------------------------------*/
6863 /* Name - mono_arch_is_breakpoint_event. */
6867 /*------------------------------------------------------------------*/
6870 mono_arch_is_breakpoint_event (void *info, void *sigctx)
6872 siginfo_t* sinfo = (siginfo_t*) info;
6875 * Sometimes the address is off by 4
6877 if (sinfo->si_addr >= bp_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)bp_trigger_page + 128)
6883 /*========================= End of Function ========================*/
6885 /*------------------------------------------------------------------*/
6887 /* Name - mono_arch_skip_breakpoint. */
6889 /* Function - Modify the CTX so the IP is placed after the */
6890 /* breakpoint instruction, so when we resume, the */
6891 /* instruction is not executed again. */
6893 /*------------------------------------------------------------------*/
6896 mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
6898 MONO_CONTEXT_SET_IP (ctx, ((guint8*)MONO_CONTEXT_GET_IP (ctx) + sizeof(RXY_Format)));
6901 /*========================= End of Function ========================*/
6903 /*------------------------------------------------------------------*/
6905 /* Name - mono_arch_start_single_stepping. */
6907 /* Function - Start single stepping. */
6909 /*------------------------------------------------------------------*/
6912 mono_arch_start_single_stepping (void)
6914 mono_mprotect (ss_trigger_page, mono_pagesize (), 0);
6917 /*========================= End of Function ========================*/
6919 /*------------------------------------------------------------------*/
6921 /* Name - mono_arch_stop_single_stepping. */
6923 /* Function - Stop single stepping. */
6925 /*------------------------------------------------------------------*/
6928 mono_arch_stop_single_stepping (void)
6930 mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ);
6933 /*========================= End of Function ========================*/
6935 /*------------------------------------------------------------------*/
6937 /* Name - mono_arch_is_single_step_event. */
6939 /* Function - Return whether the machine state in sigctx cor- */
6940 /* responds to a single step event. */
6942 /*------------------------------------------------------------------*/
6945 mono_arch_is_single_step_event (void *info, void *sigctx)
6947 siginfo_t* sinfo = (siginfo_t*) info;
6950 * Sometimes the address is off by 4
6952 if (sinfo->si_addr >= ss_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)ss_trigger_page + 128)
6958 /*========================= End of Function ========================*/
6960 /*------------------------------------------------------------------*/
6962 /* Name - mono_arch_skip_single_step. */
6964 /* Function - Modify the ctx so the IP is placed after the */
6965 /* single step trigger instruction, so that the */
6966 /* instruction is not executed again. */
6968 /*------------------------------------------------------------------*/
6971 mono_arch_skip_single_step (MonoContext *ctx)
6973 MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + BREAKPOINT_SIZE);
6976 /*========================= End of Function ========================*/
6978 /*------------------------------------------------------------------*/
6980 /* Name - mono_arch_create_seq_point_info. */
6982 /* Function - Return a pointer to a data struction which is */
6983 /* used by the sequence point implementation in */
6986 /*------------------------------------------------------------------*/
6989 mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code)
6995 /*========================= End of Function ========================*/
6997 /*------------------------------------------------------------------*/
6999 /* Name - mono_arch_init_lmf_ext. */
7003 /*------------------------------------------------------------------*/
7006 mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
7008 ext->lmf.previous_lmf = prev_lmf;
7009 /* Mark that this is a MonoLMFExt */
7010 ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
7011 ext->lmf.ebp = (gssize)ext;
7014 /*========================= End of Function ========================*/
7018 /*------------------------------------------------------------------*/
7020 /* Name - mono_arch_cpu_enumerate_simd_versions. */
7022 /* Function - If this CPU supports vector operations then it */
7023 /* supports the equivalent of SSE1-4. */
7025 /*------------------------------------------------------------------*/
7028 mono_arch_cpu_enumerate_simd_versions (void)
7030 guint32 sseOpts = 0;
7033 sseOpts = (SIMD_VERSION_SSE1 | SIMD_VERSION_SSE2 |
7034 SIMD_VERSION_SSE3 | SIMD_VERSION_SSSE3 |
7035 SIMD_VERSION_SSE41 | SIMD_VERSION_SSE42 |
7036 SIMD_VERSION_SSE4a);
7041 /*========================= End of Function ========================*/
7043 /*------------------------------------------------------------------*/
7045 /* Name - mono_arch_opcode_supported. */
7047 /* Function - Check if a given return code is supported. */
7049 /*------------------------------------------------------------------*/
7052 mono_arch_opcode_supported (int opcode)
7055 case OP_ATOMIC_ADD_I4:
7056 case OP_ATOMIC_ADD_I8:
7057 case OP_ATOMIC_EXCHANGE_I4:
7058 case OP_ATOMIC_EXCHANGE_I8:
7065 /*========================= End of Function ========================*/