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_os_mutex_lock (&mini_arch_mutex)
250 #define mono_mini_arch_unlock() mono_os_mutex_unlock (&mini_arch_mutex)
252 /*========================= End of Defines =========================*/
254 /*------------------------------------------------------------------*/
255 /* I n c l u d e s */
256 /*------------------------------------------------------------------*/
260 #include <sys/types.h>
263 #include <mono/metadata/abi-details.h>
264 #include <mono/metadata/appdomain.h>
265 #include <mono/metadata/debug-helpers.h>
266 #include <mono/metadata/profiler-private.h>
267 #include <mono/utils/mono-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"
280 /*========================= End of Includes ========================*/
282 /*------------------------------------------------------------------*/
283 /* T y p e d e f s */
284 /*------------------------------------------------------------------*/
296 /*------------------------------------------------------------------*/
297 /* Used by the instrument_emit_epilog */
298 /*------------------------------------------------------------------*/
309 typedef struct InstList InstList;
323 RegTypeStructByValInFP,
325 RegTypeStructByAddrOnStack
329 gint32 offset; /* offset from caller's stack */
330 gint32 offparm; /* offset from callee's stack */
331 guint16 vtsize; /* in param area */
334 guint32 size; /* Size of structure used by RegTypeStructByVal */
335 gint32 type; /* Data type of argument */
351 gint64 gr[5]; /* R2-R6 */
352 gdouble fp[3]; /* F0-F2 */
353 } __attribute__ ((packed)) RegParm;
361 } __attribute__ ((packed)) breakpoint_t;
363 /*========================= End of Typedefs ========================*/
365 /*------------------------------------------------------------------*/
366 /* P r o t o t y p e s */
367 /*------------------------------------------------------------------*/
369 static void indent (int);
370 static guint8 * backUpStackPtr(MonoCompile *, guint8 *);
371 static void decodeParm (MonoType *, void *, int);
372 static void enter_method (MonoMethod *, RegParm *, char *);
373 static void leave_method (MonoMethod *, ...);
374 static inline void add_general (guint *, size_data *, ArgInfo *);
375 static inline void add_stackParm (guint *, size_data *, ArgInfo *, gint);
376 static inline void add_float (guint *, size_data *, ArgInfo *);
377 static CallInfo * get_call_info (MonoCompile *, MonoMemPool *, MonoMethodSignature *);
378 static guchar * emit_float_to_int (MonoCompile *, guchar *, int, int, int, gboolean);
379 static guint8 * emit_load_volatile_arguments (guint8 *, MonoCompile *);
380 static __inline__ void emit_unwind_regs(MonoCompile *, guint8 *, int, int, long);
382 /*========================= End of Prototypes ======================*/
384 /*------------------------------------------------------------------*/
385 /* G l o b a l V a r i a b l e s */
386 /*------------------------------------------------------------------*/
388 int mono_exc_esp_offset = 0;
390 __thread int indent_level = 0;
392 static gint appdomain_tls_offset = -1,
394 lmf_addr_tls_offset = -1;
396 pthread_key_t lmf_addr_key;
398 gboolean lmf_addr_key_inited = FALSE;
403 * The code generated for sequence points reads from this location,
404 * which is made read-only when single stepping is enabled.
406 static gpointer ss_trigger_page;
409 * Enabled breakpoints read from this trigger page
411 static gpointer bp_trigger_page;
413 breakpoint_t breakpointCode;
415 static mono_mutex_t mini_arch_mutex;
417 static const char * grNames[] = {
418 "s390_r0", "s390_sp", "s390_r2", "s390_r3", "s390_r4",
419 "s390_r5", "s390_r6", "s390_r7", "s390_r8", "s390_r9",
420 "s390_r10", "s390_r11", "s390_r12", "s390_r13", "s390_r14",
424 static const char * fpNames[] = {
425 "s390_f0", "s390_f1", "s390_f2", "s390_f3", "s390_f4",
426 "s390_f5", "s390_f6", "s390_f7", "s390_f8", "s390_f9",
427 "s390_f10", "s390_f11", "s390_f12", "s390_f13", "s390_f14",
431 static const char * vrNames[] = {
432 "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7",
433 "vr8", "vr9", "vr10", "vr11", "vr12", "vr13", "vr14", "vr15",
434 "vr16", "vr17", "vr18", "vr19", "vr20", "vr21", "vr22", "vr23",
435 "vr24", "vr25", "vr26", "vr27", "vr28", "vr29", "vr30", "vr31"
438 /*====================== End of Global Variables ===================*/
440 /*------------------------------------------------------------------*/
442 /* Name - mono_arch_regname */
444 /* Function - Returns the name of the register specified by */
445 /* the input parameter. */
447 /*------------------------------------------------------------------*/
450 mono_arch_regname (int reg)
452 if (reg >= 0 && reg < 16)
453 return grNames [reg];
458 /*========================= End of Function ========================*/
460 /*------------------------------------------------------------------*/
462 /* Name - mono_arch_fregname */
464 /* Function - Returns the name of the register specified by */
465 /* the input parameter. */
467 /*------------------------------------------------------------------*/
470 mono_arch_fregname (int reg)
472 if (reg >= 0 && reg < 16)
473 return fpNames [reg];
478 /*========================= End of Function ========================*/
480 /*------------------------------------------------------------------*/
482 /* Name - mono_arch_xregname */
484 /* Function - Returns the name of the register specified by */
485 /* the input parameter. */
487 /*------------------------------------------------------------------*/
490 mono_arch_xregname (int reg)
492 if (reg < s390_VR_NREG)
493 return vrNames [reg];
498 /*========================= End of Function ========================*/
500 /*------------------------------------------------------------------*/
502 /* Name - arch_get_argument_info */
504 /* Function - Gathers information on parameters such as size, */
505 /* alignment, and padding. arg_info should be large */
506 /* enough to hold param_count + 1 entries. */
508 /* Parameters - @csig - Method signature */
509 /* @param_count - No. of parameters to consider */
510 /* @arg_info - An array to store the result info */
512 /* Returns - Size of the activation frame */
514 /*------------------------------------------------------------------*/
517 mono_arch_get_argument_info (MonoMethodSignature *csig,
519 MonoJitArgumentInfo *arg_info)
521 int k, frame_size = 0;
522 int size, align, pad;
525 if (MONO_TYPE_ISSTRUCT (csig->ret)) {
526 frame_size += sizeof (gpointer);
530 arg_info [0].offset = offset;
533 frame_size += sizeof (gpointer);
537 arg_info [0].size = frame_size;
539 for (k = 0; k < param_count; k++) {
542 size = mono_type_native_stack_size (csig->params [k], (guint32 *) &align);
544 size = mini_type_stack_size (csig->params [k], &align);
546 frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
547 arg_info [k].pad = pad;
549 arg_info [k + 1].pad = 0;
550 arg_info [k + 1].size = size;
552 arg_info [k + 1].offset = offset;
556 align = MONO_ARCH_FRAME_ALIGNMENT;
557 frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
558 arg_info [k].pad = pad;
563 /*========================= End of Function ========================*/
565 /*------------------------------------------------------------------*/
567 /* Name - emit_unwind_regs. */
569 /* Function - Determines if a value can be returned in one or */
572 /*------------------------------------------------------------------*/
574 static void __inline__
575 emit_unwind_regs(MonoCompile *cfg, guint8 *code, int start, int end, long offset)
579 for (i = start; i < end; i++) {
580 mono_emit_unwind_op_offset (cfg, code, i, offset);
581 mini_gc_set_slot_type_from_cfa (cfg, offset, SLOT_NOREF);
582 offset += sizeof(gulong);
586 /*========================= End of Function ========================*/
588 /*------------------------------------------------------------------*/
590 /* Name - retFitsInReg. */
592 /* Function - Determines if a value can be returned in one or */
595 /*------------------------------------------------------------------*/
597 static inline gboolean
598 retFitsInReg(guint32 size)
613 /*========================= End of Function ========================*/
615 /*------------------------------------------------------------------*/
617 /* Name - backStackPtr. */
619 /* Function - Restore Stack Pointer to previous frame. */
621 /*------------------------------------------------------------------*/
623 static inline guint8 *
624 backUpStackPtr(MonoCompile *cfg, guint8 *code)
626 int stackSize = cfg->stack_usage;
628 if (cfg->frame_reg != STK_BASE)
629 s390_lgr (code, STK_BASE, cfg->frame_reg);
631 if (s390_is_imm16 (stackSize)) {
632 s390_aghi (code, STK_BASE, stackSize);
634 while (stackSize > 32767) {
635 s390_aghi (code, STK_BASE, 32767);
638 s390_aghi (code, STK_BASE, stackSize);
643 /*========================= End of Function ========================*/
645 /*------------------------------------------------------------------*/
649 /* Function - Perform nice indenting to current level */
651 /*------------------------------------------------------------------*/
657 indent_level += diff;
659 printf("%p [%3d] ",(void *)pthread_self(),v);
664 indent_level += diff;
667 /*========================= End of Function ========================*/
669 /*------------------------------------------------------------------*/
671 /* Name - cvtMonoType */
673 /* Function - Convert a mono-type to a string. */
675 /*------------------------------------------------------------------*/
678 cvtMonoType(MonoTypeEnum t)
683 return "MONO_TYPE_END";
685 return "MONO_TYPE_VOID";
686 case MONO_TYPE_BOOLEAN:
687 return "MONO_TYPE_BOOLEAN";
689 return "MONO_TYPE_CHAR";
691 return "MONO_TYPE_I1";
693 return "MONO_TYPE_U1";
695 return "MONO_TYPE_I2";
697 return "MONO_TYPE_U2";
699 return "MONO_TYPE_I4";
701 return "MONO_TYPE_U4";
703 return "MONO_TYPE_I8";
705 return "MONO_TYPE_U8";
707 return "MONO_TYPE_R4";
709 return "MONO_TYPE_R8";
710 case MONO_TYPE_STRING:
711 return "MONO_TYPE_STRING";
713 return "MONO_TYPE_PTR";
714 case MONO_TYPE_BYREF:
715 return "MONO_TYPE_BYREF";
716 case MONO_TYPE_VALUETYPE:
717 return "MONO_TYPE_VALUETYPE";
718 case MONO_TYPE_CLASS:
719 return "MONO_TYPE_CLASS";
721 return "MONO_TYPE_VAR";
722 case MONO_TYPE_ARRAY:
723 return "MONO_TYPE_ARRAY";
724 case MONO_TYPE_GENERICINST:
725 return "MONO_TYPE_GENERICINST";
726 case MONO_TYPE_TYPEDBYREF:
727 return "MONO_TYPE_TYPEDBYREF";
729 return "MONO_TYPE_I";
731 return "MONO_TYPE_U";
732 case MONO_TYPE_FNPTR:
733 return "MONO_TYPE_FNPTR";
734 case MONO_TYPE_OBJECT:
735 return "MONO_TYPE_OBJECT";
736 case MONO_TYPE_SZARRAY:
737 return "MONO_TYPE_SZARRAY";
739 return "MONO_TYPE_MVAR";
740 case MONO_TYPE_CMOD_REQD:
741 return "MONO_TYPE_CMOD_REQD";
742 case MONO_TYPE_CMOD_OPT:
743 return "MONO_TYPE_CMOD_OPT";
744 case MONO_TYPE_INTERNAL:
745 return "MONO_TYPE_INTERNAL";
746 case MONO_TYPE_MODIFIER:
747 return "MONO_TYPE_MODIFIER";
748 case MONO_TYPE_SENTINEL:
749 return "MONO_TYPE_SENTINEL";
750 case MONO_TYPE_PINNED:
751 return "MONO_TYPE_PINNED";
758 /*========================= End of Function ========================*/
760 /*------------------------------------------------------------------*/
762 /* Name - decodeParm */
764 /* Function - Decode a parameter for the trace. */
766 /*------------------------------------------------------------------*/
769 decodeParm(MonoType *type, void *curParm, int size)
774 printf("[BYREF:%p], ", *((char **) curParm));
776 simpleType = mini_get_underlying_type(type)->type;
778 switch (simpleType) {
780 printf ("[INTPTR:%p], ", *((int **) curParm));
783 printf ("[UINTPTR:%p], ", *((int **) curParm));
785 case MONO_TYPE_BOOLEAN :
786 printf ("[BOOL:%ld], ", *((gint64 *) curParm));
788 case MONO_TYPE_CHAR :
789 printf ("[CHAR:%c], ", *((int *) curParm));
792 printf ("[INT1:%ld], ", *((gint64 *) curParm));
795 printf ("[INT2:%ld], ", *((gint64 *) curParm));
798 printf ("[INT4:%ld], ", *((gint64 *) curParm));
801 printf ("[UINT1:%lu], ", *((guint64 *) curParm));
804 printf ("[UINT2:%lu], ", *((guint64 *) curParm));
807 printf ("[UINT4:%lu], ", *((guint64 *) curParm));
810 printf ("[UINT8:%lu], ", *((guint64 *) curParm));
812 case MONO_TYPE_STRING : {
813 MonoString *s = *((MonoString **) curParm);
815 g_assert (((MonoObject *) s)->vtable->klass == mono_defaults.string_class);
816 printf("[STRING:%p:%s], ", s, mono_string_to_utf8(s));
818 printf("[STRING:null], ");
822 case MONO_TYPE_CLASS :
823 case MONO_TYPE_OBJECT : {
824 MonoObject *obj = *((MonoObject **) curParm);
826 if ((obj) && (obj->vtable)) {
827 printf("[CLASS/OBJ:");
828 klass = obj->vtable->klass;
829 printf("%p [%p] ",obj,curParm);
830 if (klass == mono_defaults.string_class) {
831 printf("[STRING:%p:%s]",
832 obj, mono_string_to_utf8 ((MonoString *) obj));
833 } else if (klass == mono_defaults.int32_class) {
834 printf("[INT32:%p:%d]",
835 obj, *(gint32 *)((char *)obj + sizeof (MonoObject)));
838 klass->name_space, klass->name, obj);
841 printf("[OBJECT:null], ");
846 printf("[PTR:%p], ", *((gpointer **) (curParm)));
848 case MONO_TYPE_FNPTR :
849 printf("[FNPTR:%p], ", *((gpointer **) (curParm)));
851 case MONO_TYPE_ARRAY :
852 printf("[ARRAY:%p], ", *((gpointer **) (curParm)));
854 case MONO_TYPE_SZARRAY :
855 printf("[SZARRAY:%p], ", *((gpointer **) (curParm)));
858 printf("[INT8:%ld], ", *((gint64 *) (curParm)));
861 printf("[FLOAT4:%g], ", *((float *) (curParm)));
864 printf("[FLOAT8:%g], ", *((double *) (curParm)));
866 case MONO_TYPE_VALUETYPE : {
868 MonoMarshalType *info;
870 if (type->data.klass->enumtype) {
871 simpleType = mono_class_enum_basetype (type->data.klass)->type;
872 printf("{VALUETYPE} - ");
876 info = mono_marshal_load_type_info (type->data.klass);
878 if ((info->native_size == sizeof(float)) &&
879 (info->num_fields == 1) &&
880 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
881 printf("[FLOAT4:%f], ", *((float *) (curParm)));
885 if ((info->native_size == sizeof(double)) &&
886 (info->num_fields == 1) &&
887 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
888 printf("[FLOAT8:%g], ", *((double *) (curParm)));
892 printf("[VALUETYPE:");
893 for (i = 0; i < size; i++)
894 printf("%02x,", *((guint8 *)curParm+i));
898 case MONO_TYPE_TYPEDBYREF: {
900 printf("[TYPEDBYREF:");
901 for (i = 0; i < size; i++)
902 printf("%02x,", *((guint8 *)curParm+i));
907 printf("[%s], ",cvtMonoType(simpleType));
912 /*========================= End of Function ========================*/
914 /*------------------------------------------------------------------*/
916 /* Name - enter_method */
918 /* Function - Perform tracing of the entry to the current */
921 /*------------------------------------------------------------------*/
924 enter_method (MonoMethod *method, RegParm *rParm, char *sp)
926 int i, oParm = 0, iParm = 0;
929 MonoMethodSignature *sig;
936 fname = mono_method_full_name (method, TRUE);
938 printf ("ENTER: %s ", fname);
941 ip = (*(guint64 *) (sp+S390_RET_ADDR_OFFSET));
942 printf ("ip: %p sp: %p - ", (gpointer) ip, sp);
947 sig = mono_method_signature (method);
949 cinfo = get_call_info (NULL, NULL, sig);
951 if (cinfo->struct_ret) {
952 printf ("[STRUCTRET:%p], ", (gpointer) rParm->gr[0]);
957 gpointer *this_arg = (gpointer *) rParm->gr[iParm];
958 obj = (MonoObject *) this_arg;
959 switch(method->klass->this_arg.type) {
960 case MONO_TYPE_VALUETYPE:
962 guint64 *value = (guint64 *) ((uintptr_t)this_arg + sizeof(MonoObject));
963 printf("this:[value:%p:%016lx], ", this_arg, *value);
965 printf ("this:[NULL], ");
967 case MONO_TYPE_STRING:
970 klass = obj->vtable->klass;
971 if (klass == mono_defaults.string_class) {
972 printf ("this:[STRING:%p:%s], ",
973 obj, mono_string_to_utf8 ((MonoString *)obj));
975 printf ("this:%p[%s.%s], ",
976 obj, klass->name_space, klass->name);
979 printf("vtable:[NULL], ");
981 printf ("this:[NULL], ");
984 printf("this[%s]: %p, ",cvtMonoType(method->klass->this_arg.type),this_arg);
989 for (i = 0; i < sig->param_count; ++i) {
990 ainfo = &cinfo->args[i + oParm];
991 switch (ainfo->regtype) {
992 case RegTypeGeneral :
993 decodeParm(sig->params[i], &(rParm->gr[ainfo->reg-2]), ainfo->size);
996 decodeParm(sig->params[i], &(rParm->fp[ainfo->reg]), ainfo->size);
999 decodeParm(sig->params[i], sp+ainfo->offset, ainfo->size);
1001 case RegTypeStructByVal :
1002 if (ainfo->reg != STK_BASE) {
1003 int offset = sizeof(glong) - ainfo->size;
1004 curParm = &(rParm->gr[ainfo->reg-2])+offset;
1007 curParm = sp+ainfo->offset;
1009 if (retFitsInReg (ainfo->vtsize))
1010 decodeParm(sig->params[i],
1014 decodeParm(sig->params[i],
1015 *((char **) curParm),
1018 case RegTypeStructByAddr :
1019 if (ainfo->reg != STK_BASE)
1020 curParm = &(rParm->gr[ainfo->reg-2]);
1022 curParm = sp+ainfo->offset;
1024 decodeParm(sig->params[i],
1025 *((char **) curParm),
1037 /*========================= End of Function ========================*/
1039 /*------------------------------------------------------------------*/
1041 /* Name - leave_method */
1045 /*------------------------------------------------------------------*/
1048 leave_method (MonoMethod *method, ...)
1055 va_start(ap, method);
1057 fname = mono_method_full_name (method, TRUE);
1059 printf ("LEAVE: %s", fname);
1062 type = mono_method_signature (method)->ret;
1065 switch (type->type) {
1066 case MONO_TYPE_VOID:
1068 case MONO_TYPE_BOOLEAN: {
1069 int val = va_arg (ap, int);
1071 printf ("[TRUE:%d]", val);
1077 case MONO_TYPE_CHAR: {
1078 int val = va_arg (ap, int);
1079 printf ("[CHAR:%d]", val);
1082 case MONO_TYPE_I1: {
1083 int val = va_arg (ap, int);
1084 printf ("[INT1:%d]", val);
1087 case MONO_TYPE_U1: {
1088 int val = va_arg (ap, int);
1089 printf ("[UINT1:%d]", val);
1092 case MONO_TYPE_I2: {
1093 int val = va_arg (ap, int);
1094 printf ("[INT2:%d]", val);
1097 case MONO_TYPE_U2: {
1098 int val = va_arg (ap, int);
1099 printf ("[UINT2:%d]", val);
1102 case MONO_TYPE_I4: {
1103 int val = va_arg (ap, int);
1104 printf ("[INT4:%d]", val);
1107 case MONO_TYPE_U4: {
1108 int val = va_arg (ap, int);
1109 printf ("[UINT4:%d]", val);
1113 gint64 val = va_arg (ap, gint64);
1114 printf ("[INT:%ld]", val);
1119 gint64 val = va_arg (ap, gint64);
1120 printf ("[UINT:%lu]", val);
1124 case MONO_TYPE_STRING: {
1125 MonoString *s = va_arg (ap, MonoString *);
1128 g_assert (((MonoObject *)s)->vtable->klass == mono_defaults.string_class);
1129 printf ("[STRING:%p:%s]", s, mono_string_to_utf8 (s));
1131 printf ("[STRING:null], ");
1134 case MONO_TYPE_CLASS:
1135 case MONO_TYPE_OBJECT: {
1136 MonoObject *o = va_arg (ap, MonoObject *);
1138 if ((o) && (o->vtable)) {
1139 if (o->vtable->klass == mono_defaults.boolean_class) {
1140 printf ("[BOOLEAN:%p:%d]", o, *((guint8 *)o + sizeof (MonoObject)));
1141 } else if (o->vtable->klass == mono_defaults.int32_class) {
1142 printf ("[INT32:%p:%d]", o, *((gint32 *)((char *)o + sizeof (MonoObject))));
1143 } else if (o->vtable->klass == mono_defaults.int64_class) {
1144 printf ("[INT64:%p:%ld]", o, *((gint64 *)((char *)o + sizeof (MonoObject))));
1146 printf ("[%s.%s:%p]", o->vtable->klass->name_space, o->vtable->klass->name, o);
1148 printf ("[OBJECT:%p]", o);
1153 case MONO_TYPE_FNPTR:
1154 case MONO_TYPE_ARRAY:
1155 case MONO_TYPE_SZARRAY: {
1156 gpointer p = va_arg (ap, gpointer);
1157 printf ("[result=%p]", p);
1160 case MONO_TYPE_I8: {
1161 gint64 l = va_arg (ap, gint64);
1162 printf ("[LONG:%ld]", l);
1165 case MONO_TYPE_U8: {
1166 guint64 l = va_arg (ap, guint64);
1167 printf ("[ULONG:%lu]", l);
1170 case MONO_TYPE_R4: {
1171 double f = va_arg (ap, double);
1172 printf ("[FLOAT4:%g]\n", f);
1175 case MONO_TYPE_R8: {
1176 double f = va_arg (ap, double);
1177 printf ("[FLOAT8:%g]\n", f);
1180 case MONO_TYPE_VALUETYPE: {
1181 MonoMarshalType *info;
1182 if (type->data.klass->enumtype) {
1183 type = mono_class_enum_basetype (type->data.klass);
1188 info = mono_marshal_load_type_info (type->data.klass);
1190 if ((info->native_size == sizeof(float)) &&
1191 (info->num_fields == 1) &&
1192 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1193 double f = va_arg (ap, double);
1194 printf("[FLOAT4:%g]\n", (double) f);
1198 if ((info->native_size == sizeof(double)) &&
1199 (info->num_fields == 1) &&
1200 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1201 double f = va_arg (ap, double);
1202 printf("[FLOAT8:%g]\n", f);
1206 size = mono_type_size (type, &align);
1209 guint32 p = va_arg (ap, guint32);
1210 printf ("[%02x]\n",p);
1214 guint32 p = va_arg (ap, guint32);
1215 printf ("[%04x]\n",p);
1219 guint32 p = va_arg (ap, guint32);
1220 printf ("[%08x]\n",p);
1224 guint64 p = va_arg (ap, guint64);
1225 printf ("[%016lx]\n",p);
1229 gpointer p = va_arg (ap, gpointer);
1230 printf ("[VALUETYPE] %p\n",p);
1236 case MONO_TYPE_TYPEDBYREF: {
1237 guint8 *p = va_arg (ap, gpointer);
1239 size = mono_type_size (type, &align);
1246 for (j = 0; p && j < size; j++)
1247 printf ("%02x,", p [j]);
1251 printf ("[TYPEDBYREF]\n");
1255 case MONO_TYPE_GENERICINST: {
1256 printf("[GENERICINST]\n");
1259 case MONO_TYPE_MVAR: {
1263 case MONO_TYPE_CMOD_REQD: {
1264 printf("[CMOD_REQD]\n");
1267 case MONO_TYPE_CMOD_OPT: {
1268 printf("[CMOD_OPT]\n");
1271 case MONO_TYPE_INTERNAL: {
1272 printf("[INTERNAL]\n");
1276 printf ("(unknown return type %x)",
1277 mono_method_signature (method)->ret->type);
1280 ip = ((gint64) __builtin_extract_return_addr (__builtin_return_address (0)));
1281 printf (" ip: %p\n", (gpointer) ip);
1284 /*========================= End of Function ========================*/
1286 /*------------------------------------------------------------------*/
1288 /* Name - mono_arch_cpu_init */
1290 /* Function - Perform CPU specific initialization to execute */
1293 /*------------------------------------------------------------------*/
1296 mono_arch_cpu_init (void)
1300 /*========================= End of Function ========================*/
1302 /*------------------------------------------------------------------*/
1304 /* Name - mono_arch_init. */
1306 /* Function - Initialize architecture specific code. */
1308 /*------------------------------------------------------------------*/
1311 mono_arch_init (void)
1315 mono_set_partial_sharing_supported (FALSE);
1316 mono_os_mutex_init_recursive (&mini_arch_mutex);
1318 ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ);
1319 bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ);
1320 mono_mprotect (bp_trigger_page, mono_pagesize (), 0);
1322 code = (guint8 *) &breakpointCode;
1323 s390_basr(code, s390_r13, 0);
1325 s390_llong(code, 0);
1326 s390_lg(code, s390_r13, 0, s390_r13, 4);
1327 s390_lg(code, s390_r0, 0, s390_r13, 0);
1330 /*========================= End of Function ========================*/
1332 /*------------------------------------------------------------------*/
1334 /* Name - mono_arch_cleanup. */
1336 /* Function - Cleanup architecture specific code . */
1338 /*------------------------------------------------------------------*/
1341 mono_arch_cleanup (void)
1343 if (ss_trigger_page)
1344 mono_vfree (ss_trigger_page, mono_pagesize ());
1345 if (bp_trigger_page)
1346 mono_vfree (bp_trigger_page, mono_pagesize ());
1347 mono_os_mutex_destroy (&mini_arch_mutex);
1350 /*========================= End of Function ========================*/
1352 /*------------------------------------------------------------------*/
1354 /* Name - mono_arch_cpu_optimizations */
1356 /* Function - Returns the optimizations supported on this CPU */
1358 /*------------------------------------------------------------------*/
1361 mono_arch_cpu_optimizations (guint32 *exclude_mask)
1365 /*----------------------------------------------------------*/
1366 /* No s390-specific optimizations yet */
1367 /*----------------------------------------------------------*/
1368 *exclude_mask = MONO_OPT_LINEARS;
1372 /*========================= End of Function ========================*/
1374 /*------------------------------------------------------------------*/
1376 /* Name - mono_arch_get_allocatable_int_vars */
1380 /*------------------------------------------------------------------*/
1383 mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
1388 for (i = 0; i < cfg->num_varinfo; i++) {
1389 MonoInst *ins = cfg->varinfo [i];
1390 MonoMethodVar *vmv = MONO_VARINFO (cfg, i);
1393 if (vmv->range.first_use.abs_pos >= vmv->range.last_use.abs_pos)
1396 if (ins->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) ||
1397 (ins->opcode != OP_LOCAL && ins->opcode != OP_ARG))
1400 /* we can only allocate 32 bit values */
1401 if (mono_is_regsize_var(ins->inst_vtype)) {
1402 g_assert (MONO_VARINFO (cfg, i)->reg == -1);
1403 g_assert (i == vmv->idx);
1404 vars = mono_varlist_insert_sorted (cfg, vars, vmv, FALSE);
1411 /*========================= End of Function ========================*/
1413 /*------------------------------------------------------------------*/
1415 /* Name - mono_arch_global_int_regs */
1417 /* Function - Return a list of usable integer registers. */
1419 /*------------------------------------------------------------------*/
1422 mono_arch_get_global_int_regs (MonoCompile *cfg)
1425 MonoMethodHeader *header;
1428 header = cfg->header;
1429 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
1430 cfg->frame_reg = s390_r11;
1433 /* FIXME: s390_r12 is reserved for bkchain_reg. Only reserve it if needed */
1435 for (i = 8; i < top; ++i) {
1436 if (cfg->frame_reg != i)
1437 regs = g_list_prepend (regs, GUINT_TO_POINTER (i));
1443 /*========================= End of Function ========================*/
1445 /*------------------------------------------------------------------*/
1447 /* Name - mono_arch_flush_icache */
1449 /* Function - Flush the CPU icache. */
1451 /*------------------------------------------------------------------*/
1454 mono_arch_flush_icache (guint8 *code, gint size)
1458 /*========================= End of Function ========================*/
1460 /*------------------------------------------------------------------*/
1462 /* Name - add_general */
1464 /* Function - Determine code and stack size incremements for a */
1467 /*------------------------------------------------------------------*/
1470 add_general (guint *gr, size_data *sz, ArgInfo *ainfo)
1472 if (*gr > S390_LAST_ARG_REG) {
1473 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1474 ainfo->offset = sz->stack_size;
1475 ainfo->reg = STK_BASE;
1476 ainfo->regtype = RegTypeBase;
1477 sz->stack_size += sizeof(long);
1478 sz->local_size += sizeof(long);
1479 sz->offStruct += sizeof(long);
1480 sz->code_size += 12;
1488 /*========================= End of Function ========================*/
1490 /*------------------------------------------------------------------*/
1492 /* Name - add_stackParm */
1494 /* Function - Determine code and stack size incremements for a */
1497 /*------------------------------------------------------------------*/
1500 add_stackParm (guint *gr, size_data *sz, ArgInfo *ainfo, gint size)
1502 if (*gr > S390_LAST_ARG_REG) {
1503 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1504 ainfo->reg = STK_BASE;
1505 ainfo->offset = sz->stack_size;
1506 ainfo->regtype = RegTypeStructByAddrOnStack;
1507 sz->stack_size += sizeof (gpointer);
1508 sz->parm_size += sizeof(gpointer);
1509 sz->offStruct += sizeof(gpointer);
1512 ainfo->offset = sz->stack_size;
1513 ainfo->regtype = RegTypeStructByAddr;
1516 ainfo->offparm = sz->offset;
1517 sz->offset = S390_ALIGN(sz->offset+size, sizeof(long));
1519 ainfo->vtsize = size;
1520 sz->parm_size += size;
1523 /*========================= End of Function ========================*/
1525 /*------------------------------------------------------------------*/
1527 /* Name - add_float */
1529 /* Function - Determine code and stack size incremements for a */
1530 /* float parameter. */
1532 /*------------------------------------------------------------------*/
1535 add_float (guint *fr, size_data *sz, ArgInfo *ainfo)
1537 if ((*fr) <= S390_LAST_FPARG_REG) {
1538 ainfo->regtype = RegTypeFP;
1544 ainfo->offset = sz->stack_size;
1545 ainfo->reg = STK_BASE;
1546 ainfo->regtype = RegTypeBase;
1548 sz->stack_size += sizeof(double);
1549 sz->local_size += sizeof(double);
1550 sz->offStruct += sizeof(double);
1554 /*========================= End of Function ========================*/
1556 /*------------------------------------------------------------------*/
1558 /* Name - get_call_info */
1560 /* Function - Determine the amount of space required for code */
1561 /* and stack. In addition determine starting points */
1562 /* for stack-based parameters, and area for struct- */
1563 /* ures being returned on the stack. */
1565 /*------------------------------------------------------------------*/
1568 get_call_info (MonoCompile *cfg, MonoMemPool *mp, MonoMethodSignature *sig)
1570 guint i, fr, gr, size, pstart;
1571 int nParm = sig->hasthis + sig->param_count;
1573 guint32 simpleType, align;
1574 gboolean is_pinvoke = sig->pinvoke;
1579 cinfo = mono_mempool_alloc0 (mp, sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1581 cinfo = g_malloc0 (sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1586 cinfo->struct_ret = 0;
1590 sz->offStruct = S390_MINIMAL_STACK_SIZE;
1591 sz->stack_size = S390_MINIMAL_STACK_SIZE;
1598 /*----------------------------------------------------------*/
1599 /* We determine the size of the return code/stack in case we*/
1600 /* need to reserve a register to be used to address a stack */
1601 /* area that the callee will use. */
1602 /*----------------------------------------------------------*/
1604 ret_type = mini_get_underlying_type (sig->ret);
1605 simpleType = ret_type->type;
1607 switch (simpleType) {
1608 case MONO_TYPE_BOOLEAN:
1613 case MONO_TYPE_CHAR:
1618 case MONO_TYPE_CLASS:
1619 case MONO_TYPE_OBJECT:
1620 case MONO_TYPE_SZARRAY:
1621 case MONO_TYPE_ARRAY:
1623 case MONO_TYPE_FNPTR:
1624 case MONO_TYPE_STRING:
1625 cinfo->ret.reg = s390_r2;
1630 cinfo->ret.reg = s390_f0;
1635 cinfo->ret.reg = s390_r2;
1638 case MONO_TYPE_GENERICINST:
1639 if (!mono_type_generic_inst_is_valuetype (sig->ret)) {
1640 cinfo->ret.reg = s390_r2;
1645 case MONO_TYPE_VALUETYPE: {
1646 MonoClass *klass = mono_class_from_mono_type (sig->ret);
1647 if (klass->enumtype) {
1648 simpleType = mono_class_enum_basetype (klass)->type;
1651 size = mini_type_stack_size_full (&klass->byval_arg, NULL, sig->pinvoke);
1653 cinfo->struct_ret = 1;
1654 cinfo->ret.size = size;
1655 cinfo->ret.vtsize = size;
1658 case MONO_TYPE_TYPEDBYREF:
1659 size = sizeof (MonoTypedRef);
1660 cinfo->struct_ret = 1;
1661 cinfo->ret.size = size;
1662 cinfo->ret.vtsize = size;
1664 case MONO_TYPE_VOID:
1667 g_error ("Can't handle as return value 0x%x", sig->ret->type);
1673 * To simplify get_this_arg_reg () and LLVM integration, emit the vret arg after
1674 * the first argument, allowing 'this' to be always passed in the first arg reg.
1675 * Also do this if the first argument is a reference type, since virtual calls
1676 * are sometimes made using calli without sig->hasthis set, like in the delegate
1679 if (cinfo->struct_ret && !is_pinvoke &&
1681 (sig->param_count > 0 &&
1682 MONO_TYPE_IS_REFERENCE (mini_get_underlying_type (sig->params [0]))))) {
1684 cinfo->args[nParm].size = sizeof (gpointer);
1685 add_general (&gr, sz, cinfo->args + nParm);
1687 cinfo->args[nParm].size = sizeof (gpointer);
1688 add_general (&gr, sz, &cinfo->args [sig->hasthis + nParm]);
1692 cinfo->vret_arg_index = 1;
1693 cinfo->ret.reg = gr;
1698 cinfo->args[nParm].size = sizeof (gpointer);
1699 add_general (&gr, sz, cinfo->args + nParm);
1703 if (cinfo->struct_ret) {
1704 cinfo->ret.reg = gr;
1709 if ((sig->call_convention == MONO_CALL_VARARG) && (sig->param_count == 0)) {
1710 gr = S390_LAST_ARG_REG + 1;
1711 fr = S390_LAST_FPARG_REG + 1;
1713 /* Emit the signature cookie just before the implicit arguments */
1714 add_general (&gr, sz, &cinfo->sigCookie);
1717 /*----------------------------------------------------------*/
1718 /* We determine the size of the parameter code and stack */
1719 /* requirements by checking the types and sizes of the */
1721 /*----------------------------------------------------------*/
1723 for (i = pstart; i < sig->param_count; ++i) {
1726 /*--------------------------------------------------*/
1727 /* Handle vararg type calls. All args are put on */
1729 /*--------------------------------------------------*/
1730 if ((sig->call_convention == MONO_CALL_VARARG) &&
1731 (i == sig->sentinelpos)) {
1732 gr = S390_LAST_ARG_REG + 1;
1733 fr = S390_LAST_FPARG_REG + 1;
1734 add_general (&gr, sz, &cinfo->sigCookie);
1737 if (sig->params [i]->byref) {
1738 add_general (&gr, sz, cinfo->args+nParm);
1739 cinfo->args[nParm].size = sizeof(gpointer);
1744 ptype = mini_get_underlying_type (sig->params [i]);
1745 simpleType = ptype->type;
1746 cinfo->args[nParm].type = simpleType;
1747 switch (simpleType) {
1748 case MONO_TYPE_BOOLEAN:
1751 cinfo->args[nParm].size = sizeof(char);
1752 add_general (&gr, sz, cinfo->args+nParm);
1757 case MONO_TYPE_CHAR:
1758 cinfo->args[nParm].size = sizeof(short);
1759 add_general (&gr, sz, cinfo->args+nParm);
1764 cinfo->args[nParm].size = sizeof(int);
1765 add_general (&gr, sz, cinfo->args+nParm);
1771 case MONO_TYPE_FNPTR:
1772 case MONO_TYPE_CLASS:
1773 case MONO_TYPE_OBJECT:
1774 case MONO_TYPE_STRING:
1775 case MONO_TYPE_SZARRAY:
1776 case MONO_TYPE_ARRAY:
1777 cinfo->args[nParm].size = sizeof(gpointer);
1778 add_general (&gr, sz, cinfo->args+nParm);
1783 cinfo->args[nParm].size = sizeof(long long);
1784 add_general (&gr, sz, cinfo->args+nParm);
1788 cinfo->args[nParm].size = sizeof(float);
1789 add_float (&fr, sz, cinfo->args+nParm);
1793 cinfo->args[nParm].size = sizeof(double);
1794 add_float (&fr, sz, cinfo->args+nParm);
1797 case MONO_TYPE_GENERICINST:
1798 if (!mono_type_generic_inst_is_valuetype (ptype)) {
1799 cinfo->args[nParm].size = sizeof(gpointer);
1800 add_general (&gr, sz, cinfo->args+nParm);
1805 case MONO_TYPE_VALUETYPE: {
1806 MonoMarshalType *info;
1807 MonoClass *klass = mono_class_from_mono_type (ptype);
1810 size = mono_class_native_size(klass, NULL);
1812 size = mono_class_value_size(klass, NULL);
1814 if (simpleType != MONO_TYPE_GENERICINST) {
1815 info = mono_marshal_load_type_info(klass);
1817 if ((info->native_size == sizeof(float)) &&
1818 (info->num_fields == 1) &&
1819 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1820 cinfo->args[nParm].size = sizeof(float);
1821 add_float(&fr, sz, cinfo->args+nParm);
1826 if ((info->native_size == sizeof(double)) &&
1827 (info->num_fields == 1) &&
1828 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1829 cinfo->args[nParm].size = sizeof(double);
1830 add_float(&fr, sz, cinfo->args+nParm);
1836 cinfo->args[nParm].vtsize = 0;
1837 cinfo->args[nParm].size = 0;
1840 /*----------------------------------*/
1841 /* On S/390, structures of size 1, */
1842 /* 2, 4, and 8 bytes are passed in */
1843 /* (a) register(s). */
1844 /*----------------------------------*/
1850 add_general(&gr, sz, cinfo->args+nParm);
1851 cinfo->args[nParm].size = size;
1852 cinfo->args[nParm].regtype = RegTypeStructByVal;
1854 sz->local_size += sizeof(long);
1857 add_stackParm(&gr, sz, cinfo->args+nParm, size);
1862 case MONO_TYPE_TYPEDBYREF: {
1863 int size = sizeof (MonoTypedRef);
1865 cinfo->args[nParm].vtsize = 0;
1866 cinfo->args[nParm].size = 0;
1869 /*----------------------------------*/
1870 /* On S/390, structures of size 1, */
1871 /* 2, 4, and 8 bytes are passed in */
1872 /* (a) register(s). */
1873 /*----------------------------------*/
1879 add_general(&gr, sz, cinfo->args+nParm);
1880 cinfo->args[nParm].size = size;
1881 cinfo->args[nParm].regtype = RegTypeStructByVal;
1883 sz->local_size += sizeof(long);
1886 add_stackParm(&gr, sz, cinfo->args+nParm, size);
1892 g_error ("Can't trampoline 0x%x", ptype);
1896 /*----------------------------------------------------------*/
1897 /* Handle the case where there are no implicit arguments */
1898 /*----------------------------------------------------------*/
1899 if ((sig->call_convention == MONO_CALL_VARARG) &&
1902 (sig->param_count == sig->sentinelpos)) {
1903 gr = S390_LAST_ARG_REG + 1;
1904 fr = S390_LAST_FPARG_REG + 1;
1905 add_general (&gr, sz, &cinfo->sigCookie);
1908 /*----------------------------------------------------------*/
1909 /* If we are passing a structure back then if it won't be */
1910 /* in a register(s) then we make room at the end of the */
1911 /* parameters that may have been placed on the stack */
1912 /*----------------------------------------------------------*/
1913 if (cinfo->struct_ret) {
1914 cinfo->ret.offset = sz->stack_size;
1915 switch (cinfo->ret.size) {
1923 sz->stack_size += S390_ALIGN(cinfo->ret.size, align);
1928 sz->stack_size = sz->stack_size + sz->local_size + sz->parm_size +
1930 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1935 /*========================= End of Function ========================*/
1937 /*------------------------------------------------------------------*/
1939 /* Name - mono_arch_allocate_vars */
1941 /* Function - Set var information according to the calling */
1942 /* convention for S/390. The local var stuff should */
1943 /* most likely be split in another method. */
1945 /* Parameter - @m - Compile unit. */
1947 /*------------------------------------------------------------------*/
1950 mono_arch_allocate_vars (MonoCompile *cfg)
1952 MonoMethodSignature *sig;
1953 MonoMethodHeader *header;
1956 int iParm, iVar, offset, align, size, curinst;
1957 int frame_reg = STK_BASE;
1960 header = cfg->header;
1962 cfg->flags |= MONO_CFG_HAS_SPILLUP;
1964 /*---------------------------------------------------------*/
1965 /* We use the frame register also for any method that has */
1966 /* filter clauses. This way, when the handlers are called, */
1967 /* the code will reference local variables using the frame */
1968 /* reg instead of the stack pointer: if we had to restore */
1969 /* the stack pointer, we'd corrupt the method frames that */
1970 /* are already on the stack (since filters get called */
1971 /* before stack unwinding happens) when the filter code */
1972 /* would call any method. */
1973 /*---------------------------------------------------------*/
1974 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
1975 frame_reg = s390_r11;
1977 cfg->frame_reg = frame_reg;
1979 cfg->arch.bkchain_reg = -1;
1981 if (frame_reg != STK_BASE)
1982 cfg->used_int_regs |= (1 << frame_reg);
1984 if (cfg->uses_rgctx_reg)
1985 cfg->used_int_regs |= (1 << MONO_ARCH_IMT_REG);
1987 sig = mono_method_signature (cfg->method);
1989 cinfo = get_call_info (cfg, cfg->mempool, sig);
1991 if (!cinfo->struct_ret) {
1992 switch (mini_get_underlying_type (sig->ret)->type) {
1993 case MONO_TYPE_VOID:
1996 cfg->ret->opcode = OP_REGVAR;
1997 cfg->ret->dreg = s390_r2;
2002 /*--------------------------------------------------------------*/
2003 /* local vars are at a positive offset from the stack pointer */
2004 /* also note that if the function uses alloca, we use s390_r11 */
2005 /* to point at the local variables. */
2006 /* add parameter area size for called functions */
2007 /*--------------------------------------------------------------*/
2008 if (cfg->param_area == 0)
2009 offset = S390_MINIMAL_STACK_SIZE;
2011 offset = cfg->param_area;
2013 cfg->sig_cookie = 0;
2015 if (cinfo->struct_ret) {
2016 inst = cfg->vret_addr;
2017 offset = S390_ALIGN(offset, sizeof(gpointer));
2018 inst->inst_offset = offset;
2019 inst->opcode = OP_REGOFFSET;
2020 inst->inst_basereg = frame_reg;
2021 offset += sizeof(gpointer);
2022 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2023 printf ("vret_addr =");
2024 mono_print_ins (cfg->vret_addr);
2029 inst = cfg->args [0];
2030 if (inst->opcode != OP_REGVAR) {
2031 inst->opcode = OP_REGOFFSET;
2032 inst->inst_basereg = frame_reg;
2033 offset = S390_ALIGN(offset, sizeof(gpointer));
2034 inst->inst_offset = offset;
2035 offset += sizeof (gpointer);
2042 eArg = sig->param_count + sArg;
2044 if (sig->call_convention == MONO_CALL_VARARG)
2045 cfg->sig_cookie += S390_MINIMAL_STACK_SIZE;
2047 for (iParm = sArg; iParm < eArg; ++iParm) {
2048 inst = cfg->args [curinst];
2049 if (inst->opcode != OP_REGVAR) {
2050 switch (cinfo->args[iParm].regtype) {
2051 case RegTypeStructByAddr : {
2054 size = sizeof (gpointer);
2056 inst->opcode = OP_REGOFFSET;
2057 inst->inst_basereg = frame_reg;
2058 offset = S390_ALIGN (offset, sizeof (gpointer));
2059 inst->inst_offset = offset;
2061 /* Add a level of indirection */
2062 MONO_INST_NEW (cfg, indir, 0);
2064 inst->opcode = OP_VTARG_ADDR;
2065 inst->inst_left = indir;
2068 case RegTypeStructByAddrOnStack : {
2071 size = sizeof (gpointer);
2073 /* Similar to the == STK_BASE case below */
2074 cfg->arch.bkchain_reg = s390_r12;
2075 cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2077 inst->opcode = OP_REGOFFSET;
2078 inst->dreg = mono_alloc_preg (cfg);
2079 inst->inst_basereg = cfg->arch.bkchain_reg;
2080 inst->inst_offset = cinfo->args [iParm].offset;
2082 /* Add a level of indirection */
2083 MONO_INST_NEW (cfg, indir, 0);
2085 inst->opcode = OP_VTARG_ADDR;
2086 inst->inst_left = indir;
2089 case RegTypeStructByVal :
2090 size = cinfo->args[iParm].size;
2091 offset = S390_ALIGN(offset, size);
2092 inst->opcode = OP_REGOFFSET;
2093 inst->inst_basereg = frame_reg;
2094 inst->inst_offset = offset;
2097 if (cinfo->args [iParm].reg == STK_BASE) {
2099 * These arguments are in the previous frame, so we can't
2100 * compute their offset from the current frame pointer right
2101 * now, since cfg->stack_offset is not yet known, so dedicate a
2102 * register holding the previous frame pointer.
2104 cfg->arch.bkchain_reg = s390_r12;
2105 cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2107 inst->opcode = OP_REGOFFSET;
2108 inst->inst_basereg = cfg->arch.bkchain_reg;
2109 size = (cinfo->args[iParm].size < 8
2110 ? 8 - cinfo->args[iParm].size
2112 inst->inst_offset = cinfo->args [iParm].offset + size;
2113 size = sizeof (long);
2115 inst->opcode = OP_REGOFFSET;
2116 inst->inst_basereg = frame_reg;
2117 size = (cinfo->args[iParm].size < 8
2120 offset = S390_ALIGN(offset, size);
2121 if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
2122 inst->inst_offset = offset;
2124 inst->inst_offset = offset + (8 - size);
2129 if ((sig->call_convention == MONO_CALL_VARARG) &&
2130 (cinfo->args[iParm].regtype != RegTypeGeneral) &&
2131 (iParm < sig->sentinelpos))
2132 cfg->sig_cookie += size;
2133 printf("%s %4d cookine %x\n",__FUNCTION__,__LINE__,cfg->sig_cookie);
2136 offset += MAX(size, 8);
2141 cfg->locals_min_stack_offset = offset;
2143 curinst = cfg->locals_start;
2144 for (iVar = curinst; iVar < cfg->num_varinfo; ++iVar) {
2145 inst = cfg->varinfo [iVar];
2146 if ((inst->flags & MONO_INST_IS_DEAD) ||
2147 (inst->opcode == OP_REGVAR))
2150 /*--------------------------------------------------*/
2151 /* inst->backend.is_pinvoke indicates native sized */
2152 /* value typs this is used by the pinvoke wrappers */
2153 /* when they call functions returning structure */
2154 /*--------------------------------------------------*/
2155 if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype))
2156 size = mono_class_native_size (mono_class_from_mono_type(inst->inst_vtype),
2157 (guint32 *) &align);
2159 size = mono_type_size (inst->inst_vtype, &align);
2161 offset = S390_ALIGN(offset, align);
2162 inst->inst_offset = offset;
2163 inst->opcode = OP_REGOFFSET;
2164 inst->inst_basereg = frame_reg;
2166 DEBUG (g_print("allocating local %d to %ld, size: %d\n",
2167 iVar, inst->inst_offset, size));
2170 cfg->locals_max_stack_offset = offset;
2172 /*------------------------------------------------------*/
2173 /* Allow space for the trace method stack area if needed*/
2174 /*------------------------------------------------------*/
2175 if ((mono_jit_trace_calls != NULL && mono_trace_eval (cfg->method))
2176 || (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE))
2177 offset += S390_TRACE_STACK_SIZE;
2179 /*------------------------------------------------------*/
2180 /* Reserve space to save LMF and caller saved registers */
2181 /*------------------------------------------------------*/
2182 if (cfg->method->save_lmf)
2183 offset += sizeof (MonoLMF);
2185 /*------------------------------------------------------*/
2186 /* align the offset */
2187 /*------------------------------------------------------*/
2188 cfg->stack_offset = S390_ALIGN(offset, S390_STACK_ALIGNMENT);
2190 /*------------------------------------------------------*/
2191 /* Fix offsets for args whose value is in parent frame */
2192 /*------------------------------------------------------*/
2193 for (iParm = sArg; iParm < eArg; ++iParm) {
2194 inst = cfg->args [iParm];
2196 if (inst->opcode == OP_S390_STKARG) {
2197 inst->opcode = OP_REGOFFSET;
2198 inst->inst_offset += cfg->stack_offset;
2203 /*========================= End of Function ========================*/
2205 /*------------------------------------------------------------------*/
2207 /* Name - mono_arch_create_vars */
2209 /*------------------------------------------------------------------*/
2212 mono_arch_create_vars (MonoCompile *cfg)
2214 MonoMethodSignature *sig;
2217 sig = mono_method_signature (cfg->method);
2219 cinfo = get_call_info (cfg, cfg->mempool, sig);
2221 if (cinfo->struct_ret) {
2222 cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG);
2223 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2224 printf ("vret_addr = ");
2225 mono_print_ins (cfg->vret_addr);
2230 /*========================= End of Function ========================*/
2232 /*------------------------------------------------------------------*/
2234 /* Name - add_outarg_reg2. */
2236 /*------------------------------------------------------------------*/
2239 add_outarg_reg2 (MonoCompile *cfg, MonoCallInst *call, ArgStorage storage, int reg, MonoInst *tree)
2244 case RegTypeGeneral:
2245 MONO_INST_NEW (cfg, ins, OP_MOVE);
2246 ins->dreg = mono_alloc_ireg (cfg);
2247 ins->sreg1 = tree->dreg;
2248 MONO_ADD_INS (cfg->cbb, ins);
2249 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, FALSE);
2252 MONO_INST_NEW (cfg, ins, OP_FMOVE);
2253 ins->dreg = mono_alloc_freg (cfg);
2254 ins->sreg1 = tree->dreg;
2255 MONO_ADD_INS (cfg->cbb, ins);
2256 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2259 MONO_INST_NEW (cfg, ins, OP_S390_SETF4RET);
2260 ins->dreg = mono_alloc_freg (cfg);
2261 ins->sreg1 = tree->dreg;
2262 MONO_ADD_INS (cfg->cbb, ins);
2263 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2266 g_assert_not_reached ();
2270 /*========================= End of Function ========================*/
2272 /*------------------------------------------------------------------*/
2274 /* Name - emit_sig_cookie. */
2276 /*------------------------------------------------------------------*/
2279 emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo)
2281 MonoMethodSignature *tmpSig;
2284 cfg->disable_aot = TRUE;
2286 /*----------------------------------------------------------*/
2287 /* mono_ArgIterator_Setup assumes the signature cookie is */
2288 /* passed first and all the arguments which were before it */
2289 /* passed on the stack after the signature. So compensate */
2290 /* by passing a different signature. */
2291 /*----------------------------------------------------------*/
2292 tmpSig = mono_metadata_signature_dup (call->signature);
2293 tmpSig->param_count -= call->signature->sentinelpos;
2294 tmpSig->sentinelpos = 0;
2295 if (tmpSig->param_count > 0)
2296 memcpy (tmpSig->params,
2297 call->signature->params + call->signature->sentinelpos,
2298 tmpSig->param_count * sizeof(MonoType *));
2300 MONO_INST_NEW (cfg, sig_arg, OP_ICONST);
2301 sig_arg->dreg = mono_alloc_ireg (cfg);
2302 sig_arg->inst_p0 = tmpSig;
2303 MONO_ADD_INS (cfg->cbb, sig_arg);
2305 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, STK_BASE,
2306 cinfo->sigCookie.offset, sig_arg->dreg);
2309 /*========================= End of Function ========================*/
2311 /*------------------------------------------------------------------*/
2313 /* Name - mono_arch_emit_call */
2315 /*------------------------------------------------------------------*/
2318 mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
2321 MonoMethodSignature *sig;
2323 int i, n, lParamArea;
2325 ArgInfo *ainfo = NULL;
2327 MonoMethodHeader *header;
2330 sig = call->signature;
2331 n = sig->param_count + sig->hasthis;
2332 DEBUG (g_print ("Call requires: %d parameters\n",n));
2334 cinfo = get_call_info (cfg, cfg->mempool, sig);
2336 stackSize = cinfo->sz.stack_size + cinfo->sz.local_size +
2337 cinfo->sz.parm_size + cinfo->sz.offset;
2338 call->stack_usage = MAX(stackSize, call->stack_usage);
2339 lParamArea = MAX((call->stack_usage-S390_MINIMAL_STACK_SIZE-cinfo->sz.parm_size), 0);
2340 cfg->param_area = MAX(((signed) cfg->param_area), lParamArea);
2341 cfg->flags |= MONO_CFG_HAS_CALLS;
2343 if (cinfo->struct_ret) {
2344 MONO_INST_NEW (cfg, ins, OP_MOVE);
2345 ins->sreg1 = call->vret_var->dreg;
2346 ins->dreg = mono_alloc_preg (cfg);
2347 MONO_ADD_INS (cfg->cbb, ins);
2348 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, cinfo->ret.reg, FALSE);
2351 header = cfg->header;
2352 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2357 for (i = 0; i < n; ++i) {
2360 ainfo = cinfo->args + i;
2361 if (i >= sig->hasthis)
2362 t = sig->params [i - sig->hasthis];
2364 t = &mono_defaults.int_class->byval_arg;
2365 t = mini_get_underlying_type (t);
2367 in = call->args [i];
2369 if ((sig->call_convention == MONO_CALL_VARARG) &&
2371 (i == sig->sentinelpos)) {
2372 emit_sig_cookie (cfg, call, cinfo);
2375 switch (ainfo->regtype) {
2376 case RegTypeGeneral:
2377 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2380 if (MONO_TYPE_ISSTRUCT (t)) {
2381 /* Valuetype passed in one fp register */
2382 ainfo->regtype = RegTypeStructByValInFP;
2385 if (ainfo->size == 4)
2386 ainfo->regtype = RegTypeFPR4;
2387 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2390 case RegTypeStructByVal:
2391 case RegTypeStructByAddr:
2392 case RegTypeStructByAddrOnStack: {
2396 if (sig->params [i - sig->hasthis]->type == MONO_TYPE_TYPEDBYREF) {
2397 size = sizeof (MonoTypedRef);
2398 align = sizeof (gpointer);
2402 size = mono_type_native_stack_size (&in->klass->byval_arg, &align);
2405 * Other backends use mono_type_stack_size (), but that
2406 * aligns the size to 8, which is larger than the size of
2407 * the source, leading to reads of invalid memory if the
2408 * source is at the end of address space.
2410 size = mono_class_value_size (in->klass, &align);
2413 g_assert (in->klass);
2415 ainfo->offparm += cinfo->sz.offStruct;
2417 MONO_INST_NEW (cfg, ins, OP_OUTARG_VT);
2418 ins->sreg1 = in->dreg;
2419 ins->klass = in->klass;
2420 ins->backend.size = ainfo->size;
2421 ins->inst_p0 = call;
2422 ins->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
2423 memcpy (ins->inst_p1, ainfo, sizeof (ArgInfo));
2425 MONO_ADD_INS (cfg->cbb, ins);
2427 if (ainfo->regtype == RegTypeStructByAddr) {
2429 * We use OP_OUTARG_VT to copy the valuetype to a stack location, then
2430 * use the normal OUTARG opcodes to pass the address of the location to
2433 int treg = mono_alloc_preg (cfg);
2434 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2435 frmReg, ainfo->offparm);
2436 mono_call_inst_add_outarg_reg (cfg, call, treg, ainfo->reg, FALSE);
2437 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
2438 /* The address of the valuetype is passed on the stack */
2439 int treg = mono_alloc_preg (cfg);
2440 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2441 frmReg, ainfo->offparm);
2442 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG,
2443 ainfo->reg, ainfo->offset, treg);
2445 if (cfg->compute_gc_maps) {
2448 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, t);
2454 if (!t->byref && t->type == MONO_TYPE_R4) {
2455 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG,
2456 STK_BASE, ainfo->offset + 4,
2458 } else if (!t->byref && (t->type == MONO_TYPE_R8)) {
2459 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG,
2460 STK_BASE, ainfo->offset,
2463 MONO_INST_NEW (cfg, ins, OP_STORE_MEMBASE_REG);
2464 ins->inst_destbasereg = STK_BASE;
2465 ins->inst_offset = ainfo->offset;
2466 ins->sreg1 = in->dreg;
2469 /* This is needed by MonoTypedRef->value to point to the correct data */
2470 if ((sig->call_convention == MONO_CALL_VARARG) &&
2471 (i >= sig->sentinelpos)) {
2472 switch (ainfo->size) {
2474 ins->opcode = OP_STOREI1_MEMBASE_REG;
2477 ins->opcode = OP_STOREI2_MEMBASE_REG;
2480 ins->opcode = OP_STOREI4_MEMBASE_REG;
2488 MONO_ADD_INS (cfg->cbb, ins);
2492 g_assert_not_reached ();
2498 * Handle the case where there are no implicit arguments
2500 if ((sig->call_convention == MONO_CALL_VARARG) &&
2502 (i == sig->sentinelpos)) {
2503 emit_sig_cookie (cfg, call, cinfo);
2507 /*========================= End of Function ========================*/
2509 /*------------------------------------------------------------------*/
2511 /* Name - mono_arch_emit_outarg_vt */
2513 /*------------------------------------------------------------------*/
2516 mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
2518 MonoCallInst *call = (MonoCallInst*)ins->inst_p0;
2519 ArgInfo *ainfo = (ArgInfo*)ins->inst_p1;
2520 int size = ins->backend.size;
2522 if (ainfo->regtype == RegTypeStructByVal) {
2524 arg->ins.sreg1 = ainfo->reg;
2525 arg->ins.opcode = OP_OUTARG_VT;
2526 arg->size = ainfo->size;
2527 arg->offset = ainfo->offset;
2528 arg->offPrm = ainfo->offparm + cinfo->sz.offStruct;
2530 if (ainfo->reg != STK_BASE) {
2531 MONO_OUTPUT_VTR (cfg, size, ainfo->reg, src->dreg, 0);
2533 MONO_OUTPUT_VTS (cfg, size, ainfo->reg, ainfo->offset,
2536 } else if (ainfo->regtype == RegTypeStructByValInFP) {
2537 int dreg = mono_alloc_freg (cfg);
2539 if (ainfo->size == 4) {
2540 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR4_MEMBASE, dreg, src->dreg, 0);
2541 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, dreg, dreg);
2543 g_assert (ainfo->size == 8);
2545 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR8_MEMBASE, dreg, src->dreg, 0);
2548 mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg, TRUE);
2550 MonoMethodHeader *header;
2553 header = mono_method_get_header (cfg->method);
2554 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2559 MONO_EMIT_NEW_MOVE (cfg, srcReg, ainfo->offparm,
2560 src->dreg, 0, size);
2562 if (cfg->compute_gc_maps) {
2565 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, &ins->klass->byval_arg);
2570 /*========================= End of Function ========================*/
2572 /*------------------------------------------------------------------*/
2574 /* Name - mono_arch_emit_setret */
2576 /*------------------------------------------------------------------*/
2579 mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
2581 MonoType *ret = mini_get_underlying_type (mono_method_signature (method)->ret);
2584 if (ret->type == MONO_TYPE_R4) {
2585 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, s390_f0, val->dreg);
2587 } else if (ret->type == MONO_TYPE_R8) {
2588 MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, s390_f0, val->dreg);
2593 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg);
2596 /*========================= End of Function ========================*/
2598 /*------------------------------------------------------------------*/
2600 /* Name - mono_arch_instrument_mem_needs */
2602 /* Function - Allow tracing to work with this interface (with */
2603 /* an optional argument). */
2605 /*------------------------------------------------------------------*/
2608 mono_arch_instrument_mem_needs (MonoMethod *method, int *stack, int *code)
2610 /* no stack room needed now (may be needed for FASTCALL-trace support) */
2612 /* split prolog-epilog requirements? */
2613 *code = 50; /* max bytes needed: check this number */
2616 /*========================= End of Function ========================*/
2618 /*------------------------------------------------------------------*/
2620 /* Name - mono_arch_instrument_prolog */
2622 /* Function - Create an "instrumented" prolog. */
2624 /*------------------------------------------------------------------*/
2627 mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p,
2628 gboolean enable_arguments)
2635 parmOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2636 if (cfg->method->save_lmf)
2637 parmOffset -= sizeof(MonoLMF);
2638 fpOffset = parmOffset + (5*sizeof(gpointer));
2641 s390_stmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2642 s390_stdy (code, s390_f0, 0, STK_BASE, fpOffset);
2643 s390_stdy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2644 s390_stdy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2645 s390_stdy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2646 S390_SET (code, s390_r1, func);
2647 S390_SET (code, s390_r2, cfg->method);
2648 s390_lay (code, s390_r3, 0, STK_BASE, parmOffset);
2649 s390_lgr (code, s390_r4, STK_BASE);
2650 s390_aghi (code, s390_r4, cfg->stack_usage);
2651 s390_basr (code, s390_r14, s390_r1);
2652 s390_ldy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2653 s390_ldy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2654 s390_ldy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2655 s390_ldy (code, s390_f0, 0, STK_BASE, fpOffset);
2656 s390_lmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2661 /*========================= End of Function ========================*/
2663 /*------------------------------------------------------------------*/
2665 /* Name - mono_arch_instrument_epilog */
2667 /* Function - Create an epilog that will handle the returned */
2668 /* values used in instrumentation. */
2670 /*------------------------------------------------------------------*/
2673 mono_arch_instrument_epilog_full (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments, gboolean preserve_argument_registers)
2676 int save_mode = SAVE_NONE,
2679 MonoMethod *method = cfg->method;
2680 int rtype = mini_get_underlying_type (mono_method_signature (method)->ret)->type;
2682 offset = code - cfg->native_code;
2683 /*-----------------------------------------*/
2684 /* We need about 128 bytes of instructions */
2685 /*-----------------------------------------*/
2686 if (offset > (cfg->code_size - 128)) {
2687 cfg->code_size *= 2;
2688 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
2689 code = cfg->native_code + offset;
2692 saveOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2693 if (method->save_lmf)
2694 saveOffset -= sizeof(MonoLMF);
2698 case MONO_TYPE_VOID:
2699 /* special case string .ctor icall */
2700 if (strcmp (".ctor", method->name) && method->klass == mono_defaults.string_class)
2701 save_mode = SAVE_ONE;
2703 save_mode = SAVE_NONE;
2707 save_mode = SAVE_ONE;
2710 save_mode = SAVE_R4;
2713 save_mode = SAVE_R8;
2715 case MONO_TYPE_VALUETYPE:
2716 if (mono_method_signature (method)->ret->data.klass->enumtype) {
2717 rtype = mono_class_enum_basetype (mono_method_signature (method)->ret->data.klass)->type;
2720 save_mode = SAVE_STRUCT;
2723 save_mode = SAVE_ONE;
2727 switch (save_mode) {
2729 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2730 if (enable_arguments) {
2731 s390_lgr (code, s390_r3, s390_r2);
2735 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2736 if (enable_arguments) {
2737 s390_ldebr (code, s390_f0, s390_f0);
2741 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2744 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2745 if (enable_arguments) {
2746 s390_lg (code, s390_r3, 0, cfg->frame_reg,
2747 S390_MINIMAL_STACK_SIZE+cfg->param_area);
2755 S390_SET (code, s390_r1, func);
2756 S390_SET (code, s390_r2, cfg->method);
2757 s390_basr (code, s390_r14, s390_r1);
2759 switch (save_mode) {
2761 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2765 s390_ld (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2768 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2778 /*========================= End of Function ========================*/
2780 /*------------------------------------------------------------------*/
2782 /* Name - mono_arch_peephole_pass_1 */
2784 /* Function - Form a peephole pass at the code looking for */
2785 /* simple optimizations. */
2787 /*------------------------------------------------------------------*/
2790 mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
2794 /*========================= End of Function ========================*/
2796 /*------------------------------------------------------------------*/
2798 /* Name - mono_arch_peephole_pass_2 */
2800 /* Function - Form a peephole pass at the code looking for */
2801 /* simple optimizations. */
2803 /*------------------------------------------------------------------*/
2806 mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
2810 MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
2811 mono_peephole_ins (bb, ins);
2815 /*========================= End of Function ========================*/
2817 /*------------------------------------------------------------------*/
2819 /* Name - mono_arch_lowering_pass. */
2821 /*------------------------------------------------------------------*/
2824 mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
2826 MonoInst *ins, *next;
2828 MONO_BB_FOR_EACH_INS_SAFE (bb, next, ins) {
2829 switch (ins->opcode) {
2834 case OP_IDIV_UN_IMM:
2835 case OP_IREM_UN_IMM:
2840 case OP_LOCALLOC_IMM:
2841 mono_decompose_op_imm (cfg, bb, ins);
2844 if (!s390_is_imm16 (ins->inst_imm))
2845 /* This is created by the memcpy code which ignores is_inst_imm */
2846 mono_decompose_op_imm (cfg, bb, ins);
2853 bb->max_vreg = cfg->next_vreg;
2856 /*========================= End of Function ========================*/
2858 /*------------------------------------------------------------------*/
2860 /* Name - emit_float_to_int */
2862 /* Function - Create instructions which will convert a floating */
2863 /* point value to integer. */
2865 /*------------------------------------------------------------------*/
2868 emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size, gboolean is_signed)
2870 /* sreg is a float, dreg is an integer reg. */
2872 s390_cgdbr (code, dreg, 5, sreg);
2875 s390_ltgr (code, dreg, dreg);
2877 s390_oill (code, dreg, 0x80);
2878 s390_lghi (code, s390_r0, 0xff);
2879 s390_ngr (code, dreg, s390_r0);
2882 s390_ltgr (code, dreg, dreg);
2884 s390_oill (code, dreg, 0x8000);
2885 s390_llill(code, s390_r0, 0xffff);
2886 s390_ngr (code, dreg, s390_r0);
2891 S390_SET (code, s390_r13, 0x41e0000000000000llu);
2892 s390_ldgr (code, s390_f14, s390_r13);
2893 s390_ldr (code, s390_f15, sreg);
2894 s390_cdbr (code, s390_f15, s390_f14);
2895 s390_jl (code, 0); CODEPTR (code, o[0]);
2896 S390_SET (code, s390_r13, 0x41f0000000000000llu);
2897 s390_ldgr (code, s390_f14, s390_r13);
2898 s390_sdbr (code, s390_f15, s390_f14);
2899 s390_cfdbr (code, dreg, 7, s390_f15);
2901 PTRSLOT (code, o[0]);
2902 s390_cfdbr (code, dreg, 5, sreg);
2905 s390_lghi (code, s390_r0, 0xff);
2906 s390_ngr (code, dreg, s390_r0);
2909 s390_llill(code, s390_r0, 0xffff);
2910 s390_ngr (code, dreg, s390_r0);
2917 /*========================= End of Function ========================*/
2919 /*------------------------------------------------------------------*/
2921 /* Name - gboolean_is_unsigned. */
2923 /* Function - Return TRUE if next opcode is checking for un- */
2926 /*------------------------------------------------------------------*/
2929 gboolean is_unsigned (MonoInst *next)
2932 (((next->opcode >= OP_IBNE_UN) &&
2933 (next->opcode <= OP_IBLT_UN)) ||
2934 ((next->opcode >= OP_LBNE_UN) &&
2935 (next->opcode <= OP_LBLT_UN)) ||
2936 ((next->opcode >= OP_COND_EXC_NE_UN) &&
2937 (next->opcode <= OP_COND_EXC_LT_UN)) ||
2938 ((next->opcode >= OP_COND_EXC_INE_UN) &&
2939 (next->opcode <= OP_COND_EXC_ILT_UN)) ||
2940 ((next->opcode == OP_CLT_UN) ||
2941 (next->opcode == OP_CGT_UN)) ||
2942 ((next->opcode == OP_ICLT_UN) ||
2943 (next->opcode == OP_ICGT_UN) ||
2944 (next->opcode == OP_LCLT_UN) ||
2945 (next->opcode == OP_LCGT_UN))))
2951 /*========================= End of Function ========================*/
2953 /*------------------------------------------------------------------*/
2955 /* Name - mono_arch_output_basic_block */
2957 /* Function - Perform the "real" work of emitting instructions */
2958 /* that will do the work of in the basic block. */
2960 /*------------------------------------------------------------------*/
2963 mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
2968 guint8 *code = cfg->native_code + cfg->code_len;
2969 guint last_offset = 0;
2972 /* we don't align basic blocks of loops on s390 */
2974 if (cfg->verbose_level > 2)
2975 g_print ("Basic block %d starting at offset 0x%x\n", bb->block_num, bb->native_offset);
2977 if ((cfg->prof_options & MONO_PROFILE_COVERAGE) && cfg->coverage_info) {
2978 MonoProfileCoverageInfo *cov = cfg->coverage_info;
2979 g_assert (!mono_compile_aot);
2980 cov->data [bb->dfn].cil_code = bb->cil_code;
2981 /* This is not thread save, but good enough */
2982 S390_SET (code, s390_r1, &cov->data [bb->dfn].count);
2983 s390_alsi (code, 0, s390_r1, 1);
2986 MONO_BB_FOR_EACH_INS (bb, ins) {
2987 offset = code - cfg->native_code;
2989 max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
2991 if (offset > (cfg->code_size - max_len - 16)) {
2992 cfg->code_size *= 2;
2993 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
2994 code = cfg->native_code + offset;
2997 mono_debug_record_line_number (cfg, ins, offset);
2999 switch (ins->opcode) {
3000 case OP_STOREI1_MEMBASE_IMM: {
3001 s390_lghi (code, s390_r0, ins->inst_imm);
3002 S390_LONG (code, stcy, stc, s390_r0, 0,
3003 ins->inst_destbasereg, ins->inst_offset);
3006 case OP_STOREI2_MEMBASE_IMM: {
3007 s390_lghi (code, s390_r0, ins->inst_imm);
3008 S390_LONG (code, sthy, sth, s390_r0, 0,
3009 ins->inst_destbasereg, ins->inst_offset);
3012 case OP_STOREI4_MEMBASE_IMM: {
3013 s390_lgfi (code, s390_r0, ins->inst_imm);
3014 S390_LONG (code, sty, st, s390_r0, 0,
3015 ins->inst_destbasereg, ins->inst_offset);
3018 case OP_STORE_MEMBASE_IMM:
3019 case OP_STOREI8_MEMBASE_IMM: {
3020 S390_SET (code, s390_r0, ins->inst_imm);
3021 S390_LONG (code, stg, stg, s390_r0, 0,
3022 ins->inst_destbasereg, ins->inst_offset);
3025 case OP_STOREI1_MEMBASE_REG: {
3026 S390_LONG (code, stcy, stc, ins->sreg1, 0,
3027 ins->inst_destbasereg, ins->inst_offset);
3030 case OP_STOREI2_MEMBASE_REG: {
3031 S390_LONG (code, sthy, sth, ins->sreg1, 0,
3032 ins->inst_destbasereg, ins->inst_offset);
3035 case OP_STOREI4_MEMBASE_REG: {
3036 S390_LONG (code, sty, st, ins->sreg1, 0,
3037 ins->inst_destbasereg, ins->inst_offset);
3040 case OP_STORE_MEMBASE_REG:
3041 case OP_STOREI8_MEMBASE_REG: {
3042 S390_LONG (code, stg, stg, ins->sreg1, 0,
3043 ins->inst_destbasereg, ins->inst_offset);
3047 g_assert_not_reached ();
3049 case OP_LOAD_MEMBASE:
3050 case OP_LOADI8_MEMBASE: {
3051 S390_LONG (code, lg, lg, ins->dreg, 0,
3052 ins->inst_basereg, ins->inst_offset);
3055 case OP_LOADI4_MEMBASE: {
3056 S390_LONG (code, lgf, lgf, ins->dreg, 0,
3057 ins->inst_basereg, ins->inst_offset);
3060 case OP_LOADU4_MEMBASE: {
3061 S390_LONG (code, llgf, llgf, ins->dreg, 0,
3062 ins->inst_basereg, ins->inst_offset);
3065 case OP_LOADU1_MEMBASE: {
3066 S390_LONG (code, llgc, llgc, ins->dreg, 0,
3067 ins->inst_basereg, ins->inst_offset);
3070 case OP_LOADI1_MEMBASE: {
3071 S390_LONG (code, lgb, lgb, ins->dreg, 0,
3072 ins->inst_basereg, ins->inst_offset);
3075 case OP_LOADU2_MEMBASE: {
3076 S390_LONG (code, llgh, llgh, ins->dreg, 0,
3077 ins->inst_basereg, ins->inst_offset);
3080 case OP_LOADI2_MEMBASE: {
3081 S390_LONG (code, lgh, lgh, ins->dreg, 0,
3082 ins->inst_basereg, ins->inst_offset);
3085 case OP_LCONV_TO_I1: {
3086 s390_lgbr (code, ins->dreg, ins->sreg1);
3089 case OP_LCONV_TO_I2: {
3090 s390_lghr (code, ins->dreg, ins->sreg1);
3093 case OP_LCONV_TO_U1: {
3094 s390_llgcr (code, ins->dreg, ins->sreg1);
3097 case OP_LCONV_TO_U2: {
3098 s390_llghr (code, ins->dreg, ins->sreg1);
3101 case OP_ICONV_TO_I1: {
3102 s390_lgbr (code, ins->dreg, ins->sreg1);
3105 case OP_ICONV_TO_I2: {
3106 s390_lghr (code, ins->dreg, ins->sreg1);
3109 case OP_ICONV_TO_U1: {
3110 s390_llgcr (code, ins->dreg, ins->sreg1);
3113 case OP_ICONV_TO_U2: {
3114 s390_llghr (code, ins->dreg, ins->sreg1);
3119 if (is_unsigned (ins->next))
3120 s390_clgr (code, ins->sreg1, ins->sreg2);
3122 s390_cgr (code, ins->sreg1, ins->sreg2);
3126 if (is_unsigned (ins->next))
3127 s390_clr (code, ins->sreg1, ins->sreg2);
3129 s390_cr (code, ins->sreg1, ins->sreg2);
3132 case OP_COMPARE_IMM:
3133 case OP_LCOMPARE_IMM: {
3134 S390_SET (code, s390_r0, ins->inst_imm);
3135 if (is_unsigned (ins->next))
3136 s390_clgr (code, ins->sreg1, s390_r0);
3138 s390_cgr (code, ins->sreg1, s390_r0);
3141 case OP_ICOMPARE_IMM: {
3142 S390_SET (code, s390_r0, ins->inst_imm);
3143 if (is_unsigned (ins->next))
3144 s390_clr (code, ins->sreg1, s390_r0);
3146 s390_cr (code, ins->sreg1, s390_r0);
3150 mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_ABS,
3152 S390_CALL_TEMPLATE (code, s390_r14);
3157 s390_agr (code, ins->dreg, src2);
3162 s390_agr (code, ins->dreg, src2);
3167 s390_alcgr (code, ins->dreg, src2);
3171 if (ins->dreg != ins->sreg1) {
3172 s390_lgr (code, ins->dreg, ins->sreg1);
3174 if (s390_is_imm16 (ins->inst_imm)) {
3175 s390_aghi (code, ins->dreg, ins->inst_imm);
3176 } else if (s390_is_imm32 (ins->inst_imm)) {
3177 s390_agfi (code, ins->dreg, ins->inst_imm);
3179 S390_SET (code, s390_r0, ins->inst_imm);
3180 s390_agr (code, ins->dreg, s390_r0);
3185 if (ins->dreg != ins->sreg1) {
3186 s390_lgr (code, ins->dreg, ins->sreg1);
3188 g_assert (s390_is_imm16 (ins->inst_imm));
3189 s390_aghi (code, ins->dreg, ins->inst_imm);
3193 if (ins->dreg != ins->sreg1) {
3194 s390_lgr (code, ins->dreg, ins->sreg1);
3196 if (s390_is_imm16 (ins->inst_imm)) {
3197 s390_lghi (code, s390_r0, ins->inst_imm);
3198 s390_alcgr (code, ins->dreg, s390_r0);
3200 S390_SET (code, s390_r0, ins->inst_imm);
3201 s390_alcgr (code, ins->dreg, s390_r0);
3206 case OP_S390_IADD_OVF: {
3208 s390_ar (code, ins->dreg, src2);
3209 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3210 s390_lgfr (code, ins->dreg, ins->dreg);
3213 case OP_IADD_OVF_UN:
3214 case OP_S390_IADD_OVF_UN: {
3216 s390_algr (code, ins->dreg, src2);
3217 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3218 s390_llgfr (code, ins->dreg, ins->dreg);
3221 case OP_ADD_OVF_CARRY: {
3223 s390_lghi (code, s390_r0, 0);
3224 s390_lgr (code, s390_r1, s390_r0);
3225 s390_alcgr (code, s390_r0, s390_r1);
3226 s390_agr (code, ins->dreg, src2);
3227 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3228 s390_agr (code, ins->dreg, s390_r0);
3229 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3232 case OP_ADD_OVF_UN_CARRY: {
3234 s390_alcgr (code, ins->dreg, src2);
3235 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3240 s390_sgr (code, ins->dreg, src2);
3245 s390_sgr (code, ins->dreg, src2);
3250 s390_slbgr(code, ins->dreg, src2);
3254 if (ins->dreg != ins->sreg1) {
3255 s390_lgr (code, ins->dreg, ins->sreg1);
3257 if (s390_is_imm16 (-ins->inst_imm)) {
3258 s390_aghi (code, ins->dreg, -ins->inst_imm);
3259 } else if (s390_is_imm32 (-ins->inst_imm)) {
3260 s390_slgfi (code, ins->dreg, ins->inst_imm);
3262 S390_SET (code, s390_r0, ins->inst_imm);
3263 s390_slgr (code, ins->dreg, s390_r0);
3268 if (ins->dreg != ins->sreg1) {
3269 s390_lgr (code, ins->dreg, ins->sreg1);
3271 if (s390_is_imm16 (-ins->inst_imm)) {
3272 s390_aghi (code, ins->dreg, -ins->inst_imm);
3273 } else if (s390_is_imm32 (-ins->inst_imm)) {
3274 s390_slgfi (code, ins->dreg, ins->inst_imm);
3276 S390_SET (code, s390_r0, ins->inst_imm);
3277 s390_slgr (code, ins->dreg, s390_r0);
3282 if (ins->dreg != ins->sreg1) {
3283 s390_lgr (code, ins->dreg, ins->sreg1);
3285 if (s390_is_imm16 (-ins->inst_imm)) {
3286 s390_lghi (code, s390_r0, ins->inst_imm);
3287 s390_slbgr (code, ins->dreg, s390_r0);
3289 S390_SET (code, s390_r0, ins->inst_imm);
3290 s390_slbgr(code, ins->dreg, s390_r0);
3294 case OP_SUB_OVF_CARRY: {
3296 s390_lghi (code, s390_r0, 0);
3297 s390_lgr (code, s390_r1, s390_r0);
3298 s390_slbgr (code, s390_r0, s390_r1);
3299 s390_sgr (code, ins->dreg, src2);
3300 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3301 s390_agr (code, ins->dreg, s390_r0);
3302 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3305 case OP_SUB_OVF_UN_CARRY: {
3307 s390_slbgr (code, ins->dreg, src2);
3308 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3312 if (ins->sreg1 == ins->dreg) {
3313 s390_ngr (code, ins->dreg, ins->sreg2);
3316 if (ins->sreg2 == ins->dreg) {
3317 s390_ngr (code, ins->dreg, ins->sreg1);
3320 s390_lgr (code, ins->dreg, ins->sreg1);
3321 s390_ngr (code, ins->dreg, ins->sreg2);
3327 if (ins->dreg != ins->sreg1) {
3328 s390_lgr (code, ins->dreg, ins->sreg1);
3330 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3331 s390_ngr (code, ins->dreg, s390_r0);
3335 s390_lgr (code, s390_r1, ins->sreg1);
3336 s390_dsgr (code, s390_r0, ins->sreg2);
3337 s390_lgr (code, ins->dreg, s390_r1);
3341 s390_lgr (code, s390_r1, ins->sreg1);
3342 s390_lghi (code, s390_r0, 0);
3343 s390_dlgr (code, s390_r0, ins->sreg2);
3344 s390_lgr (code, ins->dreg, s390_r1);
3348 s390_lgr (code, s390_r1, ins->sreg1);
3349 s390_dsgr (code, s390_r0, ins->sreg2);
3350 s390_lgr (code, ins->dreg, s390_r0);
3354 if (s390_is_imm16 (ins->inst_imm)) {
3355 s390_lghi (code, s390_r13, ins->inst_imm);
3357 s390_lgfi (code, s390_r13, ins->inst_imm);
3359 s390_lgr (code, s390_r0, ins->sreg1);
3360 s390_dsgr (code, s390_r0, s390_r13);
3361 s390_lgfr (code, ins->dreg, s390_r0);
3365 s390_lgr (code, s390_r1, ins->sreg1);
3366 s390_lghi (code, s390_r0, 0);
3367 s390_dlgr (code, s390_r0, ins->sreg2);
3368 s390_lgr (code, ins->dreg, s390_r0);
3372 if (ins->sreg1 == ins->dreg) {
3373 s390_ogr (code, ins->dreg, ins->sreg2);
3376 if (ins->sreg2 == ins->dreg) {
3377 s390_ogr (code, ins->dreg, ins->sreg1);
3380 s390_lgr (code, ins->dreg, ins->sreg1);
3381 s390_ogr (code, ins->dreg, ins->sreg2);
3387 if (ins->dreg != ins->sreg1) {
3388 s390_lgr (code, ins->dreg, ins->sreg1);
3390 S390_SET_MASK(code, s390_r0, ins->inst_imm);
3391 s390_ogr (code, ins->dreg, s390_r0);
3395 if (ins->sreg1 == ins->dreg) {
3396 s390_xgr (code, ins->dreg, ins->sreg2);
3399 if (ins->sreg2 == ins->dreg) {
3400 s390_xgr (code, ins->dreg, ins->sreg1);
3403 s390_lgr (code, ins->dreg, ins->sreg1);
3404 s390_xgr (code, ins->dreg, ins->sreg2);
3410 if (ins->dreg != ins->sreg1) {
3411 s390_lgr (code, ins->dreg, ins->sreg1);
3413 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3414 s390_xgr (code, ins->dreg, s390_r0);
3419 s390_sllg (code, ins->dreg, ins->dreg, src2, 0);
3424 if (ins->sreg1 != ins->dreg) {
3425 s390_lgr (code, ins->dreg, ins->sreg1);
3427 s390_sllg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3432 s390_srag (code, ins->dreg, ins->dreg, src2, 0);
3437 if (ins->sreg1 != ins->dreg) {
3438 s390_lgr (code, ins->dreg, ins->sreg1);
3440 s390_srag (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3444 case OP_LSHR_UN_IMM: {
3445 if (ins->sreg1 != ins->dreg) {
3446 s390_lgr (code, ins->dreg, ins->sreg1);
3448 s390_srlg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3453 s390_srlg (code, ins->dreg, ins->dreg, src2, 0);
3457 if (ins->sreg1 != ins->dreg) {
3458 s390_lgr (code, ins->dreg, ins->sreg1);
3460 s390_lghi (code, s390_r0, -1);
3461 s390_xgr (code, ins->dreg, s390_r0);
3465 s390_lcgr (code, ins->dreg, ins->sreg1);
3470 s390_msgr (code, ins->dreg, src2);
3475 if (ins->dreg != ins->sreg1) {
3476 s390_lgr (code, ins->dreg, ins->sreg1);
3478 if (s390_is_imm16 (ins->inst_imm)) {
3479 s390_lghi (code, s390_r13, ins->inst_imm);
3480 } else if (s390_is_imm32 (ins->inst_imm)) {
3481 s390_lgfi (code, s390_r13, ins->inst_imm);
3483 S390_SET (code, s390_r13, ins->inst_imm);
3485 s390_msgr (code, ins->dreg, s390_r13);
3490 s390_ltgr (code, s390_r1, ins->sreg1);
3491 s390_jz (code, 0); CODEPTR(code, o[0]);
3492 s390_ltgr (code, s390_r0, ins->sreg2);
3494 s390_lghi (code, s390_r1, 0);
3495 s390_j (code, 0); CODEPTR(code, o[1]);
3496 s390_xgr (code, s390_r0, s390_r1);
3497 s390_msgr (code, s390_r1, ins->sreg2);
3498 s390_xgr (code, s390_r0, s390_r1);
3499 s390_srlg (code, s390_r0, s390_r0, 0, 63);
3500 s390_ltgr (code, s390_r0, s390_r0);
3501 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3502 PTRSLOT (code, o[0]);
3503 PTRSLOT (code, o[1]);
3504 s390_lgr (code, ins->dreg, s390_r1);
3507 case OP_LMUL_OVF_UN: {
3508 s390_lghi (code, s390_r0, 0);
3509 s390_lgr (code, s390_r1, ins->sreg1);
3510 s390_mlgr (code, s390_r0, ins->sreg2);
3511 s390_ltgr (code, s390_r0, s390_r0);
3512 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3513 s390_lgr (code, ins->dreg, s390_r1);
3517 g_assert_not_reached ();
3519 s390_algr (code, ins->dreg, src2);
3524 s390_agr (code, ins->dreg, src2);
3528 g_assert_not_reached ();
3530 s390_alcgr (code, ins->dreg, src2);
3534 if (ins->dreg != ins->sreg1) {
3535 s390_lgfr (code, ins->dreg, ins->sreg1);
3537 if (s390_is_imm16 (ins->inst_imm)) {
3538 s390_aghi (code, ins->dreg, ins->inst_imm);
3540 s390_afi (code, ins->dreg, ins->inst_imm);
3545 if (ins->dreg != ins->sreg1) {
3546 s390_lgfr (code, ins->dreg, ins->sreg1);
3548 if (s390_is_imm16 (ins->inst_imm)) {
3549 s390_lghi (code, s390_r0, ins->inst_imm);
3550 s390_alcgr (code, ins->dreg, s390_r0);
3552 S390_SET (code, s390_r0, ins->inst_imm);
3553 s390_alcgr (code, ins->dreg, s390_r0);
3558 case OP_S390_LADD_OVF: {
3560 s390_agr (code, ins->dreg, src2);
3561 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3564 case OP_LADD_OVF_UN:
3565 case OP_S390_LADD_OVF_UN: {
3567 s390_algr (code, ins->dreg, src2);
3568 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3572 CHECK_SRCDST_NCOM_I;
3573 s390_slgr (code, ins->dreg, src2);
3577 CHECK_SRCDST_NCOM_I;
3578 s390_sgr (code, ins->dreg, src2);
3582 CHECK_SRCDST_NCOM_I;
3583 s390_slbgr (code, ins->dreg, src2);
3587 if (ins->dreg != ins->sreg1) {
3588 s390_lgfr (code, ins->dreg, ins->sreg1);
3590 if (s390_is_imm16 (-ins->inst_imm)) {
3591 s390_aghi (code, ins->dreg, -ins->inst_imm);
3593 s390_agfi (code, ins->dreg, -ins->inst_imm);
3598 S390_SET (code, s390_r0, ins->inst_imm);
3599 s390_slgfr (code, ins->dreg, s390_r0);
3603 case OP_S390_ISUB_OVF: {
3605 s390_sr (code, ins->dreg, src2);
3606 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3607 s390_lgfr (code, ins->dreg, ins->dreg);
3610 case OP_ISUB_OVF_UN:
3611 case OP_S390_ISUB_OVF_UN: {
3613 s390_slr (code, ins->dreg, src2);
3614 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3615 s390_llgfr(code, ins->dreg, ins->dreg);
3619 case OP_S390_LSUB_OVF: {
3621 s390_sgr (code, ins->dreg, src2);
3622 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3625 case OP_LSUB_OVF_UN:
3626 case OP_S390_LSUB_OVF_UN: {
3628 s390_slgr (code, ins->dreg, src2);
3629 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3633 CHECK_SRCDST_NCOM_I;
3634 s390_ngr (code, ins->dreg, src2);
3638 if (ins->dreg != ins->sreg1) {
3639 s390_lgfr (code, ins->dreg, ins->sreg1);
3641 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3642 s390_ngr (code, ins->dreg, s390_r0);
3646 s390_lgfr (code, s390_r0, ins->sreg1);
3647 s390_srda (code, s390_r0, 0, 32);
3648 s390_dr (code, s390_r0, ins->sreg2);
3649 s390_lgfr (code, ins->dreg, s390_r1);
3653 s390_lgfr (code, s390_r0, ins->sreg1);
3654 s390_srdl (code, s390_r0, 0, 32);
3655 s390_dlr (code, s390_r0, ins->sreg2);
3656 s390_lgfr (code, ins->dreg, s390_r1);
3660 if (s390_is_imm16 (ins->inst_imm)) {
3661 s390_lghi (code, s390_r13, ins->inst_imm);
3663 s390_lgfi (code, s390_r13, ins->inst_imm);
3665 s390_lgfr (code, s390_r0, ins->sreg1);
3666 s390_srda (code, s390_r0, 0, 32);
3667 s390_dr (code, s390_r0, ins->sreg2);
3668 s390_lgfr (code, ins->dreg, s390_r1);
3672 s390_lgfr (code, s390_r0, ins->sreg1);
3673 s390_srda (code, s390_r0, 0, 32);
3674 s390_dr (code, s390_r0, ins->sreg2);
3675 s390_lgfr (code, ins->dreg, s390_r0);
3678 s390_lgfr (code, s390_r0, ins->sreg1);
3679 s390_srdl (code, s390_r0, 0, 32);
3680 s390_dlr (code, s390_r0, ins->sreg2);
3681 s390_lgfr (code, ins->dreg, s390_r0);
3685 if (s390_is_imm16 (ins->inst_imm)) {
3686 s390_lghi (code, s390_r13, ins->inst_imm);
3688 s390_lgfi (code, s390_r13, ins->inst_imm);
3690 s390_lgfr (code, s390_r0, ins->sreg1);
3691 s390_srda (code, s390_r0, 0, 32);
3692 s390_dr (code, s390_r0, ins->sreg2);
3693 s390_lgfr (code, ins->dreg, s390_r0);
3698 s390_ogr (code, ins->dreg, src2);
3702 if (ins->dreg != ins->sreg1) {
3703 s390_lgfr (code, ins->dreg, ins->sreg1);
3705 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3706 s390_ogr (code, ins->dreg, s390_r0);
3711 s390_xgr (code, ins->dreg, src2);
3715 if (ins->dreg != ins->sreg1) {
3716 s390_lgfr (code, ins->dreg, ins->sreg1);
3718 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3719 s390_xgr (code, ins->dreg, s390_r0);
3724 s390_sll (code, ins->dreg, src2, 0);
3728 if (ins->sreg1 != ins->dreg) {
3729 s390_lgfr (code, ins->dreg, ins->sreg1);
3731 s390_sll (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3736 s390_sra (code, ins->dreg, src2, 0);
3740 if (ins->sreg1 != ins->dreg) {
3741 s390_lgfr (code, ins->dreg, ins->sreg1);
3743 s390_sra (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3746 case OP_ISHR_UN_IMM: {
3747 if (ins->sreg1 != ins->dreg) {
3748 s390_lgfr (code, ins->dreg, ins->sreg1);
3750 s390_srl (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3755 s390_srl (code, ins->dreg, src2, 0);
3759 if (ins->sreg1 != ins->dreg) {
3760 s390_lgfr (code, ins->dreg, ins->sreg1);
3762 s390_lghi (code, s390_r0, -1);
3763 s390_xgr (code, ins->dreg, s390_r0);
3767 s390_lcgr (code, ins->dreg, ins->sreg1);
3772 s390_msr (code, ins->dreg, src2);
3776 if (ins->dreg != ins->sreg1) {
3777 s390_lgfr (code, ins->dreg, ins->sreg1);
3779 if (s390_is_imm16 (ins->inst_imm)) {
3780 s390_lghi (code, s390_r0, ins->inst_imm);
3782 s390_lgfi (code, s390_r0, ins->inst_imm);
3784 s390_msr (code, ins->dreg, s390_r0);
3789 s390_ltr (code, s390_r1, ins->sreg1);
3790 s390_jz (code, 0); CODEPTR(code, o[0]);
3791 s390_ltr (code, s390_r0, ins->sreg2);
3793 s390_lhi (code, s390_r1, 0);
3794 s390_j (code, 0); CODEPTR(code, o[1]);
3795 s390_xr (code, s390_r0, s390_r1);
3796 s390_msr (code, s390_r1, ins->sreg2);
3797 s390_xr (code, s390_r0, s390_r1);
3798 s390_srl (code, s390_r0, 0, 31);
3799 s390_ltr (code, s390_r0, s390_r0);
3800 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3801 PTRSLOT (code, o[0]);
3802 PTRSLOT (code, o[1]);
3803 s390_lgfr (code, ins->dreg, s390_r1);
3806 case OP_IMUL_OVF_UN: {
3807 s390_lhi (code, s390_r0, 0);
3808 s390_lr (code, s390_r1, ins->sreg1);
3809 s390_mlr (code, s390_r0, ins->sreg2);
3810 s390_ltr (code, s390_r0, s390_r0);
3811 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3812 s390_lgfr (code, ins->dreg, s390_r1);
3817 S390_SET (code, ins->dreg, ins->inst_c0);
3821 mono_add_patch_info (cfg, code - cfg->native_code,
3822 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3823 S390_LOAD_TEMPLATE (code, ins->dreg);
3826 case OP_JUMP_TABLE: {
3827 mono_add_patch_info (cfg, code - cfg->native_code,
3828 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3829 S390_LOAD_TEMPLATE (code, ins->dreg);
3833 if (ins->dreg != ins->sreg1) {
3834 s390_lgr (code, ins->dreg, ins->sreg1);
3838 case OP_LCONV_TO_I8:
3840 s390_lgfr (code, ins->dreg, ins->sreg1);
3842 case OP_LCONV_TO_I4:
3843 s390_lgfr (code, ins->dreg, ins->sreg1);
3846 case OP_LCONV_TO_U8:
3847 case OP_LCONV_TO_U4:
3849 s390_llgfr (code, ins->dreg, ins->sreg1);
3851 case OP_LCONV_TO_OVF_U4:
3852 S390_SET (code, s390_r0, 4294967295);
3853 s390_clgr (code, ins->sreg1, s390_r0);
3854 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3855 s390_ltgr (code, ins->sreg1, ins->sreg1);
3856 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3857 s390_llgfr(code, ins->dreg, ins->sreg1);
3859 case OP_LCONV_TO_OVF_I4_UN:
3860 S390_SET (code, s390_r0, 2147483647);
3861 s390_cgr (code, ins->sreg1, s390_r0);
3862 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3863 s390_ltgr (code, ins->sreg1, ins->sreg1);
3864 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3865 s390_lgfr (code, ins->dreg, ins->sreg1);
3868 if (ins->dreg != ins->sreg1) {
3869 s390_ldr (code, ins->dreg, ins->sreg1);
3872 case OP_MOVE_F_TO_I8:
3873 s390_lgdr (code, ins->dreg, ins->sreg1);
3875 case OP_MOVE_I8_TO_F:
3876 s390_ldgr (code, ins->dreg, ins->sreg1);
3878 case OP_MOVE_F_TO_I4:
3879 s390_ledbr (code, s390_f0, ins->sreg1);
3880 s390_lgdr (code, ins->dreg, s390_f0);
3881 s390_srag (code, ins->dreg, ins->dreg, 0, 32);
3883 case OP_MOVE_I4_TO_F:
3884 s390_slag (code, s390_r0, ins->sreg1, 0, 32);
3885 s390_ldgr (code, ins->dreg, s390_r0);
3886 s390_ldebr (code, ins->dreg, ins->dreg);
3888 case OP_FCONV_TO_R4:
3889 s390_ledbr (code, ins->dreg, ins->sreg1);
3890 s390_ldebr (code, ins->dreg, ins->dreg);
3892 case OP_S390_SETF4RET:
3893 s390_ledbr (code, ins->dreg, ins->sreg1);
3896 if (s390_is_imm16 (ins->inst_offset)) {
3897 s390_lghi (code, s390_r13, ins->inst_offset);
3898 } else if (s390_is_imm32 (ins->inst_offset)) {
3899 s390_lgfi (code, s390_r13, ins->inst_offset);
3901 S390_SET (code, s390_r13, ins->inst_offset);
3903 s390_ear (code, s390_r1, 0);
3904 s390_sllg(code, s390_r1, s390_r1, 0, 32);
3905 s390_ear (code, s390_r1, 1);
3906 s390_lg (code, ins->dreg, s390_r13, s390_r1, 0);
3910 if (cfg->method->save_lmf)
3911 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
3913 if (cfg->flags & MONO_CFG_HAS_TAIL) {
3914 code = emit_load_volatile_arguments (code, cfg);
3917 code = backUpStackPtr(cfg, code);
3918 s390_lg (code, s390_r14, 0, cfg->frame_reg, S390_RET_ADDR_OFFSET);
3919 mono_add_patch_info (cfg, code - cfg->native_code,
3920 MONO_PATCH_INFO_METHOD_JUMP,
3922 s390_jcl (code, S390_CC_UN, 0);
3925 case OP_CHECK_THIS: {
3926 /* ensure ins->sreg1 is not NULL */
3927 s390_lg (code, s390_r0, 0, ins->sreg1, 0);
3928 s390_ltgr (code, s390_r0, s390_r0);
3929 // EMIT_COND_SYSTEM_EXCEPTION (S390_CC_ZR, "NullReferenceException");
3933 int offset = cfg->sig_cookie + cfg->stack_usage;
3935 if (s390_is_imm16 (offset)) {
3936 s390_lghi (code, s390_r0, offset);
3937 } else if (s390_is_imm32 (offset)) {
3938 s390_lgfi (code, s390_r0, offset);
3940 S390_SET (code, s390_r0, offset);
3942 s390_agr (code, s390_r0, cfg->frame_reg);
3943 s390_stg (code, s390_r0, 0, ins->sreg1, 0);
3947 call = (MonoCallInst*)ins;
3948 if (ins->flags & MONO_INST_HAS_METHOD)
3949 mono_add_patch_info (cfg, code-cfg->native_code,
3950 MONO_PATCH_INFO_METHOD,
3953 mono_add_patch_info (cfg, code-cfg->native_code,
3954 MONO_PATCH_INFO_ABS,
3956 S390_CALL_TEMPLATE (code, s390_r14);
3957 if (call->signature->ret->type == MONO_TYPE_R4)
3958 s390_ldebr (code, s390_f0, s390_f0);
3966 call = (MonoCallInst*)ins;
3967 if (ins->flags & MONO_INST_HAS_METHOD)
3968 mono_add_patch_info (cfg, code-cfg->native_code,
3969 MONO_PATCH_INFO_METHOD,
3972 mono_add_patch_info (cfg, code-cfg->native_code,
3973 MONO_PATCH_INFO_ABS,
3975 S390_CALL_TEMPLATE (code, s390_r14);
3978 case OP_FCALL_REG: {
3979 call = (MonoCallInst*)ins;
3980 s390_lgr (code, s390_r1, ins->sreg1);
3981 s390_basr (code, s390_r14, s390_r1);
3982 if (call->signature->ret->type == MONO_TYPE_R4)
3983 s390_ldebr (code, s390_f0, s390_f0);
3989 case OP_VOIDCALL_REG:
3991 s390_lgr (code, s390_r1, ins->sreg1);
3992 s390_basr (code, s390_r14, s390_r1);
3995 case OP_FCALL_MEMBASE: {
3996 call = (MonoCallInst*)ins;
3997 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
3998 s390_basr (code, s390_r14, s390_r1);
3999 if (call->signature->ret->type == MONO_TYPE_R4)
4000 s390_ldebr (code, s390_f0, s390_f0);
4003 case OP_LCALL_MEMBASE:
4004 case OP_VCALL_MEMBASE:
4005 case OP_VCALL2_MEMBASE:
4006 case OP_VOIDCALL_MEMBASE:
4007 case OP_CALL_MEMBASE: {
4008 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4009 s390_basr (code, s390_r14, s390_r1);
4016 if (cfg->param_area == 0)
4017 alloca_skip = S390_MINIMAL_STACK_SIZE;
4019 alloca_skip = cfg->param_area;
4021 area_offset = S390_ALIGN(alloca_skip, S390_STACK_ALIGNMENT);
4022 s390_lgr (code, s390_r1, ins->sreg1);
4023 if (ins->flags & MONO_INST_INIT)
4024 s390_lgr (code, s390_r0, ins->sreg1);
4025 s390_aghi (code, s390_r1, 14);
4026 s390_srlg (code, s390_r1, s390_r1, 0, 3);
4027 s390_sllg (code, s390_r1, s390_r1, 0, 3);
4028 if (cfg->method->save_lmf) {
4029 /*----------------------------------*/
4030 /* we have to adjust lmf ebp value */
4031 /*----------------------------------*/
4032 int lmfOffset = cfg->stack_usage - sizeof(MonoLMF);
4034 s390_lgr (code, s390_r13, cfg->frame_reg);
4035 if (s390_is_imm16(lmfOffset)) {
4036 s390_aghi (code, s390_r13, lmfOffset);
4037 } else if (s390_is_imm32(lmfOffset)) {
4038 s390_agfi (code, s390_r13, lmfOffset);
4040 S390_SET (code, s390_r13, lmfOffset);
4042 s390_lgr (code, s390_r14, STK_BASE);
4043 s390_sgr (code, s390_r14, s390_r1);
4044 s390_stg (code, s390_r14, 0, s390_r13,
4045 G_STRUCT_OFFSET(MonoLMF, ebp));
4047 s390_lg (code, s390_r13, 0, STK_BASE, 0);
4048 s390_sgr (code, STK_BASE, s390_r1);
4049 s390_stg (code, s390_r13, 0, STK_BASE, 0);
4050 s390_la (code, ins->dreg, 0, STK_BASE, area_offset);
4051 s390_srlg (code, ins->dreg, ins->dreg, 0, 3);
4052 s390_sllg (code, ins->dreg, ins->dreg, 0, 3);
4053 if (ins->flags & MONO_INST_INIT) {
4054 s390_lgr (code, s390_r1, s390_r0);
4055 s390_lgr (code, s390_r0, ins->dreg);
4056 s390_lgr (code, s390_r14, s390_r12);
4057 s390_lghi (code, s390_r13, 0);
4058 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4060 s390_lgr (code, s390_r12, s390_r14);
4065 s390_lgr (code, s390_r2, ins->sreg1);
4066 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4067 (gpointer) "mono_arch_throw_exception");
4068 S390_CALL_TEMPLATE(code, s390_r14);
4072 s390_lgr (code, s390_r2, ins->sreg1);
4073 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4074 (gpointer) "mono_arch_rethrow_exception");
4075 S390_CALL_TEMPLATE(code, s390_r14);
4078 case OP_START_HANDLER: {
4079 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4081 S390_LONG (code, stg, stg, s390_r14, 0,
4082 spvar->inst_basereg,
4083 spvar->inst_offset);
4086 case OP_ENDFILTER: {
4087 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4089 if (ins->sreg1 != s390_r2)
4090 s390_lgr(code, s390_r2, ins->sreg1);
4091 S390_LONG (code, lg, lg, s390_r14, 0,
4092 spvar->inst_basereg,
4093 spvar->inst_offset);
4094 s390_br (code, s390_r14);
4097 case OP_ENDFINALLY: {
4098 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4100 S390_LONG (code, lg, lg, s390_r14, 0,
4101 spvar->inst_basereg,
4102 spvar->inst_offset);
4103 s390_br (code, s390_r14);
4106 case OP_CALL_HANDLER: {
4107 mono_add_patch_info (cfg, code-cfg->native_code,
4108 MONO_PATCH_INFO_BB, ins->inst_target_bb);
4109 s390_brasl (code, s390_r14, 0);
4110 mono_cfg_add_try_hole (cfg, ins->inst_eh_block, code, bb);
4114 ins->inst_c0 = code - cfg->native_code;
4117 case OP_RELAXED_NOP:
4120 case OP_DUMMY_STORE:
4121 case OP_NOT_REACHED:
4125 case OP_IL_SEQ_POINT:
4126 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4128 case OP_SEQ_POINT: {
4131 if (cfg->compile_aot)
4135 * Read from the single stepping trigger page. This will cause a
4136 * SIGSEGV when single stepping is enabled.
4137 * We do this _before_ the breakpoint, so single stepping after
4138 * a breakpoint is hit will step to the next IL offset.
4140 if (ins->flags & MONO_INST_SINGLE_STEP_LOC) {
4141 breakpointCode.pTrigger = ss_trigger_page;
4142 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
4143 code += BREAKPOINT_SIZE;
4146 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4149 * A placeholder for a possible breakpoint inserted by
4150 * mono_arch_set_breakpoint ().
4152 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); ++i)
4156 * Add an additional nop so skipping the bp doesn't cause the ip to point
4157 * to another IL offset.
4163 case OP_GENERIC_CLASS_INIT: {
4164 static int byte_offset = -1;
4165 static guint8 bitmask;
4168 g_assert (ins->sreg1 == S390_FIRST_ARG_REG);
4170 if (byte_offset < 0)
4171 mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);
4173 s390_tm (code, ins->sreg1, byte_offset, bitmask);
4174 s390_jo (code, 0); CODEPTR(code, jump);
4176 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4177 "mono_generic_class_init");
4178 S390_CALL_TEMPLATE(code, s390_r14);
4180 PTRSLOT (code, jump);
4182 ins->flags |= MONO_INST_GC_CALLSITE;
4183 ins->backend.pc_offset = code - cfg->native_code;
4187 EMIT_UNCOND_BRANCH(ins);
4190 s390_br (code, ins->sreg1);
4196 s390_lghi(code, ins->dreg, 1);
4198 s390_lghi(code, ins->dreg, 0);
4204 s390_lghi(code, ins->dreg, 1);
4206 s390_lghi(code, ins->dreg, 0);
4212 s390_lghi(code, ins->dreg, 1);
4214 s390_lghi(code, ins->dreg, 0);
4220 s390_lghi(code, ins->dreg, 1);
4222 s390_lghi(code, ins->dreg, 0);
4228 s390_lghi(code, ins->dreg, 1);
4230 s390_lghi(code, ins->dreg, 0);
4233 case OP_COND_EXC_EQ:
4234 case OP_COND_EXC_IEQ:
4235 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_EQ, ins->inst_p1);
4237 case OP_COND_EXC_NE_UN:
4238 case OP_COND_EXC_INE_UN:
4239 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NE, ins->inst_p1);
4241 case OP_COND_EXC_LT:
4242 case OP_COND_EXC_ILT:
4243 case OP_COND_EXC_LT_UN:
4244 case OP_COND_EXC_ILT_UN:
4245 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, ins->inst_p1);
4247 case OP_COND_EXC_GT:
4248 case OP_COND_EXC_IGT:
4249 case OP_COND_EXC_GT_UN:
4250 case OP_COND_EXC_IGT_UN:
4251 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, ins->inst_p1);
4253 case OP_COND_EXC_GE:
4254 case OP_COND_EXC_IGE:
4255 case OP_COND_EXC_GE_UN:
4256 case OP_COND_EXC_IGE_UN:
4257 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GE, ins->inst_p1);
4259 case OP_COND_EXC_LE:
4260 case OP_COND_EXC_ILE:
4261 case OP_COND_EXC_LE_UN:
4262 case OP_COND_EXC_ILE_UN:
4263 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LE, ins->inst_p1);
4265 case OP_COND_EXC_OV:
4266 case OP_COND_EXC_IOV:
4267 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, ins->inst_p1);
4269 case OP_COND_EXC_NO:
4270 case OP_COND_EXC_INO:
4271 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NO, ins->inst_p1);
4274 case OP_COND_EXC_IC:
4275 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, ins->inst_p1);
4277 case OP_COND_EXC_NC:
4278 case OP_COND_EXC_INC:
4279 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, ins->inst_p1);
4283 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4287 EMIT_COND_BRANCH (ins, S390_CC_NE);
4293 EMIT_COND_BRANCH (ins, S390_CC_LT);
4299 EMIT_COND_BRANCH (ins, S390_CC_GT);
4305 EMIT_COND_BRANCH (ins, S390_CC_GE);
4311 EMIT_COND_BRANCH (ins, S390_CC_LE);
4314 /* floating point opcodes */
4316 if (*((double *) ins->inst_p0) == 0) {
4317 s390_lzdr (code, ins->dreg);
4319 S390_SET (code, s390_r13, ins->inst_p0);
4320 s390_ld (code, ins->dreg, 0, s390_r13, 0);
4325 if (*((float *) ins->inst_p0) == 0) {
4326 s390_lzdr (code, ins->dreg);
4328 S390_SET (code, s390_r13, ins->inst_p0);
4329 s390_ldeb (code, ins->dreg, 0, s390_r13, 0);
4333 case OP_STORER8_MEMBASE_REG: {
4334 S390_LONG (code, stdy, std, ins->sreg1, 0,
4335 ins->inst_destbasereg, ins->inst_offset);
4338 case OP_LOADR8_MEMBASE: {
4339 S390_LONG (code, ldy, ld, ins->dreg, 0,
4340 ins->inst_basereg, ins->inst_offset);
4343 case OP_STORER4_MEMBASE_REG: {
4344 s390_ledbr (code, s390_f15, ins->sreg1);
4345 S390_LONG (code, stey, ste, s390_f15, 0,
4346 ins->inst_destbasereg, ins->inst_offset);
4349 case OP_LOADR4_MEMBASE: {
4350 S390_LONG (code, ley, le, s390_f15, 0,
4351 ins->inst_basereg, ins->inst_offset);
4352 s390_ldebr (code, ins->dreg, s390_f15);
4355 case OP_ICONV_TO_R_UN: {
4357 s390_cdlfbr (code, ins->dreg, 5, ins->sreg1, 0);
4359 s390_llgfr (code, s390_r0, ins->sreg1);
4360 s390_cdgbr (code, ins->dreg, s390_r0);
4364 case OP_LCONV_TO_R_UN: {
4366 s390_cdlgbr (code, ins->dreg, 5, ins->sreg1, 0);
4369 s390_cxgbr (code, s390_f12, ins->sreg1);
4370 s390_ltgr (code, ins->sreg1, ins->sreg1);
4371 s390_jnl (code, 0); CODEPTR(code, jump);
4372 S390_SET (code, s390_r13, 0x403f000000000000llu);
4373 s390_lgdr (code, s390_f13, s390_r13);
4374 s390_lzdr (code, s390_f15);
4375 s390_axbr (code, s390_f12, s390_f13);
4376 PTRSLOT(code, jump);
4377 s390_ldxbr (code, s390_f13, s390_f12);
4378 s390_ldr (code, ins->dreg, s390_f13);
4382 case OP_LCONV_TO_R4:
4383 case OP_ICONV_TO_R4: {
4384 s390_cegbr (code, ins->dreg, ins->sreg1);
4385 s390_ldebr (code, ins->dreg, ins->dreg);
4388 case OP_LCONV_TO_R8:
4389 case OP_ICONV_TO_R8: {
4390 s390_cdgbr (code, ins->dreg, ins->sreg1);
4393 case OP_FCONV_TO_I1:
4394 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4395 s390_ltgr (code, ins->dreg, ins->dreg);
4397 s390_oill (code, ins->dreg, 0x80);
4398 s390_lghi (code, s390_r0, 0xff);
4399 s390_ngr (code, ins->dreg, s390_r0);
4401 case OP_FCONV_TO_U1:
4403 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4404 s390_lghi (code, s390_r0, 0xff);
4405 s390_ngr (code, ins->dreg, s390_r0);
4407 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 1, FALSE);
4410 case OP_FCONV_TO_I2:
4411 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4412 s390_ltgr (code, ins->dreg, ins->dreg);
4414 s390_oill (code, ins->dreg, 0x8000);
4415 s390_llill (code, s390_r0, 0xffff);
4416 s390_ngr (code, ins->dreg, s390_r0);
4418 case OP_FCONV_TO_U2:
4420 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4421 s390_llill (code, s390_r0, 0xffff);
4422 s390_ngr (code, ins->dreg, s390_r0);
4424 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 2, FALSE);
4427 case OP_FCONV_TO_I4:
4429 s390_cfdbr (code, ins->dreg, 5, ins->sreg1);
4431 case OP_FCONV_TO_U4:
4434 s390_clfdbr (code, ins->dreg, 5, ins->sreg1, 0);
4436 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE);
4439 case OP_FCONV_TO_I8:
4440 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4442 case OP_FCONV_TO_U8:
4444 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4446 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 8, FALSE);
4449 case OP_LCONV_TO_OVF_I: {
4450 /* Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000 */
4452 s390_ltgr (code, ins->sreg2, ins->sreg2);
4453 s390_jnl (code, 0); CODEPTR(code, o[0]);
4454 s390_ltgr (code, ins->sreg1, ins->sreg1);
4455 s390_jnl (code, 0); CODEPTR(code, o[1]);
4456 s390_lhi (code, s390_r13, -1);
4457 s390_cgr (code, ins->sreg1, s390_r13);
4458 s390_jnz (code, 0); CODEPTR(code, o[2]);
4459 if (ins->dreg != ins->sreg2)
4460 s390_lgr (code, ins->dreg, ins->sreg2);
4461 s390_j (code, 0); CODEPTR(code, o[3]);
4462 PTRSLOT(code, o[0]);
4463 s390_jz (code, 0); CODEPTR(code, o[4]);
4464 PTRSLOT(code, o[1]);
4465 PTRSLOT(code, o[2]);
4466 mono_add_patch_info (cfg, code - cfg->native_code,
4467 MONO_PATCH_INFO_EXC, "OverflowException");
4468 s390_brasl (code, s390_r14, 0);
4469 PTRSLOT(code, o[3]);
4470 PTRSLOT(code, o[4]);
4474 s390_lpdbr (code, ins->dreg, ins->sreg1);
4478 s390_sqdbr (code, ins->dreg, ins->sreg1);
4483 s390_adbr (code, ins->dreg, src2);
4487 CHECK_SRCDST_NCOM_F;
4488 s390_sdbr (code, ins->dreg, src2);
4493 s390_mdbr (code, ins->dreg, src2);
4497 CHECK_SRCDST_NCOM_F;
4498 s390_ddbr (code, ins->dreg, src2);
4502 s390_lcdbr (code, ins->dreg, ins->sreg1);
4506 CHECK_SRCDST_NCOM_F;
4507 s390_didbr (code, ins->dreg, src2, 5, s390_f15);
4511 s390_cdbr (code, ins->sreg1, ins->sreg2);
4515 s390_cdbr (code, ins->sreg1, ins->sreg2);
4516 s390_lghi (code, ins->dreg, 1);
4518 s390_lghi (code, ins->dreg, 0);
4522 s390_cdbr (code, ins->sreg1, ins->sreg2);
4523 s390_lghi (code, ins->dreg, 1);
4525 s390_lghi (code, ins->dreg, 0);
4529 s390_cdbr (code, ins->sreg1, ins->sreg2);
4530 s390_lghi (code, ins->dreg, 1);
4532 s390_lghi (code, ins->dreg, 0);
4536 s390_cdbr (code, ins->sreg1, ins->sreg2);
4537 s390_lghi (code, ins->dreg, 1);
4539 s390_lghi (code, ins->dreg, 0);
4543 s390_cdbr (code, ins->sreg1, ins->sreg2);
4544 s390_lghi (code, ins->dreg, 1);
4546 s390_lghi (code, ins->dreg, 0);
4551 s390_jo (code, 0); CODEPTR(code, o);
4552 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4557 EMIT_COND_BRANCH (ins, S390_CC_NE|S390_CC_OV);
4561 s390_jo (code, 0); CODEPTR(code, o);
4562 EMIT_COND_BRANCH (ins, S390_CC_LT);
4567 EMIT_COND_BRANCH (ins, S390_CC_LT|S390_CC_OV);
4571 s390_jo (code, 0); CODEPTR(code, o);
4572 EMIT_COND_BRANCH (ins, S390_CC_GT);
4577 EMIT_COND_BRANCH (ins, S390_CC_GT|S390_CC_OV);
4581 s390_jo (code, 0); CODEPTR(code, o);
4582 EMIT_COND_BRANCH (ins, S390_CC_GE);
4587 EMIT_COND_BRANCH (ins, S390_CC_GE|S390_CC_OV);
4591 s390_jo (code, 0); CODEPTR(code, o);
4592 EMIT_COND_BRANCH (ins, S390_CC_LE);
4597 EMIT_COND_BRANCH (ins, S390_CC_LE|S390_CC_OV);
4601 s390_lhi (code, s390_r13, 0x7f);
4602 s390_tcdb (code, ins->sreg1, 0, s390_r13, 0);
4603 s390_jz (code, 0); CODEPTR(code, o);
4604 mono_add_patch_info (cfg, code - cfg->native_code,
4605 MONO_PATCH_INFO_EXC, "ArithmeticException");
4606 s390_brasl (code, s390_r14,0);
4610 case OP_S390_MOVE: {
4611 if (ins->backend.size > 0) {
4612 if (ins->backend.size <= 256) {
4613 s390_mvc (code, ins->backend.size, ins->dreg,
4614 ins->inst_offset, ins->sreg1, ins->inst_imm);
4616 s390_lgr (code, s390_r0, ins->dreg);
4617 if (ins->inst_offset > 0) {
4618 if (s390_is_imm16 (ins->inst_offset)) {
4619 s390_aghi (code, s390_r0, ins->inst_offset);
4620 } else if (s390_is_imm32 (ins->inst_offset)) {
4621 s390_agfi (code, s390_r0, ins->inst_offset);
4623 S390_SET (code, s390_r13, ins->inst_offset);
4624 s390_agr (code, s390_r0, s390_r13);
4627 s390_lgr (code, s390_r12, ins->sreg1);
4628 if (ins->inst_imm > 0) {
4629 if (s390_is_imm16 (ins->inst_imm)) {
4630 s390_aghi (code, s390_r12, ins->inst_imm);
4631 } else if (s390_is_imm32 (ins->inst_imm)) {
4632 s390_agfi (code, s390_r12, ins->inst_imm);
4634 S390_SET (code, s390_r13, ins->inst_imm);
4635 s390_agr (code, s390_r12, s390_r13);
4638 if (s390_is_imm16 (ins->backend.size)) {
4639 s390_lghi (code, s390_r1, ins->backend.size);
4640 } else if (s390_is_imm32 (ins->inst_offset)) {
4641 s390_agfi (code, s390_r1, ins->backend.size);
4643 S390_SET (code, s390_r13, ins->backend.size);
4644 s390_agr (code, s390_r1, s390_r13);
4646 s390_lgr (code, s390_r13, s390_r1);
4647 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4653 case OP_ATOMIC_ADD_I8: {
4654 s390_lgr (code, s390_r1, ins->sreg2);
4655 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4656 s390_agr (code, s390_r1, s390_r0);
4657 s390_csg (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4658 s390_jnz (code, -10);
4659 s390_lgr (code, ins->dreg, s390_r1);
4662 case OP_ATOMIC_EXCHANGE_I8: {
4663 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4664 s390_csg (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
4665 s390_jnz (code, -6);
4666 s390_lgr (code, ins->dreg, s390_r0);
4669 case OP_ATOMIC_ADD_I4: {
4670 s390_lgfr(code, s390_r1, ins->sreg2);
4671 s390_lgf (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4672 s390_agr (code, s390_r1, s390_r0);
4673 s390_cs (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4674 s390_jnz (code, -9);
4675 s390_lgfr(code, ins->dreg, s390_r1);
4678 case OP_ATOMIC_EXCHANGE_I4: {
4679 s390_l (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4680 s390_cs (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
4681 s390_jnz (code, -4);
4682 s390_lgfr(code, ins->dreg, s390_r0);
4685 case OP_S390_BKCHAIN: {
4686 s390_lgr (code, ins->dreg, ins->sreg1);
4687 if (s390_is_imm16 (cfg->stack_offset)) {
4688 s390_aghi (code, ins->dreg, cfg->stack_offset);
4689 } else if (s390_is_imm32 (cfg->stack_offset)) {
4690 s390_agfi (code, ins->dreg, cfg->stack_offset);
4692 S390_SET (code, s390_r13, cfg->stack_offset);
4693 s390_agr (code, ins->dreg, s390_r13);
4697 case OP_MEMORY_BARRIER:
4700 case OP_GC_SAFE_POINT: {
4703 g_assert (mono_threads_is_coop_enabled ());
4705 s390_chi (code, ins->sreg1, 1);
4706 s390_je (code, 0); CODEPTR(code, br);
4707 mono_add_patch_info (cfg, code- cfg->native_code, MONO_PATCH_INFO_ABS,
4708 mono_threads_state_poll);
4709 S390_CALL_TEMPLATE (code, s390_r14);
4713 case OP_GC_LIVENESS_DEF:
4714 case OP_GC_LIVENESS_USE:
4715 case OP_GC_PARAM_SLOT_LIVENESS_DEF:
4716 ins->backend.pc_offset = code - cfg->native_code;
4718 case OP_GC_SPILL_SLOT_LIVENESS_DEF:
4719 ins->backend.pc_offset = code - cfg->native_code;
4720 bb->spill_slot_defs = g_slist_prepend_mempool (cfg->mempool, bb->spill_slot_defs, ins);
4722 #ifdef MONO_ARCH_SIMD_INTRINSICS
4724 s390x_addps (code, ins->sreg1, ins->sreg2);
4727 s390x_divps (code, ins->sreg1, ins->sreg2);
4730 s390x_mulps (code, ins->sreg1, ins->sreg2);
4733 s390x_subps (code, ins->sreg1, ins->sreg2);
4736 s390x_maxps (code, ins->sreg1, ins->sreg2);
4739 s390x_minps (code, ins->sreg1, ins->sreg2);
4742 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
4743 s390x_cmpps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4746 s390x_andps (code, ins->sreg1, ins->sreg2);
4749 s390x_andnps (code, ins->sreg1, ins->sreg2);
4752 s390x_orps (code, ins->sreg1, ins->sreg2);
4755 s390x_xorps (code, ins->sreg1, ins->sreg2);
4758 s390x_sqrtps (code, ins->dreg, ins->sreg1);
4761 s390x_rsqrtps (code, ins->dreg, ins->sreg1);
4764 s390x_rcpps (code, ins->dreg, ins->sreg1);
4767 s390x_addsubps (code, ins->sreg1, ins->sreg2);
4770 s390x_haddps (code, ins->sreg1, ins->sreg2);
4773 s390x_hsubps (code, ins->sreg1, ins->sreg2);
4776 s390x_movshdup (code, ins->dreg, ins->sreg1);
4779 s390x_movsldup (code, ins->dreg, ins->sreg1);
4782 case OP_PSHUFLEW_HIGH:
4783 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4784 s390x_pshufhw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4786 case OP_PSHUFLEW_LOW:
4787 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4788 s390x_pshuflw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4791 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4792 s390x_pshufd_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4795 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4796 s390x_shufps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4799 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0x3);
4800 s390x_shufpd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4804 s390x_addpd (code, ins->sreg1, ins->sreg2);
4807 s390x_divpd (code, ins->sreg1, ins->sreg2);
4810 s390x_mulpd (code, ins->sreg1, ins->sreg2);
4813 s390x_subpd (code, ins->sreg1, ins->sreg2);
4816 s390x_maxpd (code, ins->sreg1, ins->sreg2);
4819 s390x_minpd (code, ins->sreg1, ins->sreg2);
4822 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
4823 s390x_cmppd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4826 s390x_andpd (code, ins->sreg1, ins->sreg2);
4829 s390x_andnpd (code, ins->sreg1, ins->sreg2);
4832 s390x_orpd (code, ins->sreg1, ins->sreg2);
4835 s390x_xorpd (code, ins->sreg1, ins->sreg2);
4838 s390x_sqrtpd (code, ins->dreg, ins->sreg1);
4841 s390x_addsubpd (code, ins->sreg1, ins->sreg2);
4844 s390x_haddpd (code, ins->sreg1, ins->sreg2);
4847 s390x_hsubpd (code, ins->sreg1, ins->sreg2);
4850 s390x_movddup (code, ins->dreg, ins->sreg1);
4853 case OP_EXTRACT_MASK:
4854 s390x_pmovmskb (code, ins->dreg, ins->sreg1);
4858 s390x_pand (code, ins->sreg1, ins->sreg2);
4861 s390x_por (code, ins->sreg1, ins->sreg2);
4864 s390x_pxor (code, ins->sreg1, ins->sreg2);
4868 s390x_paddb (code, ins->sreg1, ins->sreg2);
4871 s390x_paddw (code, ins->sreg1, ins->sreg2);
4874 s390x_paddd (code, ins->sreg1, ins->sreg2);
4877 s390x_paddq (code, ins->sreg1, ins->sreg2);
4881 s390x_psubb (code, ins->sreg1, ins->sreg2);
4884 s390x_psubw (code, ins->sreg1, ins->sreg2);
4887 s390x_psubd (code, ins->sreg1, ins->sreg2);
4890 s390x_psubq (code, ins->sreg1, ins->sreg2);
4894 s390x_pmaxub (code, ins->sreg1, ins->sreg2);
4897 s390x_pmaxuw (code, ins->sreg1, ins->sreg2);
4900 s390x_pmaxud (code, ins->sreg1, ins->sreg2);
4904 s390x_pmaxsb (code, ins->sreg1, ins->sreg2);
4907 s390x_pmaxsw (code, ins->sreg1, ins->sreg2);
4910 s390x_pmaxsd (code, ins->sreg1, ins->sreg2);
4914 s390x_pavgb (code, ins->sreg1, ins->sreg2);
4917 s390x_pavgw (code, ins->sreg1, ins->sreg2);
4921 s390x_pminub (code, ins->sreg1, ins->sreg2);
4924 s390x_pminuw (code, ins->sreg1, ins->sreg2);
4927 s390x_pminud (code, ins->sreg1, ins->sreg2);
4931 s390x_pminsb (code, ins->sreg1, ins->sreg2);
4934 s390x_pminsw (code, ins->sreg1, ins->sreg2);
4937 s390x_pminsd (code, ins->sreg1, ins->sreg2);
4941 s390x_pcmpeqb (code, ins->sreg1, ins->sreg2);
4944 s390x_pcmpeqw (code, ins->sreg1, ins->sreg2);
4947 s390x_pcmpeqd (code, ins->sreg1, ins->sreg2);
4950 s390x_pcmpeqq (code, ins->sreg1, ins->sreg2);
4954 s390x_pcmpgtb (code, ins->sreg1, ins->sreg2);
4957 s390x_pcmpgtw (code, ins->sreg1, ins->sreg2);
4960 s390x_pcmpgtd (code, ins->sreg1, ins->sreg2);
4963 s390x_pcmpgtq (code, ins->sreg1, ins->sreg2);
4966 case OP_PSUM_ABS_DIFF:
4967 s390x_psadbw (code, ins->sreg1, ins->sreg2);
4970 case OP_UNPACK_LOWB:
4971 s390x_punpcklbw (code, ins->sreg1, ins->sreg2);
4973 case OP_UNPACK_LOWW:
4974 s390x_punpcklwd (code, ins->sreg1, ins->sreg2);
4976 case OP_UNPACK_LOWD:
4977 s390x_punpckldq (code, ins->sreg1, ins->sreg2);
4979 case OP_UNPACK_LOWQ:
4980 s390x_punpcklqdq (code, ins->sreg1, ins->sreg2);
4982 case OP_UNPACK_LOWPS:
4983 s390x_unpcklps (code, ins->sreg1, ins->sreg2);
4985 case OP_UNPACK_LOWPD:
4986 s390x_unpcklpd (code, ins->sreg1, ins->sreg2);
4989 case OP_UNPACK_HIGHB:
4990 s390x_punpckhbw (code, ins->sreg1, ins->sreg2);
4992 case OP_UNPACK_HIGHW:
4993 s390x_punpckhwd (code, ins->sreg1, ins->sreg2);
4995 case OP_UNPACK_HIGHD:
4996 s390x_punpckhdq (code, ins->sreg1, ins->sreg2);
4998 case OP_UNPACK_HIGHQ:
4999 s390x_punpckhqdq (code, ins->sreg1, ins->sreg2);
5001 case OP_UNPACK_HIGHPS:
5002 s390x_unpckhps (code, ins->sreg1, ins->sreg2);
5004 case OP_UNPACK_HIGHPD:
5005 s390x_unpckhpd (code, ins->sreg1, ins->sreg2);
5009 s390x_packsswb (code, ins->sreg1, ins->sreg2);
5012 s390x_packssdw (code, ins->sreg1, ins->sreg2);
5015 s390x_packuswb (code, ins->sreg1, ins->sreg2);
5018 s390x_packusdw (code, ins->sreg1, ins->sreg2);
5021 case OP_PADDB_SAT_UN:
5022 s390x_paddusb (code, ins->sreg1, ins->sreg2);
5024 case OP_PSUBB_SAT_UN:
5025 s390x_psubusb (code, ins->sreg1, ins->sreg2);
5027 case OP_PADDW_SAT_UN:
5028 s390x_paddusw (code, ins->sreg1, ins->sreg2);
5030 case OP_PSUBW_SAT_UN:
5031 s390x_psubusw (code, ins->sreg1, ins->sreg2);
5035 s390x_paddsb (code, ins->sreg1, ins->sreg2);
5038 s390x_psubsb (code, ins->sreg1, ins->sreg2);
5041 s390x_paddsw (code, ins->sreg1, ins->sreg2);
5044 s390x_psubsw (code, ins->sreg1, ins->sreg2);
5048 s390x_pmullw (code, ins->sreg1, ins->sreg2);
5051 s390x_pmulld (code, ins->sreg1, ins->sreg2);
5054 s390x_pmuludq (code, ins->sreg1, ins->sreg2);
5056 case OP_PMULW_HIGH_UN:
5057 s390x_pmulhuw (code, ins->sreg1, ins->sreg2);
5060 s390x_pmulhw (code, ins->sreg1, ins->sreg2);
5064 s390x_psrlw_reg_imm (code, ins->dreg, ins->inst_imm);
5067 s390x_psrlw (code, ins->dreg, ins->sreg2);
5071 s390x_psraw_reg_imm (code, ins->dreg, ins->inst_imm);
5074 s390x_psraw (code, ins->dreg, ins->sreg2);
5078 s390x_psllw_reg_imm (code, ins->dreg, ins->inst_imm);
5081 s390x_psllw (code, ins->dreg, ins->sreg2);
5085 s390x_psrld_reg_imm (code, ins->dreg, ins->inst_imm);
5088 s390x_psrld (code, ins->dreg, ins->sreg2);
5092 s390x_psrad_reg_imm (code, ins->dreg, ins->inst_imm);
5095 s390x_psrad (code, ins->dreg, ins->sreg2);
5099 s390x_pslld_reg_imm (code, ins->dreg, ins->inst_imm);
5102 s390x_pslld (code, ins->dreg, ins->sreg2);
5106 s390x_psrlq_reg_imm (code, ins->dreg, ins->inst_imm);
5109 s390x_psrlq (code, ins->dreg, ins->sreg2);
5112 /*TODO: This is appart of the sse spec but not added
5114 s390x_psraq_reg_imm (code, ins->dreg, ins->inst_imm);
5117 s390x_psraq (code, ins->dreg, ins->sreg2);
5122 s390x_psllq_reg_imm (code, ins->dreg, ins->inst_imm);
5125 s390x_psllq (code, ins->dreg, ins->sreg2);
5128 s390x_cvtdq2pd (code, ins->dreg, ins->sreg1);
5131 s390x_cvtdq2ps (code, ins->dreg, ins->sreg1);
5134 s390x_cvtpd2dq (code, ins->dreg, ins->sreg1);
5137 s390x_cvtpd2ps (code, ins->dreg, ins->sreg1);
5140 s390x_cvtps2dq (code, ins->dreg, ins->sreg1);
5143 s390x_cvtps2pd (code, ins->dreg, ins->sreg1);
5146 s390x_cvttpd2dq (code, ins->dreg, ins->sreg1);
5149 s390x_cvttps2dq (code, ins->dreg, ins->sreg1);
5153 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5156 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5160 amd64_movhlps (code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg1);
5161 amd64_movd_reg_xreg_size (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG, 8);
5163 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 8);
5168 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5170 amd64_shift_reg_imm (code, X86_SHR, ins->dreg, ins->inst_c0 * 8);
5171 amd64_widen_reg (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I1, FALSE);
5175 /*amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5177 amd64_shift_reg_imm_size (code, X86_SHR, ins->dreg, 16, 4);*/
5178 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5179 amd64_widen_reg_size (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I2, TRUE, 4);
5183 amd64_movhlps (code, ins->dreg, ins->sreg1);
5185 s390x_movsd (code, ins->dreg, ins->sreg1);
5188 s390x_pinsrw_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5190 case OP_EXTRACTX_U2:
5191 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5193 case OP_INSERTX_U1_SLOW:
5194 /*sreg1 is the extracted ireg (scratch)
5195 /sreg2 is the to be inserted ireg (scratch)
5196 /dreg is the xreg to receive the value*/
5198 /*clear the bits from the extracted word*/
5199 amd64_alu_reg_imm (code, X86_AND, ins->sreg1, ins->inst_c0 & 1 ? 0x00FF : 0xFF00);
5200 /*shift the value to insert if needed*/
5201 if (ins->inst_c0 & 1)
5202 amd64_shift_reg_imm_size (code, X86_SHL, ins->sreg2, 8, 4);
5203 /*join them together*/
5204 amd64_alu (code, X86_OR, ins->sreg1, ins->sreg2);
5205 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0 / 2);
5207 case OP_INSERTX_I4_SLOW:
5208 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2);
5209 amd64_shift_reg_imm (code, X86_SHR, ins->sreg2, 16);
5210 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2 + 1);
5212 case OP_INSERTX_I8_SLOW:
5213 amd64_movd_xreg_reg_size(code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg2, 8);
5215 amd64_movlhps (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5217 s390x_movsd (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5220 case OP_INSERTX_R4_SLOW:
5221 switch (ins->inst_c0) {
5224 s390x_movss (code, ins->dreg, ins->sreg2);
5226 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5229 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5231 s390x_movss (code, ins->dreg, ins->sreg2);
5233 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5234 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5237 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5239 s390x_movss (code, ins->dreg, ins->sreg2);
5241 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5242 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5245 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5247 s390x_movss (code, ins->dreg, ins->sreg2);
5249 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5250 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5254 case OP_INSERTX_R8_SLOW:
5256 amd64_movlhps (code, ins->dreg, ins->sreg2);
5258 s390x_movsd (code, ins->dreg, ins->sreg2);
5260 case OP_STOREX_MEMBASE_REG:
5261 case OP_STOREX_MEMBASE:
5262 s390x_movups_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5264 case OP_LOADX_MEMBASE:
5265 s390x_movups_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5267 case OP_LOADX_ALIGNED_MEMBASE:
5268 s390x_movaps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5270 case OP_STOREX_ALIGNED_MEMBASE_REG:
5271 s390x_movaps_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5273 case OP_STOREX_NTA_MEMBASE_REG:
5274 s390x_movntps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5276 case OP_PREFETCH_MEMBASE:
5277 s390x_prefetch_reg_membase (code, ins->backend.arg_info, ins->sreg1, ins->inst_offset);
5281 /*FIXME the peephole pass should have killed this*/
5282 if (ins->dreg != ins->sreg1)
5283 s390x_movaps (code, ins->dreg, ins->sreg1);
5286 s390x_pxor (code, ins->dreg, ins->dreg);
5288 case OP_ICONV_TO_R4_RAW:
5289 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5292 case OP_FCONV_TO_R8_X:
5293 s390x_movsd (code, ins->dreg, ins->sreg1);
5296 case OP_XCONV_R8_TO_I4:
5297 s390x_cvttsd2si_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5298 switch (ins->backend.source_opcode) {
5299 case OP_FCONV_TO_I1:
5300 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, FALSE);
5302 case OP_FCONV_TO_U1:
5303 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, FALSE);
5305 case OP_FCONV_TO_I2:
5306 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, TRUE);
5308 case OP_FCONV_TO_U2:
5309 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, TRUE);
5315 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 0);
5316 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 1);
5317 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5320 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5321 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5324 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 8);
5325 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5329 s390x_movsd (code, ins->dreg, ins->sreg1);
5331 s390x_movsd (code, ins->dreg, ins->sreg1);
5332 s390x_cvtsd2ss (code, ins->dreg, ins->dreg);
5334 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5337 s390x_movsd (code, ins->dreg, ins->sreg1);
5338 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5342 g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
5343 g_assert_not_reached ();
5346 if ((cfg->opt & MONO_OPT_BRANCH) && ((code - cfg->native_code - offset) > max_len)) {
5347 g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %ld)",
5348 mono_inst_name (ins->opcode), max_len, code - cfg->native_code - offset);
5349 g_assert_not_reached ();
5352 last_offset = offset;
5355 cfg->code_len = code - cfg->native_code;
5358 /*========================= End of Function ========================*/
5360 /*------------------------------------------------------------------*/
5362 /* Name - mono_arch_register_lowlevel_calls */
5364 /* Function - Register routines to help with --trace operation. */
5366 /*------------------------------------------------------------------*/
5369 mono_arch_register_lowlevel_calls (void)
5373 /*========================= End of Function ========================*/
5375 /*------------------------------------------------------------------*/
5377 /* Name - mono_arch_patch_code */
5379 /* Function - Process the patch data created during the */
5380 /* instruction build process. This resolves jumps, */
5381 /* calls, variables etc. */
5383 /*------------------------------------------------------------------*/
5386 mono_arch_patch_code (MonoCompile *cfg, MonoMethod *method, MonoDomain *domain,
5387 guint8 *code, MonoJumpInfo *ji, gboolean run_cctors)
5389 MonoJumpInfo *patch_info;
5392 for (patch_info = ji; patch_info; patch_info = patch_info->next) {
5393 unsigned char *ip = patch_info->ip.i + code;
5394 gconstpointer target = NULL;
5396 target = mono_resolve_patch_target (method, domain, code,
5397 patch_info, run_cctors, &error);
5398 mono_error_raise_exception (&error); /* FIXME: don't raise here */
5400 switch (patch_info->type) {
5401 case MONO_PATCH_INFO_IP:
5402 case MONO_PATCH_INFO_LDSTR:
5403 case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
5404 case MONO_PATCH_INFO_LDTOKEN:
5405 case MONO_PATCH_INFO_EXC:
5406 s390_patch_addr (ip, (guint64) target);
5408 case MONO_PATCH_INFO_METHOD:
5409 case MONO_PATCH_INFO_INTERNAL_METHOD:
5410 case MONO_PATCH_INFO_JIT_ICALL_ADDR:
5411 case MONO_PATCH_INFO_RGCTX_FETCH:
5412 case MONO_PATCH_INFO_ABS: {
5413 S390_EMIT_CALL (ip, target);
5416 case MONO_PATCH_INFO_SWITCH:
5417 /*----------------------------------*/
5418 /* ip points at the basr r13,0/j +4 */
5419 /* instruction the vtable value */
5420 /* follows this (i.e. ip+6) */
5421 /*----------------------------------*/
5422 S390_EMIT_LOAD (ip, target);
5424 case MONO_PATCH_INFO_METHODCONST:
5425 case MONO_PATCH_INFO_CLASS:
5426 case MONO_PATCH_INFO_IMAGE:
5427 case MONO_PATCH_INFO_FIELD:
5428 case MONO_PATCH_INFO_IID:
5429 case MONO_PATCH_INFO_EXC_NAME:
5430 target = S390_RELATIVE(target, ip);
5431 s390_patch_rel (ip, (guint64) target);
5433 case MONO_PATCH_INFO_R4:
5434 case MONO_PATCH_INFO_R8:
5435 case MONO_PATCH_INFO_METHOD_REL:
5436 g_assert_not_reached ();
5439 target = S390_RELATIVE(target, ip);
5441 s390_patch_rel (ip, (guint64) target);
5446 /*========================= End of Function ========================*/
5448 /*------------------------------------------------------------------*/
5450 /* Name - emit_load_volatile_arguments */
5452 /* Function - Emit the instructions to reload parameter regist- */
5453 /* registers for use with "tail" operations. */
5455 /* The register loading operations performed here */
5456 /* are the mirror of the store operations performed */
5457 /* in mono_arch_emit_prolog and need to be kept in */
5458 /* synchronization with it. */
5460 /*------------------------------------------------------------------*/
5463 emit_load_volatile_arguments (guint8 *code, MonoCompile *cfg)
5466 MonoMethod *method = cfg->method;
5467 MonoMethodSignature *sig = mono_method_signature(method);
5471 cinfo = get_call_info (NULL, NULL, sig);
5473 if (cinfo->struct_ret) {
5474 ArgInfo *ainfo = &cinfo->ret;
5475 inst = cfg->vret_addr;
5476 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5479 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5480 ArgInfo *ainfo = cinfo->args + i;
5481 inst = cfg->args [pos];
5483 if (inst->opcode == OP_REGVAR) {
5484 if (ainfo->regtype == RegTypeGeneral)
5485 s390_lgr (code, ainfo->reg, inst->dreg);
5486 else if (ainfo->regtype == RegTypeFP) {
5487 if (inst->dreg != ainfo->reg) {
5488 if (ainfo->size == 4) {
5489 s390_ldebr (code, ainfo->reg, inst->dreg);
5491 s390_ldr (code, ainfo->reg, inst->dreg);
5495 else if (ainfo->regtype == RegTypeBase) {
5497 g_assert_not_reached ();
5499 if (ainfo->regtype == RegTypeGeneral) {
5500 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5501 g_assert_not_reached();
5502 switch (ainfo->size) {
5504 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5507 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5510 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5513 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5516 } else if (ainfo->regtype == RegTypeBase) {
5517 } else if (ainfo->regtype == RegTypeFP) {
5518 if (ainfo->size == 8)
5519 s390_ld (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5520 else if (ainfo->size == 4)
5521 s390_le (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5523 g_assert_not_reached ();
5524 } else if (ainfo->regtype == RegTypeStructByVal) {
5525 if (ainfo->reg != STK_BASE) {
5526 switch (ainfo->size) {
5528 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5531 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5534 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5537 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5541 } else if (ainfo->regtype == RegTypeStructByAddr) {
5542 if (ainfo->reg != STK_BASE) {
5543 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5546 g_assert_not_reached ();
5554 /*========================= End of Function ========================*/
5556 /*------------------------------------------------------------------*/
5558 /* Name - mono_arch_emit_prolog */
5560 /* Function - Create the instruction sequence for a function */
5563 /*------------------------------------------------------------------*/
5566 mono_arch_emit_prolog (MonoCompile *cfg)
5568 MonoMethod *method = cfg->method;
5570 MonoMethodSignature *sig;
5572 long alloc_size, pos, max_offset, i, cfa_offset = 0;
5581 cfg->code_size = 512;
5583 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
5585 cfg->code_size += 256;
5586 } else if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
5587 cfg->code_size += 256;
5589 if (method->save_lmf)
5590 cfg->code_size += 200;
5592 cfg->native_code = code = g_malloc (cfg->code_size);
5594 mono_emit_unwind_op_def_cfa (cfg, code, STK_BASE, 0);
5595 emit_unwind_regs(cfg, code, s390_r6, s390_r14, S390_REG_SAVE_OFFSET);
5596 s390_stmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
5597 mono_emit_unwind_op_offset (cfg, code, s390_r14, S390_RET_ADDR_OFFSET);
5598 mini_gc_set_slot_type_from_cfa (cfg, S390_RET_ADDR_OFFSET, SLOT_NOREF);
5600 if (cfg->arch.bkchain_reg != -1)
5601 s390_lgr (code, cfg->arch.bkchain_reg, STK_BASE);
5603 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
5604 cfg->used_int_regs |= 1 << 11;
5607 alloc_size = cfg->stack_offset;
5609 cfg->stack_usage = cfa_offset = alloc_size;
5610 mono_emit_unwind_op_def_cfa_offset (cfg, code, alloc_size);
5611 s390_lgr (code, s390_r11, STK_BASE);
5612 if (s390_is_imm16 (alloc_size)) {
5613 s390_aghi (code, STK_BASE, -alloc_size);
5614 } else if (s390_is_imm32 (alloc_size)) {
5615 s390_agfi (code, STK_BASE, -alloc_size);
5617 int stackSize = alloc_size;
5618 while (stackSize > INT_MAX) {
5619 s390_agfi (code, STK_BASE, -INT_MAX);
5620 stackSize -= INT_MAX;
5622 s390_agfi (code, STK_BASE, -stackSize);
5624 s390_stg (code, s390_r11, 0, STK_BASE, 0);
5626 if (cfg->frame_reg != STK_BASE)
5627 s390_lgr (code, s390_r11, STK_BASE);
5629 mono_emit_unwind_op_def_cfa_reg (cfg, code, cfg->frame_reg);
5631 /* store runtime generic context */
5632 if (cfg->rgctx_var) {
5633 g_assert (cfg->rgctx_var->opcode == OP_REGOFFSET);
5635 s390_stg (code, MONO_ARCH_RGCTX_REG, 0,
5636 cfg->rgctx_var->inst_basereg,
5637 cfg->rgctx_var->inst_offset);
5640 /* compute max_offset in order to use short forward jumps
5641 * we always do it on s390 because the immediate displacement
5642 * for jumps is too small
5645 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
5647 bb->max_offset = max_offset;
5649 if (cfg->prof_options & MONO_PROFILE_COVERAGE)
5652 MONO_BB_FOR_EACH_INS (bb, ins)
5653 max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
5656 /* load arguments allocated to register from the stack */
5657 sig = mono_method_signature (method);
5660 cinfo = get_call_info (cfg, cfg->mempool, sig);
5662 if (cinfo->struct_ret) {
5663 ArgInfo *ainfo = &cinfo->ret;
5664 inst = cfg->vret_addr;
5665 inst->backend.size = ainfo->vtsize;
5666 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5669 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5670 ArgInfo *ainfo = cinfo->args + i;
5671 inst = cfg->args [pos];
5673 if (inst->opcode == OP_VTARG_ADDR)
5674 inst = inst->inst_left;
5676 if (inst->opcode == OP_REGVAR) {
5677 if (ainfo->regtype == RegTypeGeneral)
5678 s390_lgr (code, inst->dreg, ainfo->reg);
5679 else if (ainfo->regtype == RegTypeFP) {
5680 if (inst->dreg != ainfo->reg) {
5681 if (ainfo->size == 4) {
5682 s390_ledbr (code, inst->dreg, ainfo->reg);
5684 s390_ldr (code, inst->dreg, ainfo->reg);
5688 else if (ainfo->regtype == RegTypeBase) {
5689 s390_lgr (code, s390_r13, STK_BASE);
5690 s390_aghi (code, s390_r13, alloc_size);
5691 s390_lg (code, inst->dreg, 0, s390_r13, ainfo->offset);
5693 g_assert_not_reached ();
5695 if (cfg->verbose_level > 2)
5696 g_print ("Argument %d assigned to register %s\n",
5697 pos, mono_arch_regname (inst->dreg));
5699 if (ainfo->regtype == RegTypeGeneral) {
5700 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5701 g_assert_not_reached();
5702 switch (ainfo->size) {
5704 s390_stc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5707 s390_sth (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5710 s390_st (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5713 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5716 } else if (ainfo->regtype == RegTypeBase) {
5717 } else if (ainfo->regtype == RegTypeFP) {
5718 if (ainfo->size == 8)
5719 s390_std (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5720 else if (ainfo->size == 4)
5721 s390_ste (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5723 g_assert_not_reached ();
5724 } else if (ainfo->regtype == RegTypeStructByVal) {
5725 int doffset = inst->inst_offset;
5727 if (ainfo->reg != STK_BASE)
5731 s390_lgr (code, s390_r13, STK_BASE);
5732 s390_aghi (code, s390_r13, alloc_size);
5735 size = (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE
5736 ? mono_class_native_size(mono_class_from_mono_type(inst->inst_vtype), NULL)
5741 if (ainfo->reg == STK_BASE)
5742 s390_ic (code, reg, 0, s390_r13, ainfo->offset+7);
5743 s390_stc (code, reg, 0, inst->inst_basereg, doffset);
5746 if (ainfo->reg == STK_BASE)
5747 s390_lh (code, reg, 0, s390_r13, ainfo->offset+6);
5748 s390_sth (code, reg, 0, inst->inst_basereg, doffset);
5751 if (ainfo->reg == STK_BASE)
5752 s390_l (code, reg, 0, s390_r13, ainfo->offset+4);
5753 s390_st (code, reg, 0, inst->inst_basereg, doffset);
5756 if (ainfo->reg == STK_BASE)
5757 s390_lg (code, reg, 0, s390_r13, ainfo->offset);
5758 s390_stg (code, reg, 0, inst->inst_basereg, doffset);
5761 } else if (ainfo->regtype == RegTypeStructByAddr) {
5762 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5763 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
5765 g_assert_not_reached ();
5770 if (method->save_lmf) {
5771 /*---------------------------------------------------------------*/
5772 /* build the MonoLMF structure on the stack - see mini-s390x.h */
5773 /*---------------------------------------------------------------*/
5774 lmfOffset = alloc_size - sizeof(MonoLMF);
5776 s390_lgr (code, s390_r13, cfg->frame_reg);
5777 s390_aghi (code, s390_r13, lmfOffset);
5779 /*---------------------------------------------------------------*/
5780 /* Preserve the parameter registers while we fix up the lmf */
5781 /*---------------------------------------------------------------*/
5782 s390_stmg (code, s390_r2, s390_r6, s390_r13,
5783 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
5785 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[0]), SLOT_NOREF);
5786 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[1]), SLOT_NOREF);
5787 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[2]), SLOT_NOREF);
5788 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[3]), SLOT_NOREF);
5789 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[4]), SLOT_NOREF);
5791 /*---------------------------------------------------------------*/
5792 /* On return from this call r2 have the address of the &lmf */
5793 /*---------------------------------------------------------------*/
5794 if (lmf_addr_tls_offset == -1) {
5795 mono_add_patch_info (cfg, code - cfg->native_code,
5796 MONO_PATCH_INFO_INTERNAL_METHOD,
5797 (gpointer)"mono_get_lmf_addr");
5798 S390_CALL_TEMPLATE(code, s390_r1);
5800 /*-------------------------------------------------------*/
5801 /* Get LMF by getting value from thread level storage */
5802 /*-------------------------------------------------------*/
5803 s390_ear (code, s390_r1, 0);
5804 s390_sllg(code, s390_r1, s390_r1, 0, 32);
5805 s390_ear (code, s390_r1, 1);
5806 s390_lg (code, s390_r2, 0, s390_r1, lmf_addr_tls_offset);
5809 /*---------------------------------------------------------------*/
5810 /* Set lmf.lmf_addr = jit_tls->lmf */
5811 /*---------------------------------------------------------------*/
5812 s390_stg (code, s390_r2, 0, s390_r13,
5813 G_STRUCT_OFFSET(MonoLMF, lmf_addr));
5814 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, lmf_addr), SLOT_NOREF);
5816 /*---------------------------------------------------------------*/
5817 /* Get current lmf */
5818 /*---------------------------------------------------------------*/
5819 s390_lg (code, s390_r0, 0, s390_r2, 0);
5821 /*---------------------------------------------------------------*/
5822 /* Set our lmf as the current lmf */
5823 /*---------------------------------------------------------------*/
5824 s390_stg (code, s390_r13, 0, s390_r2, 0);
5826 /*---------------------------------------------------------------*/
5827 /* Have our lmf.previous_lmf point to the last lmf */
5828 /*---------------------------------------------------------------*/
5829 s390_stg (code, s390_r0, 0, s390_r13,
5830 G_STRUCT_OFFSET(MonoLMF, previous_lmf));
5831 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), SLOT_NOREF);
5833 /*---------------------------------------------------------------*/
5834 /* save method info */
5835 /*---------------------------------------------------------------*/
5836 S390_SET (code, s390_r1, method);
5837 s390_stg (code, s390_r1, 0, s390_r13,
5838 G_STRUCT_OFFSET(MonoLMF, method));
5839 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, method), SLOT_NOREF);
5841 /*---------------------------------------------------------------*/
5842 /* save the current IP */
5843 /*---------------------------------------------------------------*/
5844 s390_stg (code, STK_BASE, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp));
5845 s390_basr (code, s390_r1, 0);
5846 s390_stg (code, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip));
5847 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, ebp), SLOT_NOREF);
5848 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, eip), SLOT_NOREF);
5850 /*---------------------------------------------------------------*/
5851 /* Save general and floating point registers */
5852 /*---------------------------------------------------------------*/
5853 s390_stmg (code, s390_r2, s390_r12, s390_r13,
5854 G_STRUCT_OFFSET(MonoLMF, gregs[2]));
5855 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[0]), SLOT_NOREF);
5856 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[1]), SLOT_NOREF);
5857 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[2]), SLOT_NOREF);
5858 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[3]), SLOT_NOREF);
5859 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[4]), SLOT_NOREF);
5860 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[5]), SLOT_NOREF);
5861 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[6]), SLOT_NOREF);
5862 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[7]), SLOT_NOREF);
5863 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[8]), SLOT_NOREF);
5864 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[9]), SLOT_NOREF);
5865 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[10]), SLOT_NOREF);
5867 fpOffset = lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, fregs[0]);
5868 for (i = 0; i < 16; i++) {
5869 s390_std (code, i, 0, s390_r13,
5870 G_STRUCT_OFFSET(MonoLMF, fregs[i]));
5871 mini_gc_set_slot_type_from_fp (cfg, fpOffset, SLOT_NOREF);
5872 fpOffset += sizeof(double);
5875 /*---------------------------------------------------------------*/
5876 /* Restore the parameter registers now that we've set up the lmf */
5877 /*---------------------------------------------------------------*/
5878 s390_lmg (code, s390_r2, s390_r6, s390_r13,
5879 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
5882 if (cfg->method->save_lmf)
5883 argsClobbered = TRUE;
5886 argsClobbered = TRUE;
5887 code = mono_arch_instrument_prolog (cfg, enter_method, code, TRUE);
5890 if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
5891 argsClobbered = TRUE;
5894 * Optimize the common case of the first bblock making a call with the same
5895 * arguments as the method. This works because the arguments are still in their
5896 * original argument registers.
5898 if (!argsClobbered) {
5899 MonoBasicBlock *first_bb = cfg->bb_entry;
5901 int filter = FILTER_IL_SEQ_POINT;
5903 next = mono_bb_first_inst (first_bb, filter);
5904 if (!next && first_bb->next_bb) {
5905 first_bb = first_bb->next_bb;
5906 next = mono_bb_first_inst (first_bb, filter);
5909 if (first_bb->in_count > 1)
5912 for (i = 0; next && i < sig->param_count + sig->hasthis; ++i) {
5913 ArgInfo *ainfo = cinfo->args + i;
5914 gboolean match = FALSE;
5916 inst = cfg->args [i];
5917 if (inst->opcode != OP_REGVAR) {
5918 switch (ainfo->regtype) {
5919 case RegTypeGeneral: {
5920 if (((next->opcode == OP_LOAD_MEMBASE) ||
5921 (next->opcode == OP_LOADI4_MEMBASE)) &&
5922 next->inst_basereg == inst->inst_basereg &&
5923 next->inst_offset == inst->inst_offset) {
5924 if (next->dreg == ainfo->reg) {
5928 next->opcode = OP_MOVE;
5929 next->sreg1 = ainfo->reg;
5930 /* Only continue if the instruction doesn't change argument regs */
5931 if (next->dreg == ainfo->reg)
5941 /* Argument allocated to (non-volatile) register */
5942 switch (ainfo->regtype) {
5943 case RegTypeGeneral:
5944 if (next->opcode == OP_MOVE &&
5945 next->sreg1 == inst->dreg &&
5946 next->dreg == ainfo->reg) {
5957 next = mono_inst_next (next, filter);
5964 cfg->code_len = code - cfg->native_code;
5965 g_assert (cfg->code_len < cfg->code_size);
5970 /*========================= End of Function ========================*/
5972 /*------------------------------------------------------------------*/
5974 /* Name - mono_arch_emit_epilog */
5976 /* Function - Emit the instructions for a function epilog. */
5978 /*------------------------------------------------------------------*/
5981 mono_arch_emit_epilog (MonoCompile *cfg)
5983 MonoMethod *method = cfg->method;
5986 int max_epilog_size = 96;
5988 if (cfg->method->save_lmf)
5989 max_epilog_size += 128;
5991 if (mono_jit_trace_calls != NULL)
5992 max_epilog_size += 128;
5993 else if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
5994 max_epilog_size += 128;
5996 while ((cfg->code_len + max_epilog_size) > (cfg->code_size - 16)) {
5997 cfg->code_size *= 2;
5998 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
5999 cfg->stat_code_reallocs++;
6002 code = cfg->native_code + cfg->code_len;
6004 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
6005 code = mono_arch_instrument_epilog (cfg, leave_method, code, TRUE);
6009 if (method->save_lmf)
6010 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
6012 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
6013 s390_lg (code, STK_BASE, 0, STK_BASE, 0);
6015 code = backUpStackPtr(cfg, code);
6017 s390_lmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
6018 s390_br (code, s390_r14);
6020 cfg->code_len = code - cfg->native_code;
6022 g_assert (cfg->code_len < cfg->code_size);
6026 /*========================= End of Function ========================*/
6028 /*------------------------------------------------------------------*/
6030 /* Name - mono_arch_emit_exceptions */
6032 /* Function - Emit the blocks to handle exception conditions. */
6034 /*------------------------------------------------------------------*/
6037 mono_arch_emit_exceptions (MonoCompile *cfg)
6039 MonoJumpInfo *patch_info;
6045 MonoClass *exc_classes [MAX_EXC];
6046 guint8 *exc_throw_start [MAX_EXC];
6048 for (patch_info = cfg->patch_info;
6050 patch_info = patch_info->next) {
6051 if (patch_info->type == MONO_PATCH_INFO_EXC)
6055 code_size = exc_count * 48;
6057 while ((cfg->code_len + code_size) > (cfg->code_size - 16)) {
6058 cfg->code_size *= 2;
6059 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6060 cfg->stat_code_reallocs++;
6063 code = cfg->native_code + cfg->code_len;
6065 /*---------------------------------------------------------------------*/
6066 /* Add code to raise exceptions */
6067 /*---------------------------------------------------------------------*/
6068 for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
6069 switch (patch_info->type) {
6070 case MONO_PATCH_INFO_EXC: {
6071 guint8 *ip = patch_info->ip.i + cfg->native_code;
6072 MonoClass *exc_class;
6075 /*-----------------------------------------------------*/
6076 /* Patch the branch in epilog to come here */
6077 /*-----------------------------------------------------*/
6078 s390_patch_rel (ip + 2, (guint64) S390_RELATIVE(code,ip));
6080 exc_class = mono_class_from_name (mono_defaults.corlib,
6082 patch_info->data.name);
6083 g_assert (exc_class);
6084 throw_ip = patch_info->ip.i;
6086 for (iExc = 0; iExc < nThrows; ++iExc)
6087 if (exc_classes [iExc] == exc_class)
6090 if (iExc < nThrows) {
6091 s390_jcl (code, S390_CC_UN,
6092 (guint64) exc_throw_start [iExc]);
6093 patch_info->type = MONO_PATCH_INFO_NONE;
6096 if (nThrows < MAX_EXC) {
6097 exc_classes [nThrows] = exc_class;
6098 exc_throw_start [nThrows] = code;
6101 /*---------------------------------------------*/
6102 /* Patch the parameter passed to the handler */
6103 /*---------------------------------------------*/
6104 S390_SET (code, s390_r2, exc_class->type_token);
6105 /*---------------------------------------------*/
6106 /* Load return address & parameter register */
6107 /*---------------------------------------------*/
6108 s390_larl (code, s390_r14, (guint64)S390_RELATIVE((patch_info->ip.i +
6109 cfg->native_code + 8), code));
6110 /*---------------------------------------------*/
6111 /* Reuse the current patch to set the jump */
6112 /*---------------------------------------------*/
6113 patch_info->type = MONO_PATCH_INFO_INTERNAL_METHOD;
6114 patch_info->data.name = "mono_arch_throw_corlib_exception";
6115 patch_info->ip.i = code - cfg->native_code;
6116 S390_BR_TEMPLATE (code, s390_r1);
6126 cfg->code_len = code - cfg->native_code;
6128 g_assert (cfg->code_len < cfg->code_size);
6132 /*========================= End of Function ========================*/
6134 /*------------------------------------------------------------------*/
6136 /* Name - mono_arch_finish_init */
6138 /* Function - Setup the JIT's Thread Level Specific Data. */
6140 /*------------------------------------------------------------------*/
6143 mono_arch_finish_init (void)
6145 appdomain_tls_offset = mono_domain_get_tls_offset();
6146 lmf_tls_offset = mono_get_lmf_tls_offset();
6147 lmf_addr_tls_offset = mono_get_lmf_addr_tls_offset();
6150 /*========================= End of Function ========================*/
6152 /*------------------------------------------------------------------*/
6154 /* Name - mono_arch_free_jit_tls_data */
6156 /* Function - Free tls data. */
6158 /*------------------------------------------------------------------*/
6161 mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
6165 /*========================= End of Function ========================*/
6167 /*------------------------------------------------------------------*/
6169 /* Name - mono_arch_emit_inst_for_method */
6171 /*------------------------------------------------------------------*/
6174 mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
6179 /*========================= End of Function ========================*/
6181 /*------------------------------------------------------------------*/
6183 /* Name - mono_arch_decompose_opts */
6185 /* Function - Decompose opcode into a System z opcode. */
6187 /*------------------------------------------------------------------*/
6190 mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
6193 * Have to rename these to avoid being decomposed normally, since the normal
6194 * decomposition does not work on S390.
6196 switch (ins->opcode) {
6198 ins->opcode = OP_S390_ISUB_OVF;
6200 case OP_ISUB_OVF_UN:
6201 ins->opcode = OP_S390_ISUB_OVF_UN;
6204 ins->opcode = OP_S390_IADD_OVF;
6206 case OP_IADD_OVF_UN:
6207 ins->opcode = OP_S390_IADD_OVF_UN;
6210 ins->opcode = OP_S390_LADD_OVF;
6212 case OP_LADD_OVF_UN:
6213 ins->opcode = OP_S390_LADD_OVF_UN;
6216 ins->opcode = OP_S390_LSUB_OVF;
6218 case OP_LSUB_OVF_UN:
6219 ins->opcode = OP_S390_LSUB_OVF_UN;
6226 /*========================= End of Function ========================*/
6228 /*------------------------------------------------------------------*/
6230 /* Name - mono_arch_print_tree */
6232 /* Function - Print platform-specific opcode details. */
6234 /* Returns - 1 - opcode details have been printed */
6235 /* 0 - opcode details have not been printed */
6237 /*------------------------------------------------------------------*/
6240 mono_arch_print_tree (MonoInst *tree, int arity)
6244 switch (tree->opcode) {
6245 case OP_S390_LOADARG:
6246 case OP_S390_ARGREG:
6247 case OP_S390_ARGPTR:
6248 printf ("[0x%lx(%s)]", tree->inst_offset,
6249 mono_arch_regname (tree->inst_basereg));
6252 case OP_S390_STKARG:
6253 printf ("[0x%lx(previous_frame)]",
6258 printf ("[0x%lx(%d,%s),0x%lx(%s)]",
6259 tree->inst_offset, tree->backend.size,
6260 mono_arch_regname(tree->dreg),
6262 mono_arch_regname(tree->sreg1));
6265 case OP_S390_SETF4RET:
6266 printf ("[f%s,f%s]",
6267 mono_arch_regname (tree->dreg),
6268 mono_arch_regname (tree->sreg1));
6272 printf ("[0x%lx(0x%lx,%s)]", tree->inst_offset,
6274 mono_arch_regname (tree->sreg1));
6277 case OP_S390_BKCHAIN:
6278 printf ("[previous_frame(%s)]",
6279 mono_arch_regname (tree->sreg1));
6287 /*========================= End of Function ========================*/
6289 /*------------------------------------------------------------------*/
6291 /* Name - mono_arch_regalloc_cost */
6293 /* Function - Determine the cost, in the number of memory */
6294 /* references, of the action of allocating the var- */
6295 /* iable VMV into a register during global register */
6298 /* Returns - Cost */
6300 /*------------------------------------------------------------------*/
6303 mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
6309 /*========================= End of Function ========================*/
6311 /*------------------------------------------------------------------*/
6313 /* Name - mono_arch_flush_register_windows */
6319 /*------------------------------------------------------------------*/
6322 mono_arch_flush_register_windows (void)
6326 /*========================= End of Function ========================*/
6328 /*------------------------------------------------------------------*/
6330 /* Name - mono_arch_is_inst_imm */
6332 /* Function - Determine if operand qualifies as an immediate */
6333 /* value. For s390 this is a value -32768-32768 */
6335 /* Returns - True|False - is [not] immediate value. */
6337 /*------------------------------------------------------------------*/
6340 mono_arch_is_inst_imm (gint64 imm)
6342 return s390_is_imm32 (imm);
6345 /*========================= End of Function ========================*/
6347 /*------------------------------------------------------------------*/
6349 /* Name - mono_arch_get_patch_offset */
6351 /* Function - Dummy entry point until s390x supports aot. */
6353 /* Returns - Offset for patch. */
6355 /*------------------------------------------------------------------*/
6358 mono_arch_get_patch_offset (guint8 *code)
6363 /*========================= End of Function ========================*/
6365 /*------------------------------------------------------------------*/
6367 /* Name - mono_arch_context_get_int_reg. */
6371 /* Returns - Return a register from the context. */
6373 /*------------------------------------------------------------------*/
6376 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
6378 return ((mgreg_t) ctx->uc_mcontext.gregs[reg]);
6381 /*========================= End of Function ========================*/
6383 /*------------------------------------------------------------------*/
6385 /* Name - mono_arch_context_set_int_reg. */
6387 /* Function - Set a value in a specified register. */
6389 /*------------------------------------------------------------------*/
6392 mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val)
6394 ctx->uc_mcontext.gregs[reg] = val;
6397 /*========================= End of Function ========================*/
6399 /*------------------------------------------------------------------*/
6401 /* Name - mono_arch_get_this_arg_from_call. */
6405 /*------------------------------------------------------------------*/
6408 mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
6410 return (gpointer) regs [s390_r2];
6413 /*========================= End of Function ========================*/
6415 /*------------------------------------------------------------------*/
6417 /* Name - mono_arch_install_handler_block_guard */
6421 /*------------------------------------------------------------------*/
6424 mono_arch_install_handler_block_guard (MonoJitInfo *ji, MonoJitExceptionInfo *clause,
6425 MonoContext *ctx, gpointer new_value)
6428 gpointer *sp, old_value;
6431 offset = clause->exvar_offset;
6434 bp = MONO_CONTEXT_GET_BP (ctx);
6435 sp = *(gpointer*)(bp + offset);
6438 if (old_value < ji->code_start || (char*)old_value > ((char*)ji->code_start + ji->code_size))
6446 /*========================= End of Function ========================*/
6448 /*------------------------------------------------------------------*/
6450 /* Name - get_delegate_invoke_impl. */
6454 /*------------------------------------------------------------------*/
6457 get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 param_count, gboolean aot)
6459 guint8 *code, *start;
6464 start = code = mono_global_codeman_reserve (size);
6466 /* Replace the this argument with the target */
6467 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6468 s390_lg (code, s390_r2, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, target));
6469 s390_br (code, s390_r1);
6470 g_assert ((code - start) <= size);
6472 mono_arch_flush_icache (start, size);
6476 size = 32 + param_count * 8;
6477 start = code = mono_global_codeman_reserve (size);
6479 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6480 /* slide down the arguments */
6481 for (i = 0; i < param_count; ++i) {
6482 s390_lgr (code, (s390_r2 + i), (s390_r2 + i + 1));
6484 s390_br (code, s390_r1);
6486 g_assert ((code - start) <= size);
6488 mono_arch_flush_icache (start, size);
6491 mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
6494 *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
6496 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
6497 *info = mono_tramp_info_create (name, start, code - start, NULL, NULL);
6504 /*========================= End of Function ========================*/
6506 /*------------------------------------------------------------------*/
6508 /* Name - mono_arch_get_delegate_invoke_impls. */
6512 /*------------------------------------------------------------------*/
6515 mono_arch_get_delegate_invoke_impls (void)
6518 MonoTrampInfo *info;
6521 get_delegate_invoke_impl (&info, TRUE, 0, TRUE);
6522 res = g_slist_prepend (res, info);
6524 for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
6525 get_delegate_invoke_impl (&info, FALSE, i, TRUE);
6526 res = g_slist_prepend (res, info);
6532 /*========================= End of Function ========================*/
6534 /*------------------------------------------------------------------*/
6536 /* Name - mono_arch_get_delegate_invoke_impl. */
6540 /*------------------------------------------------------------------*/
6543 mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target)
6545 guint8 *code, *start;
6547 /* FIXME: Support more cases */
6548 if (MONO_TYPE_ISSTRUCT (sig->ret))
6552 static guint8* cached = NULL;
6557 if (mono_aot_only) {
6558 start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
6560 MonoTrampInfo *info;
6561 start = get_delegate_invoke_impl (&info, TRUE, 0, FALSE);
6562 mono_tramp_info_register (info, NULL);
6565 mono_memory_barrier ();
6569 static guint8* cache [MAX_ARCH_DELEGATE_PARAMS + 1] = {NULL};
6572 if (sig->param_count > MAX_ARCH_DELEGATE_PARAMS)
6574 for (i = 0; i < sig->param_count; ++i)
6575 if (!mono_is_regsize_var (sig->params [i]))
6579 code = cache [sig->param_count];
6583 if (mono_aot_only) {
6584 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", sig->param_count);
6585 start = mono_aot_get_trampoline (name);
6588 MonoTrampInfo *info;
6589 start = get_delegate_invoke_impl (&info, FALSE, sig->param_count, FALSE);
6590 mono_tramp_info_register (info, NULL);
6593 mono_memory_barrier ();
6595 cache [sig->param_count] = start;
6600 /*========================= End of Function ========================*/
6602 /*------------------------------------------------------------------*/
6604 /* Name - mono_arch_get_delegate_virtual_invoke_impl. */
6608 /*------------------------------------------------------------------*/
6611 mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method,
6612 int offset, gboolean load_imt_reg)
6614 guint8 *code, *start;
6617 start = code = mono_global_codeman_reserve (size);
6620 * Replace the "this" argument with the target
6622 s390_lgr (code, s390_r1, s390_r2);
6623 s390_lg (code, s390_r2, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, target));
6626 * Load the IMT register, if needed
6629 s390_lg (code, MONO_ARCH_IMT_REG, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, method));
6635 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET(MonoObject, vtable));
6637 s390_agfi(code, s390_r1, offset);
6639 s390_lg (code, s390_r1, 0, s390_r1, 0);
6640 s390_br (code, s390_r1);
6645 /*========================= End of Function ========================*/
6647 /*------------------------------------------------------------------*/
6649 /* Name - mono_arch_build_imt_thunk. */
6653 /*------------------------------------------------------------------*/
6656 mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain,
6657 MonoIMTCheckItem **imt_entries, int count,
6658 gpointer fail_tramp)
6662 guchar *code, *start;
6665 for (i = 0; i < count; ++i) {
6666 MonoIMTCheckItem *item = imt_entries [i];
6667 if (item->is_equals) {
6668 if (item->check_target_idx) {
6669 if (!item->compare_done)
6670 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6671 if (item->has_target_code)
6672 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE;
6674 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE +
6678 item->chunk_size += CMP_SIZE + 2 * BR_SIZE + JUMP_SIZE +
6680 if (!item->has_target_code)
6681 item->chunk_size += LOAD_SIZE;
6683 item->chunk_size += LOADCON_SIZE + LOAD_SIZE + BR_SIZE;
6684 #if ENABLE_WRONG_METHOD_CHECK
6685 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6690 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6691 imt_entries [item->check_target_idx]->compare_done = TRUE;
6693 size += item->chunk_size;
6697 code = mono_method_alloc_generic_virtual_thunk (domain, size);
6699 code = mono_domain_code_reserve (domain, size);
6703 for (i = 0; i < count; ++i) {
6704 MonoIMTCheckItem *item = imt_entries [i];
6705 item->code_target = (guint8 *) code;
6706 if (item->is_equals) {
6707 if (item->check_target_idx) {
6708 if (!item->compare_done) {
6709 S390_SET (code, s390_r0, item->key);
6710 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
6712 item->jmp_code = (guint8*) code;
6713 s390_jcl (code, S390_CC_NE, 0);
6715 if (item->has_target_code) {
6716 S390_SET (code, s390_r1, item->value.target_code);
6718 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6719 s390_lg (code, s390_r1, 0, s390_r1, 0);
6721 s390_br (code, s390_r1);
6726 S390_SET (code, s390_r0, item->key);
6727 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
6728 item->jmp_code = (guint8*) code;
6729 s390_jcl (code, S390_CC_NE, 0);
6730 if (item->has_target_code) {
6731 S390_SET (code, s390_r1, item->value.target_code);
6734 S390_SET (code, s390_r1,
6735 (&(vtable->vtable [item->value.vtable_slot])));
6736 s390_lg (code, s390_r1, 0, s390_r1, 0);
6738 s390_br (code, s390_r1);
6739 target = (gint64) S390_RELATIVE(code, item->jmp_code);
6740 s390_patch_rel(item->jmp_code+2, target);
6741 S390_SET (code, s390_r1, fail_tramp);
6742 s390_br (code, s390_r1);
6743 item->jmp_code = NULL;
6745 /* enable the commented code to assert on wrong method */
6746 #if ENABLE_WRONG_METHOD_CHECK
6747 g_assert_not_reached ();
6749 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6750 s390_lg (code, s390_r1, 0, s390_r1, 0);
6751 s390_br (code, s390_r1);
6755 S390_SET (code, s390_r0, item->key);
6756 s390_cgr (code, MONO_ARCH_IMT_REG, s390_r0);
6757 item->jmp_code = (guint8 *) code;
6758 s390_jcl (code, S390_CC_GE, 0);
6762 * patch the branches to get to the target items
6764 for (i = 0; i < count; ++i) {
6765 MonoIMTCheckItem *item = imt_entries [i];
6766 if (item->jmp_code) {
6767 if (item->check_target_idx) {
6769 offset = (gint64) S390_RELATIVE(imt_entries [item->check_target_idx]->code_target,
6771 s390_patch_rel ((guchar *) item->jmp_code + 2, (guint64) offset);
6776 mono_arch_flush_icache ((guint8*)start, (code - start));
6777 mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL);
6780 mono_stats.imt_thunks_size += (code - start);
6782 g_assert (code - start <= size);
6784 snprintf(trampName, sizeof(trampName), "%d_imt_thunk_trampoline", domain->domain_id);
6785 mono_tramp_info_register (mono_tramp_info_create (trampName, start, code - start, NULL, NULL), domain);
6790 /*========================= End of Function ========================*/
6792 /*------------------------------------------------------------------*/
6794 /* Name - mono_arch_find_imt_method. */
6796 /* Function - Get the method address from MONO_ARCH_IMT_REG */
6797 /* found in the save area. */
6799 /*------------------------------------------------------------------*/
6802 mono_arch_find_imt_method (mgreg_t *regs, guint8 *code)
6804 return ((MonoMethod *) regs [MONO_ARCH_IMT_REG]);
6807 /*========================= End of Function ========================*/
6809 /*------------------------------------------------------------------*/
6811 /* Name - mono_arch_find_static_call_vtable */
6813 /* Function - Find the static call vtable. */
6815 /*------------------------------------------------------------------*/
6818 mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
6820 mgreg_t *r = (mgreg_t*)regs;
6822 return (MonoVTable*)(gsize) r [MONO_ARCH_RGCTX_REG];
6825 /*========================= End of Function ========================*/
6827 /*------------------------------------------------------------------*/
6829 /* Name - mono_arch_get_cie_program */
6831 /* Function - Find the static call vtable. */
6833 /*------------------------------------------------------------------*/
6836 mono_arch_get_cie_program (void)
6840 mono_add_unwind_op_def_cfa (l, 0, 0, STK_BASE, 0);
6845 /*========================= End of Function ========================*/
6847 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
6849 /*------------------------------------------------------------------*/
6851 /* Name - mono_arch_set_breakpoint. */
6853 /* Function - Set a breakpoint at the native code corresponding */
6854 /* to JI at NATIVE_OFFSET. The location should */
6855 /* contain code emitted by OP_SEQ_POINT. */
6857 /*------------------------------------------------------------------*/
6860 mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
6864 breakpointCode.pTrigger = bp_trigger_page;
6865 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
6866 code += BREAKPOINT_SIZE;
6869 /*========================= End of Function ========================*/
6871 /*------------------------------------------------------------------*/
6873 /* Name - mono_arch_clear_breakpoint. */
6875 /* Function - Clear the breakpoint at IP. */
6877 /*------------------------------------------------------------------*/
6880 mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
6885 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); i++)
6889 /*========================= End of Function ========================*/
6891 /*------------------------------------------------------------------*/
6893 /* Name - mono_arch_is_breakpoint_event. */
6897 /*------------------------------------------------------------------*/
6900 mono_arch_is_breakpoint_event (void *info, void *sigctx)
6902 siginfo_t* sinfo = (siginfo_t*) info;
6905 * Sometimes the address is off by 4
6907 if (sinfo->si_addr >= bp_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)bp_trigger_page + 128)
6913 /*========================= End of Function ========================*/
6915 /*------------------------------------------------------------------*/
6917 /* Name - mono_arch_skip_breakpoint. */
6919 /* Function - Modify the CTX so the IP is placed after the */
6920 /* breakpoint instruction, so when we resume, the */
6921 /* instruction is not executed again. */
6923 /*------------------------------------------------------------------*/
6926 mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
6928 MONO_CONTEXT_SET_IP (ctx, ((guint8*)MONO_CONTEXT_GET_IP (ctx) + sizeof(RXY_Format)));
6931 /*========================= End of Function ========================*/
6933 /*------------------------------------------------------------------*/
6935 /* Name - mono_arch_start_single_stepping. */
6937 /* Function - Start single stepping. */
6939 /*------------------------------------------------------------------*/
6942 mono_arch_start_single_stepping (void)
6944 mono_mprotect (ss_trigger_page, mono_pagesize (), 0);
6947 /*========================= End of Function ========================*/
6949 /*------------------------------------------------------------------*/
6951 /* Name - mono_arch_stop_single_stepping. */
6953 /* Function - Stop single stepping. */
6955 /*------------------------------------------------------------------*/
6958 mono_arch_stop_single_stepping (void)
6960 mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ);
6963 /*========================= End of Function ========================*/
6965 /*------------------------------------------------------------------*/
6967 /* Name - mono_arch_is_single_step_event. */
6969 /* Function - Return whether the machine state in sigctx cor- */
6970 /* responds to a single step event. */
6972 /*------------------------------------------------------------------*/
6975 mono_arch_is_single_step_event (void *info, void *sigctx)
6977 siginfo_t* sinfo = (siginfo_t*) info;
6980 * Sometimes the address is off by 4
6982 if (sinfo->si_addr >= ss_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)ss_trigger_page + 128)
6988 /*========================= End of Function ========================*/
6990 /*------------------------------------------------------------------*/
6992 /* Name - mono_arch_skip_single_step. */
6994 /* Function - Modify the ctx so the IP is placed after the */
6995 /* single step trigger instruction, so that the */
6996 /* instruction is not executed again. */
6998 /*------------------------------------------------------------------*/
7001 mono_arch_skip_single_step (MonoContext *ctx)
7003 MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + BREAKPOINT_SIZE);
7006 /*========================= End of Function ========================*/
7008 /*------------------------------------------------------------------*/
7010 /* Name - mono_arch_create_seq_point_info. */
7012 /* Function - Return a pointer to a data struction which is */
7013 /* used by the sequence point implementation in */
7016 /*------------------------------------------------------------------*/
7019 mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code)
7025 /*========================= End of Function ========================*/
7027 /*------------------------------------------------------------------*/
7029 /* Name - mono_arch_init_lmf_ext. */
7033 /*------------------------------------------------------------------*/
7036 mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
7038 ext->lmf.previous_lmf = prev_lmf;
7039 /* Mark that this is a MonoLMFExt */
7040 ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
7041 ext->lmf.ebp = (gssize)ext;
7044 /*========================= End of Function ========================*/
7048 /*------------------------------------------------------------------*/
7050 /* Name - mono_arch_cpu_enumerate_simd_versions. */
7052 /* Function - If this CPU supports vector operations then it */
7053 /* supports the equivalent of SSE1-4. */
7055 /*------------------------------------------------------------------*/
7058 mono_arch_cpu_enumerate_simd_versions (void)
7060 guint32 sseOpts = 0;
7063 sseOpts = (SIMD_VERSION_SSE1 | SIMD_VERSION_SSE2 |
7064 SIMD_VERSION_SSE3 | SIMD_VERSION_SSSE3 |
7065 SIMD_VERSION_SSE41 | SIMD_VERSION_SSE42 |
7066 SIMD_VERSION_SSE4a);
7071 /*========================= End of Function ========================*/
7073 /*------------------------------------------------------------------*/
7075 /* Name - mono_arch_opcode_supported. */
7077 /* Function - Check if a given return code is supported. */
7079 /*------------------------------------------------------------------*/
7082 mono_arch_opcode_supported (int opcode)
7085 case OP_ATOMIC_ADD_I4:
7086 case OP_ATOMIC_ADD_I8:
7087 case OP_ATOMIC_EXCHANGE_I4:
7088 case OP_ATOMIC_EXCHANGE_I8:
7095 /*========================= End of Function ========================*/