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-error.h>
268 #include <mono/utils/mono-error-internals.h>
269 #include <mono/utils/mono-math.h>
270 #include <mono/utils/mono-mmap.h>
271 #include <mono/utils/mono-hwcap-s390x.h>
272 #include <mono/utils/mono-threads.h>
274 #include "mini-s390x.h"
275 #include "cpu-s390x.h"
276 #include "support-s390x.h"
277 #include "jit-icalls.h"
282 /*========================= End of Includes ========================*/
284 /*------------------------------------------------------------------*/
285 /* T y p e d e f s */
286 /*------------------------------------------------------------------*/
298 /*------------------------------------------------------------------*/
299 /* Used by the instrument_emit_epilog */
300 /*------------------------------------------------------------------*/
311 typedef struct InstList InstList;
325 RegTypeStructByValInFP,
327 RegTypeStructByAddrOnStack
331 gint32 offset; /* offset from caller's stack */
332 gint32 offparm; /* offset from callee's stack */
333 guint16 vtsize; /* in param area */
336 guint32 size; /* Size of structure used by RegTypeStructByVal */
337 gint32 type; /* Data type of argument */
353 gint64 gr[5]; /* R2-R6 */
354 gdouble fp[3]; /* F0-F2 */
355 } __attribute__ ((packed)) RegParm;
363 } __attribute__ ((packed)) breakpoint_t;
365 /*========================= End of Typedefs ========================*/
367 /*------------------------------------------------------------------*/
368 /* P r o t o t y p e s */
369 /*------------------------------------------------------------------*/
371 static void indent (int);
372 static guint8 * backUpStackPtr(MonoCompile *, guint8 *);
373 static void decodeParm (MonoType *, void *, int);
374 static void enter_method (MonoMethod *, RegParm *, char *);
375 static void leave_method (MonoMethod *, ...);
376 static inline void add_general (guint *, size_data *, ArgInfo *);
377 static inline void add_stackParm (guint *, size_data *, ArgInfo *, gint);
378 static inline void add_float (guint *, size_data *, ArgInfo *);
379 static CallInfo * get_call_info (MonoCompile *, MonoMemPool *, MonoMethodSignature *);
380 static guchar * emit_float_to_int (MonoCompile *, guchar *, int, int, int, gboolean);
381 static guint8 * emit_load_volatile_arguments (guint8 *, MonoCompile *);
382 static __inline__ void emit_unwind_regs(MonoCompile *, guint8 *, int, int, long);
384 /*========================= End of Prototypes ======================*/
386 /*------------------------------------------------------------------*/
387 /* G l o b a l V a r i a b l e s */
388 /*------------------------------------------------------------------*/
390 int mono_exc_esp_offset = 0;
392 __thread int indent_level = 0;
394 static gint appdomain_tls_offset = -1,
396 lmf_addr_tls_offset = -1;
398 pthread_key_t lmf_addr_key;
400 gboolean lmf_addr_key_inited = FALSE;
405 * The code generated for sequence points reads from this location,
406 * which is made read-only when single stepping is enabled.
408 static gpointer ss_trigger_page;
411 * Enabled breakpoints read from this trigger page
413 static gpointer bp_trigger_page;
415 breakpoint_t breakpointCode;
417 static mono_mutex_t mini_arch_mutex;
419 static const char * grNames[] = {
420 "s390_r0", "s390_sp", "s390_r2", "s390_r3", "s390_r4",
421 "s390_r5", "s390_r6", "s390_r7", "s390_r8", "s390_r9",
422 "s390_r10", "s390_r11", "s390_r12", "s390_r13", "s390_r14",
426 static const char * fpNames[] = {
427 "s390_f0", "s390_f1", "s390_f2", "s390_f3", "s390_f4",
428 "s390_f5", "s390_f6", "s390_f7", "s390_f8", "s390_f9",
429 "s390_f10", "s390_f11", "s390_f12", "s390_f13", "s390_f14",
433 static const char * vrNames[] = {
434 "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7",
435 "vr8", "vr9", "vr10", "vr11", "vr12", "vr13", "vr14", "vr15",
436 "vr16", "vr17", "vr18", "vr19", "vr20", "vr21", "vr22", "vr23",
437 "vr24", "vr25", "vr26", "vr27", "vr28", "vr29", "vr30", "vr31"
440 /*====================== End of Global Variables ===================*/
442 /*------------------------------------------------------------------*/
444 /* Name - mono_arch_regname */
446 /* Function - Returns the name of the register specified by */
447 /* the input parameter. */
449 /*------------------------------------------------------------------*/
452 mono_arch_regname (int reg)
454 if (reg >= 0 && reg < 16)
455 return grNames [reg];
460 /*========================= End of Function ========================*/
462 /*------------------------------------------------------------------*/
464 /* Name - mono_arch_fregname */
466 /* Function - Returns the name of the register specified by */
467 /* the input parameter. */
469 /*------------------------------------------------------------------*/
472 mono_arch_fregname (int reg)
474 if (reg >= 0 && reg < 16)
475 return fpNames [reg];
480 /*========================= End of Function ========================*/
482 /*------------------------------------------------------------------*/
484 /* Name - mono_arch_xregname */
486 /* Function - Returns the name of the register specified by */
487 /* the input parameter. */
489 /*------------------------------------------------------------------*/
492 mono_arch_xregname (int reg)
494 if (reg < s390_VR_NREG)
495 return vrNames [reg];
500 /*========================= End of Function ========================*/
502 /*------------------------------------------------------------------*/
504 /* Name - arch_get_argument_info */
506 /* Function - Gathers information on parameters such as size, */
507 /* alignment, and padding. arg_info should be large */
508 /* enough to hold param_count + 1 entries. */
510 /* Parameters - @csig - Method signature */
511 /* @param_count - No. of parameters to consider */
512 /* @arg_info - An array to store the result info */
514 /* Returns - Size of the activation frame */
516 /*------------------------------------------------------------------*/
519 mono_arch_get_argument_info (MonoMethodSignature *csig,
521 MonoJitArgumentInfo *arg_info)
523 int k, frame_size = 0;
524 int size, align, pad;
527 if (MONO_TYPE_ISSTRUCT (csig->ret)) {
528 frame_size += sizeof (gpointer);
532 arg_info [0].offset = offset;
535 frame_size += sizeof (gpointer);
539 arg_info [0].size = frame_size;
541 for (k = 0; k < param_count; k++) {
544 size = mono_type_native_stack_size (csig->params [k], (guint32 *) &align);
546 size = mini_type_stack_size (csig->params [k], &align);
548 frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
549 arg_info [k].pad = pad;
551 arg_info [k + 1].pad = 0;
552 arg_info [k + 1].size = size;
554 arg_info [k + 1].offset = offset;
558 align = MONO_ARCH_FRAME_ALIGNMENT;
559 frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
560 arg_info [k].pad = pad;
565 /*========================= End of Function ========================*/
567 /*------------------------------------------------------------------*/
569 /* Name - emit_unwind_regs. */
571 /* Function - Determines if a value can be returned in one or */
574 /*------------------------------------------------------------------*/
576 static void __inline__
577 emit_unwind_regs(MonoCompile *cfg, guint8 *code, int start, int end, long offset)
581 for (i = start; i < end; i++) {
582 mono_emit_unwind_op_offset (cfg, code, i, offset);
583 mini_gc_set_slot_type_from_cfa (cfg, offset, SLOT_NOREF);
584 offset += sizeof(gulong);
588 /*========================= End of Function ========================*/
590 /*------------------------------------------------------------------*/
592 /* Name - retFitsInReg. */
594 /* Function - Determines if a value can be returned in one or */
597 /*------------------------------------------------------------------*/
599 static inline gboolean
600 retFitsInReg(guint32 size)
615 /*========================= End of Function ========================*/
617 /*------------------------------------------------------------------*/
619 /* Name - backStackPtr. */
621 /* Function - Restore Stack Pointer to previous frame. */
623 /*------------------------------------------------------------------*/
625 static inline guint8 *
626 backUpStackPtr(MonoCompile *cfg, guint8 *code)
628 int stackSize = cfg->stack_usage;
630 if (cfg->frame_reg != STK_BASE)
631 s390_lgr (code, STK_BASE, cfg->frame_reg);
633 if (s390_is_imm16 (stackSize)) {
634 s390_aghi (code, STK_BASE, stackSize);
636 while (stackSize > 32767) {
637 s390_aghi (code, STK_BASE, 32767);
640 s390_aghi (code, STK_BASE, stackSize);
645 /*========================= End of Function ========================*/
647 /*------------------------------------------------------------------*/
651 /* Function - Perform nice indenting to current level */
653 /*------------------------------------------------------------------*/
659 indent_level += diff;
661 printf("%p [%3d] ",(void *)pthread_self(),v);
666 indent_level += diff;
669 /*========================= End of Function ========================*/
671 /*------------------------------------------------------------------*/
673 /* Name - cvtMonoType */
675 /* Function - Convert a mono-type to a string. */
677 /*------------------------------------------------------------------*/
680 cvtMonoType(MonoTypeEnum t)
685 return "MONO_TYPE_END";
687 return "MONO_TYPE_VOID";
688 case MONO_TYPE_BOOLEAN:
689 return "MONO_TYPE_BOOLEAN";
691 return "MONO_TYPE_CHAR";
693 return "MONO_TYPE_I1";
695 return "MONO_TYPE_U1";
697 return "MONO_TYPE_I2";
699 return "MONO_TYPE_U2";
701 return "MONO_TYPE_I4";
703 return "MONO_TYPE_U4";
705 return "MONO_TYPE_I8";
707 return "MONO_TYPE_U8";
709 return "MONO_TYPE_R4";
711 return "MONO_TYPE_R8";
712 case MONO_TYPE_STRING:
713 return "MONO_TYPE_STRING";
715 return "MONO_TYPE_PTR";
716 case MONO_TYPE_BYREF:
717 return "MONO_TYPE_BYREF";
718 case MONO_TYPE_VALUETYPE:
719 return "MONO_TYPE_VALUETYPE";
720 case MONO_TYPE_CLASS:
721 return "MONO_TYPE_CLASS";
723 return "MONO_TYPE_VAR";
724 case MONO_TYPE_ARRAY:
725 return "MONO_TYPE_ARRAY";
726 case MONO_TYPE_GENERICINST:
727 return "MONO_TYPE_GENERICINST";
728 case MONO_TYPE_TYPEDBYREF:
729 return "MONO_TYPE_TYPEDBYREF";
731 return "MONO_TYPE_I";
733 return "MONO_TYPE_U";
734 case MONO_TYPE_FNPTR:
735 return "MONO_TYPE_FNPTR";
736 case MONO_TYPE_OBJECT:
737 return "MONO_TYPE_OBJECT";
738 case MONO_TYPE_SZARRAY:
739 return "MONO_TYPE_SZARRAY";
741 return "MONO_TYPE_MVAR";
742 case MONO_TYPE_CMOD_REQD:
743 return "MONO_TYPE_CMOD_REQD";
744 case MONO_TYPE_CMOD_OPT:
745 return "MONO_TYPE_CMOD_OPT";
746 case MONO_TYPE_INTERNAL:
747 return "MONO_TYPE_INTERNAL";
748 case MONO_TYPE_MODIFIER:
749 return "MONO_TYPE_MODIFIER";
750 case MONO_TYPE_SENTINEL:
751 return "MONO_TYPE_SENTINEL";
752 case MONO_TYPE_PINNED:
753 return "MONO_TYPE_PINNED";
760 /*========================= End of Function ========================*/
762 /*------------------------------------------------------------------*/
764 /* Name - decodeParm */
766 /* Function - Decode a parameter for the trace. */
768 /*------------------------------------------------------------------*/
771 decodeParmString (MonoString *s)
774 char *str = mono_string_to_utf8_checked(s, &error);
775 if (is_ok (&error)) {
776 printf("[STRING:%p:%s], ", s, str);
779 mono_error_cleanup (&error);
780 printf("[STRING:%p:], ", s);
785 decodeParm(MonoType *type, void *curParm, int size)
790 printf("[BYREF:%p], ", *((char **) curParm));
792 simpleType = mini_get_underlying_type(type)->type;
794 switch (simpleType) {
796 printf ("[INTPTR:%p], ", *((int **) curParm));
799 printf ("[UINTPTR:%p], ", *((int **) curParm));
801 case MONO_TYPE_BOOLEAN :
802 printf ("[BOOL:%ld], ", *((gint64 *) curParm));
804 case MONO_TYPE_CHAR :
805 printf ("[CHAR:%c], ", *((int *) curParm));
808 printf ("[INT1:%ld], ", *((gint64 *) curParm));
811 printf ("[INT2:%ld], ", *((gint64 *) curParm));
814 printf ("[INT4:%ld], ", *((gint64 *) curParm));
817 printf ("[UINT1:%lu], ", *((guint64 *) curParm));
820 printf ("[UINT2:%lu], ", *((guint64 *) curParm));
823 printf ("[UINT4:%lu], ", *((guint64 *) curParm));
826 printf ("[UINT8:%lu], ", *((guint64 *) curParm));
828 case MONO_TYPE_STRING : {
829 MonoString *s = *((MonoString **) curParm);
831 g_assert (((MonoObject *) s)->vtable->klass == mono_defaults.string_class);
832 decodeParmString (s);
834 printf("[STRING:null], ");
838 case MONO_TYPE_CLASS :
839 case MONO_TYPE_OBJECT : {
840 MonoObject *obj = *((MonoObject **) curParm);
842 if ((obj) && (obj->vtable)) {
843 printf("[CLASS/OBJ:");
844 klass = obj->vtable->klass;
845 printf("%p [%p] ",obj,curParm);
846 if (klass == mono_defaults.string_class) {
847 decodeParmString ((MonoString *)obj);
848 } else if (klass == mono_defaults.int32_class) {
849 printf("[INT32:%p:%d]",
850 obj, *(gint32 *)((char *)obj + sizeof (MonoObject)));
853 klass->name_space, klass->name, obj);
856 printf("[OBJECT:null], ");
861 printf("[PTR:%p], ", *((gpointer **) (curParm)));
863 case MONO_TYPE_FNPTR :
864 printf("[FNPTR:%p], ", *((gpointer **) (curParm)));
866 case MONO_TYPE_ARRAY :
867 printf("[ARRAY:%p], ", *((gpointer **) (curParm)));
869 case MONO_TYPE_SZARRAY :
870 printf("[SZARRAY:%p], ", *((gpointer **) (curParm)));
873 printf("[INT8:%ld], ", *((gint64 *) (curParm)));
876 printf("[FLOAT4:%g], ", *((float *) (curParm)));
879 printf("[FLOAT8:%g], ", *((double *) (curParm)));
881 case MONO_TYPE_VALUETYPE : {
883 MonoMarshalType *info;
885 if (type->data.klass->enumtype) {
886 simpleType = mono_class_enum_basetype (type->data.klass)->type;
887 printf("{VALUETYPE} - ");
891 info = mono_marshal_load_type_info (type->data.klass);
893 if ((info->native_size == sizeof(float)) &&
894 (info->num_fields == 1) &&
895 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
896 printf("[FLOAT4:%f], ", *((float *) (curParm)));
900 if ((info->native_size == sizeof(double)) &&
901 (info->num_fields == 1) &&
902 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
903 printf("[FLOAT8:%g], ", *((double *) (curParm)));
907 printf("[VALUETYPE:");
908 for (i = 0; i < size; i++)
909 printf("%02x,", *((guint8 *)curParm+i));
913 case MONO_TYPE_TYPEDBYREF: {
915 printf("[TYPEDBYREF:");
916 for (i = 0; i < size; i++)
917 printf("%02x,", *((guint8 *)curParm+i));
922 printf("[%s], ",cvtMonoType(simpleType));
927 /*========================= End of Function ========================*/
929 /*------------------------------------------------------------------*/
931 /* Name - enter_method */
933 /* Function - Perform tracing of the entry to the current */
936 /*------------------------------------------------------------------*/
939 enter_method (MonoMethod *method, RegParm *rParm, char *sp)
941 int i, oParm = 0, iParm = 0;
944 MonoMethodSignature *sig;
951 fname = mono_method_full_name (method, TRUE);
953 printf ("ENTER: %s ", fname);
956 ip = (*(guint64 *) (sp+S390_RET_ADDR_OFFSET));
957 printf ("ip: %p sp: %p - ", (gpointer) ip, sp);
962 sig = mono_method_signature (method);
964 cinfo = get_call_info (NULL, NULL, sig);
966 if (cinfo->struct_ret) {
967 printf ("[STRUCTRET:%p], ", (gpointer) rParm->gr[0]);
972 gpointer *this_arg = (gpointer *) rParm->gr[iParm];
973 obj = (MonoObject *) this_arg;
974 switch(method->klass->this_arg.type) {
975 case MONO_TYPE_VALUETYPE:
977 guint64 *value = (guint64 *) ((uintptr_t)this_arg + sizeof(MonoObject));
978 printf("this:[value:%p:%016lx], ", this_arg, *value);
980 printf ("this:[NULL], ");
982 case MONO_TYPE_STRING:
985 klass = obj->vtable->klass;
986 if (klass == mono_defaults.string_class) {
988 decodeParmString((MonoString *)obj);
990 printf ("this:%p[%s.%s], ",
991 obj, klass->name_space, klass->name);
994 printf("vtable:[NULL], ");
996 printf ("this:[NULL], ");
999 printf("this[%s]: %p, ",cvtMonoType(method->klass->this_arg.type),this_arg);
1004 for (i = 0; i < sig->param_count; ++i) {
1005 ainfo = &cinfo->args[i + oParm];
1006 switch (ainfo->regtype) {
1007 case RegTypeGeneral :
1008 decodeParm(sig->params[i], &(rParm->gr[ainfo->reg-2]), ainfo->size);
1011 decodeParm(sig->params[i], &(rParm->fp[ainfo->reg]), ainfo->size);
1014 decodeParm(sig->params[i], sp+ainfo->offset, ainfo->size);
1016 case RegTypeStructByVal :
1017 if (ainfo->reg != STK_BASE) {
1018 int offset = sizeof(glong) - ainfo->size;
1019 curParm = &(rParm->gr[ainfo->reg-2])+offset;
1022 curParm = sp+ainfo->offset;
1024 if (retFitsInReg (ainfo->vtsize))
1025 decodeParm(sig->params[i],
1029 decodeParm(sig->params[i],
1030 *((char **) curParm),
1033 case RegTypeStructByAddr :
1034 if (ainfo->reg != STK_BASE)
1035 curParm = &(rParm->gr[ainfo->reg-2]);
1037 curParm = sp+ainfo->offset;
1039 decodeParm(sig->params[i],
1040 *((char **) curParm),
1052 /*========================= End of Function ========================*/
1054 /*------------------------------------------------------------------*/
1056 /* Name - leave_method */
1060 /*------------------------------------------------------------------*/
1063 leave_method (MonoMethod *method, ...)
1070 va_start(ap, method);
1072 fname = mono_method_full_name (method, TRUE);
1074 printf ("LEAVE: %s", fname);
1077 type = mono_method_signature (method)->ret;
1080 switch (type->type) {
1081 case MONO_TYPE_VOID:
1083 case MONO_TYPE_BOOLEAN: {
1084 int val = va_arg (ap, int);
1086 printf ("[TRUE:%d]", val);
1092 case MONO_TYPE_CHAR: {
1093 int val = va_arg (ap, int);
1094 printf ("[CHAR:%d]", val);
1097 case MONO_TYPE_I1: {
1098 int val = va_arg (ap, int);
1099 printf ("[INT1:%d]", val);
1102 case MONO_TYPE_U1: {
1103 int val = va_arg (ap, int);
1104 printf ("[UINT1:%d]", val);
1107 case MONO_TYPE_I2: {
1108 int val = va_arg (ap, int);
1109 printf ("[INT2:%d]", val);
1112 case MONO_TYPE_U2: {
1113 int val = va_arg (ap, int);
1114 printf ("[UINT2:%d]", val);
1117 case MONO_TYPE_I4: {
1118 int val = va_arg (ap, int);
1119 printf ("[INT4:%d]", val);
1122 case MONO_TYPE_U4: {
1123 int val = va_arg (ap, int);
1124 printf ("[UINT4:%d]", val);
1128 gint64 val = va_arg (ap, gint64);
1129 printf ("[INT:%ld]", val);
1134 gint64 val = va_arg (ap, gint64);
1135 printf ("[UINT:%lu]", val);
1139 case MONO_TYPE_STRING: {
1140 MonoString *s = va_arg (ap, MonoString *);
1143 g_assert (((MonoObject *)s)->vtable->klass == mono_defaults.string_class);
1144 decodeParmString (s);
1146 printf ("[STRING:null], ");
1149 case MONO_TYPE_CLASS:
1150 case MONO_TYPE_OBJECT: {
1151 MonoObject *o = va_arg (ap, MonoObject *);
1153 if ((o) && (o->vtable)) {
1154 if (o->vtable->klass == mono_defaults.boolean_class) {
1155 printf ("[BOOLEAN:%p:%d]", o, *((guint8 *)o + sizeof (MonoObject)));
1156 } else if (o->vtable->klass == mono_defaults.int32_class) {
1157 printf ("[INT32:%p:%d]", o, *((gint32 *)((char *)o + sizeof (MonoObject))));
1158 } else if (o->vtable->klass == mono_defaults.int64_class) {
1159 printf ("[INT64:%p:%ld]", o, *((gint64 *)((char *)o + sizeof (MonoObject))));
1161 printf ("[%s.%s:%p]", o->vtable->klass->name_space, o->vtable->klass->name, o);
1163 printf ("[OBJECT:%p]", o);
1168 case MONO_TYPE_FNPTR:
1169 case MONO_TYPE_ARRAY:
1170 case MONO_TYPE_SZARRAY: {
1171 gpointer p = va_arg (ap, gpointer);
1172 printf ("[result=%p]", p);
1175 case MONO_TYPE_I8: {
1176 gint64 l = va_arg (ap, gint64);
1177 printf ("[LONG:%ld]", l);
1180 case MONO_TYPE_U8: {
1181 guint64 l = va_arg (ap, guint64);
1182 printf ("[ULONG:%lu]", l);
1185 case MONO_TYPE_R4: {
1186 double f = va_arg (ap, double);
1187 printf ("[FLOAT4:%g]\n", f);
1190 case MONO_TYPE_R8: {
1191 double f = va_arg (ap, double);
1192 printf ("[FLOAT8:%g]\n", f);
1195 case MONO_TYPE_VALUETYPE: {
1196 MonoMarshalType *info;
1197 if (type->data.klass->enumtype) {
1198 type = mono_class_enum_basetype (type->data.klass);
1203 info = mono_marshal_load_type_info (type->data.klass);
1205 if ((info->native_size == sizeof(float)) &&
1206 (info->num_fields == 1) &&
1207 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1208 double f = va_arg (ap, double);
1209 printf("[FLOAT4:%g]\n", (double) f);
1213 if ((info->native_size == sizeof(double)) &&
1214 (info->num_fields == 1) &&
1215 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1216 double f = va_arg (ap, double);
1217 printf("[FLOAT8:%g]\n", f);
1221 size = mono_type_size (type, &align);
1224 guint32 p = va_arg (ap, guint32);
1225 printf ("[%02x]\n",p);
1229 guint32 p = va_arg (ap, guint32);
1230 printf ("[%04x]\n",p);
1234 guint32 p = va_arg (ap, guint32);
1235 printf ("[%08x]\n",p);
1239 guint64 p = va_arg (ap, guint64);
1240 printf ("[%016lx]\n",p);
1244 gpointer p = va_arg (ap, gpointer);
1245 printf ("[VALUETYPE] %p\n",p);
1251 case MONO_TYPE_TYPEDBYREF: {
1252 guint8 *p = va_arg (ap, gpointer);
1254 size = mono_type_size (type, &align);
1261 for (j = 0; p && j < size; j++)
1262 printf ("%02x,", p [j]);
1266 printf ("[TYPEDBYREF]\n");
1270 case MONO_TYPE_GENERICINST: {
1271 printf("[GENERICINST]\n");
1274 case MONO_TYPE_MVAR: {
1278 case MONO_TYPE_CMOD_REQD: {
1279 printf("[CMOD_REQD]\n");
1282 case MONO_TYPE_CMOD_OPT: {
1283 printf("[CMOD_OPT]\n");
1286 case MONO_TYPE_INTERNAL: {
1287 printf("[INTERNAL]\n");
1291 printf ("(unknown return type %x)",
1292 mono_method_signature (method)->ret->type);
1295 ip = ((gint64) __builtin_extract_return_addr (__builtin_return_address (0)));
1296 printf (" ip: %p\n", (gpointer) ip);
1299 /*========================= End of Function ========================*/
1301 /*------------------------------------------------------------------*/
1303 /* Name - mono_arch_cpu_init */
1305 /* Function - Perform CPU specific initialization to execute */
1308 /*------------------------------------------------------------------*/
1311 mono_arch_cpu_init (void)
1315 /*========================= End of Function ========================*/
1317 /*------------------------------------------------------------------*/
1319 /* Name - mono_arch_init. */
1321 /* Function - Initialize architecture specific code. */
1323 /*------------------------------------------------------------------*/
1326 mono_arch_init (void)
1330 mono_set_partial_sharing_supported (FALSE);
1331 mono_os_mutex_init_recursive (&mini_arch_mutex);
1333 ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ);
1334 bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ);
1335 mono_mprotect (bp_trigger_page, mono_pagesize (), 0);
1337 code = (guint8 *) &breakpointCode;
1338 s390_basr(code, s390_r13, 0);
1340 s390_llong(code, 0);
1341 s390_lg(code, s390_r13, 0, s390_r13, 4);
1342 s390_lg(code, s390_r0, 0, s390_r13, 0);
1345 /*========================= End of Function ========================*/
1347 /*------------------------------------------------------------------*/
1349 /* Name - mono_arch_cleanup. */
1351 /* Function - Cleanup architecture specific code . */
1353 /*------------------------------------------------------------------*/
1356 mono_arch_cleanup (void)
1358 if (ss_trigger_page)
1359 mono_vfree (ss_trigger_page, mono_pagesize ());
1360 if (bp_trigger_page)
1361 mono_vfree (bp_trigger_page, mono_pagesize ());
1362 mono_os_mutex_destroy (&mini_arch_mutex);
1365 /*========================= End of Function ========================*/
1367 /*------------------------------------------------------------------*/
1369 /* Name - mono_arch_cpu_optimizations */
1371 /* Function - Returns the optimizations supported on this CPU */
1373 /*------------------------------------------------------------------*/
1376 mono_arch_cpu_optimizations (guint32 *exclude_mask)
1380 /*----------------------------------------------------------*/
1381 /* No s390-specific optimizations yet */
1382 /*----------------------------------------------------------*/
1383 *exclude_mask = MONO_OPT_LINEARS;
1387 /*========================= End of Function ========================*/
1389 /*------------------------------------------------------------------*/
1391 /* Name - mono_arch_get_allocatable_int_vars */
1395 /*------------------------------------------------------------------*/
1398 mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
1403 for (i = 0; i < cfg->num_varinfo; i++) {
1404 MonoInst *ins = cfg->varinfo [i];
1405 MonoMethodVar *vmv = MONO_VARINFO (cfg, i);
1408 if (vmv->range.first_use.abs_pos >= vmv->range.last_use.abs_pos)
1411 if (ins->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) ||
1412 (ins->opcode != OP_LOCAL && ins->opcode != OP_ARG))
1415 /* we can only allocate 32 bit values */
1416 if (mono_is_regsize_var(ins->inst_vtype)) {
1417 g_assert (MONO_VARINFO (cfg, i)->reg == -1);
1418 g_assert (i == vmv->idx);
1419 vars = mono_varlist_insert_sorted (cfg, vars, vmv, FALSE);
1426 /*========================= End of Function ========================*/
1428 /*------------------------------------------------------------------*/
1430 /* Name - mono_arch_global_int_regs */
1432 /* Function - Return a list of usable integer registers. */
1434 /*------------------------------------------------------------------*/
1437 mono_arch_get_global_int_regs (MonoCompile *cfg)
1440 MonoMethodHeader *header;
1443 header = cfg->header;
1444 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
1445 cfg->frame_reg = s390_r11;
1448 /* FIXME: s390_r12 is reserved for bkchain_reg. Only reserve it if needed */
1450 for (i = 8; i < top; ++i) {
1451 if (cfg->frame_reg != i)
1452 regs = g_list_prepend (regs, GUINT_TO_POINTER (i));
1458 /*========================= End of Function ========================*/
1460 /*------------------------------------------------------------------*/
1462 /* Name - mono_arch_flush_icache */
1464 /* Function - Flush the CPU icache. */
1466 /*------------------------------------------------------------------*/
1469 mono_arch_flush_icache (guint8 *code, gint size)
1473 /*========================= End of Function ========================*/
1475 /*------------------------------------------------------------------*/
1477 /* Name - add_general */
1479 /* Function - Determine code and stack size incremements for a */
1482 /*------------------------------------------------------------------*/
1485 add_general (guint *gr, size_data *sz, ArgInfo *ainfo)
1487 if (*gr > S390_LAST_ARG_REG) {
1488 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1489 ainfo->offset = sz->stack_size;
1490 ainfo->reg = STK_BASE;
1491 ainfo->regtype = RegTypeBase;
1492 sz->stack_size += sizeof(long);
1493 sz->local_size += sizeof(long);
1494 sz->offStruct += sizeof(long);
1495 sz->code_size += 12;
1503 /*========================= End of Function ========================*/
1505 /*------------------------------------------------------------------*/
1507 /* Name - add_stackParm */
1509 /* Function - Determine code and stack size incremements for a */
1512 /*------------------------------------------------------------------*/
1515 add_stackParm (guint *gr, size_data *sz, ArgInfo *ainfo, gint size)
1517 if (*gr > S390_LAST_ARG_REG) {
1518 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1519 ainfo->reg = STK_BASE;
1520 ainfo->offset = sz->stack_size;
1521 ainfo->regtype = RegTypeStructByAddrOnStack;
1522 sz->stack_size += sizeof (gpointer);
1523 sz->parm_size += sizeof(gpointer);
1524 sz->offStruct += sizeof(gpointer);
1527 ainfo->offset = sz->stack_size;
1528 ainfo->regtype = RegTypeStructByAddr;
1531 ainfo->offparm = sz->offset;
1532 sz->offset = S390_ALIGN(sz->offset+size, sizeof(long));
1534 ainfo->vtsize = size;
1535 sz->parm_size += size;
1538 /*========================= End of Function ========================*/
1540 /*------------------------------------------------------------------*/
1542 /* Name - add_float */
1544 /* Function - Determine code and stack size incremements for a */
1545 /* float parameter. */
1547 /*------------------------------------------------------------------*/
1550 add_float (guint *fr, size_data *sz, ArgInfo *ainfo)
1552 if ((*fr) <= S390_LAST_FPARG_REG) {
1553 ainfo->regtype = RegTypeFP;
1559 ainfo->offset = sz->stack_size;
1560 ainfo->reg = STK_BASE;
1561 ainfo->regtype = RegTypeBase;
1563 sz->stack_size += sizeof(double);
1564 sz->local_size += sizeof(double);
1565 sz->offStruct += sizeof(double);
1569 /*========================= End of Function ========================*/
1571 /*------------------------------------------------------------------*/
1573 /* Name - get_call_info */
1575 /* Function - Determine the amount of space required for code */
1576 /* and stack. In addition determine starting points */
1577 /* for stack-based parameters, and area for struct- */
1578 /* ures being returned on the stack. */
1580 /*------------------------------------------------------------------*/
1583 get_call_info (MonoCompile *cfg, MonoMemPool *mp, MonoMethodSignature *sig)
1585 guint i, fr, gr, size, pstart;
1586 int nParm = sig->hasthis + sig->param_count;
1588 guint32 simpleType, align;
1589 gboolean is_pinvoke = sig->pinvoke;
1594 cinfo = mono_mempool_alloc0 (mp, sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1596 cinfo = g_malloc0 (sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1601 cinfo->struct_ret = 0;
1605 sz->offStruct = S390_MINIMAL_STACK_SIZE;
1606 sz->stack_size = S390_MINIMAL_STACK_SIZE;
1613 /*----------------------------------------------------------*/
1614 /* We determine the size of the return code/stack in case we*/
1615 /* need to reserve a register to be used to address a stack */
1616 /* area that the callee will use. */
1617 /*----------------------------------------------------------*/
1619 ret_type = mini_get_underlying_type (sig->ret);
1620 simpleType = ret_type->type;
1622 switch (simpleType) {
1623 case MONO_TYPE_BOOLEAN:
1628 case MONO_TYPE_CHAR:
1633 case MONO_TYPE_CLASS:
1634 case MONO_TYPE_OBJECT:
1635 case MONO_TYPE_SZARRAY:
1636 case MONO_TYPE_ARRAY:
1638 case MONO_TYPE_FNPTR:
1639 case MONO_TYPE_STRING:
1640 cinfo->ret.reg = s390_r2;
1645 cinfo->ret.reg = s390_f0;
1650 cinfo->ret.reg = s390_r2;
1653 case MONO_TYPE_GENERICINST:
1654 if (!mono_type_generic_inst_is_valuetype (sig->ret)) {
1655 cinfo->ret.reg = s390_r2;
1660 case MONO_TYPE_VALUETYPE: {
1661 MonoClass *klass = mono_class_from_mono_type (sig->ret);
1662 if (klass->enumtype) {
1663 simpleType = mono_class_enum_basetype (klass)->type;
1666 size = mini_type_stack_size_full (&klass->byval_arg, NULL, sig->pinvoke);
1668 cinfo->struct_ret = 1;
1669 cinfo->ret.size = size;
1670 cinfo->ret.vtsize = size;
1673 case MONO_TYPE_TYPEDBYREF:
1674 size = sizeof (MonoTypedRef);
1675 cinfo->struct_ret = 1;
1676 cinfo->ret.size = size;
1677 cinfo->ret.vtsize = size;
1679 case MONO_TYPE_VOID:
1682 g_error ("Can't handle as return value 0x%x", sig->ret->type);
1688 * To simplify get_this_arg_reg () and LLVM integration, emit the vret arg after
1689 * the first argument, allowing 'this' to be always passed in the first arg reg.
1690 * Also do this if the first argument is a reference type, since virtual calls
1691 * are sometimes made using calli without sig->hasthis set, like in the delegate
1694 if (cinfo->struct_ret && !is_pinvoke &&
1696 (sig->param_count > 0 &&
1697 MONO_TYPE_IS_REFERENCE (mini_get_underlying_type (sig->params [0]))))) {
1699 cinfo->args[nParm].size = sizeof (gpointer);
1700 add_general (&gr, sz, cinfo->args + nParm);
1702 cinfo->args[nParm].size = sizeof (gpointer);
1703 add_general (&gr, sz, &cinfo->args [sig->hasthis + nParm]);
1707 cinfo->vret_arg_index = 1;
1708 cinfo->ret.reg = gr;
1713 cinfo->args[nParm].size = sizeof (gpointer);
1714 add_general (&gr, sz, cinfo->args + nParm);
1718 if (cinfo->struct_ret) {
1719 cinfo->ret.reg = gr;
1724 if ((sig->call_convention == MONO_CALL_VARARG) && (sig->param_count == 0)) {
1725 gr = S390_LAST_ARG_REG + 1;
1726 fr = S390_LAST_FPARG_REG + 1;
1728 /* Emit the signature cookie just before the implicit arguments */
1729 add_general (&gr, sz, &cinfo->sigCookie);
1732 /*----------------------------------------------------------*/
1733 /* We determine the size of the parameter code and stack */
1734 /* requirements by checking the types and sizes of the */
1736 /*----------------------------------------------------------*/
1738 for (i = pstart; i < sig->param_count; ++i) {
1741 /*--------------------------------------------------*/
1742 /* Handle vararg type calls. All args are put on */
1744 /*--------------------------------------------------*/
1745 if ((sig->call_convention == MONO_CALL_VARARG) &&
1746 (i == sig->sentinelpos)) {
1747 gr = S390_LAST_ARG_REG + 1;
1748 fr = S390_LAST_FPARG_REG + 1;
1749 add_general (&gr, sz, &cinfo->sigCookie);
1752 if (sig->params [i]->byref) {
1753 add_general (&gr, sz, cinfo->args+nParm);
1754 cinfo->args[nParm].size = sizeof(gpointer);
1759 ptype = mini_get_underlying_type (sig->params [i]);
1760 simpleType = ptype->type;
1761 cinfo->args[nParm].type = simpleType;
1762 switch (simpleType) {
1763 case MONO_TYPE_BOOLEAN:
1766 cinfo->args[nParm].size = sizeof(char);
1767 add_general (&gr, sz, cinfo->args+nParm);
1772 case MONO_TYPE_CHAR:
1773 cinfo->args[nParm].size = sizeof(short);
1774 add_general (&gr, sz, cinfo->args+nParm);
1779 cinfo->args[nParm].size = sizeof(int);
1780 add_general (&gr, sz, cinfo->args+nParm);
1786 case MONO_TYPE_FNPTR:
1787 case MONO_TYPE_CLASS:
1788 case MONO_TYPE_OBJECT:
1789 case MONO_TYPE_STRING:
1790 case MONO_TYPE_SZARRAY:
1791 case MONO_TYPE_ARRAY:
1792 cinfo->args[nParm].size = sizeof(gpointer);
1793 add_general (&gr, sz, cinfo->args+nParm);
1798 cinfo->args[nParm].size = sizeof(long long);
1799 add_general (&gr, sz, cinfo->args+nParm);
1803 cinfo->args[nParm].size = sizeof(float);
1804 add_float (&fr, sz, cinfo->args+nParm);
1808 cinfo->args[nParm].size = sizeof(double);
1809 add_float (&fr, sz, cinfo->args+nParm);
1812 case MONO_TYPE_GENERICINST:
1813 if (!mono_type_generic_inst_is_valuetype (ptype)) {
1814 cinfo->args[nParm].size = sizeof(gpointer);
1815 add_general (&gr, sz, cinfo->args+nParm);
1820 case MONO_TYPE_VALUETYPE: {
1821 MonoMarshalType *info;
1822 MonoClass *klass = mono_class_from_mono_type (ptype);
1825 size = mono_class_native_size(klass, NULL);
1827 size = mono_class_value_size(klass, NULL);
1829 if (simpleType != MONO_TYPE_GENERICINST) {
1830 info = mono_marshal_load_type_info(klass);
1832 if ((info->native_size == sizeof(float)) &&
1833 (info->num_fields == 1) &&
1834 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1835 cinfo->args[nParm].size = sizeof(float);
1836 add_float(&fr, sz, cinfo->args+nParm);
1841 if ((info->native_size == sizeof(double)) &&
1842 (info->num_fields == 1) &&
1843 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1844 cinfo->args[nParm].size = sizeof(double);
1845 add_float(&fr, sz, cinfo->args+nParm);
1851 cinfo->args[nParm].vtsize = 0;
1852 cinfo->args[nParm].size = 0;
1855 /*----------------------------------*/
1856 /* On S/390, structures of size 1, */
1857 /* 2, 4, and 8 bytes are passed in */
1858 /* (a) register(s). */
1859 /*----------------------------------*/
1865 add_general(&gr, sz, cinfo->args+nParm);
1866 cinfo->args[nParm].size = size;
1867 cinfo->args[nParm].regtype = RegTypeStructByVal;
1869 sz->local_size += sizeof(long);
1872 add_stackParm(&gr, sz, cinfo->args+nParm, size);
1877 case MONO_TYPE_TYPEDBYREF: {
1878 int size = sizeof (MonoTypedRef);
1880 cinfo->args[nParm].vtsize = 0;
1881 cinfo->args[nParm].size = 0;
1884 /*----------------------------------*/
1885 /* On S/390, structures of size 1, */
1886 /* 2, 4, and 8 bytes are passed in */
1887 /* (a) register(s). */
1888 /*----------------------------------*/
1894 add_general(&gr, sz, cinfo->args+nParm);
1895 cinfo->args[nParm].size = size;
1896 cinfo->args[nParm].regtype = RegTypeStructByVal;
1898 sz->local_size += sizeof(long);
1901 add_stackParm(&gr, sz, cinfo->args+nParm, size);
1907 g_error ("Can't trampoline 0x%x", ptype);
1911 /*----------------------------------------------------------*/
1912 /* Handle the case where there are no implicit arguments */
1913 /*----------------------------------------------------------*/
1914 if ((sig->call_convention == MONO_CALL_VARARG) &&
1917 (sig->param_count == sig->sentinelpos)) {
1918 gr = S390_LAST_ARG_REG + 1;
1919 fr = S390_LAST_FPARG_REG + 1;
1920 add_general (&gr, sz, &cinfo->sigCookie);
1923 /*----------------------------------------------------------*/
1924 /* If we are passing a structure back then if it won't be */
1925 /* in a register(s) then we make room at the end of the */
1926 /* parameters that may have been placed on the stack */
1927 /*----------------------------------------------------------*/
1928 if (cinfo->struct_ret) {
1929 cinfo->ret.offset = sz->stack_size;
1930 switch (cinfo->ret.size) {
1938 sz->stack_size += S390_ALIGN(cinfo->ret.size, align);
1943 sz->stack_size = sz->stack_size + sz->local_size + sz->parm_size +
1945 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1950 /*========================= End of Function ========================*/
1952 /*------------------------------------------------------------------*/
1954 /* Name - mono_arch_allocate_vars */
1956 /* Function - Set var information according to the calling */
1957 /* convention for S/390. The local var stuff should */
1958 /* most likely be split in another method. */
1960 /* Parameter - @m - Compile unit. */
1962 /*------------------------------------------------------------------*/
1965 mono_arch_allocate_vars (MonoCompile *cfg)
1967 MonoMethodSignature *sig;
1968 MonoMethodHeader *header;
1971 int iParm, iVar, offset, align, size, curinst;
1972 int frame_reg = STK_BASE;
1975 header = cfg->header;
1977 cfg->flags |= MONO_CFG_HAS_SPILLUP;
1979 /*---------------------------------------------------------*/
1980 /* We use the frame register also for any method that has */
1981 /* filter clauses. This way, when the handlers are called, */
1982 /* the code will reference local variables using the frame */
1983 /* reg instead of the stack pointer: if we had to restore */
1984 /* the stack pointer, we'd corrupt the method frames that */
1985 /* are already on the stack (since filters get called */
1986 /* before stack unwinding happens) when the filter code */
1987 /* would call any method. */
1988 /*---------------------------------------------------------*/
1989 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
1990 frame_reg = s390_r11;
1992 cfg->frame_reg = frame_reg;
1994 cfg->arch.bkchain_reg = -1;
1996 if (frame_reg != STK_BASE)
1997 cfg->used_int_regs |= (1 << frame_reg);
1999 if (cfg->uses_rgctx_reg)
2000 cfg->used_int_regs |= (1 << MONO_ARCH_IMT_REG);
2002 sig = mono_method_signature (cfg->method);
2004 cinfo = get_call_info (cfg, cfg->mempool, sig);
2006 if (!cinfo->struct_ret) {
2007 switch (mini_get_underlying_type (sig->ret)->type) {
2008 case MONO_TYPE_VOID:
2011 cfg->ret->opcode = OP_REGVAR;
2012 cfg->ret->dreg = s390_r2;
2017 /*--------------------------------------------------------------*/
2018 /* local vars are at a positive offset from the stack pointer */
2019 /* also note that if the function uses alloca, we use s390_r11 */
2020 /* to point at the local variables. */
2021 /* add parameter area size for called functions */
2022 /*--------------------------------------------------------------*/
2023 if (cfg->param_area == 0)
2024 offset = S390_MINIMAL_STACK_SIZE;
2026 offset = cfg->param_area;
2028 cfg->sig_cookie = 0;
2030 if (cinfo->struct_ret) {
2031 inst = cfg->vret_addr;
2032 offset = S390_ALIGN(offset, sizeof(gpointer));
2033 inst->inst_offset = offset;
2034 inst->opcode = OP_REGOFFSET;
2035 inst->inst_basereg = frame_reg;
2036 offset += sizeof(gpointer);
2037 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2038 printf ("vret_addr =");
2039 mono_print_ins (cfg->vret_addr);
2044 inst = cfg->args [0];
2045 if (inst->opcode != OP_REGVAR) {
2046 inst->opcode = OP_REGOFFSET;
2047 inst->inst_basereg = frame_reg;
2048 offset = S390_ALIGN(offset, sizeof(gpointer));
2049 inst->inst_offset = offset;
2050 offset += sizeof (gpointer);
2057 eArg = sig->param_count + sArg;
2059 if (sig->call_convention == MONO_CALL_VARARG)
2060 cfg->sig_cookie += S390_MINIMAL_STACK_SIZE;
2062 for (iParm = sArg; iParm < eArg; ++iParm) {
2063 inst = cfg->args [curinst];
2064 if (inst->opcode != OP_REGVAR) {
2065 switch (cinfo->args[iParm].regtype) {
2066 case RegTypeStructByAddr : {
2069 size = sizeof (gpointer);
2071 inst->opcode = OP_REGOFFSET;
2072 inst->inst_basereg = frame_reg;
2073 offset = S390_ALIGN (offset, sizeof (gpointer));
2074 inst->inst_offset = offset;
2076 /* Add a level of indirection */
2077 MONO_INST_NEW (cfg, indir, 0);
2079 inst->opcode = OP_VTARG_ADDR;
2080 inst->inst_left = indir;
2083 case RegTypeStructByAddrOnStack : {
2086 size = sizeof (gpointer);
2088 /* Similar to the == STK_BASE case below */
2089 cfg->arch.bkchain_reg = s390_r12;
2090 cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2092 inst->opcode = OP_REGOFFSET;
2093 inst->dreg = mono_alloc_preg (cfg);
2094 inst->inst_basereg = cfg->arch.bkchain_reg;
2095 inst->inst_offset = cinfo->args [iParm].offset;
2097 /* Add a level of indirection */
2098 MONO_INST_NEW (cfg, indir, 0);
2100 inst->opcode = OP_VTARG_ADDR;
2101 inst->inst_left = indir;
2104 case RegTypeStructByVal :
2105 size = cinfo->args[iParm].size;
2106 offset = S390_ALIGN(offset, size);
2107 inst->opcode = OP_REGOFFSET;
2108 inst->inst_basereg = frame_reg;
2109 inst->inst_offset = offset;
2112 if (cinfo->args [iParm].reg == STK_BASE) {
2114 * These arguments are in the previous frame, so we can't
2115 * compute their offset from the current frame pointer right
2116 * now, since cfg->stack_offset is not yet known, so dedicate a
2117 * register holding the previous frame pointer.
2119 cfg->arch.bkchain_reg = s390_r12;
2120 cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2122 inst->opcode = OP_REGOFFSET;
2123 inst->inst_basereg = cfg->arch.bkchain_reg;
2124 size = (cinfo->args[iParm].size < 8
2125 ? 8 - cinfo->args[iParm].size
2127 inst->inst_offset = cinfo->args [iParm].offset + size;
2128 size = sizeof (long);
2130 inst->opcode = OP_REGOFFSET;
2131 inst->inst_basereg = frame_reg;
2132 size = (cinfo->args[iParm].size < 8
2135 offset = S390_ALIGN(offset, size);
2136 if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
2137 inst->inst_offset = offset;
2139 inst->inst_offset = offset + (8 - size);
2144 if ((sig->call_convention == MONO_CALL_VARARG) &&
2145 (cinfo->args[iParm].regtype != RegTypeGeneral) &&
2146 (iParm < sig->sentinelpos))
2147 cfg->sig_cookie += size;
2148 printf("%s %4d cookine %x\n",__FUNCTION__,__LINE__,cfg->sig_cookie);
2151 offset += MAX(size, 8);
2156 cfg->locals_min_stack_offset = offset;
2158 curinst = cfg->locals_start;
2159 for (iVar = curinst; iVar < cfg->num_varinfo; ++iVar) {
2160 inst = cfg->varinfo [iVar];
2161 if ((inst->flags & MONO_INST_IS_DEAD) ||
2162 (inst->opcode == OP_REGVAR))
2165 /*--------------------------------------------------*/
2166 /* inst->backend.is_pinvoke indicates native sized */
2167 /* value typs this is used by the pinvoke wrappers */
2168 /* when they call functions returning structure */
2169 /*--------------------------------------------------*/
2170 if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype))
2171 size = mono_class_native_size (mono_class_from_mono_type(inst->inst_vtype),
2172 (guint32 *) &align);
2174 size = mono_type_size (inst->inst_vtype, &align);
2176 offset = S390_ALIGN(offset, align);
2177 inst->inst_offset = offset;
2178 inst->opcode = OP_REGOFFSET;
2179 inst->inst_basereg = frame_reg;
2181 DEBUG (g_print("allocating local %d to %ld, size: %d\n",
2182 iVar, inst->inst_offset, size));
2185 cfg->locals_max_stack_offset = offset;
2187 /*------------------------------------------------------*/
2188 /* Allow space for the trace method stack area if needed*/
2189 /*------------------------------------------------------*/
2190 if ((mono_jit_trace_calls != NULL && mono_trace_eval (cfg->method))
2191 || (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE))
2192 offset += S390_TRACE_STACK_SIZE;
2194 /*------------------------------------------------------*/
2195 /* Reserve space to save LMF and caller saved registers */
2196 /*------------------------------------------------------*/
2197 if (cfg->method->save_lmf)
2198 offset += sizeof (MonoLMF);
2200 /*------------------------------------------------------*/
2201 /* align the offset */
2202 /*------------------------------------------------------*/
2203 cfg->stack_offset = S390_ALIGN(offset, S390_STACK_ALIGNMENT);
2205 /*------------------------------------------------------*/
2206 /* Fix offsets for args whose value is in parent frame */
2207 /*------------------------------------------------------*/
2208 for (iParm = sArg; iParm < eArg; ++iParm) {
2209 inst = cfg->args [iParm];
2211 if (inst->opcode == OP_S390_STKARG) {
2212 inst->opcode = OP_REGOFFSET;
2213 inst->inst_offset += cfg->stack_offset;
2218 /*========================= End of Function ========================*/
2220 /*------------------------------------------------------------------*/
2222 /* Name - mono_arch_create_vars */
2224 /*------------------------------------------------------------------*/
2227 mono_arch_create_vars (MonoCompile *cfg)
2229 MonoMethodSignature *sig;
2232 sig = mono_method_signature (cfg->method);
2234 cinfo = get_call_info (cfg, cfg->mempool, sig);
2236 if (cinfo->struct_ret) {
2237 cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG);
2238 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2239 printf ("vret_addr = ");
2240 mono_print_ins (cfg->vret_addr);
2245 /*========================= End of Function ========================*/
2247 /*------------------------------------------------------------------*/
2249 /* Name - add_outarg_reg2. */
2251 /*------------------------------------------------------------------*/
2254 add_outarg_reg2 (MonoCompile *cfg, MonoCallInst *call, ArgStorage storage, int reg, MonoInst *tree)
2259 case RegTypeGeneral:
2260 MONO_INST_NEW (cfg, ins, OP_MOVE);
2261 ins->dreg = mono_alloc_ireg (cfg);
2262 ins->sreg1 = tree->dreg;
2263 MONO_ADD_INS (cfg->cbb, ins);
2264 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, FALSE);
2267 MONO_INST_NEW (cfg, ins, OP_FMOVE);
2268 ins->dreg = mono_alloc_freg (cfg);
2269 ins->sreg1 = tree->dreg;
2270 MONO_ADD_INS (cfg->cbb, ins);
2271 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2274 MONO_INST_NEW (cfg, ins, OP_S390_SETF4RET);
2275 ins->dreg = mono_alloc_freg (cfg);
2276 ins->sreg1 = tree->dreg;
2277 MONO_ADD_INS (cfg->cbb, ins);
2278 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2281 g_assert_not_reached ();
2285 /*========================= End of Function ========================*/
2287 /*------------------------------------------------------------------*/
2289 /* Name - emit_sig_cookie. */
2291 /*------------------------------------------------------------------*/
2294 emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo)
2296 MonoMethodSignature *tmpSig;
2299 cfg->disable_aot = TRUE;
2301 /*----------------------------------------------------------*/
2302 /* mono_ArgIterator_Setup assumes the signature cookie is */
2303 /* passed first and all the arguments which were before it */
2304 /* passed on the stack after the signature. So compensate */
2305 /* by passing a different signature. */
2306 /*----------------------------------------------------------*/
2307 tmpSig = mono_metadata_signature_dup (call->signature);
2308 tmpSig->param_count -= call->signature->sentinelpos;
2309 tmpSig->sentinelpos = 0;
2310 if (tmpSig->param_count > 0)
2311 memcpy (tmpSig->params,
2312 call->signature->params + call->signature->sentinelpos,
2313 tmpSig->param_count * sizeof(MonoType *));
2315 MONO_INST_NEW (cfg, sig_arg, OP_ICONST);
2316 sig_arg->dreg = mono_alloc_ireg (cfg);
2317 sig_arg->inst_p0 = tmpSig;
2318 MONO_ADD_INS (cfg->cbb, sig_arg);
2320 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, STK_BASE,
2321 cinfo->sigCookie.offset, sig_arg->dreg);
2324 /*========================= End of Function ========================*/
2326 /*------------------------------------------------------------------*/
2328 /* Name - mono_arch_emit_call */
2330 /*------------------------------------------------------------------*/
2333 mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
2336 MonoMethodSignature *sig;
2338 int i, n, lParamArea;
2340 ArgInfo *ainfo = NULL;
2342 MonoMethodHeader *header;
2345 sig = call->signature;
2346 n = sig->param_count + sig->hasthis;
2347 DEBUG (g_print ("Call requires: %d parameters\n",n));
2349 cinfo = get_call_info (cfg, cfg->mempool, sig);
2351 stackSize = cinfo->sz.stack_size + cinfo->sz.local_size +
2352 cinfo->sz.parm_size + cinfo->sz.offset;
2353 call->stack_usage = MAX(stackSize, call->stack_usage);
2354 lParamArea = MAX((call->stack_usage-S390_MINIMAL_STACK_SIZE-cinfo->sz.parm_size), 0);
2355 cfg->param_area = MAX(((signed) cfg->param_area), lParamArea);
2356 cfg->flags |= MONO_CFG_HAS_CALLS;
2358 if (cinfo->struct_ret) {
2359 MONO_INST_NEW (cfg, ins, OP_MOVE);
2360 ins->sreg1 = call->vret_var->dreg;
2361 ins->dreg = mono_alloc_preg (cfg);
2362 MONO_ADD_INS (cfg->cbb, ins);
2363 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, cinfo->ret.reg, FALSE);
2366 header = cfg->header;
2367 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2372 for (i = 0; i < n; ++i) {
2375 ainfo = cinfo->args + i;
2376 if (i >= sig->hasthis)
2377 t = sig->params [i - sig->hasthis];
2379 t = &mono_defaults.int_class->byval_arg;
2380 t = mini_get_underlying_type (t);
2382 in = call->args [i];
2384 if ((sig->call_convention == MONO_CALL_VARARG) &&
2386 (i == sig->sentinelpos)) {
2387 emit_sig_cookie (cfg, call, cinfo);
2390 switch (ainfo->regtype) {
2391 case RegTypeGeneral:
2392 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2395 if (MONO_TYPE_ISSTRUCT (t)) {
2396 /* Valuetype passed in one fp register */
2397 ainfo->regtype = RegTypeStructByValInFP;
2400 if (ainfo->size == 4)
2401 ainfo->regtype = RegTypeFPR4;
2402 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2405 case RegTypeStructByVal:
2406 case RegTypeStructByAddr:
2407 case RegTypeStructByAddrOnStack: {
2411 if (sig->params [i - sig->hasthis]->type == MONO_TYPE_TYPEDBYREF) {
2412 size = sizeof (MonoTypedRef);
2413 align = sizeof (gpointer);
2417 size = mono_type_native_stack_size (&in->klass->byval_arg, &align);
2420 * Other backends use mono_type_stack_size (), but that
2421 * aligns the size to 8, which is larger than the size of
2422 * the source, leading to reads of invalid memory if the
2423 * source is at the end of address space.
2425 size = mono_class_value_size (in->klass, &align);
2428 g_assert (in->klass);
2430 ainfo->offparm += cinfo->sz.offStruct;
2432 MONO_INST_NEW (cfg, ins, OP_OUTARG_VT);
2433 ins->sreg1 = in->dreg;
2434 ins->klass = in->klass;
2435 ins->backend.size = ainfo->size;
2436 ins->inst_p0 = call;
2437 ins->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
2438 memcpy (ins->inst_p1, ainfo, sizeof (ArgInfo));
2440 MONO_ADD_INS (cfg->cbb, ins);
2442 if (ainfo->regtype == RegTypeStructByAddr) {
2444 * We use OP_OUTARG_VT to copy the valuetype to a stack location, then
2445 * use the normal OUTARG opcodes to pass the address of the location to
2448 int treg = mono_alloc_preg (cfg);
2449 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2450 frmReg, ainfo->offparm);
2451 mono_call_inst_add_outarg_reg (cfg, call, treg, ainfo->reg, FALSE);
2452 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
2453 /* The address of the valuetype is passed on the stack */
2454 int treg = mono_alloc_preg (cfg);
2455 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2456 frmReg, ainfo->offparm);
2457 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG,
2458 ainfo->reg, ainfo->offset, treg);
2460 if (cfg->compute_gc_maps) {
2463 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, t);
2469 if (!t->byref && t->type == MONO_TYPE_R4) {
2470 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG,
2471 STK_BASE, ainfo->offset + 4,
2473 } else if (!t->byref && (t->type == MONO_TYPE_R8)) {
2474 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG,
2475 STK_BASE, ainfo->offset,
2478 MONO_INST_NEW (cfg, ins, OP_STORE_MEMBASE_REG);
2479 ins->inst_destbasereg = STK_BASE;
2480 ins->inst_offset = ainfo->offset;
2481 ins->sreg1 = in->dreg;
2484 /* This is needed by MonoTypedRef->value to point to the correct data */
2485 if ((sig->call_convention == MONO_CALL_VARARG) &&
2486 (i >= sig->sentinelpos)) {
2487 switch (ainfo->size) {
2489 ins->opcode = OP_STOREI1_MEMBASE_REG;
2492 ins->opcode = OP_STOREI2_MEMBASE_REG;
2495 ins->opcode = OP_STOREI4_MEMBASE_REG;
2503 MONO_ADD_INS (cfg->cbb, ins);
2507 g_assert_not_reached ();
2513 * Handle the case where there are no implicit arguments
2515 if ((sig->call_convention == MONO_CALL_VARARG) &&
2517 (i == sig->sentinelpos)) {
2518 emit_sig_cookie (cfg, call, cinfo);
2522 /*========================= End of Function ========================*/
2524 /*------------------------------------------------------------------*/
2526 /* Name - mono_arch_emit_outarg_vt */
2528 /*------------------------------------------------------------------*/
2531 mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
2533 MonoCallInst *call = (MonoCallInst*)ins->inst_p0;
2534 ArgInfo *ainfo = (ArgInfo*)ins->inst_p1;
2535 int size = ins->backend.size;
2537 if (ainfo->regtype == RegTypeStructByVal) {
2539 arg->ins.sreg1 = ainfo->reg;
2540 arg->ins.opcode = OP_OUTARG_VT;
2541 arg->size = ainfo->size;
2542 arg->offset = ainfo->offset;
2543 arg->offPrm = ainfo->offparm + cinfo->sz.offStruct;
2545 if (ainfo->reg != STK_BASE) {
2546 MONO_OUTPUT_VTR (cfg, size, ainfo->reg, src->dreg, 0);
2548 MONO_OUTPUT_VTS (cfg, size, ainfo->reg, ainfo->offset,
2551 } else if (ainfo->regtype == RegTypeStructByValInFP) {
2552 int dreg = mono_alloc_freg (cfg);
2554 if (ainfo->size == 4) {
2555 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR4_MEMBASE, dreg, src->dreg, 0);
2556 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, dreg, dreg);
2558 g_assert (ainfo->size == 8);
2560 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR8_MEMBASE, dreg, src->dreg, 0);
2563 mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg, TRUE);
2566 MonoMethodHeader *header;
2569 header = mono_method_get_header_checked (cfg->method, &error);
2570 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
2571 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2576 MONO_EMIT_NEW_MOVE (cfg, srcReg, ainfo->offparm,
2577 src->dreg, 0, size);
2579 if (cfg->compute_gc_maps) {
2582 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, &ins->klass->byval_arg);
2587 /*========================= End of Function ========================*/
2589 /*------------------------------------------------------------------*/
2591 /* Name - mono_arch_emit_setret */
2593 /*------------------------------------------------------------------*/
2596 mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
2598 MonoType *ret = mini_get_underlying_type (mono_method_signature (method)->ret);
2601 if (ret->type == MONO_TYPE_R4) {
2602 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, s390_f0, val->dreg);
2604 } else if (ret->type == MONO_TYPE_R8) {
2605 MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, s390_f0, val->dreg);
2610 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg);
2613 /*========================= End of Function ========================*/
2615 /*------------------------------------------------------------------*/
2617 /* Name - mono_arch_instrument_mem_needs */
2619 /* Function - Allow tracing to work with this interface (with */
2620 /* an optional argument). */
2622 /*------------------------------------------------------------------*/
2625 mono_arch_instrument_mem_needs (MonoMethod *method, int *stack, int *code)
2627 /* no stack room needed now (may be needed for FASTCALL-trace support) */
2629 /* split prolog-epilog requirements? */
2630 *code = 50; /* max bytes needed: check this number */
2633 /*========================= End of Function ========================*/
2635 /*------------------------------------------------------------------*/
2637 /* Name - mono_arch_instrument_prolog */
2639 /* Function - Create an "instrumented" prolog. */
2641 /*------------------------------------------------------------------*/
2644 mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p,
2645 gboolean enable_arguments)
2652 parmOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2653 if (cfg->method->save_lmf)
2654 parmOffset -= sizeof(MonoLMF);
2655 fpOffset = parmOffset + (5*sizeof(gpointer));
2658 s390_stmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2659 s390_stdy (code, s390_f0, 0, STK_BASE, fpOffset);
2660 s390_stdy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2661 s390_stdy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2662 s390_stdy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2663 S390_SET (code, s390_r1, func);
2664 S390_SET (code, s390_r2, cfg->method);
2665 s390_lay (code, s390_r3, 0, STK_BASE, parmOffset);
2666 s390_lgr (code, s390_r4, STK_BASE);
2667 s390_aghi (code, s390_r4, cfg->stack_usage);
2668 s390_basr (code, s390_r14, s390_r1);
2669 s390_ldy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2670 s390_ldy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2671 s390_ldy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2672 s390_ldy (code, s390_f0, 0, STK_BASE, fpOffset);
2673 s390_lmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2678 /*========================= End of Function ========================*/
2680 /*------------------------------------------------------------------*/
2682 /* Name - mono_arch_instrument_epilog */
2684 /* Function - Create an epilog that will handle the returned */
2685 /* values used in instrumentation. */
2687 /*------------------------------------------------------------------*/
2690 mono_arch_instrument_epilog_full (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments, gboolean preserve_argument_registers)
2693 int save_mode = SAVE_NONE,
2696 MonoMethod *method = cfg->method;
2697 int rtype = mini_get_underlying_type (mono_method_signature (method)->ret)->type;
2699 offset = code - cfg->native_code;
2700 /*-----------------------------------------*/
2701 /* We need about 128 bytes of instructions */
2702 /*-----------------------------------------*/
2703 if (offset > (cfg->code_size - 128)) {
2704 cfg->code_size *= 2;
2705 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
2706 code = cfg->native_code + offset;
2709 saveOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2710 if (method->save_lmf)
2711 saveOffset -= sizeof(MonoLMF);
2715 case MONO_TYPE_VOID:
2716 /* special case string .ctor icall */
2717 if (strcmp (".ctor", method->name) && method->klass == mono_defaults.string_class)
2718 save_mode = SAVE_ONE;
2720 save_mode = SAVE_NONE;
2724 save_mode = SAVE_ONE;
2727 save_mode = SAVE_R4;
2730 save_mode = SAVE_R8;
2732 case MONO_TYPE_VALUETYPE:
2733 if (mono_method_signature (method)->ret->data.klass->enumtype) {
2734 rtype = mono_class_enum_basetype (mono_method_signature (method)->ret->data.klass)->type;
2737 save_mode = SAVE_STRUCT;
2740 save_mode = SAVE_ONE;
2744 switch (save_mode) {
2746 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2747 if (enable_arguments) {
2748 s390_lgr (code, s390_r3, s390_r2);
2752 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2753 if (enable_arguments) {
2754 s390_ldebr (code, s390_f0, s390_f0);
2758 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2761 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2762 if (enable_arguments) {
2763 s390_lg (code, s390_r3, 0, cfg->frame_reg,
2764 S390_MINIMAL_STACK_SIZE+cfg->param_area);
2772 S390_SET (code, s390_r1, func);
2773 S390_SET (code, s390_r2, cfg->method);
2774 s390_basr (code, s390_r14, s390_r1);
2776 switch (save_mode) {
2778 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2782 s390_ld (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2785 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2795 /*========================= End of Function ========================*/
2797 /*------------------------------------------------------------------*/
2799 /* Name - mono_arch_peephole_pass_1 */
2801 /* Function - Form a peephole pass at the code looking for */
2802 /* simple optimizations. */
2804 /*------------------------------------------------------------------*/
2807 mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
2811 /*========================= End of Function ========================*/
2813 /*------------------------------------------------------------------*/
2815 /* Name - mono_arch_peephole_pass_2 */
2817 /* Function - Form a peephole pass at the code looking for */
2818 /* simple optimizations. */
2820 /*------------------------------------------------------------------*/
2823 mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
2827 MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
2828 mono_peephole_ins (bb, ins);
2832 /*========================= End of Function ========================*/
2834 /*------------------------------------------------------------------*/
2836 /* Name - mono_arch_lowering_pass. */
2838 /*------------------------------------------------------------------*/
2841 mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
2843 MonoInst *ins, *next;
2845 MONO_BB_FOR_EACH_INS_SAFE (bb, next, ins) {
2846 switch (ins->opcode) {
2851 case OP_IDIV_UN_IMM:
2852 case OP_IREM_UN_IMM:
2857 case OP_LOCALLOC_IMM:
2858 mono_decompose_op_imm (cfg, bb, ins);
2861 if (!s390_is_imm16 (ins->inst_imm))
2862 /* This is created by the memcpy code which ignores is_inst_imm */
2863 mono_decompose_op_imm (cfg, bb, ins);
2870 bb->max_vreg = cfg->next_vreg;
2873 /*========================= End of Function ========================*/
2875 /*------------------------------------------------------------------*/
2877 /* Name - emit_float_to_int */
2879 /* Function - Create instructions which will convert a floating */
2880 /* point value to integer. */
2882 /*------------------------------------------------------------------*/
2885 emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size, gboolean is_signed)
2887 /* sreg is a float, dreg is an integer reg. */
2889 s390_cgdbr (code, dreg, 5, sreg);
2892 s390_ltgr (code, dreg, dreg);
2894 s390_oill (code, dreg, 0x80);
2895 s390_lghi (code, s390_r0, 0xff);
2896 s390_ngr (code, dreg, s390_r0);
2899 s390_ltgr (code, dreg, dreg);
2901 s390_oill (code, dreg, 0x8000);
2902 s390_llill(code, s390_r0, 0xffff);
2903 s390_ngr (code, dreg, s390_r0);
2908 S390_SET (code, s390_r13, 0x41e0000000000000llu);
2909 s390_ldgr (code, s390_f14, s390_r13);
2910 s390_ldr (code, s390_f15, sreg);
2911 s390_cdbr (code, s390_f15, s390_f14);
2912 s390_jl (code, 0); CODEPTR (code, o[0]);
2913 S390_SET (code, s390_r13, 0x41f0000000000000llu);
2914 s390_ldgr (code, s390_f14, s390_r13);
2915 s390_sdbr (code, s390_f15, s390_f14);
2916 s390_cfdbr (code, dreg, 7, s390_f15);
2918 PTRSLOT (code, o[0]);
2919 s390_cfdbr (code, dreg, 5, sreg);
2922 s390_lghi (code, s390_r0, 0xff);
2923 s390_ngr (code, dreg, s390_r0);
2926 s390_llill(code, s390_r0, 0xffff);
2927 s390_ngr (code, dreg, s390_r0);
2934 /*========================= End of Function ========================*/
2936 /*------------------------------------------------------------------*/
2938 /* Name - gboolean_is_unsigned. */
2940 /* Function - Return TRUE if next opcode is checking for un- */
2943 /*------------------------------------------------------------------*/
2946 gboolean is_unsigned (MonoInst *next)
2949 (((next->opcode >= OP_IBNE_UN) &&
2950 (next->opcode <= OP_IBLT_UN)) ||
2951 ((next->opcode >= OP_LBNE_UN) &&
2952 (next->opcode <= OP_LBLT_UN)) ||
2953 ((next->opcode >= OP_COND_EXC_NE_UN) &&
2954 (next->opcode <= OP_COND_EXC_LT_UN)) ||
2955 ((next->opcode >= OP_COND_EXC_INE_UN) &&
2956 (next->opcode <= OP_COND_EXC_ILT_UN)) ||
2957 ((next->opcode == OP_CLT_UN) ||
2958 (next->opcode == OP_CGT_UN)) ||
2959 ((next->opcode == OP_ICLT_UN) ||
2960 (next->opcode == OP_ICGT_UN) ||
2961 (next->opcode == OP_LCLT_UN) ||
2962 (next->opcode == OP_LCGT_UN))))
2968 /*========================= End of Function ========================*/
2970 /*------------------------------------------------------------------*/
2972 /* Name - mono_arch_output_basic_block */
2974 /* Function - Perform the "real" work of emitting instructions */
2975 /* that will do the work of in the basic block. */
2977 /*------------------------------------------------------------------*/
2980 mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
2985 guint8 *code = cfg->native_code + cfg->code_len;
2986 guint last_offset = 0;
2989 /* we don't align basic blocks of loops on s390 */
2991 if (cfg->verbose_level > 2)
2992 g_print ("Basic block %d starting at offset 0x%x\n", bb->block_num, bb->native_offset);
2994 if ((cfg->prof_options & MONO_PROFILE_COVERAGE) && cfg->coverage_info) {
2995 MonoProfileCoverageInfo *cov = cfg->coverage_info;
2996 g_assert (!mono_compile_aot);
2997 cov->data [bb->dfn].cil_code = bb->cil_code;
2998 /* This is not thread save, but good enough */
2999 S390_SET (code, s390_r1, &cov->data [bb->dfn].count);
3000 s390_alsi (code, 0, s390_r1, 1);
3003 MONO_BB_FOR_EACH_INS (bb, ins) {
3004 offset = code - cfg->native_code;
3006 max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
3008 if (offset > (cfg->code_size - max_len - 16)) {
3009 cfg->code_size *= 2;
3010 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
3011 code = cfg->native_code + offset;
3014 mono_debug_record_line_number (cfg, ins, offset);
3016 switch (ins->opcode) {
3017 case OP_STOREI1_MEMBASE_IMM: {
3018 s390_lghi (code, s390_r0, ins->inst_imm);
3019 S390_LONG (code, stcy, stc, s390_r0, 0,
3020 ins->inst_destbasereg, ins->inst_offset);
3023 case OP_STOREI2_MEMBASE_IMM: {
3024 s390_lghi (code, s390_r0, ins->inst_imm);
3025 S390_LONG (code, sthy, sth, s390_r0, 0,
3026 ins->inst_destbasereg, ins->inst_offset);
3029 case OP_STOREI4_MEMBASE_IMM: {
3030 s390_lgfi (code, s390_r0, ins->inst_imm);
3031 S390_LONG (code, sty, st, s390_r0, 0,
3032 ins->inst_destbasereg, ins->inst_offset);
3035 case OP_STORE_MEMBASE_IMM:
3036 case OP_STOREI8_MEMBASE_IMM: {
3037 S390_SET (code, s390_r0, ins->inst_imm);
3038 S390_LONG (code, stg, stg, s390_r0, 0,
3039 ins->inst_destbasereg, ins->inst_offset);
3042 case OP_STOREI1_MEMBASE_REG: {
3043 S390_LONG (code, stcy, stc, ins->sreg1, 0,
3044 ins->inst_destbasereg, ins->inst_offset);
3047 case OP_STOREI2_MEMBASE_REG: {
3048 S390_LONG (code, sthy, sth, ins->sreg1, 0,
3049 ins->inst_destbasereg, ins->inst_offset);
3052 case OP_STOREI4_MEMBASE_REG: {
3053 S390_LONG (code, sty, st, ins->sreg1, 0,
3054 ins->inst_destbasereg, ins->inst_offset);
3057 case OP_STORE_MEMBASE_REG:
3058 case OP_STOREI8_MEMBASE_REG: {
3059 S390_LONG (code, stg, stg, ins->sreg1, 0,
3060 ins->inst_destbasereg, ins->inst_offset);
3064 g_assert_not_reached ();
3066 case OP_LOAD_MEMBASE:
3067 case OP_LOADI8_MEMBASE: {
3068 S390_LONG (code, lg, lg, ins->dreg, 0,
3069 ins->inst_basereg, ins->inst_offset);
3072 case OP_LOADI4_MEMBASE: {
3073 S390_LONG (code, lgf, lgf, ins->dreg, 0,
3074 ins->inst_basereg, ins->inst_offset);
3077 case OP_LOADU4_MEMBASE: {
3078 S390_LONG (code, llgf, llgf, ins->dreg, 0,
3079 ins->inst_basereg, ins->inst_offset);
3082 case OP_LOADU1_MEMBASE: {
3083 S390_LONG (code, llgc, llgc, ins->dreg, 0,
3084 ins->inst_basereg, ins->inst_offset);
3087 case OP_LOADI1_MEMBASE: {
3088 S390_LONG (code, lgb, lgb, ins->dreg, 0,
3089 ins->inst_basereg, ins->inst_offset);
3092 case OP_LOADU2_MEMBASE: {
3093 S390_LONG (code, llgh, llgh, ins->dreg, 0,
3094 ins->inst_basereg, ins->inst_offset);
3097 case OP_LOADI2_MEMBASE: {
3098 S390_LONG (code, lgh, lgh, ins->dreg, 0,
3099 ins->inst_basereg, ins->inst_offset);
3102 case OP_LCONV_TO_I1: {
3103 s390_lgbr (code, ins->dreg, ins->sreg1);
3106 case OP_LCONV_TO_I2: {
3107 s390_lghr (code, ins->dreg, ins->sreg1);
3110 case OP_LCONV_TO_U1: {
3111 s390_llgcr (code, ins->dreg, ins->sreg1);
3114 case OP_LCONV_TO_U2: {
3115 s390_llghr (code, ins->dreg, ins->sreg1);
3118 case OP_ICONV_TO_I1: {
3119 s390_lgbr (code, ins->dreg, ins->sreg1);
3122 case OP_ICONV_TO_I2: {
3123 s390_lghr (code, ins->dreg, ins->sreg1);
3126 case OP_ICONV_TO_U1: {
3127 s390_llgcr (code, ins->dreg, ins->sreg1);
3130 case OP_ICONV_TO_U2: {
3131 s390_llghr (code, ins->dreg, ins->sreg1);
3136 if (is_unsigned (ins->next))
3137 s390_clgr (code, ins->sreg1, ins->sreg2);
3139 s390_cgr (code, ins->sreg1, ins->sreg2);
3143 if (is_unsigned (ins->next))
3144 s390_clr (code, ins->sreg1, ins->sreg2);
3146 s390_cr (code, ins->sreg1, ins->sreg2);
3149 case OP_COMPARE_IMM:
3150 case OP_LCOMPARE_IMM: {
3151 S390_SET (code, s390_r0, ins->inst_imm);
3152 if (is_unsigned (ins->next))
3153 s390_clgr (code, ins->sreg1, s390_r0);
3155 s390_cgr (code, ins->sreg1, s390_r0);
3158 case OP_ICOMPARE_IMM: {
3159 S390_SET (code, s390_r0, ins->inst_imm);
3160 if (is_unsigned (ins->next))
3161 s390_clr (code, ins->sreg1, s390_r0);
3163 s390_cr (code, ins->sreg1, s390_r0);
3167 mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_ABS,
3169 S390_CALL_TEMPLATE (code, s390_r14);
3174 s390_agr (code, ins->dreg, src2);
3179 s390_agr (code, ins->dreg, src2);
3184 s390_alcgr (code, ins->dreg, src2);
3188 if (ins->dreg != ins->sreg1) {
3189 s390_lgr (code, ins->dreg, ins->sreg1);
3191 if (s390_is_imm16 (ins->inst_imm)) {
3192 s390_aghi (code, ins->dreg, ins->inst_imm);
3193 } else if (s390_is_imm32 (ins->inst_imm)) {
3194 s390_agfi (code, ins->dreg, ins->inst_imm);
3196 S390_SET (code, s390_r0, ins->inst_imm);
3197 s390_agr (code, ins->dreg, s390_r0);
3202 if (ins->dreg != ins->sreg1) {
3203 s390_lgr (code, ins->dreg, ins->sreg1);
3205 g_assert (s390_is_imm16 (ins->inst_imm));
3206 s390_aghi (code, ins->dreg, ins->inst_imm);
3210 if (ins->dreg != ins->sreg1) {
3211 s390_lgr (code, ins->dreg, ins->sreg1);
3213 if (s390_is_imm16 (ins->inst_imm)) {
3214 s390_lghi (code, s390_r0, ins->inst_imm);
3215 s390_alcgr (code, ins->dreg, s390_r0);
3217 S390_SET (code, s390_r0, ins->inst_imm);
3218 s390_alcgr (code, ins->dreg, s390_r0);
3223 case OP_S390_IADD_OVF: {
3225 s390_ar (code, ins->dreg, src2);
3226 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3227 s390_lgfr (code, ins->dreg, ins->dreg);
3230 case OP_IADD_OVF_UN:
3231 case OP_S390_IADD_OVF_UN: {
3233 s390_algr (code, ins->dreg, src2);
3234 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3235 s390_llgfr (code, ins->dreg, ins->dreg);
3238 case OP_ADD_OVF_CARRY: {
3240 s390_lghi (code, s390_r0, 0);
3241 s390_lgr (code, s390_r1, s390_r0);
3242 s390_alcgr (code, s390_r0, s390_r1);
3243 s390_agr (code, ins->dreg, src2);
3244 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3245 s390_agr (code, ins->dreg, s390_r0);
3246 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3249 case OP_ADD_OVF_UN_CARRY: {
3251 s390_alcgr (code, ins->dreg, src2);
3252 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3257 s390_sgr (code, ins->dreg, src2);
3262 s390_sgr (code, ins->dreg, src2);
3267 s390_slbgr(code, ins->dreg, src2);
3271 if (ins->dreg != ins->sreg1) {
3272 s390_lgr (code, ins->dreg, ins->sreg1);
3274 if (s390_is_imm16 (-ins->inst_imm)) {
3275 s390_aghi (code, ins->dreg, -ins->inst_imm);
3276 } else if (s390_is_imm32 (-ins->inst_imm)) {
3277 s390_slgfi (code, ins->dreg, ins->inst_imm);
3279 S390_SET (code, s390_r0, ins->inst_imm);
3280 s390_slgr (code, ins->dreg, s390_r0);
3285 if (ins->dreg != ins->sreg1) {
3286 s390_lgr (code, ins->dreg, ins->sreg1);
3288 if (s390_is_imm16 (-ins->inst_imm)) {
3289 s390_aghi (code, ins->dreg, -ins->inst_imm);
3290 } else if (s390_is_imm32 (-ins->inst_imm)) {
3291 s390_slgfi (code, ins->dreg, ins->inst_imm);
3293 S390_SET (code, s390_r0, ins->inst_imm);
3294 s390_slgr (code, ins->dreg, s390_r0);
3299 if (ins->dreg != ins->sreg1) {
3300 s390_lgr (code, ins->dreg, ins->sreg1);
3302 if (s390_is_imm16 (-ins->inst_imm)) {
3303 s390_lghi (code, s390_r0, ins->inst_imm);
3304 s390_slbgr (code, ins->dreg, s390_r0);
3306 S390_SET (code, s390_r0, ins->inst_imm);
3307 s390_slbgr(code, ins->dreg, s390_r0);
3311 case OP_SUB_OVF_CARRY: {
3313 s390_lghi (code, s390_r0, 0);
3314 s390_lgr (code, s390_r1, s390_r0);
3315 s390_slbgr (code, s390_r0, s390_r1);
3316 s390_sgr (code, ins->dreg, src2);
3317 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3318 s390_agr (code, ins->dreg, s390_r0);
3319 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3322 case OP_SUB_OVF_UN_CARRY: {
3324 s390_slbgr (code, ins->dreg, src2);
3325 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3329 if (ins->sreg1 == ins->dreg) {
3330 s390_ngr (code, ins->dreg, ins->sreg2);
3333 if (ins->sreg2 == ins->dreg) {
3334 s390_ngr (code, ins->dreg, ins->sreg1);
3337 s390_lgr (code, ins->dreg, ins->sreg1);
3338 s390_ngr (code, ins->dreg, ins->sreg2);
3344 if (ins->dreg != ins->sreg1) {
3345 s390_lgr (code, ins->dreg, ins->sreg1);
3347 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3348 s390_ngr (code, ins->dreg, s390_r0);
3352 s390_lgr (code, s390_r1, ins->sreg1);
3353 s390_dsgr (code, s390_r0, ins->sreg2);
3354 s390_lgr (code, ins->dreg, s390_r1);
3358 s390_lgr (code, s390_r1, ins->sreg1);
3359 s390_lghi (code, s390_r0, 0);
3360 s390_dlgr (code, s390_r0, ins->sreg2);
3361 s390_lgr (code, ins->dreg, s390_r1);
3365 s390_lgr (code, s390_r1, ins->sreg1);
3366 s390_dsgr (code, s390_r0, ins->sreg2);
3367 s390_lgr (code, ins->dreg, s390_r0);
3371 if (s390_is_imm16 (ins->inst_imm)) {
3372 s390_lghi (code, s390_r13, ins->inst_imm);
3374 s390_lgfi (code, s390_r13, ins->inst_imm);
3376 s390_lgr (code, s390_r0, ins->sreg1);
3377 s390_dsgr (code, s390_r0, s390_r13);
3378 s390_lgfr (code, ins->dreg, s390_r0);
3382 s390_lgr (code, s390_r1, ins->sreg1);
3383 s390_lghi (code, s390_r0, 0);
3384 s390_dlgr (code, s390_r0, ins->sreg2);
3385 s390_lgr (code, ins->dreg, s390_r0);
3389 if (ins->sreg1 == ins->dreg) {
3390 s390_ogr (code, ins->dreg, ins->sreg2);
3393 if (ins->sreg2 == ins->dreg) {
3394 s390_ogr (code, ins->dreg, ins->sreg1);
3397 s390_lgr (code, ins->dreg, ins->sreg1);
3398 s390_ogr (code, ins->dreg, ins->sreg2);
3404 if (ins->dreg != ins->sreg1) {
3405 s390_lgr (code, ins->dreg, ins->sreg1);
3407 S390_SET_MASK(code, s390_r0, ins->inst_imm);
3408 s390_ogr (code, ins->dreg, s390_r0);
3412 if (ins->sreg1 == ins->dreg) {
3413 s390_xgr (code, ins->dreg, ins->sreg2);
3416 if (ins->sreg2 == ins->dreg) {
3417 s390_xgr (code, ins->dreg, ins->sreg1);
3420 s390_lgr (code, ins->dreg, ins->sreg1);
3421 s390_xgr (code, ins->dreg, ins->sreg2);
3427 if (ins->dreg != ins->sreg1) {
3428 s390_lgr (code, ins->dreg, ins->sreg1);
3430 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3431 s390_xgr (code, ins->dreg, s390_r0);
3436 s390_sllg (code, ins->dreg, ins->dreg, src2, 0);
3441 if (ins->sreg1 != ins->dreg) {
3442 s390_lgr (code, ins->dreg, ins->sreg1);
3444 s390_sllg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3449 s390_srag (code, ins->dreg, ins->dreg, src2, 0);
3454 if (ins->sreg1 != ins->dreg) {
3455 s390_lgr (code, ins->dreg, ins->sreg1);
3457 s390_srag (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3461 case OP_LSHR_UN_IMM: {
3462 if (ins->sreg1 != ins->dreg) {
3463 s390_lgr (code, ins->dreg, ins->sreg1);
3465 s390_srlg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3470 s390_srlg (code, ins->dreg, ins->dreg, src2, 0);
3474 if (ins->sreg1 != ins->dreg) {
3475 s390_lgr (code, ins->dreg, ins->sreg1);
3477 s390_lghi (code, s390_r0, -1);
3478 s390_xgr (code, ins->dreg, s390_r0);
3482 s390_lcgr (code, ins->dreg, ins->sreg1);
3487 s390_msgr (code, ins->dreg, src2);
3492 if (ins->dreg != ins->sreg1) {
3493 s390_lgr (code, ins->dreg, ins->sreg1);
3495 if (s390_is_imm16 (ins->inst_imm)) {
3496 s390_lghi (code, s390_r13, ins->inst_imm);
3497 } else if (s390_is_imm32 (ins->inst_imm)) {
3498 s390_lgfi (code, s390_r13, ins->inst_imm);
3500 S390_SET (code, s390_r13, ins->inst_imm);
3502 s390_msgr (code, ins->dreg, s390_r13);
3507 s390_ltgr (code, s390_r1, ins->sreg1);
3508 s390_jz (code, 0); CODEPTR(code, o[0]);
3509 s390_ltgr (code, s390_r0, ins->sreg2);
3511 s390_lghi (code, s390_r1, 0);
3512 s390_j (code, 0); CODEPTR(code, o[1]);
3513 s390_xgr (code, s390_r0, s390_r1);
3514 s390_msgr (code, s390_r1, ins->sreg2);
3515 s390_xgr (code, s390_r0, s390_r1);
3516 s390_srlg (code, s390_r0, s390_r0, 0, 63);
3517 s390_ltgr (code, s390_r0, s390_r0);
3518 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3519 PTRSLOT (code, o[0]);
3520 PTRSLOT (code, o[1]);
3521 s390_lgr (code, ins->dreg, s390_r1);
3524 case OP_LMUL_OVF_UN: {
3525 s390_lghi (code, s390_r0, 0);
3526 s390_lgr (code, s390_r1, ins->sreg1);
3527 s390_mlgr (code, s390_r0, ins->sreg2);
3528 s390_ltgr (code, s390_r0, s390_r0);
3529 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3530 s390_lgr (code, ins->dreg, s390_r1);
3534 g_assert_not_reached ();
3536 s390_algr (code, ins->dreg, src2);
3541 s390_agr (code, ins->dreg, src2);
3545 g_assert_not_reached ();
3547 s390_alcgr (code, ins->dreg, src2);
3551 if (ins->dreg != ins->sreg1) {
3552 s390_lgfr (code, ins->dreg, ins->sreg1);
3554 if (s390_is_imm16 (ins->inst_imm)) {
3555 s390_aghi (code, ins->dreg, ins->inst_imm);
3557 s390_afi (code, ins->dreg, ins->inst_imm);
3562 if (ins->dreg != ins->sreg1) {
3563 s390_lgfr (code, ins->dreg, ins->sreg1);
3565 if (s390_is_imm16 (ins->inst_imm)) {
3566 s390_lghi (code, s390_r0, ins->inst_imm);
3567 s390_alcgr (code, ins->dreg, s390_r0);
3569 S390_SET (code, s390_r0, ins->inst_imm);
3570 s390_alcgr (code, ins->dreg, s390_r0);
3575 case OP_S390_LADD_OVF: {
3577 s390_agr (code, ins->dreg, src2);
3578 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3581 case OP_LADD_OVF_UN:
3582 case OP_S390_LADD_OVF_UN: {
3584 s390_algr (code, ins->dreg, src2);
3585 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3589 CHECK_SRCDST_NCOM_I;
3590 s390_slgr (code, ins->dreg, src2);
3594 CHECK_SRCDST_NCOM_I;
3595 s390_sgr (code, ins->dreg, src2);
3599 CHECK_SRCDST_NCOM_I;
3600 s390_slbgr (code, ins->dreg, src2);
3604 if (ins->dreg != ins->sreg1) {
3605 s390_lgfr (code, ins->dreg, ins->sreg1);
3607 if (s390_is_imm16 (-ins->inst_imm)) {
3608 s390_aghi (code, ins->dreg, -ins->inst_imm);
3610 s390_agfi (code, ins->dreg, -ins->inst_imm);
3615 S390_SET (code, s390_r0, ins->inst_imm);
3616 s390_slgfr (code, ins->dreg, s390_r0);
3620 case OP_S390_ISUB_OVF: {
3622 s390_sr (code, ins->dreg, src2);
3623 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3624 s390_lgfr (code, ins->dreg, ins->dreg);
3627 case OP_ISUB_OVF_UN:
3628 case OP_S390_ISUB_OVF_UN: {
3630 s390_slr (code, ins->dreg, src2);
3631 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3632 s390_llgfr(code, ins->dreg, ins->dreg);
3636 case OP_S390_LSUB_OVF: {
3638 s390_sgr (code, ins->dreg, src2);
3639 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3642 case OP_LSUB_OVF_UN:
3643 case OP_S390_LSUB_OVF_UN: {
3645 s390_slgr (code, ins->dreg, src2);
3646 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3650 CHECK_SRCDST_NCOM_I;
3651 s390_ngr (code, ins->dreg, src2);
3655 if (ins->dreg != ins->sreg1) {
3656 s390_lgfr (code, ins->dreg, ins->sreg1);
3658 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3659 s390_ngr (code, ins->dreg, s390_r0);
3663 s390_lgfr (code, s390_r0, ins->sreg1);
3664 s390_srda (code, s390_r0, 0, 32);
3665 s390_dr (code, s390_r0, ins->sreg2);
3666 s390_lgfr (code, ins->dreg, s390_r1);
3670 s390_lgfr (code, s390_r0, ins->sreg1);
3671 s390_srdl (code, s390_r0, 0, 32);
3672 s390_dlr (code, s390_r0, ins->sreg2);
3673 s390_lgfr (code, ins->dreg, s390_r1);
3677 if (s390_is_imm16 (ins->inst_imm)) {
3678 s390_lghi (code, s390_r13, ins->inst_imm);
3680 s390_lgfi (code, s390_r13, ins->inst_imm);
3682 s390_lgfr (code, s390_r0, ins->sreg1);
3683 s390_srda (code, s390_r0, 0, 32);
3684 s390_dr (code, s390_r0, ins->sreg2);
3685 s390_lgfr (code, ins->dreg, s390_r1);
3689 s390_lgfr (code, s390_r0, ins->sreg1);
3690 s390_srda (code, s390_r0, 0, 32);
3691 s390_dr (code, s390_r0, ins->sreg2);
3692 s390_lgfr (code, ins->dreg, s390_r0);
3695 s390_lgfr (code, s390_r0, ins->sreg1);
3696 s390_srdl (code, s390_r0, 0, 32);
3697 s390_dlr (code, s390_r0, ins->sreg2);
3698 s390_lgfr (code, ins->dreg, s390_r0);
3702 if (s390_is_imm16 (ins->inst_imm)) {
3703 s390_lghi (code, s390_r13, ins->inst_imm);
3705 s390_lgfi (code, s390_r13, ins->inst_imm);
3707 s390_lgfr (code, s390_r0, ins->sreg1);
3708 s390_srda (code, s390_r0, 0, 32);
3709 s390_dr (code, s390_r0, ins->sreg2);
3710 s390_lgfr (code, ins->dreg, s390_r0);
3715 s390_ogr (code, ins->dreg, src2);
3719 if (ins->dreg != ins->sreg1) {
3720 s390_lgfr (code, ins->dreg, ins->sreg1);
3722 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3723 s390_ogr (code, ins->dreg, s390_r0);
3728 s390_xgr (code, ins->dreg, src2);
3732 if (ins->dreg != ins->sreg1) {
3733 s390_lgfr (code, ins->dreg, ins->sreg1);
3735 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3736 s390_xgr (code, ins->dreg, s390_r0);
3741 s390_sll (code, ins->dreg, src2, 0);
3745 if (ins->sreg1 != ins->dreg) {
3746 s390_lgfr (code, ins->dreg, ins->sreg1);
3748 s390_sll (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3753 s390_sra (code, ins->dreg, src2, 0);
3757 if (ins->sreg1 != ins->dreg) {
3758 s390_lgfr (code, ins->dreg, ins->sreg1);
3760 s390_sra (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3763 case OP_ISHR_UN_IMM: {
3764 if (ins->sreg1 != ins->dreg) {
3765 s390_lgfr (code, ins->dreg, ins->sreg1);
3767 s390_srl (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3772 s390_srl (code, ins->dreg, src2, 0);
3776 if (ins->sreg1 != ins->dreg) {
3777 s390_lgfr (code, ins->dreg, ins->sreg1);
3779 s390_lghi (code, s390_r0, -1);
3780 s390_xgr (code, ins->dreg, s390_r0);
3784 s390_lcgr (code, ins->dreg, ins->sreg1);
3789 s390_msr (code, ins->dreg, src2);
3793 if (ins->dreg != ins->sreg1) {
3794 s390_lgfr (code, ins->dreg, ins->sreg1);
3796 if (s390_is_imm16 (ins->inst_imm)) {
3797 s390_lghi (code, s390_r0, ins->inst_imm);
3799 s390_lgfi (code, s390_r0, ins->inst_imm);
3801 s390_msr (code, ins->dreg, s390_r0);
3806 s390_ltr (code, s390_r1, ins->sreg1);
3807 s390_jz (code, 0); CODEPTR(code, o[0]);
3808 s390_ltr (code, s390_r0, ins->sreg2);
3810 s390_lhi (code, s390_r1, 0);
3811 s390_j (code, 0); CODEPTR(code, o[1]);
3812 s390_xr (code, s390_r0, s390_r1);
3813 s390_msr (code, s390_r1, ins->sreg2);
3814 s390_xr (code, s390_r0, s390_r1);
3815 s390_srl (code, s390_r0, 0, 31);
3816 s390_ltr (code, s390_r0, s390_r0);
3817 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3818 PTRSLOT (code, o[0]);
3819 PTRSLOT (code, o[1]);
3820 s390_lgfr (code, ins->dreg, s390_r1);
3823 case OP_IMUL_OVF_UN: {
3824 s390_lhi (code, s390_r0, 0);
3825 s390_lr (code, s390_r1, ins->sreg1);
3826 s390_mlr (code, s390_r0, ins->sreg2);
3827 s390_ltr (code, s390_r0, s390_r0);
3828 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3829 s390_lgfr (code, ins->dreg, s390_r1);
3834 S390_SET (code, ins->dreg, ins->inst_c0);
3838 mono_add_patch_info (cfg, code - cfg->native_code,
3839 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3840 S390_LOAD_TEMPLATE (code, ins->dreg);
3843 case OP_JUMP_TABLE: {
3844 mono_add_patch_info (cfg, code - cfg->native_code,
3845 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3846 S390_LOAD_TEMPLATE (code, ins->dreg);
3850 if (ins->dreg != ins->sreg1) {
3851 s390_lgr (code, ins->dreg, ins->sreg1);
3855 case OP_LCONV_TO_I8:
3857 s390_lgfr (code, ins->dreg, ins->sreg1);
3859 case OP_LCONV_TO_I4:
3860 s390_lgfr (code, ins->dreg, ins->sreg1);
3863 case OP_LCONV_TO_U8:
3864 case OP_LCONV_TO_U4:
3866 s390_llgfr (code, ins->dreg, ins->sreg1);
3868 case OP_LCONV_TO_OVF_U4:
3869 S390_SET (code, s390_r0, 4294967295);
3870 s390_clgr (code, ins->sreg1, s390_r0);
3871 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3872 s390_ltgr (code, ins->sreg1, ins->sreg1);
3873 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3874 s390_llgfr(code, ins->dreg, ins->sreg1);
3876 case OP_LCONV_TO_OVF_I4_UN:
3877 S390_SET (code, s390_r0, 2147483647);
3878 s390_cgr (code, ins->sreg1, s390_r0);
3879 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3880 s390_ltgr (code, ins->sreg1, ins->sreg1);
3881 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3882 s390_lgfr (code, ins->dreg, ins->sreg1);
3885 if (ins->dreg != ins->sreg1) {
3886 s390_ldr (code, ins->dreg, ins->sreg1);
3889 case OP_MOVE_F_TO_I8:
3890 s390_lgdr (code, ins->dreg, ins->sreg1);
3892 case OP_MOVE_I8_TO_F:
3893 s390_ldgr (code, ins->dreg, ins->sreg1);
3895 case OP_MOVE_F_TO_I4:
3896 s390_ledbr (code, s390_f0, ins->sreg1);
3897 s390_lgdr (code, ins->dreg, s390_f0);
3898 s390_srag (code, ins->dreg, ins->dreg, 0, 32);
3900 case OP_MOVE_I4_TO_F:
3901 s390_slag (code, s390_r0, ins->sreg1, 0, 32);
3902 s390_ldgr (code, ins->dreg, s390_r0);
3903 s390_ldebr (code, ins->dreg, ins->dreg);
3905 case OP_FCONV_TO_R4:
3906 s390_ledbr (code, ins->dreg, ins->sreg1);
3907 s390_ldebr (code, ins->dreg, ins->dreg);
3909 case OP_S390_SETF4RET:
3910 s390_ledbr (code, ins->dreg, ins->sreg1);
3913 if (s390_is_imm16 (ins->inst_offset)) {
3914 s390_lghi (code, s390_r13, ins->inst_offset);
3915 } else if (s390_is_imm32 (ins->inst_offset)) {
3916 s390_lgfi (code, s390_r13, ins->inst_offset);
3918 S390_SET (code, s390_r13, ins->inst_offset);
3920 s390_ear (code, s390_r1, 0);
3921 s390_sllg(code, s390_r1, s390_r1, 0, 32);
3922 s390_ear (code, s390_r1, 1);
3923 s390_lg (code, ins->dreg, s390_r13, s390_r1, 0);
3927 if (cfg->method->save_lmf)
3928 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
3930 if (cfg->flags & MONO_CFG_HAS_TAIL) {
3931 code = emit_load_volatile_arguments (code, cfg);
3934 code = backUpStackPtr(cfg, code);
3935 s390_lg (code, s390_r14, 0, cfg->frame_reg, S390_RET_ADDR_OFFSET);
3936 mono_add_patch_info (cfg, code - cfg->native_code,
3937 MONO_PATCH_INFO_METHOD_JUMP,
3939 s390_jcl (code, S390_CC_UN, 0);
3942 case OP_CHECK_THIS: {
3943 /* ensure ins->sreg1 is not NULL */
3944 s390_lg (code, s390_r0, 0, ins->sreg1, 0);
3945 s390_ltgr (code, s390_r0, s390_r0);
3946 // EMIT_COND_SYSTEM_EXCEPTION (S390_CC_ZR, "NullReferenceException");
3950 int offset = cfg->sig_cookie + cfg->stack_usage;
3952 if (s390_is_imm16 (offset)) {
3953 s390_lghi (code, s390_r0, offset);
3954 } else if (s390_is_imm32 (offset)) {
3955 s390_lgfi (code, s390_r0, offset);
3957 S390_SET (code, s390_r0, offset);
3959 s390_agr (code, s390_r0, cfg->frame_reg);
3960 s390_stg (code, s390_r0, 0, ins->sreg1, 0);
3964 call = (MonoCallInst*)ins;
3965 if (ins->flags & MONO_INST_HAS_METHOD)
3966 mono_add_patch_info (cfg, code-cfg->native_code,
3967 MONO_PATCH_INFO_METHOD,
3970 mono_add_patch_info (cfg, code-cfg->native_code,
3971 MONO_PATCH_INFO_ABS,
3973 S390_CALL_TEMPLATE (code, s390_r14);
3974 if (call->signature->ret->type == MONO_TYPE_R4)
3975 s390_ldebr (code, s390_f0, s390_f0);
3983 call = (MonoCallInst*)ins;
3984 if (ins->flags & MONO_INST_HAS_METHOD)
3985 mono_add_patch_info (cfg, code-cfg->native_code,
3986 MONO_PATCH_INFO_METHOD,
3989 mono_add_patch_info (cfg, code-cfg->native_code,
3990 MONO_PATCH_INFO_ABS,
3992 S390_CALL_TEMPLATE (code, s390_r14);
3995 case OP_FCALL_REG: {
3996 call = (MonoCallInst*)ins;
3997 s390_lgr (code, s390_r1, ins->sreg1);
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);
4006 case OP_VOIDCALL_REG:
4008 s390_lgr (code, s390_r1, ins->sreg1);
4009 s390_basr (code, s390_r14, s390_r1);
4012 case OP_FCALL_MEMBASE: {
4013 call = (MonoCallInst*)ins;
4014 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4015 s390_basr (code, s390_r14, s390_r1);
4016 if (call->signature->ret->type == MONO_TYPE_R4)
4017 s390_ldebr (code, s390_f0, s390_f0);
4020 case OP_LCALL_MEMBASE:
4021 case OP_VCALL_MEMBASE:
4022 case OP_VCALL2_MEMBASE:
4023 case OP_VOIDCALL_MEMBASE:
4024 case OP_CALL_MEMBASE: {
4025 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4026 s390_basr (code, s390_r14, s390_r1);
4033 if (cfg->param_area == 0)
4034 alloca_skip = S390_MINIMAL_STACK_SIZE;
4036 alloca_skip = cfg->param_area;
4038 area_offset = S390_ALIGN(alloca_skip, S390_STACK_ALIGNMENT);
4039 s390_lgr (code, s390_r1, ins->sreg1);
4040 if (ins->flags & MONO_INST_INIT)
4041 s390_lgr (code, s390_r0, ins->sreg1);
4042 s390_aghi (code, s390_r1, 14);
4043 s390_srlg (code, s390_r1, s390_r1, 0, 3);
4044 s390_sllg (code, s390_r1, s390_r1, 0, 3);
4045 if (cfg->method->save_lmf) {
4046 /*----------------------------------*/
4047 /* we have to adjust lmf ebp value */
4048 /*----------------------------------*/
4049 int lmfOffset = cfg->stack_usage - sizeof(MonoLMF);
4051 s390_lgr (code, s390_r13, cfg->frame_reg);
4052 if (s390_is_imm16(lmfOffset)) {
4053 s390_aghi (code, s390_r13, lmfOffset);
4054 } else if (s390_is_imm32(lmfOffset)) {
4055 s390_agfi (code, s390_r13, lmfOffset);
4057 S390_SET (code, s390_r13, lmfOffset);
4059 s390_lgr (code, s390_r14, STK_BASE);
4060 s390_sgr (code, s390_r14, s390_r1);
4061 s390_stg (code, s390_r14, 0, s390_r13,
4062 G_STRUCT_OFFSET(MonoLMF, ebp));
4064 s390_lg (code, s390_r13, 0, STK_BASE, 0);
4065 s390_sgr (code, STK_BASE, s390_r1);
4066 s390_stg (code, s390_r13, 0, STK_BASE, 0);
4067 s390_la (code, ins->dreg, 0, STK_BASE, area_offset);
4068 s390_srlg (code, ins->dreg, ins->dreg, 0, 3);
4069 s390_sllg (code, ins->dreg, ins->dreg, 0, 3);
4070 if (ins->flags & MONO_INST_INIT) {
4071 s390_lgr (code, s390_r1, s390_r0);
4072 s390_lgr (code, s390_r0, ins->dreg);
4073 s390_lgr (code, s390_r14, s390_r12);
4074 s390_lghi (code, s390_r13, 0);
4075 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4077 s390_lgr (code, s390_r12, s390_r14);
4082 s390_lgr (code, s390_r2, ins->sreg1);
4083 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4084 (gpointer) "mono_arch_throw_exception");
4085 S390_CALL_TEMPLATE(code, s390_r14);
4089 s390_lgr (code, s390_r2, ins->sreg1);
4090 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4091 (gpointer) "mono_arch_rethrow_exception");
4092 S390_CALL_TEMPLATE(code, s390_r14);
4095 case OP_START_HANDLER: {
4096 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4098 S390_LONG (code, stg, stg, s390_r14, 0,
4099 spvar->inst_basereg,
4100 spvar->inst_offset);
4103 case OP_ENDFILTER: {
4104 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4106 if (ins->sreg1 != s390_r2)
4107 s390_lgr(code, s390_r2, ins->sreg1);
4108 S390_LONG (code, lg, lg, s390_r14, 0,
4109 spvar->inst_basereg,
4110 spvar->inst_offset);
4111 s390_br (code, s390_r14);
4114 case OP_ENDFINALLY: {
4115 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4117 S390_LONG (code, lg, lg, s390_r14, 0,
4118 spvar->inst_basereg,
4119 spvar->inst_offset);
4120 s390_br (code, s390_r14);
4123 case OP_CALL_HANDLER: {
4124 mono_add_patch_info (cfg, code-cfg->native_code,
4125 MONO_PATCH_INFO_BB, ins->inst_target_bb);
4126 s390_brasl (code, s390_r14, 0);
4127 mono_cfg_add_try_hole (cfg, ins->inst_eh_block, code, bb);
4131 ins->inst_c0 = code - cfg->native_code;
4134 case OP_RELAXED_NOP:
4137 case OP_DUMMY_STORE:
4138 case OP_NOT_REACHED:
4142 case OP_IL_SEQ_POINT:
4143 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4145 case OP_SEQ_POINT: {
4148 if (cfg->compile_aot)
4152 * Read from the single stepping trigger page. This will cause a
4153 * SIGSEGV when single stepping is enabled.
4154 * We do this _before_ the breakpoint, so single stepping after
4155 * a breakpoint is hit will step to the next IL offset.
4157 if (ins->flags & MONO_INST_SINGLE_STEP_LOC) {
4158 breakpointCode.pTrigger = ss_trigger_page;
4159 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
4160 code += BREAKPOINT_SIZE;
4163 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4166 * A placeholder for a possible breakpoint inserted by
4167 * mono_arch_set_breakpoint ().
4169 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); ++i)
4173 * Add an additional nop so skipping the bp doesn't cause the ip to point
4174 * to another IL offset.
4180 case OP_GENERIC_CLASS_INIT: {
4181 static int byte_offset = -1;
4182 static guint8 bitmask;
4185 g_assert (ins->sreg1 == S390_FIRST_ARG_REG);
4187 if (byte_offset < 0)
4188 mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);
4190 s390_tm (code, ins->sreg1, byte_offset, bitmask);
4191 s390_jo (code, 0); CODEPTR(code, jump);
4193 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4194 "mono_generic_class_init");
4195 S390_CALL_TEMPLATE(code, s390_r14);
4197 PTRSLOT (code, jump);
4199 ins->flags |= MONO_INST_GC_CALLSITE;
4200 ins->backend.pc_offset = code - cfg->native_code;
4204 EMIT_UNCOND_BRANCH(ins);
4207 s390_br (code, ins->sreg1);
4213 s390_lghi(code, ins->dreg, 1);
4215 s390_lghi(code, ins->dreg, 0);
4221 s390_lghi(code, ins->dreg, 1);
4223 s390_lghi(code, ins->dreg, 0);
4229 s390_lghi(code, ins->dreg, 1);
4231 s390_lghi(code, ins->dreg, 0);
4237 s390_lghi(code, ins->dreg, 1);
4239 s390_lghi(code, ins->dreg, 0);
4245 s390_lghi(code, ins->dreg, 1);
4247 s390_lghi(code, ins->dreg, 0);
4250 case OP_COND_EXC_EQ:
4251 case OP_COND_EXC_IEQ:
4252 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_EQ, ins->inst_p1);
4254 case OP_COND_EXC_NE_UN:
4255 case OP_COND_EXC_INE_UN:
4256 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NE, ins->inst_p1);
4258 case OP_COND_EXC_LT:
4259 case OP_COND_EXC_ILT:
4260 case OP_COND_EXC_LT_UN:
4261 case OP_COND_EXC_ILT_UN:
4262 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, ins->inst_p1);
4264 case OP_COND_EXC_GT:
4265 case OP_COND_EXC_IGT:
4266 case OP_COND_EXC_GT_UN:
4267 case OP_COND_EXC_IGT_UN:
4268 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, ins->inst_p1);
4270 case OP_COND_EXC_GE:
4271 case OP_COND_EXC_IGE:
4272 case OP_COND_EXC_GE_UN:
4273 case OP_COND_EXC_IGE_UN:
4274 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GE, ins->inst_p1);
4276 case OP_COND_EXC_LE:
4277 case OP_COND_EXC_ILE:
4278 case OP_COND_EXC_LE_UN:
4279 case OP_COND_EXC_ILE_UN:
4280 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LE, ins->inst_p1);
4282 case OP_COND_EXC_OV:
4283 case OP_COND_EXC_IOV:
4284 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, ins->inst_p1);
4286 case OP_COND_EXC_NO:
4287 case OP_COND_EXC_INO:
4288 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NO, ins->inst_p1);
4291 case OP_COND_EXC_IC:
4292 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, ins->inst_p1);
4294 case OP_COND_EXC_NC:
4295 case OP_COND_EXC_INC:
4296 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, ins->inst_p1);
4300 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4304 EMIT_COND_BRANCH (ins, S390_CC_NE);
4310 EMIT_COND_BRANCH (ins, S390_CC_LT);
4316 EMIT_COND_BRANCH (ins, S390_CC_GT);
4322 EMIT_COND_BRANCH (ins, S390_CC_GE);
4328 EMIT_COND_BRANCH (ins, S390_CC_LE);
4331 /* floating point opcodes */
4333 if (*((double *) ins->inst_p0) == 0) {
4334 s390_lzdr (code, ins->dreg);
4336 S390_SET (code, s390_r13, ins->inst_p0);
4337 s390_ld (code, ins->dreg, 0, s390_r13, 0);
4342 if (*((float *) ins->inst_p0) == 0) {
4343 s390_lzdr (code, ins->dreg);
4345 S390_SET (code, s390_r13, ins->inst_p0);
4346 s390_ldeb (code, ins->dreg, 0, s390_r13, 0);
4350 case OP_STORER8_MEMBASE_REG: {
4351 S390_LONG (code, stdy, std, ins->sreg1, 0,
4352 ins->inst_destbasereg, ins->inst_offset);
4355 case OP_LOADR8_MEMBASE: {
4356 S390_LONG (code, ldy, ld, ins->dreg, 0,
4357 ins->inst_basereg, ins->inst_offset);
4360 case OP_STORER4_MEMBASE_REG: {
4361 s390_ledbr (code, s390_f15, ins->sreg1);
4362 S390_LONG (code, stey, ste, s390_f15, 0,
4363 ins->inst_destbasereg, ins->inst_offset);
4366 case OP_LOADR4_MEMBASE: {
4367 S390_LONG (code, ley, le, s390_f15, 0,
4368 ins->inst_basereg, ins->inst_offset);
4369 s390_ldebr (code, ins->dreg, s390_f15);
4372 case OP_ICONV_TO_R_UN: {
4374 s390_cdlfbr (code, ins->dreg, 5, ins->sreg1, 0);
4376 s390_llgfr (code, s390_r0, ins->sreg1);
4377 s390_cdgbr (code, ins->dreg, s390_r0);
4381 case OP_LCONV_TO_R_UN: {
4383 s390_cdlgbr (code, ins->dreg, 5, ins->sreg1, 0);
4386 s390_cxgbr (code, s390_f12, ins->sreg1);
4387 s390_ltgr (code, ins->sreg1, ins->sreg1);
4388 s390_jnl (code, 0); CODEPTR(code, jump);
4389 S390_SET (code, s390_r13, 0x403f000000000000llu);
4390 s390_lgdr (code, s390_f13, s390_r13);
4391 s390_lzdr (code, s390_f15);
4392 s390_axbr (code, s390_f12, s390_f13);
4393 PTRSLOT(code, jump);
4394 s390_ldxbr (code, s390_f13, s390_f12);
4395 s390_ldr (code, ins->dreg, s390_f13);
4399 case OP_LCONV_TO_R4:
4400 case OP_ICONV_TO_R4: {
4401 s390_cegbr (code, ins->dreg, ins->sreg1);
4402 s390_ldebr (code, ins->dreg, ins->dreg);
4405 case OP_LCONV_TO_R8:
4406 case OP_ICONV_TO_R8: {
4407 s390_cdgbr (code, ins->dreg, ins->sreg1);
4410 case OP_FCONV_TO_I1:
4411 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4412 s390_ltgr (code, ins->dreg, ins->dreg);
4414 s390_oill (code, ins->dreg, 0x80);
4415 s390_lghi (code, s390_r0, 0xff);
4416 s390_ngr (code, ins->dreg, s390_r0);
4418 case OP_FCONV_TO_U1:
4420 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4421 s390_lghi (code, s390_r0, 0xff);
4422 s390_ngr (code, ins->dreg, s390_r0);
4424 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 1, FALSE);
4427 case OP_FCONV_TO_I2:
4428 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4429 s390_ltgr (code, ins->dreg, ins->dreg);
4431 s390_oill (code, ins->dreg, 0x8000);
4432 s390_llill (code, s390_r0, 0xffff);
4433 s390_ngr (code, ins->dreg, s390_r0);
4435 case OP_FCONV_TO_U2:
4437 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4438 s390_llill (code, s390_r0, 0xffff);
4439 s390_ngr (code, ins->dreg, s390_r0);
4441 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 2, FALSE);
4444 case OP_FCONV_TO_I4:
4446 s390_cfdbr (code, ins->dreg, 5, ins->sreg1);
4448 case OP_FCONV_TO_U4:
4451 s390_clfdbr (code, ins->dreg, 5, ins->sreg1, 0);
4453 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE);
4456 case OP_FCONV_TO_I8:
4457 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4459 case OP_FCONV_TO_U8:
4461 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4463 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 8, FALSE);
4466 case OP_LCONV_TO_OVF_I: {
4467 /* Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000 */
4469 s390_ltgr (code, ins->sreg2, ins->sreg2);
4470 s390_jnl (code, 0); CODEPTR(code, o[0]);
4471 s390_ltgr (code, ins->sreg1, ins->sreg1);
4472 s390_jnl (code, 0); CODEPTR(code, o[1]);
4473 s390_lhi (code, s390_r13, -1);
4474 s390_cgr (code, ins->sreg1, s390_r13);
4475 s390_jnz (code, 0); CODEPTR(code, o[2]);
4476 if (ins->dreg != ins->sreg2)
4477 s390_lgr (code, ins->dreg, ins->sreg2);
4478 s390_j (code, 0); CODEPTR(code, o[3]);
4479 PTRSLOT(code, o[0]);
4480 s390_jz (code, 0); CODEPTR(code, o[4]);
4481 PTRSLOT(code, o[1]);
4482 PTRSLOT(code, o[2]);
4483 mono_add_patch_info (cfg, code - cfg->native_code,
4484 MONO_PATCH_INFO_EXC, "OverflowException");
4485 s390_brasl (code, s390_r14, 0);
4486 PTRSLOT(code, o[3]);
4487 PTRSLOT(code, o[4]);
4491 s390_lpdbr (code, ins->dreg, ins->sreg1);
4495 s390_sqdbr (code, ins->dreg, ins->sreg1);
4500 s390_adbr (code, ins->dreg, src2);
4504 CHECK_SRCDST_NCOM_F;
4505 s390_sdbr (code, ins->dreg, src2);
4510 s390_mdbr (code, ins->dreg, src2);
4514 CHECK_SRCDST_NCOM_F;
4515 s390_ddbr (code, ins->dreg, src2);
4519 s390_lcdbr (code, ins->dreg, ins->sreg1);
4523 CHECK_SRCDST_NCOM_F;
4524 s390_didbr (code, ins->dreg, src2, 5, s390_f15);
4528 s390_cdbr (code, ins->sreg1, ins->sreg2);
4532 s390_cdbr (code, ins->sreg1, ins->sreg2);
4533 s390_lghi (code, ins->dreg, 1);
4535 s390_lghi (code, ins->dreg, 0);
4539 s390_cdbr (code, ins->sreg1, ins->sreg2);
4540 s390_lghi (code, ins->dreg, 1);
4542 s390_lghi (code, ins->dreg, 0);
4546 s390_cdbr (code, ins->sreg1, ins->sreg2);
4547 s390_lghi (code, ins->dreg, 1);
4549 s390_lghi (code, ins->dreg, 0);
4553 s390_cdbr (code, ins->sreg1, ins->sreg2);
4554 s390_lghi (code, ins->dreg, 1);
4556 s390_lghi (code, ins->dreg, 0);
4560 s390_cdbr (code, ins->sreg1, ins->sreg2);
4561 s390_lghi (code, ins->dreg, 1);
4563 s390_lghi (code, ins->dreg, 0);
4568 s390_jo (code, 0); CODEPTR(code, o);
4569 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4574 EMIT_COND_BRANCH (ins, S390_CC_NE|S390_CC_OV);
4578 s390_jo (code, 0); CODEPTR(code, o);
4579 EMIT_COND_BRANCH (ins, S390_CC_LT);
4584 EMIT_COND_BRANCH (ins, S390_CC_LT|S390_CC_OV);
4588 s390_jo (code, 0); CODEPTR(code, o);
4589 EMIT_COND_BRANCH (ins, S390_CC_GT);
4594 EMIT_COND_BRANCH (ins, S390_CC_GT|S390_CC_OV);
4598 s390_jo (code, 0); CODEPTR(code, o);
4599 EMIT_COND_BRANCH (ins, S390_CC_GE);
4604 EMIT_COND_BRANCH (ins, S390_CC_GE|S390_CC_OV);
4608 s390_jo (code, 0); CODEPTR(code, o);
4609 EMIT_COND_BRANCH (ins, S390_CC_LE);
4614 EMIT_COND_BRANCH (ins, S390_CC_LE|S390_CC_OV);
4618 s390_lhi (code, s390_r13, 0x7f);
4619 s390_tcdb (code, ins->sreg1, 0, s390_r13, 0);
4620 s390_jz (code, 0); CODEPTR(code, o);
4621 mono_add_patch_info (cfg, code - cfg->native_code,
4622 MONO_PATCH_INFO_EXC, "OverflowException");
4623 s390_brasl (code, s390_r14,0);
4627 case OP_S390_MOVE: {
4628 if (ins->backend.size > 0) {
4629 if (ins->backend.size <= 256) {
4630 s390_mvc (code, ins->backend.size, ins->dreg,
4631 ins->inst_offset, ins->sreg1, ins->inst_imm);
4633 s390_lgr (code, s390_r0, ins->dreg);
4634 if (ins->inst_offset > 0) {
4635 if (s390_is_imm16 (ins->inst_offset)) {
4636 s390_aghi (code, s390_r0, ins->inst_offset);
4637 } else if (s390_is_imm32 (ins->inst_offset)) {
4638 s390_agfi (code, s390_r0, ins->inst_offset);
4640 S390_SET (code, s390_r13, ins->inst_offset);
4641 s390_agr (code, s390_r0, s390_r13);
4644 s390_lgr (code, s390_r12, ins->sreg1);
4645 if (ins->inst_imm > 0) {
4646 if (s390_is_imm16 (ins->inst_imm)) {
4647 s390_aghi (code, s390_r12, ins->inst_imm);
4648 } else if (s390_is_imm32 (ins->inst_imm)) {
4649 s390_agfi (code, s390_r12, ins->inst_imm);
4651 S390_SET (code, s390_r13, ins->inst_imm);
4652 s390_agr (code, s390_r12, s390_r13);
4655 if (s390_is_imm16 (ins->backend.size)) {
4656 s390_lghi (code, s390_r1, ins->backend.size);
4657 } else if (s390_is_imm32 (ins->inst_offset)) {
4658 s390_agfi (code, s390_r1, ins->backend.size);
4660 S390_SET (code, s390_r13, ins->backend.size);
4661 s390_agr (code, s390_r1, s390_r13);
4663 s390_lgr (code, s390_r13, s390_r1);
4664 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4670 case OP_ATOMIC_ADD_I8: {
4671 s390_lgr (code, s390_r1, ins->sreg2);
4672 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4673 s390_agr (code, s390_r1, s390_r0);
4674 s390_csg (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4675 s390_jnz (code, -10);
4676 s390_lgr (code, ins->dreg, s390_r1);
4679 case OP_ATOMIC_EXCHANGE_I8: {
4680 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4681 s390_csg (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
4682 s390_jnz (code, -6);
4683 s390_lgr (code, ins->dreg, s390_r0);
4686 case OP_ATOMIC_ADD_I4: {
4687 s390_lgfr(code, s390_r1, ins->sreg2);
4688 s390_lgf (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4689 s390_agr (code, s390_r1, s390_r0);
4690 s390_cs (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4691 s390_jnz (code, -9);
4692 s390_lgfr(code, ins->dreg, s390_r1);
4695 case OP_ATOMIC_EXCHANGE_I4: {
4696 s390_l (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4697 s390_cs (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
4698 s390_jnz (code, -4);
4699 s390_lgfr(code, ins->dreg, s390_r0);
4702 case OP_S390_BKCHAIN: {
4703 s390_lgr (code, ins->dreg, ins->sreg1);
4704 if (s390_is_imm16 (cfg->stack_offset)) {
4705 s390_aghi (code, ins->dreg, cfg->stack_offset);
4706 } else if (s390_is_imm32 (cfg->stack_offset)) {
4707 s390_agfi (code, ins->dreg, cfg->stack_offset);
4709 S390_SET (code, s390_r13, cfg->stack_offset);
4710 s390_agr (code, ins->dreg, s390_r13);
4714 case OP_MEMORY_BARRIER:
4717 case OP_GC_SAFE_POINT: {
4720 g_assert (mono_threads_is_coop_enabled ());
4722 s390_chi (code, ins->sreg1, 1);
4723 s390_je (code, 0); CODEPTR(code, br);
4724 mono_add_patch_info (cfg, code- cfg->native_code, MONO_PATCH_INFO_ABS,
4725 mono_threads_state_poll);
4726 S390_CALL_TEMPLATE (code, s390_r14);
4730 case OP_GC_LIVENESS_DEF:
4731 case OP_GC_LIVENESS_USE:
4732 case OP_GC_PARAM_SLOT_LIVENESS_DEF:
4733 ins->backend.pc_offset = code - cfg->native_code;
4735 case OP_GC_SPILL_SLOT_LIVENESS_DEF:
4736 ins->backend.pc_offset = code - cfg->native_code;
4737 bb->spill_slot_defs = g_slist_prepend_mempool (cfg->mempool, bb->spill_slot_defs, ins);
4739 #ifdef MONO_ARCH_SIMD_INTRINSICS
4741 s390x_addps (code, ins->sreg1, ins->sreg2);
4744 s390x_divps (code, ins->sreg1, ins->sreg2);
4747 s390x_mulps (code, ins->sreg1, ins->sreg2);
4750 s390x_subps (code, ins->sreg1, ins->sreg2);
4753 s390x_maxps (code, ins->sreg1, ins->sreg2);
4756 s390x_minps (code, ins->sreg1, ins->sreg2);
4759 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
4760 s390x_cmpps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4763 s390x_andps (code, ins->sreg1, ins->sreg2);
4766 s390x_andnps (code, ins->sreg1, ins->sreg2);
4769 s390x_orps (code, ins->sreg1, ins->sreg2);
4772 s390x_xorps (code, ins->sreg1, ins->sreg2);
4775 s390x_sqrtps (code, ins->dreg, ins->sreg1);
4778 s390x_rsqrtps (code, ins->dreg, ins->sreg1);
4781 s390x_rcpps (code, ins->dreg, ins->sreg1);
4784 s390x_addsubps (code, ins->sreg1, ins->sreg2);
4787 s390x_haddps (code, ins->sreg1, ins->sreg2);
4790 s390x_hsubps (code, ins->sreg1, ins->sreg2);
4793 s390x_movshdup (code, ins->dreg, ins->sreg1);
4796 s390x_movsldup (code, ins->dreg, ins->sreg1);
4799 case OP_PSHUFLEW_HIGH:
4800 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4801 s390x_pshufhw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4803 case OP_PSHUFLEW_LOW:
4804 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4805 s390x_pshuflw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4808 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4809 s390x_pshufd_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4812 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4813 s390x_shufps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4816 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0x3);
4817 s390x_shufpd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4821 s390x_addpd (code, ins->sreg1, ins->sreg2);
4824 s390x_divpd (code, ins->sreg1, ins->sreg2);
4827 s390x_mulpd (code, ins->sreg1, ins->sreg2);
4830 s390x_subpd (code, ins->sreg1, ins->sreg2);
4833 s390x_maxpd (code, ins->sreg1, ins->sreg2);
4836 s390x_minpd (code, ins->sreg1, ins->sreg2);
4839 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
4840 s390x_cmppd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4843 s390x_andpd (code, ins->sreg1, ins->sreg2);
4846 s390x_andnpd (code, ins->sreg1, ins->sreg2);
4849 s390x_orpd (code, ins->sreg1, ins->sreg2);
4852 s390x_xorpd (code, ins->sreg1, ins->sreg2);
4855 s390x_sqrtpd (code, ins->dreg, ins->sreg1);
4858 s390x_addsubpd (code, ins->sreg1, ins->sreg2);
4861 s390x_haddpd (code, ins->sreg1, ins->sreg2);
4864 s390x_hsubpd (code, ins->sreg1, ins->sreg2);
4867 s390x_movddup (code, ins->dreg, ins->sreg1);
4870 case OP_EXTRACT_MASK:
4871 s390x_pmovmskb (code, ins->dreg, ins->sreg1);
4875 s390x_pand (code, ins->sreg1, ins->sreg2);
4878 s390x_por (code, ins->sreg1, ins->sreg2);
4881 s390x_pxor (code, ins->sreg1, ins->sreg2);
4885 s390x_paddb (code, ins->sreg1, ins->sreg2);
4888 s390x_paddw (code, ins->sreg1, ins->sreg2);
4891 s390x_paddd (code, ins->sreg1, ins->sreg2);
4894 s390x_paddq (code, ins->sreg1, ins->sreg2);
4898 s390x_psubb (code, ins->sreg1, ins->sreg2);
4901 s390x_psubw (code, ins->sreg1, ins->sreg2);
4904 s390x_psubd (code, ins->sreg1, ins->sreg2);
4907 s390x_psubq (code, ins->sreg1, ins->sreg2);
4911 s390x_pmaxub (code, ins->sreg1, ins->sreg2);
4914 s390x_pmaxuw (code, ins->sreg1, ins->sreg2);
4917 s390x_pmaxud (code, ins->sreg1, ins->sreg2);
4921 s390x_pmaxsb (code, ins->sreg1, ins->sreg2);
4924 s390x_pmaxsw (code, ins->sreg1, ins->sreg2);
4927 s390x_pmaxsd (code, ins->sreg1, ins->sreg2);
4931 s390x_pavgb (code, ins->sreg1, ins->sreg2);
4934 s390x_pavgw (code, ins->sreg1, ins->sreg2);
4938 s390x_pminub (code, ins->sreg1, ins->sreg2);
4941 s390x_pminuw (code, ins->sreg1, ins->sreg2);
4944 s390x_pminud (code, ins->sreg1, ins->sreg2);
4948 s390x_pminsb (code, ins->sreg1, ins->sreg2);
4951 s390x_pminsw (code, ins->sreg1, ins->sreg2);
4954 s390x_pminsd (code, ins->sreg1, ins->sreg2);
4958 s390x_pcmpeqb (code, ins->sreg1, ins->sreg2);
4961 s390x_pcmpeqw (code, ins->sreg1, ins->sreg2);
4964 s390x_pcmpeqd (code, ins->sreg1, ins->sreg2);
4967 s390x_pcmpeqq (code, ins->sreg1, ins->sreg2);
4971 s390x_pcmpgtb (code, ins->sreg1, ins->sreg2);
4974 s390x_pcmpgtw (code, ins->sreg1, ins->sreg2);
4977 s390x_pcmpgtd (code, ins->sreg1, ins->sreg2);
4980 s390x_pcmpgtq (code, ins->sreg1, ins->sreg2);
4983 case OP_PSUM_ABS_DIFF:
4984 s390x_psadbw (code, ins->sreg1, ins->sreg2);
4987 case OP_UNPACK_LOWB:
4988 s390x_punpcklbw (code, ins->sreg1, ins->sreg2);
4990 case OP_UNPACK_LOWW:
4991 s390x_punpcklwd (code, ins->sreg1, ins->sreg2);
4993 case OP_UNPACK_LOWD:
4994 s390x_punpckldq (code, ins->sreg1, ins->sreg2);
4996 case OP_UNPACK_LOWQ:
4997 s390x_punpcklqdq (code, ins->sreg1, ins->sreg2);
4999 case OP_UNPACK_LOWPS:
5000 s390x_unpcklps (code, ins->sreg1, ins->sreg2);
5002 case OP_UNPACK_LOWPD:
5003 s390x_unpcklpd (code, ins->sreg1, ins->sreg2);
5006 case OP_UNPACK_HIGHB:
5007 s390x_punpckhbw (code, ins->sreg1, ins->sreg2);
5009 case OP_UNPACK_HIGHW:
5010 s390x_punpckhwd (code, ins->sreg1, ins->sreg2);
5012 case OP_UNPACK_HIGHD:
5013 s390x_punpckhdq (code, ins->sreg1, ins->sreg2);
5015 case OP_UNPACK_HIGHQ:
5016 s390x_punpckhqdq (code, ins->sreg1, ins->sreg2);
5018 case OP_UNPACK_HIGHPS:
5019 s390x_unpckhps (code, ins->sreg1, ins->sreg2);
5021 case OP_UNPACK_HIGHPD:
5022 s390x_unpckhpd (code, ins->sreg1, ins->sreg2);
5026 s390x_packsswb (code, ins->sreg1, ins->sreg2);
5029 s390x_packssdw (code, ins->sreg1, ins->sreg2);
5032 s390x_packuswb (code, ins->sreg1, ins->sreg2);
5035 s390x_packusdw (code, ins->sreg1, ins->sreg2);
5038 case OP_PADDB_SAT_UN:
5039 s390x_paddusb (code, ins->sreg1, ins->sreg2);
5041 case OP_PSUBB_SAT_UN:
5042 s390x_psubusb (code, ins->sreg1, ins->sreg2);
5044 case OP_PADDW_SAT_UN:
5045 s390x_paddusw (code, ins->sreg1, ins->sreg2);
5047 case OP_PSUBW_SAT_UN:
5048 s390x_psubusw (code, ins->sreg1, ins->sreg2);
5052 s390x_paddsb (code, ins->sreg1, ins->sreg2);
5055 s390x_psubsb (code, ins->sreg1, ins->sreg2);
5058 s390x_paddsw (code, ins->sreg1, ins->sreg2);
5061 s390x_psubsw (code, ins->sreg1, ins->sreg2);
5065 s390x_pmullw (code, ins->sreg1, ins->sreg2);
5068 s390x_pmulld (code, ins->sreg1, ins->sreg2);
5071 s390x_pmuludq (code, ins->sreg1, ins->sreg2);
5073 case OP_PMULW_HIGH_UN:
5074 s390x_pmulhuw (code, ins->sreg1, ins->sreg2);
5077 s390x_pmulhw (code, ins->sreg1, ins->sreg2);
5081 s390x_psrlw_reg_imm (code, ins->dreg, ins->inst_imm);
5084 s390x_psrlw (code, ins->dreg, ins->sreg2);
5088 s390x_psraw_reg_imm (code, ins->dreg, ins->inst_imm);
5091 s390x_psraw (code, ins->dreg, ins->sreg2);
5095 s390x_psllw_reg_imm (code, ins->dreg, ins->inst_imm);
5098 s390x_psllw (code, ins->dreg, ins->sreg2);
5102 s390x_psrld_reg_imm (code, ins->dreg, ins->inst_imm);
5105 s390x_psrld (code, ins->dreg, ins->sreg2);
5109 s390x_psrad_reg_imm (code, ins->dreg, ins->inst_imm);
5112 s390x_psrad (code, ins->dreg, ins->sreg2);
5116 s390x_pslld_reg_imm (code, ins->dreg, ins->inst_imm);
5119 s390x_pslld (code, ins->dreg, ins->sreg2);
5123 s390x_psrlq_reg_imm (code, ins->dreg, ins->inst_imm);
5126 s390x_psrlq (code, ins->dreg, ins->sreg2);
5129 /*TODO: This is appart of the sse spec but not added
5131 s390x_psraq_reg_imm (code, ins->dreg, ins->inst_imm);
5134 s390x_psraq (code, ins->dreg, ins->sreg2);
5139 s390x_psllq_reg_imm (code, ins->dreg, ins->inst_imm);
5142 s390x_psllq (code, ins->dreg, ins->sreg2);
5145 s390x_cvtdq2pd (code, ins->dreg, ins->sreg1);
5148 s390x_cvtdq2ps (code, ins->dreg, ins->sreg1);
5151 s390x_cvtpd2dq (code, ins->dreg, ins->sreg1);
5154 s390x_cvtpd2ps (code, ins->dreg, ins->sreg1);
5157 s390x_cvtps2dq (code, ins->dreg, ins->sreg1);
5160 s390x_cvtps2pd (code, ins->dreg, ins->sreg1);
5163 s390x_cvttpd2dq (code, ins->dreg, ins->sreg1);
5166 s390x_cvttps2dq (code, ins->dreg, ins->sreg1);
5170 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5173 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5177 amd64_movhlps (code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg1);
5178 amd64_movd_reg_xreg_size (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG, 8);
5180 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 8);
5185 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5187 amd64_shift_reg_imm (code, X86_SHR, ins->dreg, ins->inst_c0 * 8);
5188 amd64_widen_reg (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I1, FALSE);
5192 /*amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5194 amd64_shift_reg_imm_size (code, X86_SHR, ins->dreg, 16, 4);*/
5195 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5196 amd64_widen_reg_size (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I2, TRUE, 4);
5200 amd64_movhlps (code, ins->dreg, ins->sreg1);
5202 s390x_movsd (code, ins->dreg, ins->sreg1);
5205 s390x_pinsrw_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5207 case OP_EXTRACTX_U2:
5208 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5210 case OP_INSERTX_U1_SLOW:
5211 /*sreg1 is the extracted ireg (scratch)
5212 /sreg2 is the to be inserted ireg (scratch)
5213 /dreg is the xreg to receive the value*/
5215 /*clear the bits from the extracted word*/
5216 amd64_alu_reg_imm (code, X86_AND, ins->sreg1, ins->inst_c0 & 1 ? 0x00FF : 0xFF00);
5217 /*shift the value to insert if needed*/
5218 if (ins->inst_c0 & 1)
5219 amd64_shift_reg_imm_size (code, X86_SHL, ins->sreg2, 8, 4);
5220 /*join them together*/
5221 amd64_alu (code, X86_OR, ins->sreg1, ins->sreg2);
5222 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0 / 2);
5224 case OP_INSERTX_I4_SLOW:
5225 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2);
5226 amd64_shift_reg_imm (code, X86_SHR, ins->sreg2, 16);
5227 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2 + 1);
5229 case OP_INSERTX_I8_SLOW:
5230 amd64_movd_xreg_reg_size(code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg2, 8);
5232 amd64_movlhps (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5234 s390x_movsd (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5237 case OP_INSERTX_R4_SLOW:
5238 switch (ins->inst_c0) {
5241 s390x_movss (code, ins->dreg, ins->sreg2);
5243 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5246 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5248 s390x_movss (code, ins->dreg, ins->sreg2);
5250 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5251 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5254 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5256 s390x_movss (code, ins->dreg, ins->sreg2);
5258 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5259 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5262 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5264 s390x_movss (code, ins->dreg, ins->sreg2);
5266 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5267 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5271 case OP_INSERTX_R8_SLOW:
5273 amd64_movlhps (code, ins->dreg, ins->sreg2);
5275 s390x_movsd (code, ins->dreg, ins->sreg2);
5277 case OP_STOREX_MEMBASE_REG:
5278 case OP_STOREX_MEMBASE:
5279 s390x_movups_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5281 case OP_LOADX_MEMBASE:
5282 s390x_movups_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5284 case OP_LOADX_ALIGNED_MEMBASE:
5285 s390x_movaps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5287 case OP_STOREX_ALIGNED_MEMBASE_REG:
5288 s390x_movaps_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5290 case OP_STOREX_NTA_MEMBASE_REG:
5291 s390x_movntps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5293 case OP_PREFETCH_MEMBASE:
5294 s390x_prefetch_reg_membase (code, ins->backend.arg_info, ins->sreg1, ins->inst_offset);
5298 /*FIXME the peephole pass should have killed this*/
5299 if (ins->dreg != ins->sreg1)
5300 s390x_movaps (code, ins->dreg, ins->sreg1);
5303 s390x_pxor (code, ins->dreg, ins->dreg);
5305 case OP_ICONV_TO_R4_RAW:
5306 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5309 case OP_FCONV_TO_R8_X:
5310 s390x_movsd (code, ins->dreg, ins->sreg1);
5313 case OP_XCONV_R8_TO_I4:
5314 s390x_cvttsd2si_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5315 switch (ins->backend.source_opcode) {
5316 case OP_FCONV_TO_I1:
5317 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, FALSE);
5319 case OP_FCONV_TO_U1:
5320 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, FALSE);
5322 case OP_FCONV_TO_I2:
5323 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, TRUE);
5325 case OP_FCONV_TO_U2:
5326 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, TRUE);
5332 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 0);
5333 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 1);
5334 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5337 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5338 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5341 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 8);
5342 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5346 s390x_movsd (code, ins->dreg, ins->sreg1);
5348 s390x_movsd (code, ins->dreg, ins->sreg1);
5349 s390x_cvtsd2ss (code, ins->dreg, ins->dreg);
5351 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5354 s390x_movsd (code, ins->dreg, ins->sreg1);
5355 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5359 g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
5360 g_assert_not_reached ();
5363 if ((cfg->opt & MONO_OPT_BRANCH) && ((code - cfg->native_code - offset) > max_len)) {
5364 g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %ld)",
5365 mono_inst_name (ins->opcode), max_len, code - cfg->native_code - offset);
5366 g_assert_not_reached ();
5369 last_offset = offset;
5372 cfg->code_len = code - cfg->native_code;
5375 /*========================= End of Function ========================*/
5377 /*------------------------------------------------------------------*/
5379 /* Name - mono_arch_register_lowlevel_calls */
5381 /* Function - Register routines to help with --trace operation. */
5383 /*------------------------------------------------------------------*/
5386 mono_arch_register_lowlevel_calls (void)
5390 /*========================= End of Function ========================*/
5392 /*------------------------------------------------------------------*/
5394 /* Name - mono_arch_patch_code */
5396 /* Function - Process the patch data created during the */
5397 /* instruction build process. This resolves jumps, */
5398 /* calls, variables etc. */
5400 /*------------------------------------------------------------------*/
5403 mono_arch_patch_code (MonoCompile *cfg, MonoMethod *method, MonoDomain *domain,
5404 guint8 *code, MonoJumpInfo *ji, gboolean run_cctors,
5407 MonoJumpInfo *patch_info;
5409 mono_error_init (error);
5411 for (patch_info = ji; patch_info; patch_info = patch_info->next) {
5412 unsigned char *ip = patch_info->ip.i + code;
5413 gconstpointer target = NULL;
5415 target = mono_resolve_patch_target (method, domain, code,
5416 patch_info, run_cctors, error);
5417 return_if_nok (error);
5419 switch (patch_info->type) {
5420 case MONO_PATCH_INFO_IP:
5421 case MONO_PATCH_INFO_LDSTR:
5422 case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
5423 case MONO_PATCH_INFO_LDTOKEN:
5424 case MONO_PATCH_INFO_EXC:
5425 s390_patch_addr (ip, (guint64) target);
5427 case MONO_PATCH_INFO_METHOD:
5428 case MONO_PATCH_INFO_INTERNAL_METHOD:
5429 case MONO_PATCH_INFO_JIT_ICALL_ADDR:
5430 case MONO_PATCH_INFO_RGCTX_FETCH:
5431 case MONO_PATCH_INFO_ABS: {
5432 S390_EMIT_CALL (ip, target);
5435 case MONO_PATCH_INFO_SWITCH:
5436 /*----------------------------------*/
5437 /* ip points at the basr r13,0/j +4 */
5438 /* instruction the vtable value */
5439 /* follows this (i.e. ip+6) */
5440 /*----------------------------------*/
5441 S390_EMIT_LOAD (ip, target);
5443 case MONO_PATCH_INFO_METHODCONST:
5444 case MONO_PATCH_INFO_CLASS:
5445 case MONO_PATCH_INFO_IMAGE:
5446 case MONO_PATCH_INFO_FIELD:
5447 case MONO_PATCH_INFO_IID:
5448 case MONO_PATCH_INFO_EXC_NAME:
5449 target = S390_RELATIVE(target, ip);
5450 s390_patch_rel (ip, (guint64) target);
5452 case MONO_PATCH_INFO_R4:
5453 case MONO_PATCH_INFO_R8:
5454 case MONO_PATCH_INFO_METHOD_REL:
5455 g_assert_not_reached ();
5458 target = S390_RELATIVE(target, ip);
5460 s390_patch_rel (ip, (guint64) target);
5465 /*========================= End of Function ========================*/
5467 /*------------------------------------------------------------------*/
5469 /* Name - emit_load_volatile_arguments */
5471 /* Function - Emit the instructions to reload parameter regist- */
5472 /* registers for use with "tail" operations. */
5474 /* The register loading operations performed here */
5475 /* are the mirror of the store operations performed */
5476 /* in mono_arch_emit_prolog and need to be kept in */
5477 /* synchronization with it. */
5479 /*------------------------------------------------------------------*/
5482 emit_load_volatile_arguments (guint8 *code, MonoCompile *cfg)
5485 MonoMethod *method = cfg->method;
5486 MonoMethodSignature *sig = mono_method_signature(method);
5490 cinfo = get_call_info (NULL, NULL, sig);
5492 if (cinfo->struct_ret) {
5493 ArgInfo *ainfo = &cinfo->ret;
5494 inst = cfg->vret_addr;
5495 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5498 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5499 ArgInfo *ainfo = cinfo->args + i;
5500 inst = cfg->args [pos];
5502 if (inst->opcode == OP_REGVAR) {
5503 if (ainfo->regtype == RegTypeGeneral)
5504 s390_lgr (code, ainfo->reg, inst->dreg);
5505 else if (ainfo->regtype == RegTypeFP) {
5506 if (inst->dreg != ainfo->reg) {
5507 if (ainfo->size == 4) {
5508 s390_ldebr (code, ainfo->reg, inst->dreg);
5510 s390_ldr (code, ainfo->reg, inst->dreg);
5514 else if (ainfo->regtype == RegTypeBase) {
5516 g_assert_not_reached ();
5518 if (ainfo->regtype == RegTypeGeneral) {
5519 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5520 g_assert_not_reached();
5521 switch (ainfo->size) {
5523 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5526 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5529 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5532 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5535 } else if (ainfo->regtype == RegTypeBase) {
5536 } else if (ainfo->regtype == RegTypeFP) {
5537 if (ainfo->size == 8)
5538 s390_ld (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5539 else if (ainfo->size == 4)
5540 s390_le (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5542 g_assert_not_reached ();
5543 } else if (ainfo->regtype == RegTypeStructByVal) {
5544 if (ainfo->reg != STK_BASE) {
5545 switch (ainfo->size) {
5547 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5550 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5553 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5556 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5560 } else if (ainfo->regtype == RegTypeStructByAddr) {
5561 if (ainfo->reg != STK_BASE) {
5562 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5565 g_assert_not_reached ();
5573 /*========================= End of Function ========================*/
5575 /*------------------------------------------------------------------*/
5577 /* Name - mono_arch_emit_prolog */
5579 /* Function - Create the instruction sequence for a function */
5582 /*------------------------------------------------------------------*/
5585 mono_arch_emit_prolog (MonoCompile *cfg)
5587 MonoMethod *method = cfg->method;
5589 MonoMethodSignature *sig;
5591 long alloc_size, pos, max_offset, i, cfa_offset = 0;
5600 cfg->code_size = 512;
5602 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
5604 cfg->code_size += 256;
5605 } else if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
5606 cfg->code_size += 256;
5608 if (method->save_lmf)
5609 cfg->code_size += 200;
5611 cfg->native_code = code = g_malloc (cfg->code_size);
5613 mono_emit_unwind_op_def_cfa (cfg, code, STK_BASE, 0);
5614 emit_unwind_regs(cfg, code, s390_r6, s390_r14, S390_REG_SAVE_OFFSET);
5615 s390_stmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
5616 mono_emit_unwind_op_offset (cfg, code, s390_r14, S390_RET_ADDR_OFFSET);
5617 mini_gc_set_slot_type_from_cfa (cfg, S390_RET_ADDR_OFFSET, SLOT_NOREF);
5619 if (cfg->arch.bkchain_reg != -1)
5620 s390_lgr (code, cfg->arch.bkchain_reg, STK_BASE);
5622 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
5623 cfg->used_int_regs |= 1 << 11;
5626 alloc_size = cfg->stack_offset;
5628 cfg->stack_usage = cfa_offset = alloc_size;
5629 mono_emit_unwind_op_def_cfa_offset (cfg, code, alloc_size);
5630 s390_lgr (code, s390_r11, STK_BASE);
5631 if (s390_is_imm16 (alloc_size)) {
5632 s390_aghi (code, STK_BASE, -alloc_size);
5633 } else if (s390_is_imm32 (alloc_size)) {
5634 s390_agfi (code, STK_BASE, -alloc_size);
5636 int stackSize = alloc_size;
5637 while (stackSize > INT_MAX) {
5638 s390_agfi (code, STK_BASE, -INT_MAX);
5639 stackSize -= INT_MAX;
5641 s390_agfi (code, STK_BASE, -stackSize);
5643 s390_stg (code, s390_r11, 0, STK_BASE, 0);
5645 if (cfg->frame_reg != STK_BASE)
5646 s390_lgr (code, s390_r11, STK_BASE);
5648 mono_emit_unwind_op_def_cfa_reg (cfg, code, cfg->frame_reg);
5650 /* store runtime generic context */
5651 if (cfg->rgctx_var) {
5652 g_assert (cfg->rgctx_var->opcode == OP_REGOFFSET);
5654 s390_stg (code, MONO_ARCH_RGCTX_REG, 0,
5655 cfg->rgctx_var->inst_basereg,
5656 cfg->rgctx_var->inst_offset);
5659 /* compute max_offset in order to use short forward jumps
5660 * we always do it on s390 because the immediate displacement
5661 * for jumps is too small
5664 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
5666 bb->max_offset = max_offset;
5668 if (cfg->prof_options & MONO_PROFILE_COVERAGE)
5671 MONO_BB_FOR_EACH_INS (bb, ins)
5672 max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
5675 /* load arguments allocated to register from the stack */
5676 sig = mono_method_signature (method);
5679 cinfo = get_call_info (cfg, cfg->mempool, sig);
5681 if (cinfo->struct_ret) {
5682 ArgInfo *ainfo = &cinfo->ret;
5683 inst = cfg->vret_addr;
5684 inst->backend.size = ainfo->vtsize;
5685 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5688 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5689 ArgInfo *ainfo = cinfo->args + i;
5690 inst = cfg->args [pos];
5692 if (inst->opcode == OP_VTARG_ADDR)
5693 inst = inst->inst_left;
5695 if (inst->opcode == OP_REGVAR) {
5696 if (ainfo->regtype == RegTypeGeneral)
5697 s390_lgr (code, inst->dreg, ainfo->reg);
5698 else if (ainfo->regtype == RegTypeFP) {
5699 if (inst->dreg != ainfo->reg) {
5700 if (ainfo->size == 4) {
5701 s390_ledbr (code, inst->dreg, ainfo->reg);
5703 s390_ldr (code, inst->dreg, ainfo->reg);
5707 else if (ainfo->regtype == RegTypeBase) {
5708 s390_lgr (code, s390_r13, STK_BASE);
5709 s390_aghi (code, s390_r13, alloc_size);
5710 s390_lg (code, inst->dreg, 0, s390_r13, ainfo->offset);
5712 g_assert_not_reached ();
5714 if (cfg->verbose_level > 2)
5715 g_print ("Argument %d assigned to register %s\n",
5716 pos, mono_arch_regname (inst->dreg));
5718 if (ainfo->regtype == RegTypeGeneral) {
5719 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5720 g_assert_not_reached();
5721 switch (ainfo->size) {
5723 s390_stc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5726 s390_sth (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5729 s390_st (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5732 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5735 } else if (ainfo->regtype == RegTypeBase) {
5736 } else if (ainfo->regtype == RegTypeFP) {
5737 if (ainfo->size == 8)
5738 s390_std (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5739 else if (ainfo->size == 4)
5740 s390_ste (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5742 g_assert_not_reached ();
5743 } else if (ainfo->regtype == RegTypeStructByVal) {
5744 int doffset = inst->inst_offset;
5746 if (ainfo->reg != STK_BASE)
5750 s390_lgr (code, s390_r13, STK_BASE);
5751 s390_aghi (code, s390_r13, alloc_size);
5754 size = (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE
5755 ? mono_class_native_size(mono_class_from_mono_type(inst->inst_vtype), NULL)
5760 if (ainfo->reg == STK_BASE)
5761 s390_ic (code, reg, 0, s390_r13, ainfo->offset+7);
5762 s390_stc (code, reg, 0, inst->inst_basereg, doffset);
5765 if (ainfo->reg == STK_BASE)
5766 s390_lh (code, reg, 0, s390_r13, ainfo->offset+6);
5767 s390_sth (code, reg, 0, inst->inst_basereg, doffset);
5770 if (ainfo->reg == STK_BASE)
5771 s390_l (code, reg, 0, s390_r13, ainfo->offset+4);
5772 s390_st (code, reg, 0, inst->inst_basereg, doffset);
5775 if (ainfo->reg == STK_BASE)
5776 s390_lg (code, reg, 0, s390_r13, ainfo->offset);
5777 s390_stg (code, reg, 0, inst->inst_basereg, doffset);
5780 } else if (ainfo->regtype == RegTypeStructByAddr) {
5781 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5782 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
5784 g_assert_not_reached ();
5789 if (method->save_lmf) {
5790 /*---------------------------------------------------------------*/
5791 /* build the MonoLMF structure on the stack - see mini-s390x.h */
5792 /*---------------------------------------------------------------*/
5793 lmfOffset = alloc_size - sizeof(MonoLMF);
5795 s390_lgr (code, s390_r13, cfg->frame_reg);
5796 s390_aghi (code, s390_r13, lmfOffset);
5798 /*---------------------------------------------------------------*/
5799 /* Preserve the parameter registers while we fix up the lmf */
5800 /*---------------------------------------------------------------*/
5801 s390_stmg (code, s390_r2, s390_r6, s390_r13,
5802 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
5804 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[0]), SLOT_NOREF);
5805 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[1]), SLOT_NOREF);
5806 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[2]), SLOT_NOREF);
5807 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[3]), SLOT_NOREF);
5808 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[4]), SLOT_NOREF);
5810 /*---------------------------------------------------------------*/
5811 /* On return from this call r2 have the address of the &lmf */
5812 /*---------------------------------------------------------------*/
5813 if (lmf_addr_tls_offset == -1) {
5814 mono_add_patch_info (cfg, code - cfg->native_code,
5815 MONO_PATCH_INFO_INTERNAL_METHOD,
5816 (gpointer)"mono_get_lmf_addr");
5817 S390_CALL_TEMPLATE(code, s390_r1);
5819 /*-------------------------------------------------------*/
5820 /* Get LMF by getting value from thread level storage */
5821 /*-------------------------------------------------------*/
5822 s390_ear (code, s390_r1, 0);
5823 s390_sllg(code, s390_r1, s390_r1, 0, 32);
5824 s390_ear (code, s390_r1, 1);
5825 s390_lg (code, s390_r2, 0, s390_r1, lmf_addr_tls_offset);
5828 /*---------------------------------------------------------------*/
5829 /* Set lmf.lmf_addr = jit_tls->lmf */
5830 /*---------------------------------------------------------------*/
5831 s390_stg (code, s390_r2, 0, s390_r13,
5832 G_STRUCT_OFFSET(MonoLMF, lmf_addr));
5833 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, lmf_addr), SLOT_NOREF);
5835 /*---------------------------------------------------------------*/
5836 /* Get current lmf */
5837 /*---------------------------------------------------------------*/
5838 s390_lg (code, s390_r0, 0, s390_r2, 0);
5840 /*---------------------------------------------------------------*/
5841 /* Set our lmf as the current lmf */
5842 /*---------------------------------------------------------------*/
5843 s390_stg (code, s390_r13, 0, s390_r2, 0);
5845 /*---------------------------------------------------------------*/
5846 /* Have our lmf.previous_lmf point to the last lmf */
5847 /*---------------------------------------------------------------*/
5848 s390_stg (code, s390_r0, 0, s390_r13,
5849 G_STRUCT_OFFSET(MonoLMF, previous_lmf));
5850 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), SLOT_NOREF);
5852 /*---------------------------------------------------------------*/
5853 /* save method info */
5854 /*---------------------------------------------------------------*/
5855 S390_SET (code, s390_r1, method);
5856 s390_stg (code, s390_r1, 0, s390_r13,
5857 G_STRUCT_OFFSET(MonoLMF, method));
5858 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, method), SLOT_NOREF);
5860 /*---------------------------------------------------------------*/
5861 /* save the current IP */
5862 /*---------------------------------------------------------------*/
5863 s390_stg (code, STK_BASE, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp));
5864 s390_basr (code, s390_r1, 0);
5865 s390_stg (code, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip));
5866 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, ebp), SLOT_NOREF);
5867 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, eip), SLOT_NOREF);
5869 /*---------------------------------------------------------------*/
5870 /* Save general and floating point registers */
5871 /*---------------------------------------------------------------*/
5872 s390_stmg (code, s390_r2, s390_r12, s390_r13,
5873 G_STRUCT_OFFSET(MonoLMF, gregs[2]));
5874 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[0]), SLOT_NOREF);
5875 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[1]), SLOT_NOREF);
5876 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[2]), SLOT_NOREF);
5877 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[3]), SLOT_NOREF);
5878 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[4]), SLOT_NOREF);
5879 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[5]), SLOT_NOREF);
5880 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[6]), SLOT_NOREF);
5881 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[7]), SLOT_NOREF);
5882 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[8]), SLOT_NOREF);
5883 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[9]), SLOT_NOREF);
5884 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[10]), SLOT_NOREF);
5886 fpOffset = lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, fregs[0]);
5887 for (i = 0; i < 16; i++) {
5888 s390_std (code, i, 0, s390_r13,
5889 G_STRUCT_OFFSET(MonoLMF, fregs[i]));
5890 mini_gc_set_slot_type_from_fp (cfg, fpOffset, SLOT_NOREF);
5891 fpOffset += sizeof(double);
5894 /*---------------------------------------------------------------*/
5895 /* Restore the parameter registers now that we've set up the lmf */
5896 /*---------------------------------------------------------------*/
5897 s390_lmg (code, s390_r2, s390_r6, s390_r13,
5898 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
5901 if (cfg->method->save_lmf)
5902 argsClobbered = TRUE;
5905 argsClobbered = TRUE;
5906 code = mono_arch_instrument_prolog (cfg, enter_method, code, TRUE);
5909 if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
5910 argsClobbered = TRUE;
5913 * Optimize the common case of the first bblock making a call with the same
5914 * arguments as the method. This works because the arguments are still in their
5915 * original argument registers.
5917 if (!argsClobbered) {
5918 MonoBasicBlock *first_bb = cfg->bb_entry;
5920 int filter = FILTER_IL_SEQ_POINT;
5922 next = mono_bb_first_inst (first_bb, filter);
5923 if (!next && first_bb->next_bb) {
5924 first_bb = first_bb->next_bb;
5925 next = mono_bb_first_inst (first_bb, filter);
5928 if (first_bb->in_count > 1)
5931 for (i = 0; next && i < sig->param_count + sig->hasthis; ++i) {
5932 ArgInfo *ainfo = cinfo->args + i;
5933 gboolean match = FALSE;
5935 inst = cfg->args [i];
5936 if (inst->opcode != OP_REGVAR) {
5937 switch (ainfo->regtype) {
5938 case RegTypeGeneral: {
5939 if (((next->opcode == OP_LOAD_MEMBASE) ||
5940 (next->opcode == OP_LOADI4_MEMBASE)) &&
5941 next->inst_basereg == inst->inst_basereg &&
5942 next->inst_offset == inst->inst_offset) {
5943 if (next->dreg == ainfo->reg) {
5947 next->opcode = OP_MOVE;
5948 next->sreg1 = ainfo->reg;
5949 /* Only continue if the instruction doesn't change argument regs */
5950 if (next->dreg == ainfo->reg)
5960 /* Argument allocated to (non-volatile) register */
5961 switch (ainfo->regtype) {
5962 case RegTypeGeneral:
5963 if (next->opcode == OP_MOVE &&
5964 next->sreg1 == inst->dreg &&
5965 next->dreg == ainfo->reg) {
5976 next = mono_inst_next (next, filter);
5983 cfg->code_len = code - cfg->native_code;
5984 g_assert (cfg->code_len < cfg->code_size);
5989 /*========================= End of Function ========================*/
5991 /*------------------------------------------------------------------*/
5993 /* Name - mono_arch_emit_epilog */
5995 /* Function - Emit the instructions for a function epilog. */
5997 /*------------------------------------------------------------------*/
6000 mono_arch_emit_epilog (MonoCompile *cfg)
6002 MonoMethod *method = cfg->method;
6005 int max_epilog_size = 96;
6007 if (cfg->method->save_lmf)
6008 max_epilog_size += 128;
6010 if (mono_jit_trace_calls != NULL)
6011 max_epilog_size += 128;
6012 else if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
6013 max_epilog_size += 128;
6015 while ((cfg->code_len + max_epilog_size) > (cfg->code_size - 16)) {
6016 cfg->code_size *= 2;
6017 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6018 cfg->stat_code_reallocs++;
6021 code = cfg->native_code + cfg->code_len;
6023 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
6024 code = mono_arch_instrument_epilog (cfg, leave_method, code, TRUE);
6028 if (method->save_lmf)
6029 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
6031 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
6032 s390_lg (code, STK_BASE, 0, STK_BASE, 0);
6034 code = backUpStackPtr(cfg, code);
6036 s390_lmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
6037 s390_br (code, s390_r14);
6039 cfg->code_len = code - cfg->native_code;
6041 g_assert (cfg->code_len < cfg->code_size);
6045 /*========================= End of Function ========================*/
6047 /*------------------------------------------------------------------*/
6049 /* Name - mono_arch_emit_exceptions */
6051 /* Function - Emit the blocks to handle exception conditions. */
6053 /*------------------------------------------------------------------*/
6056 mono_arch_emit_exceptions (MonoCompile *cfg)
6058 MonoJumpInfo *patch_info;
6064 MonoClass *exc_classes [MAX_EXC];
6065 guint8 *exc_throw_start [MAX_EXC];
6067 for (patch_info = cfg->patch_info;
6069 patch_info = patch_info->next) {
6070 if (patch_info->type == MONO_PATCH_INFO_EXC)
6074 code_size = exc_count * 48;
6076 while ((cfg->code_len + code_size) > (cfg->code_size - 16)) {
6077 cfg->code_size *= 2;
6078 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6079 cfg->stat_code_reallocs++;
6082 code = cfg->native_code + cfg->code_len;
6084 /*---------------------------------------------------------------------*/
6085 /* Add code to raise exceptions */
6086 /*---------------------------------------------------------------------*/
6087 for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
6088 switch (patch_info->type) {
6089 case MONO_PATCH_INFO_EXC: {
6090 guint8 *ip = patch_info->ip.i + cfg->native_code;
6091 MonoClass *exc_class;
6094 /*-----------------------------------------------------*/
6095 /* Patch the branch in epilog to come here */
6096 /*-----------------------------------------------------*/
6097 s390_patch_rel (ip + 2, (guint64) S390_RELATIVE(code,ip));
6099 exc_class = mono_class_load_from_name (mono_defaults.corlib,
6101 patch_info->data.name);
6102 throw_ip = patch_info->ip.i;
6104 for (iExc = 0; iExc < nThrows; ++iExc)
6105 if (exc_classes [iExc] == exc_class)
6108 if (iExc < nThrows) {
6109 s390_jcl (code, S390_CC_UN,
6110 (guint64) exc_throw_start [iExc]);
6111 patch_info->type = MONO_PATCH_INFO_NONE;
6114 if (nThrows < MAX_EXC) {
6115 exc_classes [nThrows] = exc_class;
6116 exc_throw_start [nThrows] = code;
6119 /*---------------------------------------------*/
6120 /* Patch the parameter passed to the handler */
6121 /*---------------------------------------------*/
6122 S390_SET (code, s390_r2, exc_class->type_token);
6123 /*---------------------------------------------*/
6124 /* Load return address & parameter register */
6125 /*---------------------------------------------*/
6126 s390_larl (code, s390_r14, (guint64)S390_RELATIVE((patch_info->ip.i +
6127 cfg->native_code + 8), code));
6128 /*---------------------------------------------*/
6129 /* Reuse the current patch to set the jump */
6130 /*---------------------------------------------*/
6131 patch_info->type = MONO_PATCH_INFO_INTERNAL_METHOD;
6132 patch_info->data.name = "mono_arch_throw_corlib_exception";
6133 patch_info->ip.i = code - cfg->native_code;
6134 S390_BR_TEMPLATE (code, s390_r1);
6144 cfg->code_len = code - cfg->native_code;
6146 g_assert (cfg->code_len < cfg->code_size);
6150 /*========================= End of Function ========================*/
6152 /*------------------------------------------------------------------*/
6154 /* Name - mono_arch_finish_init */
6156 /* Function - Setup the JIT's Thread Level Specific Data. */
6158 /*------------------------------------------------------------------*/
6161 mono_arch_finish_init (void)
6163 appdomain_tls_offset = mono_domain_get_tls_offset();
6164 lmf_tls_offset = mono_get_lmf_tls_offset();
6165 lmf_addr_tls_offset = mono_get_lmf_addr_tls_offset();
6168 /*========================= End of Function ========================*/
6170 /*------------------------------------------------------------------*/
6172 /* Name - mono_arch_free_jit_tls_data */
6174 /* Function - Free tls data. */
6176 /*------------------------------------------------------------------*/
6179 mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
6183 /*========================= End of Function ========================*/
6185 /*------------------------------------------------------------------*/
6187 /* Name - mono_arch_emit_inst_for_method */
6189 /*------------------------------------------------------------------*/
6192 mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
6197 /*========================= End of Function ========================*/
6199 /*------------------------------------------------------------------*/
6201 /* Name - mono_arch_decompose_opts */
6203 /* Function - Decompose opcode into a System z opcode. */
6205 /*------------------------------------------------------------------*/
6208 mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
6211 * Have to rename these to avoid being decomposed normally, since the normal
6212 * decomposition does not work on S390.
6214 switch (ins->opcode) {
6216 ins->opcode = OP_S390_ISUB_OVF;
6218 case OP_ISUB_OVF_UN:
6219 ins->opcode = OP_S390_ISUB_OVF_UN;
6222 ins->opcode = OP_S390_IADD_OVF;
6224 case OP_IADD_OVF_UN:
6225 ins->opcode = OP_S390_IADD_OVF_UN;
6228 ins->opcode = OP_S390_LADD_OVF;
6230 case OP_LADD_OVF_UN:
6231 ins->opcode = OP_S390_LADD_OVF_UN;
6234 ins->opcode = OP_S390_LSUB_OVF;
6236 case OP_LSUB_OVF_UN:
6237 ins->opcode = OP_S390_LSUB_OVF_UN;
6244 /*========================= End of Function ========================*/
6246 /*------------------------------------------------------------------*/
6248 /* Name - mono_arch_print_tree */
6250 /* Function - Print platform-specific opcode details. */
6252 /* Returns - 1 - opcode details have been printed */
6253 /* 0 - opcode details have not been printed */
6255 /*------------------------------------------------------------------*/
6258 mono_arch_print_tree (MonoInst *tree, int arity)
6262 switch (tree->opcode) {
6263 case OP_S390_LOADARG:
6264 case OP_S390_ARGREG:
6265 case OP_S390_ARGPTR:
6266 printf ("[0x%lx(%s)]", tree->inst_offset,
6267 mono_arch_regname (tree->inst_basereg));
6270 case OP_S390_STKARG:
6271 printf ("[0x%lx(previous_frame)]",
6276 printf ("[0x%lx(%d,%s),0x%lx(%s)]",
6277 tree->inst_offset, tree->backend.size,
6278 mono_arch_regname(tree->dreg),
6280 mono_arch_regname(tree->sreg1));
6283 case OP_S390_SETF4RET:
6284 printf ("[f%s,f%s]",
6285 mono_arch_regname (tree->dreg),
6286 mono_arch_regname (tree->sreg1));
6290 printf ("[0x%lx(0x%lx,%s)]", tree->inst_offset,
6292 mono_arch_regname (tree->sreg1));
6295 case OP_S390_BKCHAIN:
6296 printf ("[previous_frame(%s)]",
6297 mono_arch_regname (tree->sreg1));
6305 /*========================= End of Function ========================*/
6307 /*------------------------------------------------------------------*/
6309 /* Name - mono_arch_regalloc_cost */
6311 /* Function - Determine the cost, in the number of memory */
6312 /* references, of the action of allocating the var- */
6313 /* iable VMV into a register during global register */
6316 /* Returns - Cost */
6318 /*------------------------------------------------------------------*/
6321 mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
6327 /*========================= End of Function ========================*/
6329 /*------------------------------------------------------------------*/
6331 /* Name - mono_arch_flush_register_windows */
6337 /*------------------------------------------------------------------*/
6340 mono_arch_flush_register_windows (void)
6344 /*========================= End of Function ========================*/
6346 /*------------------------------------------------------------------*/
6348 /* Name - mono_arch_is_inst_imm */
6350 /* Function - Determine if operand qualifies as an immediate */
6351 /* value. For s390 this is a value -32768-32768 */
6353 /* Returns - True|False - is [not] immediate value. */
6355 /*------------------------------------------------------------------*/
6358 mono_arch_is_inst_imm (gint64 imm)
6360 return s390_is_imm32 (imm);
6363 /*========================= End of Function ========================*/
6365 /*------------------------------------------------------------------*/
6367 /* Name - mono_arch_get_patch_offset */
6369 /* Function - Dummy entry point until s390x supports aot. */
6371 /* Returns - Offset for patch. */
6373 /*------------------------------------------------------------------*/
6376 mono_arch_get_patch_offset (guint8 *code)
6381 /*========================= End of Function ========================*/
6383 /*------------------------------------------------------------------*/
6385 /* Name - mono_arch_context_get_int_reg. */
6389 /* Returns - Return a register from the context. */
6391 /*------------------------------------------------------------------*/
6394 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
6396 return ((mgreg_t) ctx->uc_mcontext.gregs[reg]);
6399 /*========================= End of Function ========================*/
6401 /*------------------------------------------------------------------*/
6403 /* Name - mono_arch_context_set_int_reg. */
6405 /* Function - Set a value in a specified register. */
6407 /*------------------------------------------------------------------*/
6410 mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val)
6412 ctx->uc_mcontext.gregs[reg] = val;
6415 /*========================= End of Function ========================*/
6417 /*------------------------------------------------------------------*/
6419 /* Name - mono_arch_get_this_arg_from_call. */
6423 /*------------------------------------------------------------------*/
6426 mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
6428 return (gpointer) regs [s390_r2];
6431 /*========================= End of Function ========================*/
6433 /*------------------------------------------------------------------*/
6435 /* Name - mono_arch_install_handler_block_guard */
6439 /*------------------------------------------------------------------*/
6442 mono_arch_install_handler_block_guard (MonoJitInfo *ji, MonoJitExceptionInfo *clause,
6443 MonoContext *ctx, gpointer new_value)
6446 gpointer *sp, old_value;
6449 offset = clause->exvar_offset;
6452 bp = MONO_CONTEXT_GET_BP (ctx);
6453 sp = *(gpointer*)(bp + offset);
6456 if (old_value < ji->code_start || (char*)old_value > ((char*)ji->code_start + ji->code_size))
6464 /*========================= End of Function ========================*/
6466 /*------------------------------------------------------------------*/
6468 /* Name - get_delegate_invoke_impl. */
6472 /*------------------------------------------------------------------*/
6475 get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 param_count, gboolean aot)
6477 guint8 *code, *start;
6482 start = code = mono_global_codeman_reserve (size);
6484 /* Replace the this argument with the target */
6485 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6486 s390_lg (code, s390_r2, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, target));
6487 s390_br (code, s390_r1);
6488 g_assert ((code - start) <= size);
6490 mono_arch_flush_icache (start, size);
6494 size = 32 + param_count * 8;
6495 start = code = mono_global_codeman_reserve (size);
6497 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6498 /* slide down the arguments */
6499 for (i = 0; i < param_count; ++i) {
6500 s390_lgr (code, (s390_r2 + i), (s390_r2 + i + 1));
6502 s390_br (code, s390_r1);
6504 g_assert ((code - start) <= size);
6506 mono_arch_flush_icache (start, size);
6509 mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
6512 *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
6514 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
6515 *info = mono_tramp_info_create (name, start, code - start, NULL, NULL);
6522 /*========================= End of Function ========================*/
6524 /*------------------------------------------------------------------*/
6526 /* Name - mono_arch_get_delegate_invoke_impls. */
6530 /*------------------------------------------------------------------*/
6533 mono_arch_get_delegate_invoke_impls (void)
6536 MonoTrampInfo *info;
6539 get_delegate_invoke_impl (&info, TRUE, 0, TRUE);
6540 res = g_slist_prepend (res, info);
6542 for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
6543 get_delegate_invoke_impl (&info, FALSE, i, TRUE);
6544 res = g_slist_prepend (res, info);
6550 /*========================= End of Function ========================*/
6552 /*------------------------------------------------------------------*/
6554 /* Name - mono_arch_get_delegate_invoke_impl. */
6558 /*------------------------------------------------------------------*/
6561 mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target)
6563 guint8 *code, *start;
6565 /* FIXME: Support more cases */
6566 if (MONO_TYPE_ISSTRUCT (sig->ret))
6570 static guint8* cached = NULL;
6575 if (mono_aot_only) {
6576 start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
6578 MonoTrampInfo *info;
6579 start = get_delegate_invoke_impl (&info, TRUE, 0, FALSE);
6580 mono_tramp_info_register (info, NULL);
6583 mono_memory_barrier ();
6587 static guint8* cache [MAX_ARCH_DELEGATE_PARAMS + 1] = {NULL};
6590 if (sig->param_count > MAX_ARCH_DELEGATE_PARAMS)
6592 for (i = 0; i < sig->param_count; ++i)
6593 if (!mono_is_regsize_var (sig->params [i]))
6597 code = cache [sig->param_count];
6601 if (mono_aot_only) {
6602 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", sig->param_count);
6603 start = mono_aot_get_trampoline (name);
6606 MonoTrampInfo *info;
6607 start = get_delegate_invoke_impl (&info, FALSE, sig->param_count, FALSE);
6608 mono_tramp_info_register (info, NULL);
6611 mono_memory_barrier ();
6613 cache [sig->param_count] = start;
6618 /*========================= End of Function ========================*/
6620 /*------------------------------------------------------------------*/
6622 /* Name - mono_arch_get_delegate_virtual_invoke_impl. */
6626 /*------------------------------------------------------------------*/
6629 mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method,
6630 int offset, gboolean load_imt_reg)
6632 guint8 *code, *start;
6635 start = code = mono_global_codeman_reserve (size);
6638 * Replace the "this" argument with the target
6640 s390_lgr (code, s390_r1, s390_r2);
6641 s390_lg (code, s390_r2, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, target));
6644 * Load the IMT register, if needed
6647 s390_lg (code, MONO_ARCH_IMT_REG, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, method));
6653 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET(MonoObject, vtable));
6655 s390_agfi(code, s390_r1, offset);
6657 s390_lg (code, s390_r1, 0, s390_r1, 0);
6658 s390_br (code, s390_r1);
6663 /*========================= End of Function ========================*/
6665 /*------------------------------------------------------------------*/
6667 /* Name - mono_arch_build_imt_thunk. */
6671 /*------------------------------------------------------------------*/
6674 mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain,
6675 MonoIMTCheckItem **imt_entries, int count,
6676 gpointer fail_tramp)
6680 guchar *code, *start;
6683 for (i = 0; i < count; ++i) {
6684 MonoIMTCheckItem *item = imt_entries [i];
6685 if (item->is_equals) {
6686 if (item->check_target_idx) {
6687 if (!item->compare_done)
6688 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6689 if (item->has_target_code)
6690 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE;
6692 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE +
6696 item->chunk_size += CMP_SIZE + 2 * BR_SIZE + JUMP_SIZE +
6698 if (!item->has_target_code)
6699 item->chunk_size += LOAD_SIZE;
6701 item->chunk_size += LOADCON_SIZE + LOAD_SIZE + BR_SIZE;
6702 #if ENABLE_WRONG_METHOD_CHECK
6703 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6708 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6709 imt_entries [item->check_target_idx]->compare_done = TRUE;
6711 size += item->chunk_size;
6715 code = mono_method_alloc_generic_virtual_thunk (domain, size);
6717 code = mono_domain_code_reserve (domain, size);
6721 for (i = 0; i < count; ++i) {
6722 MonoIMTCheckItem *item = imt_entries [i];
6723 item->code_target = (guint8 *) code;
6724 if (item->is_equals) {
6725 if (item->check_target_idx) {
6726 if (!item->compare_done) {
6727 S390_SET (code, s390_r0, item->key);
6728 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
6730 item->jmp_code = (guint8*) code;
6731 s390_jcl (code, S390_CC_NE, 0);
6733 if (item->has_target_code) {
6734 S390_SET (code, s390_r1, item->value.target_code);
6736 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6737 s390_lg (code, s390_r1, 0, s390_r1, 0);
6739 s390_br (code, s390_r1);
6744 S390_SET (code, s390_r0, item->key);
6745 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
6746 item->jmp_code = (guint8*) code;
6747 s390_jcl (code, S390_CC_NE, 0);
6748 if (item->has_target_code) {
6749 S390_SET (code, s390_r1, item->value.target_code);
6752 S390_SET (code, s390_r1,
6753 (&(vtable->vtable [item->value.vtable_slot])));
6754 s390_lg (code, s390_r1, 0, s390_r1, 0);
6756 s390_br (code, s390_r1);
6757 target = (gint64) S390_RELATIVE(code, item->jmp_code);
6758 s390_patch_rel(item->jmp_code+2, target);
6759 S390_SET (code, s390_r1, fail_tramp);
6760 s390_br (code, s390_r1);
6761 item->jmp_code = NULL;
6763 /* enable the commented code to assert on wrong method */
6764 #if ENABLE_WRONG_METHOD_CHECK
6765 g_assert_not_reached ();
6767 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6768 s390_lg (code, s390_r1, 0, s390_r1, 0);
6769 s390_br (code, s390_r1);
6773 S390_SET (code, s390_r0, item->key);
6774 s390_cgr (code, MONO_ARCH_IMT_REG, s390_r0);
6775 item->jmp_code = (guint8 *) code;
6776 s390_jcl (code, S390_CC_GE, 0);
6780 * patch the branches to get to the target items
6782 for (i = 0; i < count; ++i) {
6783 MonoIMTCheckItem *item = imt_entries [i];
6784 if (item->jmp_code) {
6785 if (item->check_target_idx) {
6787 offset = (gint64) S390_RELATIVE(imt_entries [item->check_target_idx]->code_target,
6789 s390_patch_rel ((guchar *) item->jmp_code + 2, (guint64) offset);
6794 mono_arch_flush_icache ((guint8*)start, (code - start));
6795 mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL);
6798 mono_stats.imt_thunks_size += (code - start);
6800 g_assert (code - start <= size);
6802 snprintf(trampName, sizeof(trampName), "%d_imt_thunk_trampoline", domain->domain_id);
6803 mono_tramp_info_register (mono_tramp_info_create (trampName, start, code - start, NULL, NULL), domain);
6808 /*========================= End of Function ========================*/
6810 /*------------------------------------------------------------------*/
6812 /* Name - mono_arch_find_imt_method. */
6814 /* Function - Get the method address from MONO_ARCH_IMT_REG */
6815 /* found in the save area. */
6817 /*------------------------------------------------------------------*/
6820 mono_arch_find_imt_method (mgreg_t *regs, guint8 *code)
6822 return ((MonoMethod *) regs [MONO_ARCH_IMT_REG]);
6825 /*========================= End of Function ========================*/
6827 /*------------------------------------------------------------------*/
6829 /* Name - mono_arch_find_static_call_vtable */
6831 /* Function - Find the static call vtable. */
6833 /*------------------------------------------------------------------*/
6836 mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
6838 mgreg_t *r = (mgreg_t*)regs;
6840 return (MonoVTable*)(gsize) r [MONO_ARCH_RGCTX_REG];
6843 /*========================= End of Function ========================*/
6845 /*------------------------------------------------------------------*/
6847 /* Name - mono_arch_get_cie_program */
6849 /* Function - Find the static call vtable. */
6851 /*------------------------------------------------------------------*/
6854 mono_arch_get_cie_program (void)
6858 mono_add_unwind_op_def_cfa (l, 0, 0, STK_BASE, 0);
6863 /*========================= End of Function ========================*/
6865 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
6867 /*------------------------------------------------------------------*/
6869 /* Name - mono_arch_set_breakpoint. */
6871 /* Function - Set a breakpoint at the native code corresponding */
6872 /* to JI at NATIVE_OFFSET. The location should */
6873 /* contain code emitted by OP_SEQ_POINT. */
6875 /*------------------------------------------------------------------*/
6878 mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
6882 breakpointCode.pTrigger = bp_trigger_page;
6883 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
6884 code += BREAKPOINT_SIZE;
6887 /*========================= End of Function ========================*/
6889 /*------------------------------------------------------------------*/
6891 /* Name - mono_arch_clear_breakpoint. */
6893 /* Function - Clear the breakpoint at IP. */
6895 /*------------------------------------------------------------------*/
6898 mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
6903 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); i++)
6907 /*========================= End of Function ========================*/
6909 /*------------------------------------------------------------------*/
6911 /* Name - mono_arch_is_breakpoint_event. */
6915 /*------------------------------------------------------------------*/
6918 mono_arch_is_breakpoint_event (void *info, void *sigctx)
6920 siginfo_t* sinfo = (siginfo_t*) info;
6923 * Sometimes the address is off by 4
6925 if (sinfo->si_addr >= bp_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)bp_trigger_page + 128)
6931 /*========================= End of Function ========================*/
6933 /*------------------------------------------------------------------*/
6935 /* Name - mono_arch_skip_breakpoint. */
6937 /* Function - Modify the CTX so the IP is placed after the */
6938 /* breakpoint instruction, so when we resume, the */
6939 /* instruction is not executed again. */
6941 /*------------------------------------------------------------------*/
6944 mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
6946 MONO_CONTEXT_SET_IP (ctx, ((guint8*)MONO_CONTEXT_GET_IP (ctx) + sizeof(RXY_Format)));
6949 /*========================= End of Function ========================*/
6951 /*------------------------------------------------------------------*/
6953 /* Name - mono_arch_start_single_stepping. */
6955 /* Function - Start single stepping. */
6957 /*------------------------------------------------------------------*/
6960 mono_arch_start_single_stepping (void)
6962 mono_mprotect (ss_trigger_page, mono_pagesize (), 0);
6965 /*========================= End of Function ========================*/
6967 /*------------------------------------------------------------------*/
6969 /* Name - mono_arch_stop_single_stepping. */
6971 /* Function - Stop single stepping. */
6973 /*------------------------------------------------------------------*/
6976 mono_arch_stop_single_stepping (void)
6978 mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ);
6981 /*========================= End of Function ========================*/
6983 /*------------------------------------------------------------------*/
6985 /* Name - mono_arch_is_single_step_event. */
6987 /* Function - Return whether the machine state in sigctx cor- */
6988 /* responds to a single step event. */
6990 /*------------------------------------------------------------------*/
6993 mono_arch_is_single_step_event (void *info, void *sigctx)
6995 siginfo_t* sinfo = (siginfo_t*) info;
6998 * Sometimes the address is off by 4
7000 if (sinfo->si_addr >= ss_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)ss_trigger_page + 128)
7006 /*========================= End of Function ========================*/
7008 /*------------------------------------------------------------------*/
7010 /* Name - mono_arch_skip_single_step. */
7012 /* Function - Modify the ctx so the IP is placed after the */
7013 /* single step trigger instruction, so that the */
7014 /* instruction is not executed again. */
7016 /*------------------------------------------------------------------*/
7019 mono_arch_skip_single_step (MonoContext *ctx)
7021 MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + BREAKPOINT_SIZE);
7024 /*========================= End of Function ========================*/
7026 /*------------------------------------------------------------------*/
7028 /* Name - mono_arch_create_seq_point_info. */
7030 /* Function - Return a pointer to a data struction which is */
7031 /* used by the sequence point implementation in */
7034 /*------------------------------------------------------------------*/
7037 mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code)
7043 /*========================= End of Function ========================*/
7045 /*------------------------------------------------------------------*/
7047 /* Name - mono_arch_init_lmf_ext. */
7051 /*------------------------------------------------------------------*/
7054 mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
7056 ext->lmf.previous_lmf = prev_lmf;
7057 /* Mark that this is a MonoLMFExt */
7058 ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
7059 ext->lmf.ebp = (gssize)ext;
7062 /*========================= End of Function ========================*/
7066 /*------------------------------------------------------------------*/
7068 /* Name - mono_arch_cpu_enumerate_simd_versions. */
7070 /* Function - If this CPU supports vector operations then it */
7071 /* supports the equivalent of SSE1-4. */
7073 /*------------------------------------------------------------------*/
7076 mono_arch_cpu_enumerate_simd_versions (void)
7078 guint32 sseOpts = 0;
7081 sseOpts = (SIMD_VERSION_SSE1 | SIMD_VERSION_SSE2 |
7082 SIMD_VERSION_SSE3 | SIMD_VERSION_SSSE3 |
7083 SIMD_VERSION_SSE41 | SIMD_VERSION_SSE42 |
7084 SIMD_VERSION_SSE4a);
7089 /*========================= End of Function ========================*/
7091 /*------------------------------------------------------------------*/
7093 /* Name - mono_arch_opcode_supported. */
7095 /* Function - Check if a given return code is supported. */
7097 /*------------------------------------------------------------------*/
7100 mono_arch_opcode_supported (int opcode)
7103 case OP_ATOMIC_ADD_I4:
7104 case OP_ATOMIC_ADD_I8:
7105 case OP_ATOMIC_EXCHANGE_I4:
7106 case OP_ATOMIC_EXCHANGE_I8:
7113 /*========================= End of Function ========================*/