-/*------------------------------------------------------------------*/
-/* */
-/* Name - mini-s390.c */
-/* */
-/* Function - S/390 backend for the Mono code generator. */
-/* */
-/* Name - Neale Ferguson (Neale.Ferguson@SoftwareAG-usa.com) */
-/* */
-/* Date - January, 2004 */
-/* */
-/* Derivation - From mini-x86 & mini-ppc by - */
-/* Paolo Molaro (lupus@ximian.com) */
-/* Dietmar Maurer (dietmar@ximian.com) */
-/* */
-/*------------------------------------------------------------------*/
+/**
+ * \file
+ * Function - S/390 backend for the Mono code generator.
+ *
+ * Name - Neale Ferguson (Neale.Ferguson@SoftwareAG-usa.com)
+ *
+ * Date - January, 2004
+ *
+ * Derivation - From mini-x86 & mini-ppc by -
+ * Paolo Molaro (lupus@ximian.com)
+ * Dietmar Maurer (dietmar@ximian.com)
+ *
+ */
/*------------------------------------------------------------------*/
/* D e f i n e s */
#define MAX(a, b) ((a) > (b) ? (a) : (b))
/*
- * imt thunking size values
+ * imt trampoline size values
*/
#define CMP_SIZE 24
#define LOADCON_SIZE 20
#include <mono/metadata/appdomain.h>
#include <mono/metadata/debug-helpers.h>
#include <mono/metadata/profiler-private.h>
+#include <mono/utils/mono-error.h>
+#include <mono/utils/mono-error-internals.h>
#include <mono/utils/mono-math.h>
#include <mono/utils/mono-mmap.h>
-#include <mono/utils/mono-hwcap-s390x.h>
+#include <mono/utils/mono-hwcap.h>
#include <mono/utils/mono-threads.h>
#include "mini-s390x.h"
typedef struct {
gint64 gr[5]; /* R2-R6 */
gdouble fp[3]; /* F0-F2 */
-} __attribute__ ((packed)) RegParm;
+} __attribute__ ((__packed__)) RegParm;
typedef struct {
RR_Format basr;
void *pTrigger;
RXY_Format lg;
RXY_Format trigger;
-} __attribute__ ((packed)) breakpoint_t;
+} __attribute__ ((__packed__)) breakpoint_t;
/*========================= End of Typedefs ========================*/
__thread int indent_level = 0;
-static gint appdomain_tls_offset = -1,
- lmf_tls_offset = -1,
- lmf_addr_tls_offset = -1;
-
-pthread_key_t lmf_addr_key;
-
-gboolean lmf_addr_key_inited = FALSE;
-
-facilityList_t facs;
-
/*
* The code generated for sequence points reads from this location,
* which is made read-only when single stepping is enabled.
/* */
/*------------------------------------------------------------------*/
+static void
+decodeParmString (MonoString *s)
+{
+ MonoError error;
+ char *str = mono_string_to_utf8_checked(s, &error);
+ if (is_ok (&error)) {
+ printf("[STRING:%p:%s], ", s, str);
+ g_free (str);
+ } else {
+ mono_error_cleanup (&error);
+ printf("[STRING:%p:], ", s);
+ }
+}
+
static void
decodeParm(MonoType *type, void *curParm, int size)
{
MonoString *s = *((MonoString **) curParm);
if (s) {
g_assert (((MonoObject *) s)->vtable->klass == mono_defaults.string_class);
- printf("[STRING:%p:%s], ", s, mono_string_to_utf8(s));
+ decodeParmString (s);
} else {
printf("[STRING:null], ");
}
klass = obj->vtable->klass;
printf("%p [%p] ",obj,curParm);
if (klass == mono_defaults.string_class) {
- printf("[STRING:%p:%s]",
- obj, mono_string_to_utf8 ((MonoString *) obj));
+ decodeParmString ((MonoString *)obj);
} else if (klass == mono_defaults.int32_class) {
printf("[INT32:%p:%d]",
obj, *(gint32 *)((char *)obj + sizeof (MonoObject)));
if (obj->vtable) {
klass = obj->vtable->klass;
if (klass == mono_defaults.string_class) {
- printf ("this:[STRING:%p:%s], ",
- obj, mono_string_to_utf8 ((MonoString *)obj));
+ printf ("this:");
+ decodeParmString((MonoString *)obj);
} else {
printf ("this:%p[%s.%s], ",
obj, klass->name_space, klass->name);
;
if (s) {
g_assert (((MonoObject *)s)->vtable->klass == mono_defaults.string_class);
- printf ("[STRING:%p:%s]", s, mono_string_to_utf8 (s));
+ decodeParmString (s);
} else
printf ("[STRING:null], ");
break;
ip = ((gint64) __builtin_extract_return_addr (__builtin_return_address (0)));
printf (" ip: %p\n", (gpointer) ip);
+ va_end (ap);
}
/*========================= End of Function ========================*/
mono_set_partial_sharing_supported (FALSE);
mono_os_mutex_init_recursive (&mini_arch_mutex);
- ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ);
- bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ);
+ ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ, MONO_MEM_ACCOUNT_OTHER);
+ bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ, MONO_MEM_ACCOUNT_OTHER);
mono_mprotect (bp_trigger_page, mono_pagesize (), 0);
code = (guint8 *) &breakpointCode;
mono_arch_cleanup (void)
{
if (ss_trigger_page)
- mono_vfree (ss_trigger_page, mono_pagesize ());
+ mono_vfree (ss_trigger_page, mono_pagesize (), MONO_MEM_ACCOUNT_OTHER);
if (bp_trigger_page)
- mono_vfree (bp_trigger_page, mono_pagesize ());
+ mono_vfree (bp_trigger_page, mono_pagesize (), MONO_MEM_ACCOUNT_OTHER);
mono_os_mutex_destroy (&mini_arch_mutex);
}
/*========================= End of Function ========================*/
+/*------------------------------------------------------------------*/
+/* */
+/* Name - mono_arch_have_fast_tls */
+/* */
+/* Function - Returns whether we use fast inlined thread local */
+/* storage managed access, instead of falling back */
+/* to native code. */
+/* */
+/*------------------------------------------------------------------*/
+
+gboolean
+mono_arch_have_fast_tls (void)
+{
+ return TRUE;
+}
+
+/*========================= End of Function ========================*/
+
/*------------------------------------------------------------------*/
/* */
/* Name - mono_arch_cpu_optimizations */
simpleType = ret_type->type;
enum_retvalue:
switch (simpleType) {
- case MONO_TYPE_BOOLEAN:
case MONO_TYPE_I1:
case MONO_TYPE_U1:
case MONO_TYPE_I2:
case MONO_TYPE_U2:
- case MONO_TYPE_CHAR:
case MONO_TYPE_I4:
case MONO_TYPE_U4:
case MONO_TYPE_I:
case MONO_TYPE_U:
- case MONO_TYPE_CLASS:
case MONO_TYPE_OBJECT:
- case MONO_TYPE_SZARRAY:
- case MONO_TYPE_ARRAY:
case MONO_TYPE_PTR:
case MONO_TYPE_FNPTR:
- case MONO_TYPE_STRING:
cinfo->ret.reg = s390_r2;
sz->code_size += 4;
break;
simpleType = ptype->type;
cinfo->args[nParm].type = simpleType;
switch (simpleType) {
- case MONO_TYPE_BOOLEAN:
case MONO_TYPE_I1:
case MONO_TYPE_U1:
cinfo->args[nParm].size = sizeof(char);
break;
case MONO_TYPE_I2:
case MONO_TYPE_U2:
- case MONO_TYPE_CHAR:
cinfo->args[nParm].size = sizeof(short);
add_general (&gr, sz, cinfo->args+nParm);
nParm++;
case MONO_TYPE_U:
case MONO_TYPE_PTR:
case MONO_TYPE_FNPTR:
- case MONO_TYPE_CLASS:
case MONO_TYPE_OBJECT:
- case MONO_TYPE_STRING:
- case MONO_TYPE_SZARRAY:
- case MONO_TYPE_ARRAY:
cinfo->args[nParm].size = sizeof(gpointer);
add_general (&gr, sz, cinfo->args+nParm);
nParm++;
mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg, TRUE);
} else {
+ MonoError error;
MonoMethodHeader *header;
int srcReg;
- header = mono_method_get_header (cfg->method);
+ header = mono_method_get_header_checked (cfg->method, &error);
+ mono_error_assert_ok (&error); /* FIXME don't swallow the error */
if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
srcReg = s390_r11;
else
case OP_S390_SETF4RET:
s390_ledbr (code, ins->dreg, ins->sreg1);
break;
- case OP_TLS_GET: {
+ case OP_TLS_GET: {
if (s390_is_imm16 (ins->inst_offset)) {
s390_lghi (code, s390_r13, ins->inst_offset);
} else if (s390_is_imm32 (ins->inst_offset)) {
s390_sllg(code, s390_r1, s390_r1, 0, 32);
s390_ear (code, s390_r1, 1);
s390_lg (code, ins->dreg, s390_r13, s390_r1, 0);
- }
+ }
+ break;
+ case OP_TLS_SET: {
+ if (s390_is_imm16 (ins->inst_offset)) {
+ s390_lghi (code, s390_r13, ins->inst_offset);
+ } else if (s390_is_imm32 (ins->inst_offset)) {
+ s390_lgfi (code, s390_r13, ins->inst_offset);
+ } else {
+ S390_SET (code, s390_r13, ins->inst_offset);
+ }
+ s390_ear (code, s390_r1, 0);
+ s390_sllg(code, s390_r1, s390_r1, 0, 32);
+ s390_ear (code, s390_r1, 1);
+ s390_stg (code, ins->sreg1, s390_r13, s390_r1, 0);
+ }
break;
case OP_JMP: {
if (cfg->method->save_lmf)
}
break;
case OP_ICONV_TO_R_UN: {
- if (facs.fpe) {
+ if (mono_hwcap_s390x_has_fpe) {
s390_cdlfbr (code, ins->dreg, 5, ins->sreg1, 0);
} else {
s390_llgfr (code, s390_r0, ins->sreg1);
}
break;
case OP_LCONV_TO_R_UN: {
- if (facs.fpe) {
+ if (mono_hwcap_s390x_has_fpe) {
s390_cdlgbr (code, ins->dreg, 5, ins->sreg1, 0);
} else {
short int *jump;
s390_ngr (code, ins->dreg, s390_r0);
break;
case OP_FCONV_TO_U1:
- if (facs.fpe) {
+ if (mono_hwcap_s390x_has_fpe) {
s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
s390_lghi (code, s390_r0, 0xff);
s390_ngr (code, ins->dreg, s390_r0);
s390_ngr (code, ins->dreg, s390_r0);
break;
case OP_FCONV_TO_U2:
- if (facs.fpe) {
+ if (mono_hwcap_s390x_has_fpe) {
s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
s390_llill (code, s390_r0, 0xffff);
s390_ngr (code, ins->dreg, s390_r0);
break;
case OP_FCONV_TO_U4:
case OP_FCONV_TO_U:
- if (facs.fpe) {
+ if (mono_hwcap_s390x_has_fpe) {
s390_clfdbr (code, ins->dreg, 5, ins->sreg1, 0);
} else {
code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE);
s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
break;
case OP_FCONV_TO_U8:
- if (facs.fpe) {
+ if (mono_hwcap_s390x_has_fpe) {
s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
} else {
code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 8, FALSE);
s390_tcdb (code, ins->sreg1, 0, s390_r13, 0);
s390_jz (code, 0); CODEPTR(code, o);
mono_add_patch_info (cfg, code - cfg->native_code,
- MONO_PATCH_INFO_EXC, "ArithmeticException");
+ MONO_PATCH_INFO_EXC, "OverflowException");
s390_brasl (code, s390_r14,0);
PTRSLOT(code, o);
}
void
mono_arch_patch_code (MonoCompile *cfg, MonoMethod *method, MonoDomain *domain,
- guint8 *code, MonoJumpInfo *ji, gboolean run_cctors)
+ guint8 *code, MonoJumpInfo *ji, gboolean run_cctors,
+ MonoError *error)
{
MonoJumpInfo *patch_info;
+ error_init (error);
+
for (patch_info = ji; patch_info; patch_info = patch_info->next) {
unsigned char *ip = patch_info->ip.i + code;
gconstpointer target = NULL;
target = mono_resolve_patch_target (method, domain, code,
- patch_info, run_cctors);
+ patch_info, run_cctors, error);
+ return_if_nok (error);
switch (patch_info->type) {
case MONO_PATCH_INFO_IP:
/*---------------------------------------------------------------*/
/* On return from this call r2 have the address of the &lmf */
/*---------------------------------------------------------------*/
- if (lmf_addr_tls_offset == -1) {
- mono_add_patch_info (cfg, code - cfg->native_code,
- MONO_PATCH_INFO_INTERNAL_METHOD,
- (gpointer)"mono_get_lmf_addr");
- S390_CALL_TEMPLATE(code, s390_r1);
- } else {
- /*-------------------------------------------------------*/
- /* Get LMF by getting value from thread level storage */
- /*-------------------------------------------------------*/
- s390_ear (code, s390_r1, 0);
- s390_sllg(code, s390_r1, s390_r1, 0, 32);
- s390_ear (code, s390_r1, 1);
- s390_lg (code, s390_r2, 0, s390_r1, lmf_addr_tls_offset);
- }
+ mono_add_patch_info (cfg, code - cfg->native_code,
+ MONO_PATCH_INFO_INTERNAL_METHOD,
+ (gpointer)"mono_tls_get_lmf_addr");
+ S390_CALL_TEMPLATE(code, s390_r1);
/*---------------------------------------------------------------*/
/* Set lmf.lmf_addr = jit_tls->lmf */
/*-----------------------------------------------------*/
s390_patch_rel (ip + 2, (guint64) S390_RELATIVE(code,ip));
- exc_class = mono_class_from_name (mono_defaults.corlib,
+ exc_class = mono_class_load_from_name (mono_defaults.corlib,
"System",
patch_info->data.name);
- g_assert (exc_class);
throw_ip = patch_info->ip.i;
for (iExc = 0; iExc < nThrows; ++iExc)
void
mono_arch_finish_init (void)
{
- appdomain_tls_offset = mono_domain_get_tls_offset();
- lmf_tls_offset = mono_get_lmf_tls_offset();
- lmf_addr_tls_offset = mono_get_lmf_addr_tls_offset();
}
/*========================= End of Function ========================*/
break;
case OP_TLS_GET:
printf ("[0x%lx(0x%lx,%s)]", tree->inst_offset,
- tree->inst_imm,
- mono_arch_regname (tree->sreg1));
+ tree->inst_imm,
+ mono_arch_regname (tree->sreg1));
+ done = 1;
+ break;
+ case OP_TLS_SET:
+ printf ("[0x%lx(0x%lx,%s)]", tree->inst_offset,
+ tree->inst_imm,
+ mono_arch_regname (tree->sreg1));
done = 1;
break;
case OP_S390_BKCHAIN:
/*------------------------------------------------------------------*/
/* */
-/* Name - mono_arch_build_imt_thunk. */
+/* Name - mono_arch_build_imt_trampoline. */
/* */
/* Function - */
/* */
/*------------------------------------------------------------------*/
gpointer
-mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain,
- MonoIMTCheckItem **imt_entries, int count,
- gpointer fail_tramp)
+mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain,
+ MonoIMTCheckItem **imt_entries, int count,
+ gpointer fail_tramp)
{
int i;
int size = 0;
}
if (fail_tramp)
- code = mono_method_alloc_generic_virtual_thunk (domain, size);
+ code = mono_method_alloc_generic_virtual_trampoline (domain, size);
else
code = mono_domain_code_reserve (domain, size);
mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL);
if (!fail_tramp)
- mono_stats.imt_thunks_size += (code - start);
+ mono_stats.imt_trampolines_size += (code - start);
g_assert (code - start <= size);
- snprintf(trampName, sizeof(trampName), "%d_imt_thunk_trampoline", domain->domain_id);
+ snprintf(trampName, sizeof(trampName), "%d_imt_trampoline", domain->domain_id);
mono_tramp_info_register (mono_tramp_info_create (trampName, start, code - start, NULL, NULL), domain);
return (start);
{
guint32 sseOpts = 0;
- if (facs.vec != 0)
+ if (mono_hwcap_s390x_has_vec)
sseOpts = (SIMD_VERSION_SSE1 | SIMD_VERSION_SSE2 |
SIMD_VERSION_SSE3 | SIMD_VERSION_SSSE3 |
SIMD_VERSION_SSE41 | SIMD_VERSION_SSE42 |