3 * Function - S/390 backend for the Mono code generator.
5 * Name - Neale Ferguson (Neale.Ferguson@SoftwareAG-usa.com)
9 * Derivation - From mini-x86 & mini-ppc by -
10 * Paolo Molaro (lupus@ximian.com)
11 * Dietmar Maurer (dietmar@ximian.com)
15 /*------------------------------------------------------------------*/
17 /*------------------------------------------------------------------*/
19 #define MAX_ARCH_DELEGATE_PARAMS 7
21 #define EMIT_COND_BRANCH(ins,cond) \
23 if (ins->inst_true_bb->native_offset) { \
25 displace = ((cfg->native_code + \
26 ins->inst_true_bb->native_offset) - code) / 2; \
27 if (s390_is_imm16(displace)) { \
28 s390_brc (code, cond, displace); \
30 s390_jcl (code, cond, displace); \
33 mono_add_patch_info (cfg, code - cfg->native_code, \
34 MONO_PATCH_INFO_BB, ins->inst_true_bb); \
35 s390_jcl (code, cond, 0); \
39 #define EMIT_UNCOND_BRANCH(ins) \
41 if (ins->inst_target_bb->native_offset) { \
43 displace = ((cfg->native_code + \
44 ins->inst_target_bb->native_offset) - code) / 2; \
45 if (s390_is_imm16(displace)) { \
46 s390_brc (code, S390_CC_UN, displace); \
48 s390_jcl (code, S390_CC_UN, displace); \
51 mono_add_patch_info (cfg, code - cfg->native_code, \
52 MONO_PATCH_INFO_BB, ins->inst_target_bb); \
53 s390_jcl (code, S390_CC_UN, 0); \
57 #define EMIT_COND_SYSTEM_EXCEPTION(cond,exc_name) \
59 mono_add_patch_info (cfg, code - cfg->native_code, \
60 MONO_PATCH_INFO_EXC, exc_name); \
61 s390_jcl (code, cond, 0); \
64 #define CHECK_SRCDST_COM \
65 if (ins->dreg == ins->sreg2) { \
69 if (ins->dreg != ins->sreg1) { \
70 s390_lgr (code, ins->dreg, ins->sreg1); \
74 #define CHECK_SRCDST_NCOM \
75 if (ins->dreg == ins->sreg2) { \
77 s390_lgr (code, s390_r13, ins->sreg2); \
81 if (ins->dreg != ins->sreg1) { \
82 s390_lgr (code, ins->dreg, ins->sreg1); \
85 #define CHECK_SRCDST_COM_I \
86 if (ins->dreg == ins->sreg2) { \
90 if (ins->dreg != ins->sreg1) { \
91 s390_lgfr (code, ins->dreg, ins->sreg1); \
95 #define CHECK_SRCDST_NCOM_I \
96 if (ins->dreg == ins->sreg2) { \
98 s390_lgfr (code, s390_r13, ins->sreg2); \
102 if (ins->dreg != ins->sreg1) { \
103 s390_lgfr (code, ins->dreg, ins->sreg1); \
106 #define CHECK_SRCDST_COM_F \
107 if (ins->dreg == ins->sreg2) { \
111 if (ins->dreg != ins->sreg1) { \
112 s390_ldr (code, ins->dreg, ins->sreg1); \
116 #define CHECK_SRCDST_NCOM_F \
117 if (ins->dreg == ins->sreg2) { \
119 s390_ldr (code, s390_r13, ins->sreg2); \
123 if (ins->dreg != ins->sreg1) { \
124 s390_ldr (code, ins->dreg, ins->sreg1); \
127 #define MONO_EMIT_NEW_MOVE(cfg,dest,offset,src,imm,size) do { \
130 MONO_INST_NEW (cfg, inst, OP_NOP); \
133 inst->inst_offset = offset; \
135 inst->inst_imm = imm; \
137 if (s390_is_uimm12(offset)) { \
139 inst->inst_offset = offset; \
141 dReg = mono_alloc_preg (cfg); \
142 MONO_EMIT_NEW_BIALU_IMM(cfg, OP_ADD_IMM, \
143 dReg, dest, offset); \
145 inst->inst_offset = 0; \
147 if (s390_is_uimm12(imm)) { \
149 inst->inst_imm = imm; \
151 sReg = mono_alloc_preg (cfg); \
152 MONO_EMIT_NEW_BIALU_IMM(cfg, OP_ADD_IMM, \
154 inst->sreg1 = sReg; \
155 inst->inst_imm = 0; \
158 inst->opcode = OP_S390_MOVE; \
159 inst->backend.size = size; \
160 MONO_ADD_INS (cfg->cbb, inst); \
163 #define MONO_OUTPUT_VTR(cfg, size, dr, sr, so) do { \
164 int reg = mono_alloc_preg (cfg); \
167 MONO_EMIT_NEW_ICONST(cfg, reg, 0); \
170 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU1_MEMBASE, \
174 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU2_MEMBASE, \
178 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI4_MEMBASE, \
182 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI8_MEMBASE, \
186 mono_call_inst_add_outarg_reg(cfg, call, reg, dr, FALSE); \
189 #define MONO_OUTPUT_VTS(cfg, size, dr, dx, sr, so) do { \
193 tmpr = mono_alloc_preg (cfg); \
194 MONO_EMIT_NEW_ICONST(cfg, tmpr, 0); \
195 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
199 tmpr = mono_alloc_preg (cfg); \
200 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU1_MEMBASE, \
202 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
206 tmpr = mono_alloc_preg (cfg); \
207 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU2_MEMBASE, \
209 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
213 tmpr = mono_alloc_preg (cfg); \
214 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI4_MEMBASE, \
216 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
220 MONO_EMIT_NEW_MOVE (cfg, dr, dx, sr, so, size); \
226 #define DEBUG(a) if (cfg->verbose_level > 1) a
230 #define S390_TRACE_STACK_SIZE (5*sizeof(gpointer)+4*sizeof(gdouble))
232 #define BREAKPOINT_SIZE sizeof(breakpoint_t)
233 #define S390X_NOP_SIZE sizeof(RR_Format)
235 #define MAX(a, b) ((a) > (b) ? (a) : (b))
238 * imt trampoline size values
241 #define LOADCON_SIZE 20
245 #define ENABLE_WRONG_METHOD_CHECK 0
247 #define mono_mini_arch_lock() mono_os_mutex_lock (&mini_arch_mutex)
248 #define mono_mini_arch_unlock() mono_os_mutex_unlock (&mini_arch_mutex)
250 /*========================= End of Defines =========================*/
252 /*------------------------------------------------------------------*/
253 /* I n c l u d e s */
254 /*------------------------------------------------------------------*/
258 #include <sys/types.h>
261 #include <mono/metadata/abi-details.h>
262 #include <mono/metadata/appdomain.h>
263 #include <mono/metadata/debug-helpers.h>
264 #include <mono/metadata/profiler-private.h>
265 #include <mono/utils/mono-error.h>
266 #include <mono/utils/mono-error-internals.h>
267 #include <mono/utils/mono-math.h>
268 #include <mono/utils/mono-mmap.h>
269 #include <mono/utils/mono-hwcap.h>
270 #include <mono/utils/mono-threads.h>
271 #include <mono/utils/unlocked.h>
273 #include "mini-s390x.h"
274 #include "cpu-s390x.h"
275 #include "support-s390x.h"
276 #include "jit-icalls.h"
281 /*========================= End of Includes ========================*/
283 /*------------------------------------------------------------------*/
284 /* T y p e d e f s */
285 /*------------------------------------------------------------------*/
297 /*------------------------------------------------------------------*/
298 /* Used by the instrument_emit_epilog */
299 /*------------------------------------------------------------------*/
310 typedef struct InstList InstList;
324 RegTypeStructByValInFP,
326 RegTypeStructByAddrOnStack
330 gint32 offset; /* offset from caller's stack */
331 gint32 offparm; /* offset from callee's stack */
332 guint16 vtsize; /* in param area */
335 guint32 size; /* Size of structure used by RegTypeStructByVal */
336 gint32 type; /* Data type of argument */
352 gint64 gr[5]; /* R2-R6 */
353 gdouble fp[3]; /* F0-F2 */
354 } __attribute__ ((__packed__)) RegParm;
362 } __attribute__ ((__packed__)) breakpoint_t;
364 /*========================= End of Typedefs ========================*/
366 /*------------------------------------------------------------------*/
367 /* P r o t o t y p e s */
368 /*------------------------------------------------------------------*/
370 static void indent (int);
371 static guint8 * backUpStackPtr(MonoCompile *, guint8 *);
372 static void decodeParm (MonoType *, void *, int);
373 static void enter_method (MonoMethod *, RegParm *, char *);
374 static void leave_method (MonoMethod *, ...);
375 static inline void add_general (guint *, size_data *, ArgInfo *);
376 static inline void add_stackParm (guint *, size_data *, ArgInfo *, gint);
377 static inline void add_float (guint *, size_data *, ArgInfo *);
378 static CallInfo * get_call_info (MonoCompile *, MonoMemPool *, MonoMethodSignature *);
379 static guchar * emit_float_to_int (MonoCompile *, guchar *, int, int, int, gboolean);
380 static guint8 * emit_load_volatile_arguments (guint8 *, MonoCompile *);
381 static __inline__ void emit_unwind_regs(MonoCompile *, guint8 *, int, int, long);
383 /*========================= End of Prototypes ======================*/
385 /*------------------------------------------------------------------*/
386 /* G l o b a l V a r i a b l e s */
387 /*------------------------------------------------------------------*/
389 int mono_exc_esp_offset = 0;
391 __thread int indent_level = 0;
394 * The code generated for sequence points reads from this location,
395 * which is made read-only when single stepping is enabled.
397 static gpointer ss_trigger_page;
400 * Enabled breakpoints read from this trigger page
402 static gpointer bp_trigger_page;
404 breakpoint_t breakpointCode;
406 static mono_mutex_t mini_arch_mutex;
408 static const char * grNames[] = {
409 "s390_r0", "s390_sp", "s390_r2", "s390_r3", "s390_r4",
410 "s390_r5", "s390_r6", "s390_r7", "s390_r8", "s390_r9",
411 "s390_r10", "s390_r11", "s390_r12", "s390_r13", "s390_r14",
415 static const char * fpNames[] = {
416 "s390_f0", "s390_f1", "s390_f2", "s390_f3", "s390_f4",
417 "s390_f5", "s390_f6", "s390_f7", "s390_f8", "s390_f9",
418 "s390_f10", "s390_f11", "s390_f12", "s390_f13", "s390_f14",
422 static const char * vrNames[] = {
423 "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7",
424 "vr8", "vr9", "vr10", "vr11", "vr12", "vr13", "vr14", "vr15",
425 "vr16", "vr17", "vr18", "vr19", "vr20", "vr21", "vr22", "vr23",
426 "vr24", "vr25", "vr26", "vr27", "vr28", "vr29", "vr30", "vr31"
429 /*====================== End of Global Variables ===================*/
431 /*------------------------------------------------------------------*/
433 /* Name - mono_arch_regname */
435 /* Function - Returns the name of the register specified by */
436 /* the input parameter. */
438 /*------------------------------------------------------------------*/
441 mono_arch_regname (int reg)
443 if (reg >= 0 && reg < 16)
444 return grNames [reg];
449 /*========================= End of Function ========================*/
451 /*------------------------------------------------------------------*/
453 /* Name - mono_arch_fregname */
455 /* Function - Returns the name of the register specified by */
456 /* the input parameter. */
458 /*------------------------------------------------------------------*/
461 mono_arch_fregname (int reg)
463 if (reg >= 0 && reg < 16)
464 return fpNames [reg];
469 /*========================= End of Function ========================*/
471 /*------------------------------------------------------------------*/
473 /* Name - mono_arch_xregname */
475 /* Function - Returns the name of the register specified by */
476 /* the input parameter. */
478 /*------------------------------------------------------------------*/
481 mono_arch_xregname (int reg)
483 if (reg < s390_VR_NREG)
484 return vrNames [reg];
489 /*========================= End of Function ========================*/
491 /*------------------------------------------------------------------*/
493 /* Name - arch_get_argument_info */
495 /* Function - Gathers information on parameters such as size, */
496 /* alignment, and padding. arg_info should be large */
497 /* enough to hold param_count + 1 entries. */
499 /* Parameters - @csig - Method signature */
500 /* @param_count - No. of parameters to consider */
501 /* @arg_info - An array to store the result info */
503 /* Returns - Size of the activation frame */
505 /*------------------------------------------------------------------*/
508 mono_arch_get_argument_info (MonoMethodSignature *csig,
510 MonoJitArgumentInfo *arg_info)
512 int k, frame_size = 0;
513 int size, align, pad;
516 if (MONO_TYPE_ISSTRUCT (csig->ret)) {
517 frame_size += sizeof (gpointer);
521 arg_info [0].offset = offset;
524 frame_size += sizeof (gpointer);
528 arg_info [0].size = frame_size;
530 for (k = 0; k < param_count; k++) {
533 size = mono_type_native_stack_size (csig->params [k], (guint32 *) &align);
535 size = mini_type_stack_size (csig->params [k], &align);
537 frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
538 arg_info [k].pad = pad;
540 arg_info [k + 1].pad = 0;
541 arg_info [k + 1].size = size;
543 arg_info [k + 1].offset = offset;
547 align = MONO_ARCH_FRAME_ALIGNMENT;
548 frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
549 arg_info [k].pad = pad;
554 /*========================= End of Function ========================*/
556 /*------------------------------------------------------------------*/
558 /* Name - emit_unwind_regs. */
560 /* Function - Determines if a value can be returned in one or */
563 /*------------------------------------------------------------------*/
565 static void __inline__
566 emit_unwind_regs(MonoCompile *cfg, guint8 *code, int start, int end, long offset)
570 for (i = start; i < end; i++) {
571 mono_emit_unwind_op_offset (cfg, code, i, offset);
572 mini_gc_set_slot_type_from_cfa (cfg, offset, SLOT_NOREF);
573 offset += sizeof(gulong);
577 /*========================= End of Function ========================*/
579 /*------------------------------------------------------------------*/
581 /* Name - retFitsInReg. */
583 /* Function - Determines if a value can be returned in one or */
586 /*------------------------------------------------------------------*/
588 static inline gboolean
589 retFitsInReg(guint32 size)
604 /*========================= End of Function ========================*/
606 /*------------------------------------------------------------------*/
608 /* Name - backStackPtr. */
610 /* Function - Restore Stack Pointer to previous frame. */
612 /*------------------------------------------------------------------*/
614 static inline guint8 *
615 backUpStackPtr(MonoCompile *cfg, guint8 *code)
617 int stackSize = cfg->stack_usage;
619 if (cfg->frame_reg != STK_BASE)
620 s390_lgr (code, STK_BASE, cfg->frame_reg);
622 if (s390_is_imm16 (stackSize)) {
623 s390_aghi (code, STK_BASE, stackSize);
625 while (stackSize > 32767) {
626 s390_aghi (code, STK_BASE, 32767);
629 s390_aghi (code, STK_BASE, stackSize);
634 /*========================= End of Function ========================*/
636 /*------------------------------------------------------------------*/
640 /* Function - Perform nice indenting to current level */
642 /*------------------------------------------------------------------*/
648 indent_level += diff;
650 printf("%p [%3d] ",(void *)pthread_self(),v);
655 indent_level += diff;
658 /*========================= End of Function ========================*/
660 /*------------------------------------------------------------------*/
662 /* Name - cvtMonoType */
664 /* Function - Convert a mono-type to a string. */
666 /*------------------------------------------------------------------*/
669 cvtMonoType(MonoTypeEnum t)
674 return "MONO_TYPE_END";
676 return "MONO_TYPE_VOID";
677 case MONO_TYPE_BOOLEAN:
678 return "MONO_TYPE_BOOLEAN";
680 return "MONO_TYPE_CHAR";
682 return "MONO_TYPE_I1";
684 return "MONO_TYPE_U1";
686 return "MONO_TYPE_I2";
688 return "MONO_TYPE_U2";
690 return "MONO_TYPE_I4";
692 return "MONO_TYPE_U4";
694 return "MONO_TYPE_I8";
696 return "MONO_TYPE_U8";
698 return "MONO_TYPE_R4";
700 return "MONO_TYPE_R8";
701 case MONO_TYPE_STRING:
702 return "MONO_TYPE_STRING";
704 return "MONO_TYPE_PTR";
705 case MONO_TYPE_BYREF:
706 return "MONO_TYPE_BYREF";
707 case MONO_TYPE_VALUETYPE:
708 return "MONO_TYPE_VALUETYPE";
709 case MONO_TYPE_CLASS:
710 return "MONO_TYPE_CLASS";
712 return "MONO_TYPE_VAR";
713 case MONO_TYPE_ARRAY:
714 return "MONO_TYPE_ARRAY";
715 case MONO_TYPE_GENERICINST:
716 return "MONO_TYPE_GENERICINST";
717 case MONO_TYPE_TYPEDBYREF:
718 return "MONO_TYPE_TYPEDBYREF";
720 return "MONO_TYPE_I";
722 return "MONO_TYPE_U";
723 case MONO_TYPE_FNPTR:
724 return "MONO_TYPE_FNPTR";
725 case MONO_TYPE_OBJECT:
726 return "MONO_TYPE_OBJECT";
727 case MONO_TYPE_SZARRAY:
728 return "MONO_TYPE_SZARRAY";
730 return "MONO_TYPE_MVAR";
731 case MONO_TYPE_CMOD_REQD:
732 return "MONO_TYPE_CMOD_REQD";
733 case MONO_TYPE_CMOD_OPT:
734 return "MONO_TYPE_CMOD_OPT";
735 case MONO_TYPE_INTERNAL:
736 return "MONO_TYPE_INTERNAL";
737 case MONO_TYPE_MODIFIER:
738 return "MONO_TYPE_MODIFIER";
739 case MONO_TYPE_SENTINEL:
740 return "MONO_TYPE_SENTINEL";
741 case MONO_TYPE_PINNED:
742 return "MONO_TYPE_PINNED";
749 /*========================= End of Function ========================*/
751 /*------------------------------------------------------------------*/
753 /* Name - decodeParm */
755 /* Function - Decode a parameter for the trace. */
757 /*------------------------------------------------------------------*/
760 decodeParmString (MonoString *s)
763 char *str = mono_string_to_utf8_checked(s, &error);
764 if (is_ok (&error)) {
765 printf("[STRING:%p:%s], ", s, str);
768 mono_error_cleanup (&error);
769 printf("[STRING:%p:], ", s);
774 decodeParm(MonoType *type, void *curParm, int size)
779 printf("[BYREF:%p], ", *((char **) curParm));
781 simpleType = mini_get_underlying_type(type)->type;
783 switch (simpleType) {
785 printf ("[INTPTR:%p], ", *((int **) curParm));
788 printf ("[UINTPTR:%p], ", *((int **) curParm));
790 case MONO_TYPE_BOOLEAN :
791 printf ("[BOOL:%ld], ", *((gint64 *) curParm));
793 case MONO_TYPE_CHAR :
794 printf ("[CHAR:%c], ", *((int *) curParm));
797 printf ("[INT1:%ld], ", *((gint64 *) curParm));
800 printf ("[INT2:%ld], ", *((gint64 *) curParm));
803 printf ("[INT4:%ld], ", *((gint64 *) curParm));
806 printf ("[UINT1:%lu], ", *((guint64 *) curParm));
809 printf ("[UINT2:%lu], ", *((guint64 *) curParm));
812 printf ("[UINT4:%lu], ", *((guint64 *) curParm));
815 printf ("[UINT8:%lu], ", *((guint64 *) curParm));
817 case MONO_TYPE_STRING : {
818 MonoString *s = *((MonoString **) curParm);
820 g_assert (((MonoObject *) s)->vtable->klass == mono_defaults.string_class);
821 decodeParmString (s);
823 printf("[STRING:null], ");
827 case MONO_TYPE_CLASS :
828 case MONO_TYPE_OBJECT : {
829 MonoObject *obj = *((MonoObject **) curParm);
831 if ((obj) && (obj->vtable)) {
832 printf("[CLASS/OBJ:");
833 klass = obj->vtable->klass;
834 printf("%p [%p] ",obj,curParm);
835 if (klass == mono_defaults.string_class) {
836 decodeParmString ((MonoString *)obj);
837 } else if (klass == mono_defaults.int32_class) {
838 printf("[INT32:%p:%d]",
839 obj, *(gint32 *)((char *)obj + sizeof (MonoObject)));
842 klass->name_space, klass->name, obj);
845 printf("[OBJECT:null], ");
850 printf("[PTR:%p], ", *((gpointer **) (curParm)));
852 case MONO_TYPE_FNPTR :
853 printf("[FNPTR:%p], ", *((gpointer **) (curParm)));
855 case MONO_TYPE_ARRAY :
856 printf("[ARRAY:%p], ", *((gpointer **) (curParm)));
858 case MONO_TYPE_SZARRAY :
859 printf("[SZARRAY:%p], ", *((gpointer **) (curParm)));
862 printf("[INT8:%ld], ", *((gint64 *) (curParm)));
865 printf("[FLOAT4:%g], ", *((float *) (curParm)));
868 printf("[FLOAT8:%g], ", *((double *) (curParm)));
870 case MONO_TYPE_VALUETYPE : {
872 MonoMarshalType *info;
874 if (type->data.klass->enumtype) {
875 simpleType = mono_class_enum_basetype (type->data.klass)->type;
876 printf("{VALUETYPE} - ");
880 info = mono_marshal_load_type_info (type->data.klass);
882 if ((info->native_size == sizeof(float)) &&
883 (info->num_fields == 1) &&
884 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
885 printf("[FLOAT4:%f], ", *((float *) (curParm)));
889 if ((info->native_size == sizeof(double)) &&
890 (info->num_fields == 1) &&
891 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
892 printf("[FLOAT8:%g], ", *((double *) (curParm)));
896 printf("[VALUETYPE:");
897 for (i = 0; i < size; i++)
898 printf("%02x,", *((guint8 *)curParm+i));
902 case MONO_TYPE_TYPEDBYREF: {
904 printf("[TYPEDBYREF:");
905 for (i = 0; i < size; i++)
906 printf("%02x,", *((guint8 *)curParm+i));
911 printf("[%s], ",cvtMonoType(simpleType));
916 /*========================= End of Function ========================*/
918 /*------------------------------------------------------------------*/
920 /* Name - enter_method */
922 /* Function - Perform tracing of the entry to the current */
925 /*------------------------------------------------------------------*/
928 enter_method (MonoMethod *method, RegParm *rParm, char *sp)
930 int i, oParm = 0, iParm = 0;
933 MonoMethodSignature *sig;
940 fname = mono_method_full_name (method, TRUE);
942 printf ("ENTER: %s ", fname);
945 ip = (*(guint64 *) (sp+S390_RET_ADDR_OFFSET));
946 printf ("ip: %p sp: %p - ", (gpointer) ip, sp);
951 sig = mono_method_signature (method);
953 cinfo = get_call_info (NULL, NULL, sig);
955 if (cinfo->struct_ret) {
956 printf ("[STRUCTRET:%p], ", (gpointer) rParm->gr[0]);
961 gpointer *this_arg = (gpointer *) rParm->gr[iParm];
962 obj = (MonoObject *) this_arg;
963 switch(method->klass->this_arg.type) {
964 case MONO_TYPE_VALUETYPE:
966 guint64 *value = (guint64 *) ((uintptr_t)this_arg + sizeof(MonoObject));
967 printf("this:[value:%p:%016lx], ", this_arg, *value);
969 printf ("this:[NULL], ");
971 case MONO_TYPE_STRING:
974 klass = obj->vtable->klass;
975 if (klass == mono_defaults.string_class) {
977 decodeParmString((MonoString *)obj);
979 printf ("this:%p[%s.%s], ",
980 obj, klass->name_space, klass->name);
983 printf("vtable:[NULL], ");
985 printf ("this:[NULL], ");
988 printf("this[%s]: %p, ",cvtMonoType(method->klass->this_arg.type),this_arg);
993 for (i = 0; i < sig->param_count; ++i) {
994 ainfo = &cinfo->args[i + oParm];
995 switch (ainfo->regtype) {
996 case RegTypeGeneral :
997 decodeParm(sig->params[i], &(rParm->gr[ainfo->reg-2]), ainfo->size);
1000 decodeParm(sig->params[i], &(rParm->fp[ainfo->reg]), ainfo->size);
1003 decodeParm(sig->params[i], sp+ainfo->offset, ainfo->size);
1005 case RegTypeStructByVal :
1006 if (ainfo->reg != STK_BASE) {
1007 int offset = sizeof(glong) - ainfo->size;
1008 curParm = &(rParm->gr[ainfo->reg-2])+offset;
1011 curParm = sp+ainfo->offset;
1013 if (retFitsInReg (ainfo->vtsize))
1014 decodeParm(sig->params[i],
1018 decodeParm(sig->params[i],
1019 *((char **) curParm),
1022 case RegTypeStructByAddr :
1023 if (ainfo->reg != STK_BASE)
1024 curParm = &(rParm->gr[ainfo->reg-2]);
1026 curParm = sp+ainfo->offset;
1028 decodeParm(sig->params[i],
1029 *((char **) curParm),
1041 /*========================= End of Function ========================*/
1043 /*------------------------------------------------------------------*/
1045 /* Name - leave_method */
1049 /*------------------------------------------------------------------*/
1052 leave_method (MonoMethod *method, ...)
1059 va_start(ap, method);
1061 fname = mono_method_full_name (method, TRUE);
1063 printf ("LEAVE: %s", fname);
1066 type = mono_method_signature (method)->ret;
1069 switch (type->type) {
1070 case MONO_TYPE_VOID:
1072 case MONO_TYPE_BOOLEAN: {
1073 int val = va_arg (ap, int);
1075 printf ("[TRUE:%d]", val);
1081 case MONO_TYPE_CHAR: {
1082 int val = va_arg (ap, int);
1083 printf ("[CHAR:%d]", val);
1086 case MONO_TYPE_I1: {
1087 int val = va_arg (ap, int);
1088 printf ("[INT1:%d]", val);
1091 case MONO_TYPE_U1: {
1092 int val = va_arg (ap, int);
1093 printf ("[UINT1:%d]", val);
1096 case MONO_TYPE_I2: {
1097 int val = va_arg (ap, int);
1098 printf ("[INT2:%d]", val);
1101 case MONO_TYPE_U2: {
1102 int val = va_arg (ap, int);
1103 printf ("[UINT2:%d]", val);
1106 case MONO_TYPE_I4: {
1107 int val = va_arg (ap, int);
1108 printf ("[INT4:%d]", val);
1111 case MONO_TYPE_U4: {
1112 int val = va_arg (ap, int);
1113 printf ("[UINT4:%d]", val);
1117 gint64 val = va_arg (ap, gint64);
1118 printf ("[INT:%ld]", val);
1123 gint64 val = va_arg (ap, gint64);
1124 printf ("[UINT:%lu]", val);
1128 case MONO_TYPE_STRING: {
1129 MonoString *s = va_arg (ap, MonoString *);
1132 g_assert (((MonoObject *)s)->vtable->klass == mono_defaults.string_class);
1133 decodeParmString (s);
1135 printf ("[STRING:null], ");
1138 case MONO_TYPE_CLASS:
1139 case MONO_TYPE_OBJECT: {
1140 MonoObject *o = va_arg (ap, MonoObject *);
1142 if ((o) && (o->vtable)) {
1143 if (o->vtable->klass == mono_defaults.boolean_class) {
1144 printf ("[BOOLEAN:%p:%d]", o, *((guint8 *)o + sizeof (MonoObject)));
1145 } else if (o->vtable->klass == mono_defaults.int32_class) {
1146 printf ("[INT32:%p:%d]", o, *((gint32 *)((char *)o + sizeof (MonoObject))));
1147 } else if (o->vtable->klass == mono_defaults.int64_class) {
1148 printf ("[INT64:%p:%ld]", o, *((gint64 *)((char *)o + sizeof (MonoObject))));
1150 printf ("[%s.%s:%p]", o->vtable->klass->name_space, o->vtable->klass->name, o);
1152 printf ("[OBJECT:%p]", o);
1157 case MONO_TYPE_FNPTR:
1158 case MONO_TYPE_ARRAY:
1159 case MONO_TYPE_SZARRAY: {
1160 gpointer p = va_arg (ap, gpointer);
1161 printf ("[result=%p]", p);
1164 case MONO_TYPE_I8: {
1165 gint64 l = va_arg (ap, gint64);
1166 printf ("[LONG:%ld]", l);
1169 case MONO_TYPE_U8: {
1170 guint64 l = va_arg (ap, guint64);
1171 printf ("[ULONG:%lu]", l);
1174 case MONO_TYPE_R4: {
1175 double f = va_arg (ap, double);
1176 printf ("[FLOAT4:%g]\n", f);
1179 case MONO_TYPE_R8: {
1180 double f = va_arg (ap, double);
1181 printf ("[FLOAT8:%g]\n", f);
1184 case MONO_TYPE_VALUETYPE: {
1185 MonoMarshalType *info;
1186 if (type->data.klass->enumtype) {
1187 type = mono_class_enum_basetype (type->data.klass);
1192 info = mono_marshal_load_type_info (type->data.klass);
1194 if ((info->native_size == sizeof(float)) &&
1195 (info->num_fields == 1) &&
1196 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1197 double f = va_arg (ap, double);
1198 printf("[FLOAT4:%g]\n", (double) f);
1202 if ((info->native_size == sizeof(double)) &&
1203 (info->num_fields == 1) &&
1204 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1205 double f = va_arg (ap, double);
1206 printf("[FLOAT8:%g]\n", f);
1210 size = mono_type_size (type, &align);
1213 guint32 p = va_arg (ap, guint32);
1214 printf ("[%02x]\n",p);
1218 guint32 p = va_arg (ap, guint32);
1219 printf ("[%04x]\n",p);
1223 guint32 p = va_arg (ap, guint32);
1224 printf ("[%08x]\n",p);
1228 guint64 p = va_arg (ap, guint64);
1229 printf ("[%016lx]\n",p);
1233 gpointer p = va_arg (ap, gpointer);
1234 printf ("[VALUETYPE] %p\n",p);
1240 case MONO_TYPE_TYPEDBYREF: {
1241 guint8 *p = va_arg (ap, gpointer);
1243 size = mono_type_size (type, &align);
1250 for (j = 0; p && j < size; j++)
1251 printf ("%02x,", p [j]);
1255 printf ("[TYPEDBYREF]\n");
1259 case MONO_TYPE_GENERICINST: {
1260 printf("[GENERICINST]\n");
1263 case MONO_TYPE_MVAR: {
1267 case MONO_TYPE_CMOD_REQD: {
1268 printf("[CMOD_REQD]\n");
1271 case MONO_TYPE_CMOD_OPT: {
1272 printf("[CMOD_OPT]\n");
1275 case MONO_TYPE_INTERNAL: {
1276 printf("[INTERNAL]\n");
1280 printf ("(unknown return type %x)",
1281 mono_method_signature (method)->ret->type);
1284 ip = ((gint64) __builtin_extract_return_addr (__builtin_return_address (0)));
1285 printf (" ip: %p\n", (gpointer) ip);
1289 /*========================= End of Function ========================*/
1291 /*------------------------------------------------------------------*/
1293 /* Name - mono_arch_cpu_init */
1295 /* Function - Perform CPU specific initialization to execute */
1298 /*------------------------------------------------------------------*/
1301 mono_arch_cpu_init (void)
1305 /*========================= End of Function ========================*/
1307 /*------------------------------------------------------------------*/
1309 /* Name - mono_arch_init. */
1311 /* Function - Initialize architecture specific code. */
1313 /*------------------------------------------------------------------*/
1316 mono_arch_init (void)
1320 mono_set_partial_sharing_supported (FALSE);
1321 mono_os_mutex_init_recursive (&mini_arch_mutex);
1323 ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ, MONO_MEM_ACCOUNT_OTHER);
1324 bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ, MONO_MEM_ACCOUNT_OTHER);
1325 mono_mprotect (bp_trigger_page, mono_pagesize (), 0);
1327 code = (guint8 *) &breakpointCode;
1328 s390_basr(code, s390_r13, 0);
1330 s390_llong(code, 0);
1331 s390_lg(code, s390_r13, 0, s390_r13, 4);
1332 s390_lg(code, s390_r0, 0, s390_r13, 0);
1335 /*========================= End of Function ========================*/
1337 /*------------------------------------------------------------------*/
1339 /* Name - mono_arch_cleanup. */
1341 /* Function - Cleanup architecture specific code . */
1343 /*------------------------------------------------------------------*/
1346 mono_arch_cleanup (void)
1348 if (ss_trigger_page)
1349 mono_vfree (ss_trigger_page, mono_pagesize (), MONO_MEM_ACCOUNT_OTHER);
1350 if (bp_trigger_page)
1351 mono_vfree (bp_trigger_page, mono_pagesize (), MONO_MEM_ACCOUNT_OTHER);
1352 mono_os_mutex_destroy (&mini_arch_mutex);
1355 /*========================= End of Function ========================*/
1357 /*------------------------------------------------------------------*/
1359 /* Name - mono_arch_have_fast_tls */
1361 /* Function - Returns whether we use fast inlined thread local */
1362 /* storage managed access, instead of falling back */
1363 /* to native code. */
1365 /*------------------------------------------------------------------*/
1368 mono_arch_have_fast_tls (void)
1373 /*========================= End of Function ========================*/
1375 /*------------------------------------------------------------------*/
1377 /* Name - mono_arch_cpu_optimizations */
1379 /* Function - Returns the optimizations supported on this CPU */
1381 /*------------------------------------------------------------------*/
1384 mono_arch_cpu_optimizations (guint32 *exclude_mask)
1388 /*----------------------------------------------------------*/
1389 /* No s390-specific optimizations yet */
1390 /*----------------------------------------------------------*/
1391 *exclude_mask = MONO_OPT_LINEARS;
1395 /*========================= End of Function ========================*/
1397 /*------------------------------------------------------------------*/
1399 /* Name - mono_arch_get_allocatable_int_vars */
1403 /*------------------------------------------------------------------*/
1406 mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
1411 for (i = 0; i < cfg->num_varinfo; i++) {
1412 MonoInst *ins = cfg->varinfo [i];
1413 MonoMethodVar *vmv = MONO_VARINFO (cfg, i);
1416 if (vmv->range.first_use.abs_pos >= vmv->range.last_use.abs_pos)
1419 if (ins->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) ||
1420 (ins->opcode != OP_LOCAL && ins->opcode != OP_ARG))
1423 /* we can only allocate 32 bit values */
1424 if (mono_is_regsize_var(ins->inst_vtype)) {
1425 g_assert (MONO_VARINFO (cfg, i)->reg == -1);
1426 g_assert (i == vmv->idx);
1427 vars = mono_varlist_insert_sorted (cfg, vars, vmv, FALSE);
1434 /*========================= End of Function ========================*/
1436 /*------------------------------------------------------------------*/
1438 /* Name - mono_arch_global_int_regs */
1440 /* Function - Return a list of usable integer registers. */
1442 /*------------------------------------------------------------------*/
1445 mono_arch_get_global_int_regs (MonoCompile *cfg)
1448 MonoMethodHeader *header;
1451 header = cfg->header;
1452 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
1453 cfg->frame_reg = s390_r11;
1456 /* FIXME: s390_r12 is reserved for bkchain_reg. Only reserve it if needed */
1458 for (i = 8; i < top; ++i) {
1459 if (cfg->frame_reg != i)
1460 regs = g_list_prepend (regs, GUINT_TO_POINTER (i));
1466 /*========================= End of Function ========================*/
1468 /*------------------------------------------------------------------*/
1470 /* Name - mono_arch_flush_icache */
1472 /* Function - Flush the CPU icache. */
1474 /*------------------------------------------------------------------*/
1477 mono_arch_flush_icache (guint8 *code, gint size)
1481 /*========================= End of Function ========================*/
1483 /*------------------------------------------------------------------*/
1485 /* Name - add_general */
1487 /* Function - Determine code and stack size incremements for a */
1490 /*------------------------------------------------------------------*/
1493 add_general (guint *gr, size_data *sz, ArgInfo *ainfo)
1495 if (*gr > S390_LAST_ARG_REG) {
1496 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1497 ainfo->offset = sz->stack_size;
1498 ainfo->reg = STK_BASE;
1499 ainfo->regtype = RegTypeBase;
1500 sz->stack_size += sizeof(long);
1501 sz->local_size += sizeof(long);
1502 sz->offStruct += sizeof(long);
1503 sz->code_size += 12;
1511 /*========================= End of Function ========================*/
1513 /*------------------------------------------------------------------*/
1515 /* Name - add_stackParm */
1517 /* Function - Determine code and stack size incremements for a */
1520 /*------------------------------------------------------------------*/
1523 add_stackParm (guint *gr, size_data *sz, ArgInfo *ainfo, gint size)
1525 if (*gr > S390_LAST_ARG_REG) {
1526 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1527 ainfo->reg = STK_BASE;
1528 ainfo->offset = sz->stack_size;
1529 ainfo->regtype = RegTypeStructByAddrOnStack;
1530 sz->stack_size += sizeof (gpointer);
1531 sz->parm_size += sizeof(gpointer);
1532 sz->offStruct += sizeof(gpointer);
1535 ainfo->offset = sz->stack_size;
1536 ainfo->regtype = RegTypeStructByAddr;
1539 ainfo->offparm = sz->offset;
1540 sz->offset = S390_ALIGN(sz->offset+size, sizeof(long));
1542 ainfo->vtsize = size;
1543 sz->parm_size += size;
1546 /*========================= End of Function ========================*/
1548 /*------------------------------------------------------------------*/
1550 /* Name - add_float */
1552 /* Function - Determine code and stack size incremements for a */
1553 /* float parameter. */
1555 /*------------------------------------------------------------------*/
1558 add_float (guint *fr, size_data *sz, ArgInfo *ainfo)
1560 if ((*fr) <= S390_LAST_FPARG_REG) {
1561 ainfo->regtype = RegTypeFP;
1567 ainfo->offset = sz->stack_size;
1568 ainfo->reg = STK_BASE;
1569 ainfo->regtype = RegTypeBase;
1571 sz->stack_size += sizeof(double);
1572 sz->local_size += sizeof(double);
1573 sz->offStruct += sizeof(double);
1577 /*========================= End of Function ========================*/
1579 /*------------------------------------------------------------------*/
1581 /* Name - get_call_info */
1583 /* Function - Determine the amount of space required for code */
1584 /* and stack. In addition determine starting points */
1585 /* for stack-based parameters, and area for struct- */
1586 /* ures being returned on the stack. */
1588 /*------------------------------------------------------------------*/
1591 get_call_info (MonoCompile *cfg, MonoMemPool *mp, MonoMethodSignature *sig)
1593 guint i, fr, gr, size, pstart;
1594 int nParm = sig->hasthis + sig->param_count;
1596 guint32 simpleType, align;
1597 gboolean is_pinvoke = sig->pinvoke;
1602 cinfo = mono_mempool_alloc0 (mp, sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1604 cinfo = g_malloc0 (sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1609 cinfo->struct_ret = 0;
1613 sz->offStruct = S390_MINIMAL_STACK_SIZE;
1614 sz->stack_size = S390_MINIMAL_STACK_SIZE;
1621 /*----------------------------------------------------------*/
1622 /* We determine the size of the return code/stack in case we*/
1623 /* need to reserve a register to be used to address a stack */
1624 /* area that the callee will use. */
1625 /*----------------------------------------------------------*/
1627 ret_type = mini_get_underlying_type (sig->ret);
1628 simpleType = ret_type->type;
1630 switch (simpleType) {
1639 case MONO_TYPE_OBJECT:
1641 case MONO_TYPE_FNPTR:
1642 cinfo->ret.reg = s390_r2;
1647 cinfo->ret.reg = s390_f0;
1652 cinfo->ret.reg = s390_r2;
1655 case MONO_TYPE_GENERICINST:
1656 if (!mono_type_generic_inst_is_valuetype (sig->ret)) {
1657 cinfo->ret.reg = s390_r2;
1662 case MONO_TYPE_VALUETYPE: {
1663 MonoClass *klass = mono_class_from_mono_type (sig->ret);
1664 if (klass->enumtype) {
1665 simpleType = mono_class_enum_basetype (klass)->type;
1668 size = mini_type_stack_size_full (&klass->byval_arg, NULL, sig->pinvoke);
1670 cinfo->struct_ret = 1;
1671 cinfo->ret.size = size;
1672 cinfo->ret.vtsize = size;
1675 case MONO_TYPE_TYPEDBYREF:
1676 size = sizeof (MonoTypedRef);
1677 cinfo->struct_ret = 1;
1678 cinfo->ret.size = size;
1679 cinfo->ret.vtsize = size;
1681 case MONO_TYPE_VOID:
1684 g_error ("Can't handle as return value 0x%x", sig->ret->type);
1690 * To simplify get_this_arg_reg () and LLVM integration, emit the vret arg after
1691 * the first argument, allowing 'this' to be always passed in the first arg reg.
1692 * Also do this if the first argument is a reference type, since virtual calls
1693 * are sometimes made using calli without sig->hasthis set, like in the delegate
1696 if (cinfo->struct_ret && !is_pinvoke &&
1698 (sig->param_count > 0 &&
1699 MONO_TYPE_IS_REFERENCE (mini_get_underlying_type (sig->params [0]))))) {
1701 cinfo->args[nParm].size = sizeof (gpointer);
1702 add_general (&gr, sz, cinfo->args + nParm);
1704 cinfo->args[nParm].size = sizeof (gpointer);
1705 add_general (&gr, sz, &cinfo->args [sig->hasthis + nParm]);
1709 cinfo->vret_arg_index = 1;
1710 cinfo->ret.reg = gr;
1715 cinfo->args[nParm].size = sizeof (gpointer);
1716 add_general (&gr, sz, cinfo->args + nParm);
1720 if (cinfo->struct_ret) {
1721 cinfo->ret.reg = gr;
1726 if ((sig->call_convention == MONO_CALL_VARARG) && (sig->param_count == 0)) {
1727 gr = S390_LAST_ARG_REG + 1;
1728 fr = S390_LAST_FPARG_REG + 1;
1730 /* Emit the signature cookie just before the implicit arguments */
1731 add_general (&gr, sz, &cinfo->sigCookie);
1734 /*----------------------------------------------------------*/
1735 /* We determine the size of the parameter code and stack */
1736 /* requirements by checking the types and sizes of the */
1738 /*----------------------------------------------------------*/
1740 for (i = pstart; i < sig->param_count; ++i) {
1743 /*--------------------------------------------------*/
1744 /* Handle vararg type calls. All args are put on */
1746 /*--------------------------------------------------*/
1747 if ((sig->call_convention == MONO_CALL_VARARG) &&
1748 (i == sig->sentinelpos)) {
1749 gr = S390_LAST_ARG_REG + 1;
1750 fr = S390_LAST_FPARG_REG + 1;
1751 add_general (&gr, sz, &cinfo->sigCookie);
1754 if (sig->params [i]->byref) {
1755 add_general (&gr, sz, cinfo->args+nParm);
1756 cinfo->args[nParm].size = sizeof(gpointer);
1761 ptype = mini_get_underlying_type (sig->params [i]);
1762 simpleType = ptype->type;
1763 cinfo->args[nParm].type = simpleType;
1764 switch (simpleType) {
1767 cinfo->args[nParm].size = sizeof(char);
1768 add_general (&gr, sz, cinfo->args+nParm);
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_OBJECT:
1788 cinfo->args[nParm].size = sizeof(gpointer);
1789 add_general (&gr, sz, cinfo->args+nParm);
1794 cinfo->args[nParm].size = sizeof(long long);
1795 add_general (&gr, sz, cinfo->args+nParm);
1799 cinfo->args[nParm].size = sizeof(float);
1800 add_float (&fr, sz, cinfo->args+nParm);
1804 cinfo->args[nParm].size = sizeof(double);
1805 add_float (&fr, sz, cinfo->args+nParm);
1808 case MONO_TYPE_GENERICINST:
1809 if (!mono_type_generic_inst_is_valuetype (ptype)) {
1810 cinfo->args[nParm].size = sizeof(gpointer);
1811 add_general (&gr, sz, cinfo->args+nParm);
1816 case MONO_TYPE_VALUETYPE: {
1817 MonoMarshalType *info;
1818 MonoClass *klass = mono_class_from_mono_type (ptype);
1821 size = mono_class_native_size(klass, NULL);
1823 size = mono_class_value_size(klass, NULL);
1825 if (simpleType != MONO_TYPE_GENERICINST) {
1826 info = mono_marshal_load_type_info(klass);
1828 if ((info->native_size == sizeof(float)) &&
1829 (info->num_fields == 1) &&
1830 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1831 cinfo->args[nParm].size = sizeof(float);
1832 add_float(&fr, sz, cinfo->args+nParm);
1837 if ((info->native_size == sizeof(double)) &&
1838 (info->num_fields == 1) &&
1839 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1840 cinfo->args[nParm].size = sizeof(double);
1841 add_float(&fr, sz, cinfo->args+nParm);
1847 cinfo->args[nParm].vtsize = 0;
1848 cinfo->args[nParm].size = 0;
1851 /*----------------------------------*/
1852 /* On S/390, structures of size 1, */
1853 /* 2, 4, and 8 bytes are passed in */
1854 /* (a) register(s). */
1855 /*----------------------------------*/
1861 add_general(&gr, sz, cinfo->args+nParm);
1862 cinfo->args[nParm].size = size;
1863 cinfo->args[nParm].regtype = RegTypeStructByVal;
1865 sz->local_size += sizeof(long);
1868 add_stackParm(&gr, sz, cinfo->args+nParm, size);
1873 case MONO_TYPE_TYPEDBYREF: {
1874 int size = sizeof (MonoTypedRef);
1876 cinfo->args[nParm].vtsize = 0;
1877 cinfo->args[nParm].size = 0;
1880 /*----------------------------------*/
1881 /* On S/390, structures of size 1, */
1882 /* 2, 4, and 8 bytes are passed in */
1883 /* (a) register(s). */
1884 /*----------------------------------*/
1890 add_general(&gr, sz, cinfo->args+nParm);
1891 cinfo->args[nParm].size = size;
1892 cinfo->args[nParm].regtype = RegTypeStructByVal;
1894 sz->local_size += sizeof(long);
1897 add_stackParm(&gr, sz, cinfo->args+nParm, size);
1903 g_error ("Can't trampoline 0x%x", ptype);
1907 /*----------------------------------------------------------*/
1908 /* Handle the case where there are no implicit arguments */
1909 /*----------------------------------------------------------*/
1910 if ((sig->call_convention == MONO_CALL_VARARG) &&
1913 (sig->param_count == sig->sentinelpos)) {
1914 gr = S390_LAST_ARG_REG + 1;
1915 fr = S390_LAST_FPARG_REG + 1;
1916 add_general (&gr, sz, &cinfo->sigCookie);
1919 /*----------------------------------------------------------*/
1920 /* If we are passing a structure back then if it won't be */
1921 /* in a register(s) then we make room at the end of the */
1922 /* parameters that may have been placed on the stack */
1923 /*----------------------------------------------------------*/
1924 if (cinfo->struct_ret) {
1925 cinfo->ret.offset = sz->stack_size;
1926 switch (cinfo->ret.size) {
1934 sz->stack_size += S390_ALIGN(cinfo->ret.size, align);
1939 sz->stack_size = sz->stack_size + sz->local_size + sz->parm_size +
1941 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1946 /*========================= End of Function ========================*/
1948 /*------------------------------------------------------------------*/
1950 /* Name - mono_arch_allocate_vars */
1952 /* Function - Set var information according to the calling */
1953 /* convention for S/390. The local var stuff should */
1954 /* most likely be split in another method. */
1956 /* Parameter - @m - Compile unit. */
1958 /*------------------------------------------------------------------*/
1961 mono_arch_allocate_vars (MonoCompile *cfg)
1963 MonoMethodSignature *sig;
1964 MonoMethodHeader *header;
1967 int iParm, iVar, offset, align, size, curinst;
1968 int frame_reg = STK_BASE;
1971 header = cfg->header;
1973 cfg->flags |= MONO_CFG_HAS_SPILLUP;
1975 /*---------------------------------------------------------*/
1976 /* We use the frame register also for any method that has */
1977 /* filter clauses. This way, when the handlers are called, */
1978 /* the code will reference local variables using the frame */
1979 /* reg instead of the stack pointer: if we had to restore */
1980 /* the stack pointer, we'd corrupt the method frames that */
1981 /* are already on the stack (since filters get called */
1982 /* before stack unwinding happens) when the filter code */
1983 /* would call any method. */
1984 /*---------------------------------------------------------*/
1985 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
1986 frame_reg = s390_r11;
1988 cfg->frame_reg = frame_reg;
1990 cfg->arch.bkchain_reg = -1;
1992 if (frame_reg != STK_BASE)
1993 cfg->used_int_regs |= (1 << frame_reg);
1995 if (cfg->uses_rgctx_reg)
1996 cfg->used_int_regs |= (1 << MONO_ARCH_IMT_REG);
1998 sig = mono_method_signature (cfg->method);
2000 cinfo = get_call_info (cfg, cfg->mempool, sig);
2002 if (!cinfo->struct_ret) {
2003 switch (mini_get_underlying_type (sig->ret)->type) {
2004 case MONO_TYPE_VOID:
2007 cfg->ret->opcode = OP_REGVAR;
2008 cfg->ret->dreg = s390_r2;
2013 /*--------------------------------------------------------------*/
2014 /* local vars are at a positive offset from the stack pointer */
2015 /* also note that if the function uses alloca, we use s390_r11 */
2016 /* to point at the local variables. */
2017 /* add parameter area size for called functions */
2018 /*--------------------------------------------------------------*/
2019 if (cfg->param_area == 0)
2020 offset = S390_MINIMAL_STACK_SIZE;
2022 offset = cfg->param_area;
2024 cfg->sig_cookie = 0;
2026 if (cinfo->struct_ret) {
2027 inst = cfg->vret_addr;
2028 offset = S390_ALIGN(offset, sizeof(gpointer));
2029 inst->inst_offset = offset;
2030 inst->opcode = OP_REGOFFSET;
2031 inst->inst_basereg = frame_reg;
2032 offset += sizeof(gpointer);
2033 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2034 printf ("vret_addr =");
2035 mono_print_ins (cfg->vret_addr);
2040 inst = cfg->args [0];
2041 if (inst->opcode != OP_REGVAR) {
2042 inst->opcode = OP_REGOFFSET;
2043 inst->inst_basereg = frame_reg;
2044 offset = S390_ALIGN(offset, sizeof(gpointer));
2045 inst->inst_offset = offset;
2046 offset += sizeof (gpointer);
2053 eArg = sig->param_count + sArg;
2055 if (sig->call_convention == MONO_CALL_VARARG)
2056 cfg->sig_cookie += S390_MINIMAL_STACK_SIZE;
2058 for (iParm = sArg; iParm < eArg; ++iParm) {
2059 inst = cfg->args [curinst];
2060 if (inst->opcode != OP_REGVAR) {
2061 switch (cinfo->args[iParm].regtype) {
2062 case RegTypeStructByAddr : {
2065 size = sizeof (gpointer);
2067 inst->opcode = OP_REGOFFSET;
2068 inst->inst_basereg = frame_reg;
2069 offset = S390_ALIGN (offset, sizeof (gpointer));
2070 inst->inst_offset = offset;
2072 /* Add a level of indirection */
2073 MONO_INST_NEW (cfg, indir, 0);
2075 inst->opcode = OP_VTARG_ADDR;
2076 inst->inst_left = indir;
2079 case RegTypeStructByAddrOnStack : {
2082 size = sizeof (gpointer);
2084 /* Similar to the == STK_BASE case below */
2085 cfg->arch.bkchain_reg = s390_r12;
2086 cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2088 inst->opcode = OP_REGOFFSET;
2089 inst->dreg = mono_alloc_preg (cfg);
2090 inst->inst_basereg = cfg->arch.bkchain_reg;
2091 inst->inst_offset = cinfo->args [iParm].offset;
2093 /* Add a level of indirection */
2094 MONO_INST_NEW (cfg, indir, 0);
2096 inst->opcode = OP_VTARG_ADDR;
2097 inst->inst_left = indir;
2100 case RegTypeStructByVal :
2101 size = cinfo->args[iParm].size;
2102 offset = S390_ALIGN(offset, size);
2103 inst->opcode = OP_REGOFFSET;
2104 inst->inst_basereg = frame_reg;
2105 inst->inst_offset = offset;
2108 if (cinfo->args [iParm].reg == STK_BASE) {
2110 * These arguments are in the previous frame, so we can't
2111 * compute their offset from the current frame pointer right
2112 * now, since cfg->stack_offset is not yet known, so dedicate a
2113 * register holding the previous frame pointer.
2115 cfg->arch.bkchain_reg = s390_r12;
2116 cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2118 inst->opcode = OP_REGOFFSET;
2119 inst->inst_basereg = cfg->arch.bkchain_reg;
2120 size = (cinfo->args[iParm].size < 8
2121 ? 8 - cinfo->args[iParm].size
2123 inst->inst_offset = cinfo->args [iParm].offset + size;
2124 size = sizeof (long);
2126 inst->opcode = OP_REGOFFSET;
2127 inst->inst_basereg = frame_reg;
2128 size = (cinfo->args[iParm].size < 8
2131 offset = S390_ALIGN(offset, size);
2132 if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
2133 inst->inst_offset = offset;
2135 inst->inst_offset = offset + (8 - size);
2140 if ((sig->call_convention == MONO_CALL_VARARG) &&
2141 (cinfo->args[iParm].regtype != RegTypeGeneral) &&
2142 (iParm < sig->sentinelpos))
2143 cfg->sig_cookie += size;
2144 printf("%s %4d cookine %x\n",__FUNCTION__,__LINE__,cfg->sig_cookie);
2147 offset += MAX(size, 8);
2152 cfg->locals_min_stack_offset = offset;
2154 curinst = cfg->locals_start;
2155 for (iVar = curinst; iVar < cfg->num_varinfo; ++iVar) {
2156 inst = cfg->varinfo [iVar];
2157 if ((inst->flags & MONO_INST_IS_DEAD) ||
2158 (inst->opcode == OP_REGVAR))
2161 /*--------------------------------------------------*/
2162 /* inst->backend.is_pinvoke indicates native sized */
2163 /* value typs this is used by the pinvoke wrappers */
2164 /* when they call functions returning structure */
2165 /*--------------------------------------------------*/
2166 if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype))
2167 size = mono_class_native_size (mono_class_from_mono_type(inst->inst_vtype),
2168 (guint32 *) &align);
2170 size = mono_type_size (inst->inst_vtype, &align);
2172 offset = S390_ALIGN(offset, align);
2173 inst->inst_offset = offset;
2174 inst->opcode = OP_REGOFFSET;
2175 inst->inst_basereg = frame_reg;
2177 DEBUG (g_print("allocating local %d to %ld, size: %d\n",
2178 iVar, inst->inst_offset, size));
2181 cfg->locals_max_stack_offset = offset;
2183 /*------------------------------------------------------*/
2184 /* Allow space for the trace method stack area if needed*/
2185 /*------------------------------------------------------*/
2186 if ((mono_jit_trace_calls != NULL && mono_trace_eval (cfg->method)))
2187 offset += S390_TRACE_STACK_SIZE;
2189 /*------------------------------------------------------*/
2190 /* Reserve space to save LMF and caller saved registers */
2191 /*------------------------------------------------------*/
2192 if (cfg->method->save_lmf)
2193 offset += sizeof (MonoLMF);
2195 /*------------------------------------------------------*/
2196 /* align the offset */
2197 /*------------------------------------------------------*/
2198 cfg->stack_offset = S390_ALIGN(offset, S390_STACK_ALIGNMENT);
2200 /*------------------------------------------------------*/
2201 /* Fix offsets for args whose value is in parent frame */
2202 /*------------------------------------------------------*/
2203 for (iParm = sArg; iParm < eArg; ++iParm) {
2204 inst = cfg->args [iParm];
2206 if (inst->opcode == OP_S390_STKARG) {
2207 inst->opcode = OP_REGOFFSET;
2208 inst->inst_offset += cfg->stack_offset;
2213 /*========================= End of Function ========================*/
2215 /*------------------------------------------------------------------*/
2217 /* Name - mono_arch_create_vars */
2219 /*------------------------------------------------------------------*/
2222 mono_arch_create_vars (MonoCompile *cfg)
2224 MonoMethodSignature *sig;
2227 sig = mono_method_signature (cfg->method);
2229 cinfo = get_call_info (cfg, cfg->mempool, sig);
2231 if (cinfo->struct_ret) {
2232 cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG);
2233 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2234 printf ("vret_addr = ");
2235 mono_print_ins (cfg->vret_addr);
2240 /*========================= End of Function ========================*/
2242 /*------------------------------------------------------------------*/
2244 /* Name - add_outarg_reg2. */
2246 /*------------------------------------------------------------------*/
2249 add_outarg_reg2 (MonoCompile *cfg, MonoCallInst *call, ArgStorage storage, int reg, MonoInst *tree)
2254 case RegTypeGeneral:
2255 MONO_INST_NEW (cfg, ins, OP_MOVE);
2256 ins->dreg = mono_alloc_ireg (cfg);
2257 ins->sreg1 = tree->dreg;
2258 MONO_ADD_INS (cfg->cbb, ins);
2259 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, FALSE);
2262 MONO_INST_NEW (cfg, ins, OP_FMOVE);
2263 ins->dreg = mono_alloc_freg (cfg);
2264 ins->sreg1 = tree->dreg;
2265 MONO_ADD_INS (cfg->cbb, ins);
2266 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2269 MONO_INST_NEW (cfg, ins, OP_S390_SETF4RET);
2270 ins->dreg = mono_alloc_freg (cfg);
2271 ins->sreg1 = tree->dreg;
2272 MONO_ADD_INS (cfg->cbb, ins);
2273 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2276 g_assert_not_reached ();
2280 /*========================= End of Function ========================*/
2282 /*------------------------------------------------------------------*/
2284 /* Name - emit_sig_cookie. */
2286 /*------------------------------------------------------------------*/
2289 emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo)
2291 MonoMethodSignature *tmpSig;
2294 cfg->disable_aot = TRUE;
2296 /*----------------------------------------------------------*/
2297 /* mono_ArgIterator_Setup assumes the signature cookie is */
2298 /* passed first and all the arguments which were before it */
2299 /* passed on the stack after the signature. So compensate */
2300 /* by passing a different signature. */
2301 /*----------------------------------------------------------*/
2302 tmpSig = mono_metadata_signature_dup (call->signature);
2303 tmpSig->param_count -= call->signature->sentinelpos;
2304 tmpSig->sentinelpos = 0;
2305 if (tmpSig->param_count > 0)
2306 memcpy (tmpSig->params,
2307 call->signature->params + call->signature->sentinelpos,
2308 tmpSig->param_count * sizeof(MonoType *));
2310 MONO_INST_NEW (cfg, sig_arg, OP_ICONST);
2311 sig_arg->dreg = mono_alloc_ireg (cfg);
2312 sig_arg->inst_p0 = tmpSig;
2313 MONO_ADD_INS (cfg->cbb, sig_arg);
2315 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, STK_BASE,
2316 cinfo->sigCookie.offset, sig_arg->dreg);
2319 /*========================= End of Function ========================*/
2321 /*------------------------------------------------------------------*/
2323 /* Name - mono_arch_emit_call */
2325 /*------------------------------------------------------------------*/
2328 mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
2331 MonoMethodSignature *sig;
2333 int i, n, lParamArea;
2335 ArgInfo *ainfo = NULL;
2337 MonoMethodHeader *header;
2340 sig = call->signature;
2341 n = sig->param_count + sig->hasthis;
2342 DEBUG (g_print ("Call requires: %d parameters\n",n));
2344 cinfo = get_call_info (cfg, cfg->mempool, sig);
2346 stackSize = cinfo->sz.stack_size + cinfo->sz.local_size +
2347 cinfo->sz.parm_size + cinfo->sz.offset;
2348 call->stack_usage = MAX(stackSize, call->stack_usage);
2349 lParamArea = MAX((call->stack_usage-S390_MINIMAL_STACK_SIZE-cinfo->sz.parm_size), 0);
2350 cfg->param_area = MAX(((signed) cfg->param_area), lParamArea);
2351 cfg->flags |= MONO_CFG_HAS_CALLS;
2353 if (cinfo->struct_ret) {
2354 MONO_INST_NEW (cfg, ins, OP_MOVE);
2355 ins->sreg1 = call->vret_var->dreg;
2356 ins->dreg = mono_alloc_preg (cfg);
2357 MONO_ADD_INS (cfg->cbb, ins);
2358 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, cinfo->ret.reg, FALSE);
2361 header = cfg->header;
2362 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2367 for (i = 0; i < n; ++i) {
2370 ainfo = cinfo->args + i;
2371 if (i >= sig->hasthis)
2372 t = sig->params [i - sig->hasthis];
2374 t = &mono_defaults.int_class->byval_arg;
2375 t = mini_get_underlying_type (t);
2377 in = call->args [i];
2379 if ((sig->call_convention == MONO_CALL_VARARG) &&
2381 (i == sig->sentinelpos)) {
2382 emit_sig_cookie (cfg, call, cinfo);
2385 switch (ainfo->regtype) {
2386 case RegTypeGeneral:
2387 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2390 if (MONO_TYPE_ISSTRUCT (t)) {
2391 /* Valuetype passed in one fp register */
2392 ainfo->regtype = RegTypeStructByValInFP;
2395 if (ainfo->size == 4)
2396 ainfo->regtype = RegTypeFPR4;
2397 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2400 case RegTypeStructByVal:
2401 case RegTypeStructByAddr:
2402 case RegTypeStructByAddrOnStack: {
2406 if (sig->params [i - sig->hasthis]->type == MONO_TYPE_TYPEDBYREF) {
2407 size = sizeof (MonoTypedRef);
2408 align = sizeof (gpointer);
2412 size = mono_type_native_stack_size (&in->klass->byval_arg, &align);
2415 * Other backends use mono_type_stack_size (), but that
2416 * aligns the size to 8, which is larger than the size of
2417 * the source, leading to reads of invalid memory if the
2418 * source is at the end of address space.
2420 size = mono_class_value_size (in->klass, &align);
2423 g_assert (in->klass);
2425 ainfo->offparm += cinfo->sz.offStruct;
2427 MONO_INST_NEW (cfg, ins, OP_OUTARG_VT);
2428 ins->sreg1 = in->dreg;
2429 ins->klass = in->klass;
2430 ins->backend.size = ainfo->size;
2431 ins->inst_p0 = call;
2432 ins->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
2433 memcpy (ins->inst_p1, ainfo, sizeof (ArgInfo));
2435 MONO_ADD_INS (cfg->cbb, ins);
2437 if (ainfo->regtype == RegTypeStructByAddr) {
2439 * We use OP_OUTARG_VT to copy the valuetype to a stack location, then
2440 * use the normal OUTARG opcodes to pass the address of the location to
2443 int treg = mono_alloc_preg (cfg);
2444 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2445 frmReg, ainfo->offparm);
2446 mono_call_inst_add_outarg_reg (cfg, call, treg, ainfo->reg, FALSE);
2447 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
2448 /* The address of the valuetype is passed on the stack */
2449 int treg = mono_alloc_preg (cfg);
2450 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2451 frmReg, ainfo->offparm);
2452 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG,
2453 ainfo->reg, ainfo->offset, treg);
2455 if (cfg->compute_gc_maps) {
2458 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, t);
2464 if (!t->byref && t->type == MONO_TYPE_R4) {
2465 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG,
2466 STK_BASE, ainfo->offset + 4,
2468 } else if (!t->byref && (t->type == MONO_TYPE_R8)) {
2469 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG,
2470 STK_BASE, ainfo->offset,
2473 MONO_INST_NEW (cfg, ins, OP_STORE_MEMBASE_REG);
2474 ins->inst_destbasereg = STK_BASE;
2475 ins->inst_offset = ainfo->offset;
2476 ins->sreg1 = in->dreg;
2479 /* This is needed by MonoTypedRef->value to point to the correct data */
2480 if ((sig->call_convention == MONO_CALL_VARARG) &&
2481 (i >= sig->sentinelpos)) {
2482 switch (ainfo->size) {
2484 ins->opcode = OP_STOREI1_MEMBASE_REG;
2487 ins->opcode = OP_STOREI2_MEMBASE_REG;
2490 ins->opcode = OP_STOREI4_MEMBASE_REG;
2498 MONO_ADD_INS (cfg->cbb, ins);
2502 g_assert_not_reached ();
2508 * Handle the case where there are no implicit arguments
2510 if ((sig->call_convention == MONO_CALL_VARARG) &&
2512 (i == sig->sentinelpos)) {
2513 emit_sig_cookie (cfg, call, cinfo);
2517 /*========================= End of Function ========================*/
2519 /*------------------------------------------------------------------*/
2521 /* Name - mono_arch_emit_outarg_vt */
2523 /*------------------------------------------------------------------*/
2526 mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
2528 MonoCallInst *call = (MonoCallInst*)ins->inst_p0;
2529 ArgInfo *ainfo = (ArgInfo*)ins->inst_p1;
2530 int size = ins->backend.size;
2532 if (ainfo->regtype == RegTypeStructByVal) {
2534 arg->ins.sreg1 = ainfo->reg;
2535 arg->ins.opcode = OP_OUTARG_VT;
2536 arg->size = ainfo->size;
2537 arg->offset = ainfo->offset;
2538 arg->offPrm = ainfo->offparm + cinfo->sz.offStruct;
2540 if (ainfo->reg != STK_BASE) {
2541 MONO_OUTPUT_VTR (cfg, size, ainfo->reg, src->dreg, 0);
2543 MONO_OUTPUT_VTS (cfg, size, ainfo->reg, ainfo->offset,
2546 } else if (ainfo->regtype == RegTypeStructByValInFP) {
2547 int dreg = mono_alloc_freg (cfg);
2549 if (ainfo->size == 4) {
2550 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR4_MEMBASE, dreg, src->dreg, 0);
2551 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, dreg, dreg);
2553 g_assert (ainfo->size == 8);
2555 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR8_MEMBASE, dreg, src->dreg, 0);
2558 mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg, TRUE);
2561 MonoMethodHeader *header;
2564 header = mono_method_get_header_checked (cfg->method, &error);
2565 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
2566 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2571 MONO_EMIT_NEW_MOVE (cfg, srcReg, ainfo->offparm,
2572 src->dreg, 0, size);
2574 if (cfg->compute_gc_maps) {
2577 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, &ins->klass->byval_arg);
2582 /*========================= End of Function ========================*/
2584 /*------------------------------------------------------------------*/
2586 /* Name - mono_arch_emit_setret */
2588 /*------------------------------------------------------------------*/
2591 mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
2593 MonoType *ret = mini_get_underlying_type (mono_method_signature (method)->ret);
2596 if (ret->type == MONO_TYPE_R4) {
2597 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, s390_f0, val->dreg);
2599 } else if (ret->type == MONO_TYPE_R8) {
2600 MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, s390_f0, val->dreg);
2605 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg);
2608 /*========================= End of Function ========================*/
2610 /*------------------------------------------------------------------*/
2612 /* Name - mono_arch_instrument_mem_needs */
2614 /* Function - Allow tracing to work with this interface (with */
2615 /* an optional argument). */
2617 /*------------------------------------------------------------------*/
2620 mono_arch_instrument_mem_needs (MonoMethod *method, int *stack, int *code)
2622 /* no stack room needed now (may be needed for FASTCALL-trace support) */
2624 /* split prolog-epilog requirements? */
2625 *code = 50; /* max bytes needed: check this number */
2628 /*========================= End of Function ========================*/
2630 /*------------------------------------------------------------------*/
2632 /* Name - mono_arch_instrument_prolog */
2634 /* Function - Create an "instrumented" prolog. */
2636 /*------------------------------------------------------------------*/
2639 mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p,
2640 gboolean enable_arguments)
2647 parmOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2648 if (cfg->method->save_lmf)
2649 parmOffset -= sizeof(MonoLMF);
2650 fpOffset = parmOffset + (5*sizeof(gpointer));
2653 s390_stmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2654 s390_stdy (code, s390_f0, 0, STK_BASE, fpOffset);
2655 s390_stdy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2656 s390_stdy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2657 s390_stdy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2658 S390_SET (code, s390_r1, func);
2659 S390_SET (code, s390_r2, cfg->method);
2660 s390_lay (code, s390_r3, 0, STK_BASE, parmOffset);
2661 s390_lgr (code, s390_r4, STK_BASE);
2662 s390_aghi (code, s390_r4, cfg->stack_usage);
2663 s390_basr (code, s390_r14, s390_r1);
2664 s390_ldy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2665 s390_ldy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2666 s390_ldy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2667 s390_ldy (code, s390_f0, 0, STK_BASE, fpOffset);
2668 s390_lmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2673 /*========================= End of Function ========================*/
2675 /*------------------------------------------------------------------*/
2677 /* Name - mono_arch_instrument_epilog */
2679 /* Function - Create an epilog that will handle the returned */
2680 /* values used in instrumentation. */
2682 /*------------------------------------------------------------------*/
2685 mono_arch_instrument_epilog_full (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments, gboolean preserve_argument_registers)
2688 int save_mode = SAVE_NONE,
2691 MonoMethod *method = cfg->method;
2692 int rtype = mini_get_underlying_type (mono_method_signature (method)->ret)->type;
2694 offset = code - cfg->native_code;
2695 /*-----------------------------------------*/
2696 /* We need about 128 bytes of instructions */
2697 /*-----------------------------------------*/
2698 if (offset > (cfg->code_size - 128)) {
2699 cfg->code_size *= 2;
2700 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
2701 code = cfg->native_code + offset;
2704 saveOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2705 if (method->save_lmf)
2706 saveOffset -= sizeof(MonoLMF);
2710 case MONO_TYPE_VOID:
2711 /* special case string .ctor icall */
2712 if (strcmp (".ctor", method->name) && method->klass == mono_defaults.string_class)
2713 save_mode = SAVE_ONE;
2715 save_mode = SAVE_NONE;
2719 save_mode = SAVE_ONE;
2722 save_mode = SAVE_R4;
2725 save_mode = SAVE_R8;
2727 case MONO_TYPE_VALUETYPE:
2728 if (mono_method_signature (method)->ret->data.klass->enumtype) {
2729 rtype = mono_class_enum_basetype (mono_method_signature (method)->ret->data.klass)->type;
2732 save_mode = SAVE_STRUCT;
2735 save_mode = SAVE_ONE;
2739 switch (save_mode) {
2741 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2742 if (enable_arguments) {
2743 s390_lgr (code, s390_r3, s390_r2);
2747 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2748 if (enable_arguments) {
2749 s390_ldebr (code, s390_f0, s390_f0);
2753 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2756 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2757 if (enable_arguments) {
2758 s390_lg (code, s390_r3, 0, cfg->frame_reg,
2759 S390_MINIMAL_STACK_SIZE+cfg->param_area);
2767 S390_SET (code, s390_r1, func);
2768 S390_SET (code, s390_r2, cfg->method);
2769 s390_basr (code, s390_r14, s390_r1);
2771 switch (save_mode) {
2773 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2777 s390_ld (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2780 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2790 /*========================= End of Function ========================*/
2792 /*------------------------------------------------------------------*/
2794 /* Name - mono_arch_peephole_pass_1 */
2796 /* Function - Form a peephole pass at the code looking for */
2797 /* simple optimizations. */
2799 /*------------------------------------------------------------------*/
2802 mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
2806 /*========================= End of Function ========================*/
2808 /*------------------------------------------------------------------*/
2810 /* Name - mono_arch_peephole_pass_2 */
2812 /* Function - Form a peephole pass at the code looking for */
2813 /* simple optimizations. */
2815 /*------------------------------------------------------------------*/
2818 mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
2822 MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
2823 mono_peephole_ins (bb, ins);
2827 /*========================= End of Function ========================*/
2829 /*------------------------------------------------------------------*/
2831 /* Name - mono_arch_lowering_pass. */
2833 /*------------------------------------------------------------------*/
2836 mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
2838 MonoInst *ins, *next;
2840 MONO_BB_FOR_EACH_INS_SAFE (bb, next, ins) {
2841 switch (ins->opcode) {
2846 case OP_IDIV_UN_IMM:
2847 case OP_IREM_UN_IMM:
2852 case OP_LOCALLOC_IMM:
2853 mono_decompose_op_imm (cfg, bb, ins);
2856 if (!s390_is_imm16 (ins->inst_imm))
2857 /* This is created by the memcpy code which ignores is_inst_imm */
2858 mono_decompose_op_imm (cfg, bb, ins);
2865 bb->max_vreg = cfg->next_vreg;
2868 /*========================= End of Function ========================*/
2870 /*------------------------------------------------------------------*/
2872 /* Name - emit_float_to_int */
2874 /* Function - Create instructions which will convert a floating */
2875 /* point value to integer. */
2877 /*------------------------------------------------------------------*/
2880 emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size, gboolean is_signed)
2882 /* sreg is a float, dreg is an integer reg. */
2884 s390_cgdbr (code, dreg, 5, sreg);
2887 s390_ltgr (code, dreg, dreg);
2889 s390_oill (code, dreg, 0x80);
2890 s390_lghi (code, s390_r0, 0xff);
2891 s390_ngr (code, dreg, s390_r0);
2894 s390_ltgr (code, dreg, dreg);
2896 s390_oill (code, dreg, 0x8000);
2897 s390_llill(code, s390_r0, 0xffff);
2898 s390_ngr (code, dreg, s390_r0);
2903 S390_SET (code, s390_r13, 0x41e0000000000000llu);
2904 s390_ldgr (code, s390_f14, s390_r13);
2905 s390_ldr (code, s390_f15, sreg);
2906 s390_cdbr (code, s390_f15, s390_f14);
2907 s390_jl (code, 0); CODEPTR (code, o[0]);
2908 S390_SET (code, s390_r13, 0x41f0000000000000llu);
2909 s390_ldgr (code, s390_f14, s390_r13);
2910 s390_sdbr (code, s390_f15, s390_f14);
2911 s390_cfdbr (code, dreg, 7, s390_f15);
2913 PTRSLOT (code, o[0]);
2914 s390_cfdbr (code, dreg, 5, sreg);
2917 s390_lghi (code, s390_r0, 0xff);
2918 s390_ngr (code, dreg, s390_r0);
2921 s390_llill(code, s390_r0, 0xffff);
2922 s390_ngr (code, dreg, s390_r0);
2929 /*========================= End of Function ========================*/
2931 /*------------------------------------------------------------------*/
2933 /* Name - gboolean_is_unsigned. */
2935 /* Function - Return TRUE if next opcode is checking for un- */
2938 /*------------------------------------------------------------------*/
2941 gboolean is_unsigned (MonoInst *next)
2944 (((next->opcode >= OP_IBNE_UN) &&
2945 (next->opcode <= OP_IBLT_UN)) ||
2946 ((next->opcode >= OP_LBNE_UN) &&
2947 (next->opcode <= OP_LBLT_UN)) ||
2948 ((next->opcode >= OP_COND_EXC_NE_UN) &&
2949 (next->opcode <= OP_COND_EXC_LT_UN)) ||
2950 ((next->opcode >= OP_COND_EXC_INE_UN) &&
2951 (next->opcode <= OP_COND_EXC_ILT_UN)) ||
2952 ((next->opcode == OP_CLT_UN) ||
2953 (next->opcode == OP_CGT_UN)) ||
2954 ((next->opcode == OP_ICLT_UN) ||
2955 (next->opcode == OP_ICGT_UN) ||
2956 (next->opcode == OP_LCLT_UN) ||
2957 (next->opcode == OP_LCGT_UN))))
2963 /*========================= End of Function ========================*/
2965 /*------------------------------------------------------------------*/
2967 /* Name - mono_arch_output_basic_block */
2969 /* Function - Perform the "real" work of emitting instructions */
2970 /* that will do the work of in the basic block. */
2972 /*------------------------------------------------------------------*/
2975 mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
2980 guint8 *code = cfg->native_code + cfg->code_len;
2981 guint last_offset = 0;
2984 /* we don't align basic blocks of loops on s390 */
2986 if (cfg->verbose_level > 2)
2987 g_print ("Basic block %d starting at offset 0x%x\n", bb->block_num, bb->native_offset);
2989 MONO_BB_FOR_EACH_INS (bb, ins) {
2990 offset = code - cfg->native_code;
2992 max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
2994 if (offset > (cfg->code_size - max_len - 16)) {
2995 cfg->code_size *= 2;
2996 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
2997 code = cfg->native_code + offset;
3000 mono_debug_record_line_number (cfg, ins, offset);
3002 switch (ins->opcode) {
3003 case OP_STOREI1_MEMBASE_IMM: {
3004 s390_lghi (code, s390_r0, ins->inst_imm);
3005 S390_LONG (code, stcy, stc, s390_r0, 0,
3006 ins->inst_destbasereg, ins->inst_offset);
3009 case OP_STOREI2_MEMBASE_IMM: {
3010 s390_lghi (code, s390_r0, ins->inst_imm);
3011 S390_LONG (code, sthy, sth, s390_r0, 0,
3012 ins->inst_destbasereg, ins->inst_offset);
3015 case OP_STOREI4_MEMBASE_IMM: {
3016 s390_lgfi (code, s390_r0, ins->inst_imm);
3017 S390_LONG (code, sty, st, s390_r0, 0,
3018 ins->inst_destbasereg, ins->inst_offset);
3021 case OP_STORE_MEMBASE_IMM:
3022 case OP_STOREI8_MEMBASE_IMM: {
3023 S390_SET (code, s390_r0, ins->inst_imm);
3024 S390_LONG (code, stg, stg, s390_r0, 0,
3025 ins->inst_destbasereg, ins->inst_offset);
3028 case OP_STOREI1_MEMBASE_REG: {
3029 S390_LONG (code, stcy, stc, ins->sreg1, 0,
3030 ins->inst_destbasereg, ins->inst_offset);
3033 case OP_STOREI2_MEMBASE_REG: {
3034 S390_LONG (code, sthy, sth, ins->sreg1, 0,
3035 ins->inst_destbasereg, ins->inst_offset);
3038 case OP_STOREI4_MEMBASE_REG: {
3039 S390_LONG (code, sty, st, ins->sreg1, 0,
3040 ins->inst_destbasereg, ins->inst_offset);
3043 case OP_STORE_MEMBASE_REG:
3044 case OP_STOREI8_MEMBASE_REG: {
3045 S390_LONG (code, stg, stg, ins->sreg1, 0,
3046 ins->inst_destbasereg, ins->inst_offset);
3050 g_assert_not_reached ();
3052 case OP_LOAD_MEMBASE:
3053 case OP_LOADI8_MEMBASE: {
3054 S390_LONG (code, lg, lg, ins->dreg, 0,
3055 ins->inst_basereg, ins->inst_offset);
3058 case OP_LOADI4_MEMBASE: {
3059 S390_LONG (code, lgf, lgf, ins->dreg, 0,
3060 ins->inst_basereg, ins->inst_offset);
3063 case OP_LOADU4_MEMBASE: {
3064 S390_LONG (code, llgf, llgf, ins->dreg, 0,
3065 ins->inst_basereg, ins->inst_offset);
3068 case OP_LOADU1_MEMBASE: {
3069 S390_LONG (code, llgc, llgc, ins->dreg, 0,
3070 ins->inst_basereg, ins->inst_offset);
3073 case OP_LOADI1_MEMBASE: {
3074 S390_LONG (code, lgb, lgb, ins->dreg, 0,
3075 ins->inst_basereg, ins->inst_offset);
3078 case OP_LOADU2_MEMBASE: {
3079 S390_LONG (code, llgh, llgh, ins->dreg, 0,
3080 ins->inst_basereg, ins->inst_offset);
3083 case OP_LOADI2_MEMBASE: {
3084 S390_LONG (code, lgh, lgh, ins->dreg, 0,
3085 ins->inst_basereg, ins->inst_offset);
3088 case OP_LCONV_TO_I1: {
3089 s390_lgbr (code, ins->dreg, ins->sreg1);
3092 case OP_LCONV_TO_I2: {
3093 s390_lghr (code, ins->dreg, ins->sreg1);
3096 case OP_LCONV_TO_U1: {
3097 s390_llgcr (code, ins->dreg, ins->sreg1);
3100 case OP_LCONV_TO_U2: {
3101 s390_llghr (code, ins->dreg, ins->sreg1);
3104 case OP_ICONV_TO_I1: {
3105 s390_lgbr (code, ins->dreg, ins->sreg1);
3108 case OP_ICONV_TO_I2: {
3109 s390_lghr (code, ins->dreg, ins->sreg1);
3112 case OP_ICONV_TO_U1: {
3113 s390_llgcr (code, ins->dreg, ins->sreg1);
3116 case OP_ICONV_TO_U2: {
3117 s390_llghr (code, ins->dreg, ins->sreg1);
3122 if (is_unsigned (ins->next))
3123 s390_clgr (code, ins->sreg1, ins->sreg2);
3125 s390_cgr (code, ins->sreg1, ins->sreg2);
3129 if (is_unsigned (ins->next))
3130 s390_clr (code, ins->sreg1, ins->sreg2);
3132 s390_cr (code, ins->sreg1, ins->sreg2);
3135 case OP_COMPARE_IMM:
3136 case OP_LCOMPARE_IMM: {
3137 S390_SET (code, s390_r0, ins->inst_imm);
3138 if (is_unsigned (ins->next))
3139 s390_clgr (code, ins->sreg1, s390_r0);
3141 s390_cgr (code, ins->sreg1, s390_r0);
3144 case OP_ICOMPARE_IMM: {
3145 S390_SET (code, s390_r0, ins->inst_imm);
3146 if (is_unsigned (ins->next))
3147 s390_clr (code, ins->sreg1, s390_r0);
3149 s390_cr (code, ins->sreg1, s390_r0);
3153 mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_ABS,
3155 S390_CALL_TEMPLATE (code, s390_r14);
3160 s390_agr (code, ins->dreg, src2);
3165 s390_agr (code, ins->dreg, src2);
3170 s390_alcgr (code, ins->dreg, src2);
3174 if (ins->dreg != ins->sreg1) {
3175 s390_lgr (code, ins->dreg, ins->sreg1);
3177 if (s390_is_imm16 (ins->inst_imm)) {
3178 s390_aghi (code, ins->dreg, ins->inst_imm);
3179 } else if (s390_is_imm32 (ins->inst_imm)) {
3180 s390_agfi (code, ins->dreg, ins->inst_imm);
3182 S390_SET (code, s390_r0, ins->inst_imm);
3183 s390_agr (code, ins->dreg, s390_r0);
3188 if (ins->dreg != ins->sreg1) {
3189 s390_lgr (code, ins->dreg, ins->sreg1);
3191 g_assert (s390_is_imm16 (ins->inst_imm));
3192 s390_aghi (code, ins->dreg, ins->inst_imm);
3196 if (ins->dreg != ins->sreg1) {
3197 s390_lgr (code, ins->dreg, ins->sreg1);
3199 if (s390_is_imm16 (ins->inst_imm)) {
3200 s390_lghi (code, s390_r0, ins->inst_imm);
3201 s390_alcgr (code, ins->dreg, s390_r0);
3203 S390_SET (code, s390_r0, ins->inst_imm);
3204 s390_alcgr (code, ins->dreg, s390_r0);
3209 case OP_S390_IADD_OVF: {
3211 s390_ar (code, ins->dreg, src2);
3212 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3213 s390_lgfr (code, ins->dreg, ins->dreg);
3216 case OP_IADD_OVF_UN:
3217 case OP_S390_IADD_OVF_UN: {
3219 s390_algr (code, ins->dreg, src2);
3220 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3221 s390_llgfr (code, ins->dreg, ins->dreg);
3224 case OP_ADD_OVF_CARRY: {
3226 s390_lghi (code, s390_r0, 0);
3227 s390_lgr (code, s390_r1, s390_r0);
3228 s390_alcgr (code, s390_r0, s390_r1);
3229 s390_agr (code, ins->dreg, src2);
3230 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3231 s390_agr (code, ins->dreg, s390_r0);
3232 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3235 case OP_ADD_OVF_UN_CARRY: {
3237 s390_alcgr (code, ins->dreg, src2);
3238 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3243 s390_sgr (code, ins->dreg, src2);
3248 s390_sgr (code, ins->dreg, src2);
3253 s390_slbgr(code, ins->dreg, src2);
3257 if (ins->dreg != ins->sreg1) {
3258 s390_lgr (code, ins->dreg, ins->sreg1);
3260 if (s390_is_imm16 (-ins->inst_imm)) {
3261 s390_aghi (code, ins->dreg, -ins->inst_imm);
3262 } else if (s390_is_imm32 (-ins->inst_imm)) {
3263 s390_slgfi (code, ins->dreg, ins->inst_imm);
3265 S390_SET (code, s390_r0, ins->inst_imm);
3266 s390_slgr (code, ins->dreg, s390_r0);
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_lghi (code, s390_r0, ins->inst_imm);
3290 s390_slbgr (code, ins->dreg, s390_r0);
3292 S390_SET (code, s390_r0, ins->inst_imm);
3293 s390_slbgr(code, ins->dreg, s390_r0);
3297 case OP_SUB_OVF_CARRY: {
3299 s390_lghi (code, s390_r0, 0);
3300 s390_lgr (code, s390_r1, s390_r0);
3301 s390_slbgr (code, s390_r0, s390_r1);
3302 s390_sgr (code, ins->dreg, src2);
3303 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3304 s390_agr (code, ins->dreg, s390_r0);
3305 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3308 case OP_SUB_OVF_UN_CARRY: {
3310 s390_slbgr (code, ins->dreg, src2);
3311 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3315 if (ins->sreg1 == ins->dreg) {
3316 s390_ngr (code, ins->dreg, ins->sreg2);
3319 if (ins->sreg2 == ins->dreg) {
3320 s390_ngr (code, ins->dreg, ins->sreg1);
3323 s390_lgr (code, ins->dreg, ins->sreg1);
3324 s390_ngr (code, ins->dreg, ins->sreg2);
3330 if (ins->dreg != ins->sreg1) {
3331 s390_lgr (code, ins->dreg, ins->sreg1);
3333 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3334 s390_ngr (code, ins->dreg, s390_r0);
3338 s390_lgr (code, s390_r1, ins->sreg1);
3339 s390_dsgr (code, s390_r0, ins->sreg2);
3340 s390_lgr (code, ins->dreg, s390_r1);
3344 s390_lgr (code, s390_r1, ins->sreg1);
3345 s390_lghi (code, s390_r0, 0);
3346 s390_dlgr (code, s390_r0, ins->sreg2);
3347 s390_lgr (code, ins->dreg, s390_r1);
3351 s390_lgr (code, s390_r1, ins->sreg1);
3352 s390_dsgr (code, s390_r0, ins->sreg2);
3353 s390_lgr (code, ins->dreg, s390_r0);
3357 if (s390_is_imm16 (ins->inst_imm)) {
3358 s390_lghi (code, s390_r13, ins->inst_imm);
3360 s390_lgfi (code, s390_r13, ins->inst_imm);
3362 s390_lgr (code, s390_r0, ins->sreg1);
3363 s390_dsgr (code, s390_r0, s390_r13);
3364 s390_lgfr (code, ins->dreg, s390_r0);
3368 s390_lgr (code, s390_r1, ins->sreg1);
3369 s390_lghi (code, s390_r0, 0);
3370 s390_dlgr (code, s390_r0, ins->sreg2);
3371 s390_lgr (code, ins->dreg, s390_r0);
3375 if (ins->sreg1 == ins->dreg) {
3376 s390_ogr (code, ins->dreg, ins->sreg2);
3379 if (ins->sreg2 == ins->dreg) {
3380 s390_ogr (code, ins->dreg, ins->sreg1);
3383 s390_lgr (code, ins->dreg, ins->sreg1);
3384 s390_ogr (code, ins->dreg, ins->sreg2);
3390 if (ins->dreg != ins->sreg1) {
3391 s390_lgr (code, ins->dreg, ins->sreg1);
3393 S390_SET_MASK(code, s390_r0, ins->inst_imm);
3394 s390_ogr (code, ins->dreg, s390_r0);
3398 if (ins->sreg1 == ins->dreg) {
3399 s390_xgr (code, ins->dreg, ins->sreg2);
3402 if (ins->sreg2 == ins->dreg) {
3403 s390_xgr (code, ins->dreg, ins->sreg1);
3406 s390_lgr (code, ins->dreg, ins->sreg1);
3407 s390_xgr (code, ins->dreg, ins->sreg2);
3413 if (ins->dreg != ins->sreg1) {
3414 s390_lgr (code, ins->dreg, ins->sreg1);
3416 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3417 s390_xgr (code, ins->dreg, s390_r0);
3422 s390_sllg (code, ins->dreg, ins->dreg, src2, 0);
3427 if (ins->sreg1 != ins->dreg) {
3428 s390_lgr (code, ins->dreg, ins->sreg1);
3430 s390_sllg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3435 s390_srag (code, ins->dreg, ins->dreg, src2, 0);
3440 if (ins->sreg1 != ins->dreg) {
3441 s390_lgr (code, ins->dreg, ins->sreg1);
3443 s390_srag (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3447 case OP_LSHR_UN_IMM: {
3448 if (ins->sreg1 != ins->dreg) {
3449 s390_lgr (code, ins->dreg, ins->sreg1);
3451 s390_srlg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3456 s390_srlg (code, ins->dreg, ins->dreg, src2, 0);
3460 if (ins->sreg1 != ins->dreg) {
3461 s390_lgr (code, ins->dreg, ins->sreg1);
3463 s390_lghi (code, s390_r0, -1);
3464 s390_xgr (code, ins->dreg, s390_r0);
3468 s390_lcgr (code, ins->dreg, ins->sreg1);
3473 s390_msgr (code, ins->dreg, src2);
3478 if (ins->dreg != ins->sreg1) {
3479 s390_lgr (code, ins->dreg, ins->sreg1);
3481 if (s390_is_imm16 (ins->inst_imm)) {
3482 s390_lghi (code, s390_r13, ins->inst_imm);
3483 } else if (s390_is_imm32 (ins->inst_imm)) {
3484 s390_lgfi (code, s390_r13, ins->inst_imm);
3486 S390_SET (code, s390_r13, ins->inst_imm);
3488 s390_msgr (code, ins->dreg, s390_r13);
3493 s390_ltgr (code, s390_r1, ins->sreg1);
3494 s390_jz (code, 0); CODEPTR(code, o[0]);
3495 s390_ltgr (code, s390_r0, ins->sreg2);
3497 s390_lghi (code, s390_r1, 0);
3498 s390_j (code, 0); CODEPTR(code, o[1]);
3499 s390_xgr (code, s390_r0, s390_r1);
3500 s390_msgr (code, s390_r1, ins->sreg2);
3501 s390_xgr (code, s390_r0, s390_r1);
3502 s390_srlg (code, s390_r0, s390_r0, 0, 63);
3503 s390_ltgr (code, s390_r0, s390_r0);
3504 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3505 PTRSLOT (code, o[0]);
3506 PTRSLOT (code, o[1]);
3507 s390_lgr (code, ins->dreg, s390_r1);
3510 case OP_LMUL_OVF_UN: {
3511 s390_lghi (code, s390_r0, 0);
3512 s390_lgr (code, s390_r1, ins->sreg1);
3513 s390_mlgr (code, s390_r0, ins->sreg2);
3514 s390_ltgr (code, s390_r0, s390_r0);
3515 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3516 s390_lgr (code, ins->dreg, s390_r1);
3520 g_assert_not_reached ();
3522 s390_algr (code, ins->dreg, src2);
3527 s390_agr (code, ins->dreg, src2);
3531 g_assert_not_reached ();
3533 s390_alcgr (code, ins->dreg, src2);
3537 if (ins->dreg != ins->sreg1) {
3538 s390_lgfr (code, ins->dreg, ins->sreg1);
3540 if (s390_is_imm16 (ins->inst_imm)) {
3541 s390_aghi (code, ins->dreg, ins->inst_imm);
3543 s390_afi (code, ins->dreg, ins->inst_imm);
3548 if (ins->dreg != ins->sreg1) {
3549 s390_lgfr (code, ins->dreg, ins->sreg1);
3551 if (s390_is_imm16 (ins->inst_imm)) {
3552 s390_lghi (code, s390_r0, ins->inst_imm);
3553 s390_alcgr (code, ins->dreg, s390_r0);
3555 S390_SET (code, s390_r0, ins->inst_imm);
3556 s390_alcgr (code, ins->dreg, s390_r0);
3561 case OP_S390_LADD_OVF: {
3563 s390_agr (code, ins->dreg, src2);
3564 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3567 case OP_LADD_OVF_UN:
3568 case OP_S390_LADD_OVF_UN: {
3570 s390_algr (code, ins->dreg, src2);
3571 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3575 CHECK_SRCDST_NCOM_I;
3576 s390_slgr (code, ins->dreg, src2);
3580 CHECK_SRCDST_NCOM_I;
3581 s390_sgr (code, ins->dreg, src2);
3585 CHECK_SRCDST_NCOM_I;
3586 s390_slbgr (code, ins->dreg, src2);
3590 if (ins->dreg != ins->sreg1) {
3591 s390_lgfr (code, ins->dreg, ins->sreg1);
3593 if (s390_is_imm16 (-ins->inst_imm)) {
3594 s390_aghi (code, ins->dreg, -ins->inst_imm);
3596 s390_agfi (code, ins->dreg, -ins->inst_imm);
3601 S390_SET (code, s390_r0, ins->inst_imm);
3602 s390_slgfr (code, ins->dreg, s390_r0);
3606 case OP_S390_ISUB_OVF: {
3608 s390_sr (code, ins->dreg, src2);
3609 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3610 s390_lgfr (code, ins->dreg, ins->dreg);
3613 case OP_ISUB_OVF_UN:
3614 case OP_S390_ISUB_OVF_UN: {
3616 s390_slr (code, ins->dreg, src2);
3617 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3618 s390_llgfr(code, ins->dreg, ins->dreg);
3622 case OP_S390_LSUB_OVF: {
3624 s390_sgr (code, ins->dreg, src2);
3625 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3628 case OP_LSUB_OVF_UN:
3629 case OP_S390_LSUB_OVF_UN: {
3631 s390_slgr (code, ins->dreg, src2);
3632 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3636 CHECK_SRCDST_NCOM_I;
3637 s390_ngr (code, ins->dreg, src2);
3641 if (ins->dreg != ins->sreg1) {
3642 s390_lgfr (code, ins->dreg, ins->sreg1);
3644 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3645 s390_ngr (code, ins->dreg, s390_r0);
3649 s390_lgfr (code, s390_r0, ins->sreg1);
3650 s390_srda (code, s390_r0, 0, 32);
3651 s390_dr (code, s390_r0, ins->sreg2);
3652 s390_lgfr (code, ins->dreg, s390_r1);
3656 s390_lgfr (code, s390_r0, ins->sreg1);
3657 s390_srdl (code, s390_r0, 0, 32);
3658 s390_dlr (code, s390_r0, ins->sreg2);
3659 s390_lgfr (code, ins->dreg, s390_r1);
3663 if (s390_is_imm16 (ins->inst_imm)) {
3664 s390_lghi (code, s390_r13, ins->inst_imm);
3666 s390_lgfi (code, s390_r13, ins->inst_imm);
3668 s390_lgfr (code, s390_r0, ins->sreg1);
3669 s390_srda (code, s390_r0, 0, 32);
3670 s390_dr (code, s390_r0, ins->sreg2);
3671 s390_lgfr (code, ins->dreg, s390_r1);
3675 s390_lgfr (code, s390_r0, ins->sreg1);
3676 s390_srda (code, s390_r0, 0, 32);
3677 s390_dr (code, s390_r0, ins->sreg2);
3678 s390_lgfr (code, ins->dreg, s390_r0);
3681 s390_lgfr (code, s390_r0, ins->sreg1);
3682 s390_srdl (code, s390_r0, 0, 32);
3683 s390_dlr (code, s390_r0, ins->sreg2);
3684 s390_lgfr (code, ins->dreg, s390_r0);
3688 if (s390_is_imm16 (ins->inst_imm)) {
3689 s390_lghi (code, s390_r13, ins->inst_imm);
3691 s390_lgfi (code, s390_r13, ins->inst_imm);
3693 s390_lgfr (code, s390_r0, ins->sreg1);
3694 s390_srda (code, s390_r0, 0, 32);
3695 s390_dr (code, s390_r0, ins->sreg2);
3696 s390_lgfr (code, ins->dreg, s390_r0);
3701 s390_ogr (code, ins->dreg, src2);
3705 if (ins->dreg != ins->sreg1) {
3706 s390_lgfr (code, ins->dreg, ins->sreg1);
3708 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3709 s390_ogr (code, ins->dreg, s390_r0);
3714 s390_xgr (code, ins->dreg, src2);
3718 if (ins->dreg != ins->sreg1) {
3719 s390_lgfr (code, ins->dreg, ins->sreg1);
3721 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3722 s390_xgr (code, ins->dreg, s390_r0);
3727 s390_sll (code, ins->dreg, src2, 0);
3731 if (ins->sreg1 != ins->dreg) {
3732 s390_lgfr (code, ins->dreg, ins->sreg1);
3734 s390_sll (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3739 s390_sra (code, ins->dreg, src2, 0);
3743 if (ins->sreg1 != ins->dreg) {
3744 s390_lgfr (code, ins->dreg, ins->sreg1);
3746 s390_sra (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3749 case OP_ISHR_UN_IMM: {
3750 if (ins->sreg1 != ins->dreg) {
3751 s390_lgfr (code, ins->dreg, ins->sreg1);
3753 s390_srl (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3758 s390_srl (code, ins->dreg, src2, 0);
3762 if (ins->sreg1 != ins->dreg) {
3763 s390_lgfr (code, ins->dreg, ins->sreg1);
3765 s390_lghi (code, s390_r0, -1);
3766 s390_xgr (code, ins->dreg, s390_r0);
3770 s390_lcgr (code, ins->dreg, ins->sreg1);
3775 s390_msr (code, ins->dreg, src2);
3779 if (ins->dreg != ins->sreg1) {
3780 s390_lgfr (code, ins->dreg, ins->sreg1);
3782 if (s390_is_imm16 (ins->inst_imm)) {
3783 s390_lghi (code, s390_r0, ins->inst_imm);
3785 s390_lgfi (code, s390_r0, ins->inst_imm);
3787 s390_msr (code, ins->dreg, s390_r0);
3792 s390_ltr (code, s390_r1, ins->sreg1);
3793 s390_jz (code, 0); CODEPTR(code, o[0]);
3794 s390_ltr (code, s390_r0, ins->sreg2);
3796 s390_lhi (code, s390_r1, 0);
3797 s390_j (code, 0); CODEPTR(code, o[1]);
3798 s390_xr (code, s390_r0, s390_r1);
3799 s390_msr (code, s390_r1, ins->sreg2);
3800 s390_xr (code, s390_r0, s390_r1);
3801 s390_srl (code, s390_r0, 0, 31);
3802 s390_ltr (code, s390_r0, s390_r0);
3803 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3804 PTRSLOT (code, o[0]);
3805 PTRSLOT (code, o[1]);
3806 s390_lgfr (code, ins->dreg, s390_r1);
3809 case OP_IMUL_OVF_UN: {
3810 s390_lhi (code, s390_r0, 0);
3811 s390_lr (code, s390_r1, ins->sreg1);
3812 s390_mlr (code, s390_r0, ins->sreg2);
3813 s390_ltr (code, s390_r0, s390_r0);
3814 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3815 s390_lgfr (code, ins->dreg, s390_r1);
3820 S390_SET (code, ins->dreg, ins->inst_c0);
3824 mono_add_patch_info (cfg, code - cfg->native_code,
3825 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3826 S390_LOAD_TEMPLATE (code, ins->dreg);
3829 case OP_JUMP_TABLE: {
3830 mono_add_patch_info (cfg, code - cfg->native_code,
3831 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3832 S390_LOAD_TEMPLATE (code, ins->dreg);
3836 if (ins->dreg != ins->sreg1) {
3837 s390_lgr (code, ins->dreg, ins->sreg1);
3841 case OP_LCONV_TO_I8:
3843 s390_lgfr (code, ins->dreg, ins->sreg1);
3845 case OP_LCONV_TO_I4:
3846 s390_lgfr (code, ins->dreg, ins->sreg1);
3849 case OP_LCONV_TO_U8:
3850 case OP_LCONV_TO_U4:
3852 s390_llgfr (code, ins->dreg, ins->sreg1);
3854 case OP_LCONV_TO_OVF_U4:
3855 S390_SET (code, s390_r0, 4294967295);
3856 s390_clgr (code, ins->sreg1, s390_r0);
3857 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3858 s390_ltgr (code, ins->sreg1, ins->sreg1);
3859 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3860 s390_llgfr(code, ins->dreg, ins->sreg1);
3862 case OP_LCONV_TO_OVF_I4_UN:
3863 S390_SET (code, s390_r0, 2147483647);
3864 s390_cgr (code, ins->sreg1, s390_r0);
3865 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3866 s390_ltgr (code, ins->sreg1, ins->sreg1);
3867 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3868 s390_lgfr (code, ins->dreg, ins->sreg1);
3871 if (ins->dreg != ins->sreg1) {
3872 s390_ldr (code, ins->dreg, ins->sreg1);
3875 case OP_MOVE_F_TO_I8:
3876 s390_lgdr (code, ins->dreg, ins->sreg1);
3878 case OP_MOVE_I8_TO_F:
3879 s390_ldgr (code, ins->dreg, ins->sreg1);
3881 case OP_MOVE_F_TO_I4:
3882 s390_ledbr (code, s390_f0, ins->sreg1);
3883 s390_lgdr (code, ins->dreg, s390_f0);
3884 s390_srag (code, ins->dreg, ins->dreg, 0, 32);
3886 case OP_MOVE_I4_TO_F:
3887 s390_slag (code, s390_r0, ins->sreg1, 0, 32);
3888 s390_ldgr (code, ins->dreg, s390_r0);
3889 s390_ldebr (code, ins->dreg, ins->dreg);
3891 case OP_FCONV_TO_R4:
3892 s390_ledbr (code, ins->dreg, ins->sreg1);
3893 s390_ldebr (code, ins->dreg, ins->dreg);
3895 case OP_S390_SETF4RET:
3896 s390_ledbr (code, ins->dreg, ins->sreg1);
3899 if (s390_is_imm16 (ins->inst_offset)) {
3900 s390_lghi (code, s390_r13, ins->inst_offset);
3901 } else if (s390_is_imm32 (ins->inst_offset)) {
3902 s390_lgfi (code, s390_r13, ins->inst_offset);
3904 S390_SET (code, s390_r13, ins->inst_offset);
3906 s390_ear (code, s390_r1, 0);
3907 s390_sllg(code, s390_r1, s390_r1, 0, 32);
3908 s390_ear (code, s390_r1, 1);
3909 s390_lg (code, ins->dreg, s390_r13, s390_r1, 0);
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_stg (code, ins->sreg1, 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: {
4373 if (mono_hwcap_s390x_has_fpe) {
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: {
4382 if (mono_hwcap_s390x_has_fpe) {
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:
4419 if (mono_hwcap_s390x_has_fpe) {
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:
4436 if (mono_hwcap_s390x_has_fpe) {
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:
4450 if (mono_hwcap_s390x_has_fpe) {
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:
4460 if (mono_hwcap_s390x_has_fpe) {
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;
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;
5607 if (method->save_lmf)
5608 cfg->code_size += 200;
5610 cfg->native_code = code = g_malloc (cfg->code_size);
5612 mono_emit_unwind_op_def_cfa (cfg, code, STK_BASE, 0);
5613 emit_unwind_regs(cfg, code, s390_r6, s390_r14, S390_REG_SAVE_OFFSET);
5614 s390_stmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
5615 mono_emit_unwind_op_offset (cfg, code, s390_r14, S390_RET_ADDR_OFFSET);
5616 mini_gc_set_slot_type_from_cfa (cfg, S390_RET_ADDR_OFFSET, SLOT_NOREF);
5618 if (cfg->arch.bkchain_reg != -1)
5619 s390_lgr (code, cfg->arch.bkchain_reg, STK_BASE);
5621 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
5622 cfg->used_int_regs |= 1 << 11;
5625 alloc_size = cfg->stack_offset;
5627 cfg->stack_usage = cfa_offset = alloc_size;
5628 mono_emit_unwind_op_def_cfa_offset (cfg, code, alloc_size);
5629 s390_lgr (code, s390_r11, STK_BASE);
5630 if (s390_is_imm16 (alloc_size)) {
5631 s390_aghi (code, STK_BASE, -alloc_size);
5632 } else if (s390_is_imm32 (alloc_size)) {
5633 s390_agfi (code, STK_BASE, -alloc_size);
5635 int stackSize = alloc_size;
5636 while (stackSize > INT_MAX) {
5637 s390_agfi (code, STK_BASE, -INT_MAX);
5638 stackSize -= INT_MAX;
5640 s390_agfi (code, STK_BASE, -stackSize);
5642 s390_stg (code, s390_r11, 0, STK_BASE, 0);
5644 if (cfg->frame_reg != STK_BASE)
5645 s390_lgr (code, s390_r11, STK_BASE);
5647 mono_emit_unwind_op_def_cfa_reg (cfg, code, cfg->frame_reg);
5649 /* store runtime generic context */
5650 if (cfg->rgctx_var) {
5651 g_assert (cfg->rgctx_var->opcode == OP_REGOFFSET);
5653 s390_stg (code, MONO_ARCH_RGCTX_REG, 0,
5654 cfg->rgctx_var->inst_basereg,
5655 cfg->rgctx_var->inst_offset);
5658 /* compute max_offset in order to use short forward jumps
5659 * we always do it on s390 because the immediate displacement
5660 * for jumps is too small
5663 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
5665 bb->max_offset = max_offset;
5667 MONO_BB_FOR_EACH_INS (bb, ins)
5668 max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
5671 /* load arguments allocated to register from the stack */
5672 sig = mono_method_signature (method);
5675 cinfo = get_call_info (cfg, cfg->mempool, sig);
5677 if (cinfo->struct_ret) {
5678 ArgInfo *ainfo = &cinfo->ret;
5679 inst = cfg->vret_addr;
5680 inst->backend.size = ainfo->vtsize;
5681 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5684 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5685 ArgInfo *ainfo = cinfo->args + i;
5686 inst = cfg->args [pos];
5688 if (inst->opcode == OP_VTARG_ADDR)
5689 inst = inst->inst_left;
5691 if (inst->opcode == OP_REGVAR) {
5692 if (ainfo->regtype == RegTypeGeneral)
5693 s390_lgr (code, inst->dreg, ainfo->reg);
5694 else if (ainfo->regtype == RegTypeFP) {
5695 if (inst->dreg != ainfo->reg) {
5696 if (ainfo->size == 4) {
5697 s390_ledbr (code, inst->dreg, ainfo->reg);
5699 s390_ldr (code, inst->dreg, ainfo->reg);
5703 else if (ainfo->regtype == RegTypeBase) {
5704 s390_lgr (code, s390_r13, STK_BASE);
5705 s390_aghi (code, s390_r13, alloc_size);
5706 s390_lg (code, inst->dreg, 0, s390_r13, ainfo->offset);
5708 g_assert_not_reached ();
5710 if (cfg->verbose_level > 2)
5711 g_print ("Argument %d assigned to register %s\n",
5712 pos, mono_arch_regname (inst->dreg));
5714 if (ainfo->regtype == RegTypeGeneral) {
5715 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5716 g_assert_not_reached();
5717 switch (ainfo->size) {
5719 s390_stc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5722 s390_sth (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5725 s390_st (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5728 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5731 } else if (ainfo->regtype == RegTypeBase) {
5732 } else if (ainfo->regtype == RegTypeFP) {
5733 if (ainfo->size == 8)
5734 s390_std (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5735 else if (ainfo->size == 4)
5736 s390_ste (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5738 g_assert_not_reached ();
5739 } else if (ainfo->regtype == RegTypeStructByVal) {
5740 int doffset = inst->inst_offset;
5742 if (ainfo->reg != STK_BASE)
5746 s390_lgr (code, s390_r13, STK_BASE);
5747 s390_aghi (code, s390_r13, alloc_size);
5750 size = (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE
5751 ? mono_class_native_size(mono_class_from_mono_type(inst->inst_vtype), NULL)
5756 if (ainfo->reg == STK_BASE)
5757 s390_ic (code, reg, 0, s390_r13, ainfo->offset+7);
5758 s390_stc (code, reg, 0, inst->inst_basereg, doffset);
5761 if (ainfo->reg == STK_BASE)
5762 s390_lh (code, reg, 0, s390_r13, ainfo->offset+6);
5763 s390_sth (code, reg, 0, inst->inst_basereg, doffset);
5766 if (ainfo->reg == STK_BASE)
5767 s390_l (code, reg, 0, s390_r13, ainfo->offset+4);
5768 s390_st (code, reg, 0, inst->inst_basereg, doffset);
5771 if (ainfo->reg == STK_BASE)
5772 s390_lg (code, reg, 0, s390_r13, ainfo->offset);
5773 s390_stg (code, reg, 0, inst->inst_basereg, doffset);
5776 } else if (ainfo->regtype == RegTypeStructByAddr) {
5777 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5778 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
5780 g_assert_not_reached ();
5785 if (method->save_lmf) {
5786 /*---------------------------------------------------------------*/
5787 /* build the MonoLMF structure on the stack - see mini-s390x.h */
5788 /*---------------------------------------------------------------*/
5789 lmfOffset = alloc_size - sizeof(MonoLMF);
5791 s390_lgr (code, s390_r13, cfg->frame_reg);
5792 s390_aghi (code, s390_r13, lmfOffset);
5794 /*---------------------------------------------------------------*/
5795 /* Preserve the parameter registers while we fix up the lmf */
5796 /*---------------------------------------------------------------*/
5797 s390_stmg (code, s390_r2, s390_r6, s390_r13,
5798 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
5800 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[0]), SLOT_NOREF);
5801 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[1]), SLOT_NOREF);
5802 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[2]), SLOT_NOREF);
5803 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[3]), SLOT_NOREF);
5804 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[4]), SLOT_NOREF);
5806 /*---------------------------------------------------------------*/
5807 /* On return from this call r2 have the address of the &lmf */
5808 /*---------------------------------------------------------------*/
5809 mono_add_patch_info (cfg, code - cfg->native_code,
5810 MONO_PATCH_INFO_INTERNAL_METHOD,
5811 (gpointer)"mono_tls_get_lmf_addr");
5812 S390_CALL_TEMPLATE(code, s390_r1);
5814 /*---------------------------------------------------------------*/
5815 /* Set lmf.lmf_addr = jit_tls->lmf */
5816 /*---------------------------------------------------------------*/
5817 s390_stg (code, s390_r2, 0, s390_r13,
5818 G_STRUCT_OFFSET(MonoLMF, lmf_addr));
5819 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, lmf_addr), SLOT_NOREF);
5821 /*---------------------------------------------------------------*/
5822 /* Get current lmf */
5823 /*---------------------------------------------------------------*/
5824 s390_lg (code, s390_r0, 0, s390_r2, 0);
5826 /*---------------------------------------------------------------*/
5827 /* Set our lmf as the current lmf */
5828 /*---------------------------------------------------------------*/
5829 s390_stg (code, s390_r13, 0, s390_r2, 0);
5831 /*---------------------------------------------------------------*/
5832 /* Have our lmf.previous_lmf point to the last lmf */
5833 /*---------------------------------------------------------------*/
5834 s390_stg (code, s390_r0, 0, s390_r13,
5835 G_STRUCT_OFFSET(MonoLMF, previous_lmf));
5836 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), SLOT_NOREF);
5838 /*---------------------------------------------------------------*/
5839 /* save method info */
5840 /*---------------------------------------------------------------*/
5841 S390_SET (code, s390_r1, method);
5842 s390_stg (code, s390_r1, 0, s390_r13,
5843 G_STRUCT_OFFSET(MonoLMF, method));
5844 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, method), SLOT_NOREF);
5846 /*---------------------------------------------------------------*/
5847 /* save the current IP */
5848 /*---------------------------------------------------------------*/
5849 s390_stg (code, STK_BASE, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp));
5850 s390_basr (code, s390_r1, 0);
5851 s390_stg (code, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip));
5852 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, ebp), SLOT_NOREF);
5853 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, eip), SLOT_NOREF);
5855 /*---------------------------------------------------------------*/
5856 /* Save general and floating point registers */
5857 /*---------------------------------------------------------------*/
5858 s390_stmg (code, s390_r2, s390_r12, s390_r13,
5859 G_STRUCT_OFFSET(MonoLMF, gregs[2]));
5860 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[0]), SLOT_NOREF);
5861 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[1]), SLOT_NOREF);
5862 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[2]), SLOT_NOREF);
5863 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[3]), SLOT_NOREF);
5864 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[4]), SLOT_NOREF);
5865 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[5]), SLOT_NOREF);
5866 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[6]), SLOT_NOREF);
5867 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[7]), SLOT_NOREF);
5868 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[8]), SLOT_NOREF);
5869 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[9]), SLOT_NOREF);
5870 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[10]), SLOT_NOREF);
5872 fpOffset = lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, fregs[0]);
5873 for (i = 0; i < 16; i++) {
5874 s390_std (code, i, 0, s390_r13,
5875 G_STRUCT_OFFSET(MonoLMF, fregs[i]));
5876 mini_gc_set_slot_type_from_fp (cfg, fpOffset, SLOT_NOREF);
5877 fpOffset += sizeof(double);
5880 /*---------------------------------------------------------------*/
5881 /* Restore the parameter registers now that we've set up the lmf */
5882 /*---------------------------------------------------------------*/
5883 s390_lmg (code, s390_r2, s390_r6, s390_r13,
5884 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
5887 if (cfg->method->save_lmf)
5888 argsClobbered = TRUE;
5891 argsClobbered = TRUE;
5892 code = mono_arch_instrument_prolog (cfg, enter_method, code, TRUE);
5896 * Optimize the common case of the first bblock making a call with the same
5897 * arguments as the method. This works because the arguments are still in their
5898 * original argument registers.
5900 if (!argsClobbered) {
5901 MonoBasicBlock *first_bb = cfg->bb_entry;
5903 int filter = FILTER_IL_SEQ_POINT;
5905 next = mono_bb_first_inst (first_bb, filter);
5906 if (!next && first_bb->next_bb) {
5907 first_bb = first_bb->next_bb;
5908 next = mono_bb_first_inst (first_bb, filter);
5911 if (first_bb->in_count > 1)
5914 for (i = 0; next && i < sig->param_count + sig->hasthis; ++i) {
5915 ArgInfo *ainfo = cinfo->args + i;
5916 gboolean match = FALSE;
5918 inst = cfg->args [i];
5919 if (inst->opcode != OP_REGVAR) {
5920 switch (ainfo->regtype) {
5921 case RegTypeGeneral: {
5922 if (((next->opcode == OP_LOAD_MEMBASE) ||
5923 (next->opcode == OP_LOADI4_MEMBASE)) &&
5924 next->inst_basereg == inst->inst_basereg &&
5925 next->inst_offset == inst->inst_offset) {
5926 if (next->dreg == ainfo->reg) {
5930 next->opcode = OP_MOVE;
5931 next->sreg1 = ainfo->reg;
5932 /* Only continue if the instruction doesn't change argument regs */
5933 if (next->dreg == ainfo->reg)
5943 /* Argument allocated to (non-volatile) register */
5944 switch (ainfo->regtype) {
5945 case RegTypeGeneral:
5946 if (next->opcode == OP_MOVE &&
5947 next->sreg1 == inst->dreg &&
5948 next->dreg == ainfo->reg) {
5959 next = mono_inst_next (next, filter);
5966 cfg->code_len = code - cfg->native_code;
5967 g_assert (cfg->code_len < cfg->code_size);
5972 /*========================= End of Function ========================*/
5974 /*------------------------------------------------------------------*/
5976 /* Name - mono_arch_emit_epilog */
5978 /* Function - Emit the instructions for a function epilog. */
5980 /*------------------------------------------------------------------*/
5983 mono_arch_emit_epilog (MonoCompile *cfg)
5985 MonoMethod *method = cfg->method;
5988 int max_epilog_size = 96;
5990 if (cfg->method->save_lmf)
5991 max_epilog_size += 128;
5993 if (mono_jit_trace_calls != NULL)
5994 max_epilog_size += 128;
5996 while ((cfg->code_len + max_epilog_size) > (cfg->code_size - 16)) {
5997 cfg->code_size *= 2;
5998 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
5999 cfg->stat_code_reallocs++;
6002 code = cfg->native_code + cfg->code_len;
6004 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
6005 code = mono_arch_instrument_epilog (cfg, leave_method, code, TRUE);
6009 if (method->save_lmf)
6010 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
6012 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
6013 s390_lg (code, STK_BASE, 0, STK_BASE, 0);
6015 code = backUpStackPtr(cfg, code);
6017 s390_lmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
6018 s390_br (code, s390_r14);
6020 cfg->code_len = code - cfg->native_code;
6022 g_assert (cfg->code_len < cfg->code_size);
6026 /*========================= End of Function ========================*/
6028 /*------------------------------------------------------------------*/
6030 /* Name - mono_arch_emit_exceptions */
6032 /* Function - Emit the blocks to handle exception conditions. */
6034 /*------------------------------------------------------------------*/
6037 mono_arch_emit_exceptions (MonoCompile *cfg)
6039 MonoJumpInfo *patch_info;
6045 MonoClass *exc_classes [MAX_EXC];
6046 guint8 *exc_throw_start [MAX_EXC];
6048 for (patch_info = cfg->patch_info;
6050 patch_info = patch_info->next) {
6051 if (patch_info->type == MONO_PATCH_INFO_EXC)
6055 code_size = exc_count * 48;
6057 while ((cfg->code_len + code_size) > (cfg->code_size - 16)) {
6058 cfg->code_size *= 2;
6059 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6060 cfg->stat_code_reallocs++;
6063 code = cfg->native_code + cfg->code_len;
6065 /*---------------------------------------------------------------------*/
6066 /* Add code to raise exceptions */
6067 /*---------------------------------------------------------------------*/
6068 for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
6069 switch (patch_info->type) {
6070 case MONO_PATCH_INFO_EXC: {
6071 guint8 *ip = patch_info->ip.i + cfg->native_code;
6072 MonoClass *exc_class;
6075 /*-----------------------------------------------------*/
6076 /* Patch the branch in epilog to come here */
6077 /*-----------------------------------------------------*/
6078 s390_patch_rel (ip + 2, (guint64) S390_RELATIVE(code,ip));
6080 exc_class = mono_class_load_from_name (mono_defaults.corlib,
6082 patch_info->data.name);
6083 throw_ip = patch_info->ip.i;
6085 for (iExc = 0; iExc < nThrows; ++iExc)
6086 if (exc_classes [iExc] == exc_class)
6089 if (iExc < nThrows) {
6090 s390_jcl (code, S390_CC_UN,
6091 (guint64) exc_throw_start [iExc]);
6092 patch_info->type = MONO_PATCH_INFO_NONE;
6095 if (nThrows < MAX_EXC) {
6096 exc_classes [nThrows] = exc_class;
6097 exc_throw_start [nThrows] = code;
6100 /*---------------------------------------------*/
6101 /* Patch the parameter passed to the handler */
6102 /*---------------------------------------------*/
6103 S390_SET (code, s390_r2, exc_class->type_token);
6104 /*---------------------------------------------*/
6105 /* Load return address & parameter register */
6106 /*---------------------------------------------*/
6107 s390_larl (code, s390_r14, (guint64)S390_RELATIVE((patch_info->ip.i +
6108 cfg->native_code + 8), code));
6109 /*---------------------------------------------*/
6110 /* Reuse the current patch to set the jump */
6111 /*---------------------------------------------*/
6112 patch_info->type = MONO_PATCH_INFO_INTERNAL_METHOD;
6113 patch_info->data.name = "mono_arch_throw_corlib_exception";
6114 patch_info->ip.i = code - cfg->native_code;
6115 S390_BR_TEMPLATE (code, s390_r1);
6125 cfg->code_len = code - cfg->native_code;
6127 g_assert (cfg->code_len < cfg->code_size);
6131 /*========================= End of Function ========================*/
6133 /*------------------------------------------------------------------*/
6135 /* Name - mono_arch_finish_init */
6137 /* Function - Setup the JIT's Thread Level Specific Data. */
6139 /*------------------------------------------------------------------*/
6142 mono_arch_finish_init (void)
6146 /*========================= End of Function ========================*/
6148 /*------------------------------------------------------------------*/
6150 /* Name - mono_arch_free_jit_tls_data */
6152 /* Function - Free tls data. */
6154 /*------------------------------------------------------------------*/
6157 mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
6161 /*========================= End of Function ========================*/
6163 /*------------------------------------------------------------------*/
6165 /* Name - mono_arch_emit_inst_for_method */
6167 /*------------------------------------------------------------------*/
6170 mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
6175 /*========================= End of Function ========================*/
6177 /*------------------------------------------------------------------*/
6179 /* Name - mono_arch_decompose_opts */
6181 /* Function - Decompose opcode into a System z opcode. */
6183 /*------------------------------------------------------------------*/
6186 mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
6189 * Have to rename these to avoid being decomposed normally, since the normal
6190 * decomposition does not work on S390.
6192 switch (ins->opcode) {
6194 ins->opcode = OP_S390_ISUB_OVF;
6196 case OP_ISUB_OVF_UN:
6197 ins->opcode = OP_S390_ISUB_OVF_UN;
6200 ins->opcode = OP_S390_IADD_OVF;
6202 case OP_IADD_OVF_UN:
6203 ins->opcode = OP_S390_IADD_OVF_UN;
6206 ins->opcode = OP_S390_LADD_OVF;
6208 case OP_LADD_OVF_UN:
6209 ins->opcode = OP_S390_LADD_OVF_UN;
6212 ins->opcode = OP_S390_LSUB_OVF;
6214 case OP_LSUB_OVF_UN:
6215 ins->opcode = OP_S390_LSUB_OVF_UN;
6222 /*========================= End of Function ========================*/
6224 /*------------------------------------------------------------------*/
6226 /* Name - mono_arch_regalloc_cost */
6228 /* Function - Determine the cost, in the number of memory */
6229 /* references, of the action of allocating the var- */
6230 /* iable VMV into a register during global register */
6233 /* Returns - Cost */
6235 /*------------------------------------------------------------------*/
6238 mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
6244 /*========================= End of Function ========================*/
6246 /*------------------------------------------------------------------*/
6248 /* Name - mono_arch_flush_register_windows */
6254 /*------------------------------------------------------------------*/
6257 mono_arch_flush_register_windows (void)
6261 /*========================= End of Function ========================*/
6263 /*------------------------------------------------------------------*/
6265 /* Name - mono_arch_is_inst_imm */
6267 /* Function - Determine if operand qualifies as an immediate */
6268 /* value. For s390 this is a value -32768-32768 */
6270 /* Returns - True|False - is [not] immediate value. */
6272 /*------------------------------------------------------------------*/
6275 mono_arch_is_inst_imm (gint64 imm)
6277 return s390_is_imm32 (imm);
6280 /*========================= End of Function ========================*/
6282 /*------------------------------------------------------------------*/
6284 /* Name - mono_arch_get_patch_offset */
6286 /* Function - Dummy entry point until s390x supports aot. */
6288 /* Returns - Offset for patch. */
6290 /*------------------------------------------------------------------*/
6293 mono_arch_get_patch_offset (guint8 *code)
6298 /*========================= End of Function ========================*/
6300 /*------------------------------------------------------------------*/
6302 /* Name - mono_arch_context_get_int_reg. */
6306 /* Returns - Return a register from the context. */
6308 /*------------------------------------------------------------------*/
6311 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
6313 return ((mgreg_t) ctx->uc_mcontext.gregs[reg]);
6316 /*========================= End of Function ========================*/
6318 /*------------------------------------------------------------------*/
6320 /* Name - mono_arch_context_set_int_reg. */
6322 /* Function - Set a value in a specified register. */
6324 /*------------------------------------------------------------------*/
6327 mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val)
6329 ctx->uc_mcontext.gregs[reg] = val;
6332 /*========================= End of Function ========================*/
6334 /*------------------------------------------------------------------*/
6336 /* Name - mono_arch_get_this_arg_from_call. */
6340 /*------------------------------------------------------------------*/
6343 mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
6345 return (gpointer) regs [s390_r2];
6348 /*========================= End of Function ========================*/
6350 /*------------------------------------------------------------------*/
6352 /* Name - get_delegate_invoke_impl. */
6356 /*------------------------------------------------------------------*/
6359 get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 param_count, gboolean aot)
6361 guint8 *code, *start;
6366 start = code = mono_global_codeman_reserve (size);
6368 /* Replace the this argument with the target */
6369 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6370 s390_lg (code, s390_r2, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, target));
6371 s390_br (code, s390_r1);
6372 g_assert ((code - start) <= size);
6374 mono_arch_flush_icache (start, size);
6378 size = 32 + param_count * 8;
6379 start = code = mono_global_codeman_reserve (size);
6381 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6382 /* slide down the arguments */
6383 for (i = 0; i < param_count; ++i) {
6384 s390_lgr (code, (s390_r2 + i), (s390_r2 + i + 1));
6386 s390_br (code, s390_r1);
6388 g_assert ((code - start) <= size);
6390 mono_arch_flush_icache (start, size);
6393 MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL));
6396 *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
6398 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
6399 *info = mono_tramp_info_create (name, start, code - start, NULL, NULL);
6406 /*========================= End of Function ========================*/
6408 /*------------------------------------------------------------------*/
6410 /* Name - mono_arch_get_delegate_invoke_impls. */
6414 /*------------------------------------------------------------------*/
6417 mono_arch_get_delegate_invoke_impls (void)
6420 MonoTrampInfo *info;
6423 get_delegate_invoke_impl (&info, TRUE, 0, TRUE);
6424 res = g_slist_prepend (res, info);
6426 for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
6427 get_delegate_invoke_impl (&info, FALSE, i, TRUE);
6428 res = g_slist_prepend (res, info);
6434 /*========================= End of Function ========================*/
6436 /*------------------------------------------------------------------*/
6438 /* Name - mono_arch_get_delegate_invoke_impl. */
6442 /*------------------------------------------------------------------*/
6445 mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target)
6447 guint8 *code, *start;
6449 /* FIXME: Support more cases */
6450 if (MONO_TYPE_ISSTRUCT (sig->ret))
6454 static guint8* cached = NULL;
6459 if (mono_aot_only) {
6460 start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
6462 MonoTrampInfo *info;
6463 start = get_delegate_invoke_impl (&info, TRUE, 0, FALSE);
6464 mono_tramp_info_register (info, NULL);
6467 mono_memory_barrier ();
6471 static guint8* cache [MAX_ARCH_DELEGATE_PARAMS + 1] = {NULL};
6474 if (sig->param_count > MAX_ARCH_DELEGATE_PARAMS)
6476 for (i = 0; i < sig->param_count; ++i)
6477 if (!mono_is_regsize_var (sig->params [i]))
6481 code = cache [sig->param_count];
6485 if (mono_aot_only) {
6486 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", sig->param_count);
6487 start = mono_aot_get_trampoline (name);
6490 MonoTrampInfo *info;
6491 start = get_delegate_invoke_impl (&info, FALSE, sig->param_count, FALSE);
6492 mono_tramp_info_register (info, NULL);
6495 mono_memory_barrier ();
6497 cache [sig->param_count] = start;
6502 /*========================= End of Function ========================*/
6504 /*------------------------------------------------------------------*/
6506 /* Name - mono_arch_get_delegate_virtual_invoke_impl. */
6510 /*------------------------------------------------------------------*/
6513 mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method,
6514 int offset, gboolean load_imt_reg)
6516 guint8 *code, *start;
6519 start = code = mono_global_codeman_reserve (size);
6522 * Replace the "this" argument with the target
6524 s390_lgr (code, s390_r1, s390_r2);
6525 s390_lg (code, s390_r2, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, target));
6528 * Load the IMT register, if needed
6531 s390_lg (code, MONO_ARCH_IMT_REG, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, method));
6537 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET(MonoObject, vtable));
6539 s390_agfi(code, s390_r1, offset);
6541 s390_lg (code, s390_r1, 0, s390_r1, 0);
6542 s390_br (code, s390_r1);
6547 /*========================= End of Function ========================*/
6549 /*------------------------------------------------------------------*/
6551 /* Name - mono_arch_build_imt_trampoline. */
6555 /*------------------------------------------------------------------*/
6558 mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain,
6559 MonoIMTCheckItem **imt_entries, int count,
6560 gpointer fail_tramp)
6564 guchar *code, *start;
6567 for (i = 0; i < count; ++i) {
6568 MonoIMTCheckItem *item = imt_entries [i];
6569 if (item->is_equals) {
6570 if (item->check_target_idx) {
6571 if (!item->compare_done)
6572 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6573 if (item->has_target_code)
6574 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE;
6576 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE +
6580 item->chunk_size += CMP_SIZE + 2 * BR_SIZE + JUMP_SIZE +
6582 if (!item->has_target_code)
6583 item->chunk_size += LOAD_SIZE;
6585 item->chunk_size += LOADCON_SIZE + LOAD_SIZE + BR_SIZE;
6586 #if ENABLE_WRONG_METHOD_CHECK
6587 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6592 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6593 imt_entries [item->check_target_idx]->compare_done = TRUE;
6595 size += item->chunk_size;
6599 code = mono_method_alloc_generic_virtual_trampoline (domain, size);
6601 code = mono_domain_code_reserve (domain, size);
6605 for (i = 0; i < count; ++i) {
6606 MonoIMTCheckItem *item = imt_entries [i];
6607 item->code_target = (guint8 *) code;
6608 if (item->is_equals) {
6609 if (item->check_target_idx) {
6610 if (!item->compare_done) {
6611 S390_SET (code, s390_r0, item->key);
6612 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
6614 item->jmp_code = (guint8*) code;
6615 s390_jcl (code, S390_CC_NE, 0);
6617 if (item->has_target_code) {
6618 S390_SET (code, s390_r1, item->value.target_code);
6620 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6621 s390_lg (code, s390_r1, 0, s390_r1, 0);
6623 s390_br (code, s390_r1);
6628 S390_SET (code, s390_r0, item->key);
6629 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
6630 item->jmp_code = (guint8*) code;
6631 s390_jcl (code, S390_CC_NE, 0);
6632 if (item->has_target_code) {
6633 S390_SET (code, s390_r1, item->value.target_code);
6636 S390_SET (code, s390_r1,
6637 (&(vtable->vtable [item->value.vtable_slot])));
6638 s390_lg (code, s390_r1, 0, s390_r1, 0);
6640 s390_br (code, s390_r1);
6641 target = (gint64) S390_RELATIVE(code, item->jmp_code);
6642 s390_patch_rel(item->jmp_code+2, target);
6643 S390_SET (code, s390_r1, fail_tramp);
6644 s390_br (code, s390_r1);
6645 item->jmp_code = NULL;
6647 /* enable the commented code to assert on wrong method */
6648 #if ENABLE_WRONG_METHOD_CHECK
6649 g_assert_not_reached ();
6651 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6652 s390_lg (code, s390_r1, 0, s390_r1, 0);
6653 s390_br (code, s390_r1);
6657 S390_SET (code, s390_r0, item->key);
6658 s390_cgr (code, MONO_ARCH_IMT_REG, s390_r0);
6659 item->jmp_code = (guint8 *) code;
6660 s390_jcl (code, S390_CC_GE, 0);
6664 * patch the branches to get to the target items
6666 for (i = 0; i < count; ++i) {
6667 MonoIMTCheckItem *item = imt_entries [i];
6668 if (item->jmp_code) {
6669 if (item->check_target_idx) {
6671 offset = (gint64) S390_RELATIVE(imt_entries [item->check_target_idx]->code_target,
6673 s390_patch_rel ((guchar *) item->jmp_code + 2, (guint64) offset);
6678 mono_arch_flush_icache ((guint8*)start, (code - start));
6679 MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL));
6682 UnlockedAdd (&mono_stats.imt_trampolines_size, code - start);
6684 g_assert (code - start <= size);
6686 snprintf(trampName, sizeof(trampName), "%d_imt_trampoline", domain->domain_id);
6687 mono_tramp_info_register (mono_tramp_info_create (trampName, start, code - start, NULL, NULL), domain);
6692 /*========================= End of Function ========================*/
6694 /*------------------------------------------------------------------*/
6696 /* Name - mono_arch_find_imt_method. */
6698 /* Function - Get the method address from MONO_ARCH_IMT_REG */
6699 /* found in the save area. */
6701 /*------------------------------------------------------------------*/
6704 mono_arch_find_imt_method (mgreg_t *regs, guint8 *code)
6706 return ((MonoMethod *) regs [MONO_ARCH_IMT_REG]);
6709 /*========================= End of Function ========================*/
6711 /*------------------------------------------------------------------*/
6713 /* Name - mono_arch_find_static_call_vtable */
6715 /* Function - Find the static call vtable. */
6717 /*------------------------------------------------------------------*/
6720 mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
6722 mgreg_t *r = (mgreg_t*)regs;
6724 return (MonoVTable*)(gsize) r [MONO_ARCH_RGCTX_REG];
6727 /*========================= End of Function ========================*/
6729 /*------------------------------------------------------------------*/
6731 /* Name - mono_arch_get_cie_program */
6733 /* Function - Find the static call vtable. */
6735 /*------------------------------------------------------------------*/
6738 mono_arch_get_cie_program (void)
6742 mono_add_unwind_op_def_cfa (l, 0, 0, STK_BASE, 0);
6747 /*========================= End of Function ========================*/
6749 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
6751 /*------------------------------------------------------------------*/
6753 /* Name - mono_arch_set_breakpoint. */
6755 /* Function - Set a breakpoint at the native code corresponding */
6756 /* to JI at NATIVE_OFFSET. The location should */
6757 /* contain code emitted by OP_SEQ_POINT. */
6759 /*------------------------------------------------------------------*/
6762 mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
6766 breakpointCode.pTrigger = bp_trigger_page;
6767 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
6768 code += BREAKPOINT_SIZE;
6771 /*========================= End of Function ========================*/
6773 /*------------------------------------------------------------------*/
6775 /* Name - mono_arch_clear_breakpoint. */
6777 /* Function - Clear the breakpoint at IP. */
6779 /*------------------------------------------------------------------*/
6782 mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
6787 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); i++)
6791 /*========================= End of Function ========================*/
6793 /*------------------------------------------------------------------*/
6795 /* Name - mono_arch_is_breakpoint_event. */
6799 /*------------------------------------------------------------------*/
6802 mono_arch_is_breakpoint_event (void *info, void *sigctx)
6804 siginfo_t* sinfo = (siginfo_t*) info;
6807 * Sometimes the address is off by 4
6809 if (sinfo->si_addr >= bp_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)bp_trigger_page + 128)
6815 /*========================= End of Function ========================*/
6817 /*------------------------------------------------------------------*/
6819 /* Name - mono_arch_skip_breakpoint. */
6821 /* Function - Modify the CTX so the IP is placed after the */
6822 /* breakpoint instruction, so when we resume, the */
6823 /* instruction is not executed again. */
6825 /*------------------------------------------------------------------*/
6828 mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
6830 MONO_CONTEXT_SET_IP (ctx, ((guint8*)MONO_CONTEXT_GET_IP (ctx) + sizeof(RXY_Format)));
6833 /*========================= End of Function ========================*/
6835 /*------------------------------------------------------------------*/
6837 /* Name - mono_arch_start_single_stepping. */
6839 /* Function - Start single stepping. */
6841 /*------------------------------------------------------------------*/
6844 mono_arch_start_single_stepping (void)
6846 mono_mprotect (ss_trigger_page, mono_pagesize (), 0);
6849 /*========================= End of Function ========================*/
6851 /*------------------------------------------------------------------*/
6853 /* Name - mono_arch_stop_single_stepping. */
6855 /* Function - Stop single stepping. */
6857 /*------------------------------------------------------------------*/
6860 mono_arch_stop_single_stepping (void)
6862 mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ);
6865 /*========================= End of Function ========================*/
6867 /*------------------------------------------------------------------*/
6869 /* Name - mono_arch_is_single_step_event. */
6871 /* Function - Return whether the machine state in sigctx cor- */
6872 /* responds to a single step event. */
6874 /*------------------------------------------------------------------*/
6877 mono_arch_is_single_step_event (void *info, void *sigctx)
6879 siginfo_t* sinfo = (siginfo_t*) info;
6882 * Sometimes the address is off by 4
6884 if (sinfo->si_addr >= ss_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)ss_trigger_page + 128)
6890 /*========================= End of Function ========================*/
6892 /*------------------------------------------------------------------*/
6894 /* Name - mono_arch_skip_single_step. */
6896 /* Function - Modify the ctx so the IP is placed after the */
6897 /* single step trigger instruction, so that the */
6898 /* instruction is not executed again. */
6900 /*------------------------------------------------------------------*/
6903 mono_arch_skip_single_step (MonoContext *ctx)
6905 MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + BREAKPOINT_SIZE);
6908 /*========================= End of Function ========================*/
6910 /*------------------------------------------------------------------*/
6912 /* Name - mono_arch_create_seq_point_info. */
6914 /* Function - Return a pointer to a data struction which is */
6915 /* used by the sequence point implementation in */
6918 /*------------------------------------------------------------------*/
6921 mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code)
6927 /*========================= End of Function ========================*/
6929 /*------------------------------------------------------------------*/
6931 /* Name - mono_arch_init_lmf_ext. */
6935 /*------------------------------------------------------------------*/
6938 mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
6940 ext->lmf.previous_lmf = prev_lmf;
6941 /* Mark that this is a MonoLMFExt */
6942 ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
6943 ext->lmf.ebp = (gssize)ext;
6946 /*========================= End of Function ========================*/
6950 /*------------------------------------------------------------------*/
6952 /* Name - mono_arch_cpu_enumerate_simd_versions. */
6954 /* Function - If this CPU supports vector operations then it */
6955 /* supports the equivalent of SSE1-4. */
6957 /*------------------------------------------------------------------*/
6960 mono_arch_cpu_enumerate_simd_versions (void)
6962 guint32 sseOpts = 0;
6964 if (mono_hwcap_s390x_has_vec)
6965 sseOpts = (SIMD_VERSION_SSE1 | SIMD_VERSION_SSE2 |
6966 SIMD_VERSION_SSE3 | SIMD_VERSION_SSSE3 |
6967 SIMD_VERSION_SSE41 | SIMD_VERSION_SSE42 |
6968 SIMD_VERSION_SSE4a);
6973 /*========================= End of Function ========================*/
6975 /*------------------------------------------------------------------*/
6977 /* Name - mono_arch_opcode_supported. */
6979 /* Function - Check if a given return code is supported. */
6981 /*------------------------------------------------------------------*/
6984 mono_arch_opcode_supported (int opcode)
6987 case OP_ATOMIC_ADD_I4:
6988 case OP_ATOMIC_ADD_I8:
6989 case OP_ATOMIC_EXCHANGE_I4:
6990 case OP_ATOMIC_EXCHANGE_I8:
6997 /*========================= End of Function ========================*/