-/*
- * mini-sparc.c: Sparc backend for the Mono code generator
+/**
+ * \file
+ * Sparc backend for the Mono code generator
*
* Authors:
* Paolo Molaro (lupus@ximian.com)
#include <mono/metadata/debug-helpers.h>
#include <mono/metadata/tokentype.h>
#include <mono/utils/mono-math.h>
-#include <mono/utils/mono-hwcap-sparc.h>
+#include <mono/utils/mono-hwcap.h>
+#include <mono/utils/unlocked.h>
#include "mini-sparc.h"
#include "trace.h"
{
}
+gboolean
+mono_arch_have_fast_tls (void)
+{
+ return FALSE;
+}
+
/*
* This function returns the optimizations supported on this cpu.
*/
case ArgInIRegPair: {
MonoType *t = mini_get_underlying_type (sig->ret);
if (((t->type == MONO_TYPE_I8) || (t->type == MONO_TYPE_U8))) {
- MonoInst *low = get_vreg_to_inst (cfg, cfg->ret->dreg + 1);
- MonoInst *high = get_vreg_to_inst (cfg, cfg->ret->dreg + 2);
+ MonoInst *low = get_vreg_to_inst (cfg, MONO_LVREG_LS (cfg->ret->dreg));
+ MonoInst *high = get_vreg_to_inst (cfg, MONO_LVREG_MS (cfg->ret->dreg));
low->opcode = OP_REGVAR;
low->dreg = cinfo->ret.reg + 1;
break;
case ArgInIRegPair:
if (inst->type == STACK_I8) {
- MonoInst *low = get_vreg_to_inst (cfg, inst->dreg + 1);
- MonoInst *high = get_vreg_to_inst (cfg, inst->dreg + 2);
+ MonoInst *low = get_vreg_to_inst (cfg, MONO_LVREG_LS (inst->dreg));
+ MonoInst *high = get_vreg_to_inst (cfg, MONO_LVREG_MS (inst->dreg));
low->opcode = OP_REGVAR;
low->dreg = sparc_i0 + ainfo->reg + 1;
}
if (!sig->ret->byref && (sig->ret->type == MONO_TYPE_I8 || sig->ret->type == MONO_TYPE_U8)) {
- MonoInst *low = get_vreg_to_inst (cfg, cfg->ret->dreg + 1);
- MonoInst *high = get_vreg_to_inst (cfg, cfg->ret->dreg + 2);
+ MonoInst *low = get_vreg_to_inst (cfg, MONO_LVREG_LS (cfg->ret->dreg));
+ MonoInst *high = get_vreg_to_inst (cfg, MONO_LVREG_MS (cfg->ret->dreg));
low->flags |= MONO_INST_VOLATILE;
high->flags |= MONO_INST_VOLATILE;
switch (ainfo->storage) {
case ArgInIRegPair:
- add_outarg_reg (cfg, call, ArgInIReg, sparc_o0 + ainfo->reg + 1, in->dreg + 1);
- add_outarg_reg (cfg, call, ArgInIReg, sparc_o0 + ainfo->reg, in->dreg + 2);
+ add_outarg_reg (cfg, call, ArgInIReg, sparc_o0 + ainfo->reg + 1, MONO_LVREG_LS (in->dreg));
+ add_outarg_reg (cfg, call, ArgInIReg, sparc_o0 + ainfo->reg, MONO_LVREG_MS (in->dreg));
break;
case ArgOnStackPair:
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, sparc_sp, offset, in->dreg + 2);
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, sparc_sp, offset + 4, in->dreg + 1);
+ MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, sparc_sp, offset, MONO_LVREG_MS (in->dreg));
+ MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, sparc_sp, offset + 4, MONO_LVREG_LS (in->dreg));
break;
case ArgInSplitRegStack:
- add_outarg_reg (cfg, call, ArgInIReg, sparc_o0 + ainfo->reg, in->dreg + 2);
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, sparc_sp, offset + 4, in->dreg + 1);
+ add_outarg_reg (cfg, call, ArgInIReg, sparc_o0 + ainfo->reg, MONO_LVREG_MS (in->dreg));
+ MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, sparc_sp, offset + 4, MONO_LVREG_LS (in->dreg));
break;
default:
g_assert_not_reached ();
ArgInfo *ainfo = (ArgInfo*)ins->inst_p1;
int size = ins->backend.size;
- mini_emit_memcpy (cfg, sparc_sp, ainfo->offset, src->dreg, 0, size, 0);
+ mini_emit_memcpy (cfg, sparc_sp, ainfo->offset, src->dreg, 0, size, SIZEOF_VOID_P);
}
void
if (ret->type == MONO_TYPE_I8 || ret->type == MONO_TYPE_U8) {
MONO_EMIT_NEW_UNALU (cfg, OP_LMOVE, cfg->ret->dreg, val->dreg);
} else {
- MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg + 2, val->dreg + 2);
- MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg + 1, val->dreg + 1);
+ MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_MS (cfg->ret->dreg), MONO_LVREG_MS (val->dreg));
+ MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, MONO_LVREG_LS (cfg->ret->dreg), MONO_LVREG_LS (val->dreg));
}
break;
case ArgInFReg:
static guint32*
emit_call (MonoCompile *cfg, guint32 *code, guint32 patch_type, gconstpointer data)
{
+ MonoError error;
gpointer target;
/* FIXME: This only works if the target method is already compiled */
patch_info.type = patch_type;
patch_info.data.target = data;
- target = mono_resolve_patch_target (cfg->method, cfg->domain, NULL, &patch_info, FALSE);
+ target = mono_resolve_patch_target (cfg->method, cfg->domain, NULL, &patch_info, FALSE, &error);
+ mono_error_raise_exception (&error); /* FIXME: don't raise here */
/* FIXME: Add optimizations if the target is close enough */
sparc_set (code, target, sparc_o7);
{
switch (ins->opcode) {
case OP_LNEG:
- MONO_EMIT_NEW_BIALU (cfg, OP_SUBCC, ins->dreg + 1, 0, ins->sreg1 + 1);
- MONO_EMIT_NEW_BIALU (cfg, OP_SBB, ins->dreg + 2, 0, ins->sreg1 + 2);
+ MONO_EMIT_NEW_BIALU (cfg, OP_SUBCC, MONO_LVREG_LS (ins->dreg), 0, MONO_LVREG_LS (ins->sreg1));
+ MONO_EMIT_NEW_BIALU (cfg, OP_SBB, MONO_LVREG_MS (ins->dreg), 0, MONO_LVREG_MS (ins->sreg1));
NULLIFY_INS (ins);
break;
default:
* LOCKING: called with the domain lock held
*/
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;
size += item->chunk_size;
}
if (fail_tramp)
- code = mono_method_alloc_generic_virtual_thunk (domain, size * 4);
+ code = mono_method_alloc_generic_virtual_trampoline (domain, size * 4);
else
code = mono_domain_code_reserve (domain, size * 4);
start = code;
mono_arch_flush_icache ((guint8*)start, (code - start) * 4);
- mono_stats.imt_thunks_size += (code - start) * 4;
+ UnlockedAdd (&mono_stats.imt_trampolines_size, (code - start) * 4);
g_assert (code - start <= size);
mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, NULL), domain);
cpos = bb->max_offset;
- if (cfg->prof_options & MONO_PROFILE_COVERAGE) {
- NOT_IMPLEMENTED;
- }
-
MONO_BB_FOR_EACH_INS (bb, ins) {
guint8* code_start;
sparc_srl_imm (code, sparc_o7, 4, sparc_o7);
sparc_and_imm (code, FALSE, sparc_o7, 2047, sparc_o7);
sparc_cmp_imm (code, sparc_o7, 2047);
- EMIT_COND_SYSTEM_EXCEPTION (ins, sparc_be, "ArithmeticException");
+ EMIT_COND_SYSTEM_EXCEPTION (ins, sparc_be, "OverflowException");
#ifdef SPARCV9
sparc_fmovd (code, ins->sreg1, ins->dreg);
#else
case OP_MEMORY_BARRIER:
sparc_membar (code, sparc_membar_all);
break;
+ case OP_GC_SAFE_POINT:
+ break;
default:
#ifdef __GNUC__
}
void
-mono_arch_patch_code (MonoCompile *cfg, MonoMethod *method, MonoDomain *domain, guint8 *code, MonoJumpInfo *ji, gboolean run_cctors)
+mono_arch_patch_code (MonoCompile *cfg, MonoMethod *method, MonoDomain *domain, guint8 *code, MonoJumpInfo *ji, gboolean run_cctors, MonoError *error)
{
MonoJumpInfo *patch_info;
+ error_init (error);
+
/* FIXME: Move part of this to arch independent code */
for (patch_info = ji; patch_info; patch_info = patch_info->next) {
unsigned char *ip = patch_info->ip.i + code;
gpointer target;
- target = mono_resolve_patch_target (method, domain, code, patch_info, run_cctors);
+ target = mono_resolve_patch_target (method, domain, code, patch_info, run_cctors, error);
+ return_if_nok (error);
switch (patch_info->type) {
case MONO_PATCH_INFO_NONE:
if (mono_jit_trace_calls != NULL)
max_epilog_size += 50;
- if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
- max_epilog_size += 50;
-
while (cfg->code_len + max_epilog_size > (cfg->code_size - 16)) {
cfg->code_size *= 2;
cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
sparc_patch ((guint32*)(cfg->native_code + patch_info->ip.i), code);
- exc_class = mono_class_from_name (mono_defaults.corlib, "System", patch_info->data.name);
- g_assert (exc_class);
+ exc_class = mono_class_load_from_name (mono_defaults.corlib, "System", patch_info->data.name);
type_idx = exc_class->type_token - MONO_TOKEN_TYPE_DEF;
throw_ip = patch_info->ip.i;
return 0;
}
-gboolean
-mono_arch_print_tree (MonoInst *tree, int arity)
-{
- return 0;
-}
-
mgreg_t
mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
{