* Dietmar Maurer (dietmar@ximian.com)
*
* (C) 2003 Ximian, Inc.
+ * Copyright 2003-2011 Novell, Inc (http://www.novell.com)
+ * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
*/
#include "mini.h"
#include <string.h>
#include "trace.h"
#include "ir-emit.h"
#include "debugger-agent.h"
-#ifdef ARM_FPU_FPA
+#include "mini-gc.h"
#include "mono/arch/arm/arm-fpa-codegen.h"
-#elif defined(ARM_FPU_VFP)
#include "mono/arch/arm/arm-vfp-codegen.h"
-#endif
#if defined(__ARM_EABI__) && defined(__linux__) && !defined(PLATFORM_ANDROID)
#define HAVE_AEABI_READ_TP 1
#endif
+#ifdef ARM_FPU_FPA
+#define IS_FPA 1
+#else
+#define IS_FPA 0
+#endif
+
+#ifdef ARM_FPU_VFP
+#define IS_VFP 1
+#else
+#define IS_VFP 0
+#endif
+
+#ifdef MONO_ARCH_SOFT_FLOAT
+#define IS_SOFT_FLOAT 1
+#else
+#define IS_SOFT_FLOAT 0
+#endif
+
+#define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
+
static gint lmf_tls_offset = -1;
static gint lmf_addr_tls_offset = -1;
* only be turned on in debug builds.
*/
static int iphone_abi = 0;
+
+/*
+ * The FPU we are generating code for. This is NOT runtime configurable right now,
+ * since some things like MONO_ARCH_CALLEE_FREGS still depend on defines.
+ */
+static MonoArmFPU arm_fpu;
+
static int i8_align;
static volatile int ss_trigger_var = 0;
static gpointer single_step_func_wrapper;
static gpointer breakpoint_func_wrapper;
-
/*
* The code generated for sequence points reads from this location, which is
* made read-only when single stepping is enabled.
case OP_FCALL:
case OP_FCALL_REG:
case OP_FCALL_MEMBASE:
-#ifdef ARM_FPU_FPA
- if (ins->dreg != ARM_FPA_F0)
- ARM_MVFD (code, ins->dreg, ARM_FPA_F0);
-#elif defined(ARM_FPU_VFP)
- if (((MonoCallInst*)ins)->signature->ret->type == MONO_TYPE_R4) {
- ARM_FMSR (code, ins->dreg, ARMREG_R0);
- ARM_CVTS (code, ins->dreg, ins->dreg);
- } else {
- ARM_FMDRR (code, ARMREG_R0, ARMREG_R1, ins->dreg);
+ if (IS_FPA) {
+ if (ins->dreg != ARM_FPA_F0)
+ ARM_FPA_MVFD (code, ins->dreg, ARM_FPA_F0);
+ } else if (IS_VFP) {
+ if (((MonoCallInst*)ins)->signature->ret->type == MONO_TYPE_R4) {
+ ARM_FMSR (code, ins->dreg, ARMREG_R0);
+ ARM_CVTS (code, ins->dreg, ins->dreg);
+ } else {
+ ARM_FMDRR (code, ARMREG_R0, ARMREG_R1, ins->dreg);
+ }
}
-#endif
break;
}
emit_save_lmf (MonoCompile *cfg, guint8 *code, gint32 lmf_offset)
{
gboolean get_lmf_fast = FALSE;
+ int i;
#ifdef HAVE_AEABI_READ_TP
gint32 lmf_addr_tls_offset = mono_get_lmf_addr_tls_offset ();
/* *(lmf_addr) = r1 */
ARM_STR_IMM (code, ARMREG_R1, ARMREG_R0, G_STRUCT_OFFSET (MonoLMF, previous_lmf));
/* Skip method (only needed for trampoline LMF frames) */
- ARM_STR_IMM (code, ARMREG_SP, ARMREG_R1, G_STRUCT_OFFSET (MonoLMF, esp));
+ ARM_STR_IMM (code, ARMREG_SP, ARMREG_R1, G_STRUCT_OFFSET (MonoLMF, sp));
+ ARM_STR_IMM (code, ARMREG_FP, ARMREG_R1, G_STRUCT_OFFSET (MonoLMF, fp));
/* save the current IP */
ARM_MOV_REG_REG (code, ARMREG_IP, ARMREG_PC);
- ARM_STR_IMM (code, ARMREG_IP, ARMREG_R1, G_STRUCT_OFFSET (MonoLMF, eip));
+ ARM_STR_IMM (code, ARMREG_IP, ARMREG_R1, G_STRUCT_OFFSET (MonoLMF, ip));
+
+ for (i = 0; i < sizeof (MonoLMF); i += sizeof (mgreg_t))
+ mini_gc_set_slot_type_from_fp (cfg, lmf_offset + i, SLOT_NOREF);
return code;
}
mono_aot_register_jit_icall ("mono_arm_throw_exception", mono_arm_throw_exception);
mono_aot_register_jit_icall ("mono_arm_throw_exception_by_token", mono_arm_throw_exception_by_token);
mono_aot_register_jit_icall ("mono_arm_resume_unwind", mono_arm_resume_unwind);
+
+#ifdef ARM_FPU_FPA
+ arm_fpu = MONO_ARM_FPU_FPA;
+#elif defined(ARM_FPU_VFP)
+ arm_fpu = MONO_ARM_FPU_VFP;
+#else
+ arm_fpu = MONO_ARM_FPU_NONE;
+#endif
}
/*
offset += size;
}
+ cfg->locals_min_stack_offset = offset;
+
curinst = cfg->locals_start;
for (i = curinst; i < cfg->num_varinfo; ++i) {
ins = cfg->varinfo [i];
*/
if (align < 4 && size >= 4)
align = 4;
+ if (ALIGN_TO (offset, align) > ALIGN_TO (offset, 4))
+ mini_gc_set_slot_type_from_fp (cfg, ALIGN_TO (offset, 4), SLOT_NOREF);
offset += align - 1;
offset &= ~(align - 1);
ins->opcode = OP_REGOFFSET;
//g_print ("allocating local %d to %d\n", i, inst->inst_offset);
}
+ cfg->locals_max_stack_offset = offset;
+
curinst = 0;
if (sig->hasthis) {
ins = cfg->args [curinst];
/* The code in the prolog () stores words when storing vtypes received in a register */
if (MONO_TYPE_ISSTRUCT (sig->params [i]))
align = 4;
+ if (ALIGN_TO (offset, align) > ALIGN_TO (offset, 4))
+ mini_gc_set_slot_type_from_fp (cfg, ALIGN_TO (offset, 4), SLOT_NOREF);
offset += align - 1;
offset &= ~(align - 1);
ins->inst_offset = offset;
}
/* align the offset to 8 bytes */
+ if (ALIGN_TO (offset, 8) > ALIGN_TO (offset, 4))
+ mini_gc_set_slot_type_from_fp (cfg, ALIGN_TO (offset, 4), SLOT_NOREF);
offset += 8 - 1;
offset &= ~(8 - 1);
MONO_ADD_INS (cfg->cbb, ins);
mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, ainfo->reg + 1, FALSE);
} else if (!t->byref && ((t->type == MONO_TYPE_R8) || (t->type == MONO_TYPE_R4))) {
-#ifndef MONO_ARCH_SOFT_FLOAT
- int creg;
-#endif
-
if (ainfo->size == 4) {
-#ifdef MONO_ARCH_SOFT_FLOAT
- /* mono_emit_call_args () have already done the r8->r4 conversion */
- /* The converted value is in an int vreg */
- MONO_INST_NEW (cfg, ins, OP_MOVE);
- ins->dreg = mono_alloc_ireg (cfg);
- ins->sreg1 = in->dreg;
- MONO_ADD_INS (cfg->cbb, ins);
- mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, ainfo->reg, FALSE);
-#else
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG, ARMREG_SP, (cfg->param_area - 8), in->dreg);
- creg = mono_alloc_ireg (cfg);
- MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOAD_MEMBASE, creg, ARMREG_SP, (cfg->param_area - 8));
- mono_call_inst_add_outarg_reg (cfg, call, creg, ainfo->reg, FALSE);
-#endif
+ if (IS_SOFT_FLOAT) {
+ /* mono_emit_call_args () have already done the r8->r4 conversion */
+ /* The converted value is in an int vreg */
+ MONO_INST_NEW (cfg, ins, OP_MOVE);
+ ins->dreg = mono_alloc_ireg (cfg);
+ ins->sreg1 = in->dreg;
+ MONO_ADD_INS (cfg->cbb, ins);
+ mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, ainfo->reg, FALSE);
+ } else {
+ int creg;
+
+ MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG, ARMREG_SP, (cfg->param_area - 8), in->dreg);
+ creg = mono_alloc_ireg (cfg);
+ MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOAD_MEMBASE, creg, ARMREG_SP, (cfg->param_area - 8));
+ mono_call_inst_add_outarg_reg (cfg, call, creg, ainfo->reg, FALSE);
+ }
} else {
-#ifdef MONO_ARCH_SOFT_FLOAT
- MONO_INST_NEW (cfg, ins, OP_FGETLOW32);
- ins->dreg = mono_alloc_ireg (cfg);
- ins->sreg1 = in->dreg;
- MONO_ADD_INS (cfg->cbb, ins);
- mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, ainfo->reg, FALSE);
-
- MONO_INST_NEW (cfg, ins, OP_FGETHIGH32);
- ins->dreg = mono_alloc_ireg (cfg);
- ins->sreg1 = in->dreg;
- MONO_ADD_INS (cfg->cbb, ins);
- mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, ainfo->reg + 1, FALSE);
-#else
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, ARMREG_SP, (cfg->param_area - 8), in->dreg);
- creg = mono_alloc_ireg (cfg);
- MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOAD_MEMBASE, creg, ARMREG_SP, (cfg->param_area - 8));
- mono_call_inst_add_outarg_reg (cfg, call, creg, ainfo->reg, FALSE);
- creg = mono_alloc_ireg (cfg);
- MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOAD_MEMBASE, creg, ARMREG_SP, (cfg->param_area - 8 + 4));
- mono_call_inst_add_outarg_reg (cfg, call, creg, ainfo->reg + 1, FALSE);
-#endif
+ if (IS_SOFT_FLOAT) {
+ MONO_INST_NEW (cfg, ins, OP_FGETLOW32);
+ ins->dreg = mono_alloc_ireg (cfg);
+ ins->sreg1 = in->dreg;
+ MONO_ADD_INS (cfg->cbb, ins);
+ mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, ainfo->reg, FALSE);
+
+ MONO_INST_NEW (cfg, ins, OP_FGETHIGH32);
+ ins->dreg = mono_alloc_ireg (cfg);
+ ins->sreg1 = in->dreg;
+ MONO_ADD_INS (cfg->cbb, ins);
+ mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, ainfo->reg + 1, FALSE);
+ } else {
+ int creg;
+
+ MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, ARMREG_SP, (cfg->param_area - 8), in->dreg);
+ creg = mono_alloc_ireg (cfg);
+ MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOAD_MEMBASE, creg, ARMREG_SP, (cfg->param_area - 8));
+ mono_call_inst_add_outarg_reg (cfg, call, creg, ainfo->reg, FALSE);
+ creg = mono_alloc_ireg (cfg);
+ MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOAD_MEMBASE, creg, ARMREG_SP, (cfg->param_area - 8 + 4));
+ mono_call_inst_add_outarg_reg (cfg, call, creg, ainfo->reg + 1, FALSE);
+ }
}
cfg->flags |= MONO_CFG_HAS_FPOUT;
} else {
if (t->type == MONO_TYPE_R8) {
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, ARMREG_SP, ainfo->offset, in->dreg);
} else {
-#ifdef MONO_ARCH_SOFT_FLOAT
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, ARMREG_SP, ainfo->offset, in->dreg);
-#else
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG, ARMREG_SP, ainfo->offset, in->dreg);
-#endif
+ if (IS_SOFT_FLOAT)
+ MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, ARMREG_SP, ainfo->offset, in->dreg);
+ else
+ MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG, ARMREG_SP, ainfo->offset, in->dreg);
}
} else {
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, ARMREG_SP, ainfo->offset, in->dreg);
}
return;
}
-#ifdef MONO_ARCH_SOFT_FLOAT
- if (ret->type == MONO_TYPE_R8) {
- MonoInst *ins;
-
- MONO_INST_NEW (cfg, ins, OP_SETFRET);
- ins->dreg = cfg->ret->dreg;
- ins->sreg1 = val->dreg;
- MONO_ADD_INS (cfg->cbb, ins);
- return;
- }
- if (ret->type == MONO_TYPE_R4) {
- /* Already converted to an int in method_to_ir () */
- MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg);
- return;
- }
-#elif defined(ARM_FPU_VFP)
- if (ret->type == MONO_TYPE_R8 || ret->type == MONO_TYPE_R4) {
- MonoInst *ins;
+ switch (arm_fpu) {
+ case MONO_ARM_FPU_NONE:
+ if (ret->type == MONO_TYPE_R8) {
+ MonoInst *ins;
+
+ MONO_INST_NEW (cfg, ins, OP_SETFRET);
+ ins->dreg = cfg->ret->dreg;
+ ins->sreg1 = val->dreg;
+ MONO_ADD_INS (cfg->cbb, ins);
+ return;
+ }
+ if (ret->type == MONO_TYPE_R4) {
+ /* Already converted to an int in method_to_ir () */
+ MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg);
+ return;
+ }
+ break;
+ case MONO_ARM_FPU_VFP:
+ if (ret->type == MONO_TYPE_R8 || ret->type == MONO_TYPE_R4) {
+ MonoInst *ins;
- MONO_INST_NEW (cfg, ins, OP_SETFRET);
- ins->dreg = cfg->ret->dreg;
- ins->sreg1 = val->dreg;
- MONO_ADD_INS (cfg->cbb, ins);
- return;
- }
-#else
- if (ret->type == MONO_TYPE_R4 || ret->type == MONO_TYPE_R8) {
- MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, cfg->ret->dreg, val->dreg);
- return;
+ MONO_INST_NEW (cfg, ins, OP_SETFRET);
+ ins->dreg = cfg->ret->dreg;
+ ins->sreg1 = val->dreg;
+ MONO_ADD_INS (cfg->cbb, ins);
+ return;
+ }
+ break;
+ case MONO_ARM_FPU_FPA:
+ if (ret->type == MONO_TYPE_R4 || ret->type == MONO_TYPE_R8) {
+ MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, cfg->ret->dreg, val->dreg);
+ return;
+ }
+ break;
+ default:
+ g_assert_not_reached ();
}
-#endif
}
- /* FIXME: */
MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg);
}
case RegTypeStructByAddr:
break;
case RegTypeFP:
-#ifdef ARM_FPU_FPA
- return FALSE;
-#elif defined(ARM_FPU_VFP)
- break;
-#else
- return FALSE;
-#endif
+ if (IS_FPA)
+ return FALSE;
+ else if (IS_VFP)
+ break;
+ else
+ return FALSE;
default:
return FALSE;
}
switch (t->type) {
case MONO_TYPE_R4:
case MONO_TYPE_R8:
-#ifdef MONO_ARCH_SOFT_FLOAT
- return FALSE;
-#else
- break;
-#endif
+ if (IS_SOFT_FLOAT)
+ return FALSE;
+ else
+ break;
/*
case MONO_TYPE_I8:
case MONO_TYPE_U8:
g_assert (ainfo->cinfo->vtype_retaddr);
/* Nothing to do */
break;
-#if defined(ARM_FPU_VFP)
case MONO_TYPE_R4:
+ g_assert (IS_VFP);
*(float*)ret = *(float*)&res;
break;
case MONO_TYPE_R8: {
mgreg_t regs [2];
+ g_assert (IS_VFP);
regs [0] = res;
regs [1] = res2;
*(double*)ret = *(double*)®s;
break;
}
-#endif
default:
g_assert_not_reached ();
}
emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size, gboolean is_signed)
{
/* sreg is a float, dreg is an integer reg */
-#ifdef ARM_FPU_FPA
- ARM_FIXZ (code, dreg, sreg);
-#elif defined(ARM_FPU_VFP)
- if (is_signed)
- ARM_TOSIZD (code, ARM_VFP_F0, sreg);
- else
- ARM_TOUIZD (code, ARM_VFP_F0, sreg);
- ARM_FMRS (code, dreg, ARM_VFP_F0);
-#endif
+ if (IS_FPA)
+ ARM_FPA_FIXZ (code, dreg, sreg);
+ else if (IS_VFP) {
+ if (is_signed)
+ ARM_TOSIZD (code, ARM_VFP_F0, sreg);
+ else
+ ARM_TOUIZD (code, ARM_VFP_F0, sreg);
+ ARM_FMRS (code, dreg, ARM_VFP_F0);
+ }
if (!is_signed) {
if (size == 1)
ARM_AND_REG_IMM8 (code, dreg, dreg, 0xff);
* Have to emit nops to keep the difference between the offset
* stored in seq_points and breakpoint instruction constant,
* mono_arch_get_ip_for_breakpoint () depends on this.
+ * FIXME: This is no longer needed.
*/
if (val & 0xFF00)
ARM_ADD_REG_IMM (code, dreg, dreg, (val & 0xFF00) >> 8, 24);
break;
}
case OP_FMOVE:
-#ifdef ARM_FPU_FPA
- ARM_MVFD (code, ins->dreg, ins->sreg1);
-#elif defined(ARM_FPU_VFP)
- ARM_CPYD (code, ins->dreg, ins->sreg1);
-#endif
+ if (IS_FPA)
+ ARM_FPA_MVFD (code, ins->dreg, ins->sreg1);
+ else if (IS_VFP)
+ ARM_CPYD (code, ins->dreg, ins->sreg1);
break;
case OP_FCONV_TO_R4:
-#ifdef ARM_FPU_FPA
- ARM_MVFS (code, ins->dreg, ins->sreg1);
-#elif defined(ARM_FPU_VFP)
- ARM_CVTD (code, ins->dreg, ins->sreg1);
- ARM_CVTS (code, ins->dreg, ins->dreg);
-#endif
+ if (IS_FPA)
+ ARM_FPA_MVFS (code, ins->dreg, ins->sreg1);
+ else if (IS_VFP) {
+ ARM_CVTD (code, ins->dreg, ins->sreg1);
+ ARM_CVTS (code, ins->dreg, ins->dreg);
+ }
break;
case OP_JMP:
/*
else
mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_ABS, call->fptr);
code = emit_call_seq (cfg, code);
+ ins->flags |= MONO_INST_GC_CALLSITE;
+ ins->backend.pc_offset = code - cfg->native_code;
code = emit_move_return_value (cfg, ins, code);
break;
case OP_FCALL_REG:
case OP_VOIDCALL_REG:
case OP_CALL_REG:
code = emit_call_reg (code, ins->sreg1);
+ ins->flags |= MONO_INST_GC_CALLSITE;
+ ins->backend.pc_offset = code - cfg->native_code;
code = emit_move_return_value (cfg, ins, code);
break;
case OP_FCALL_MEMBASE:
ARM_MOV_REG_REG (code, ARMREG_LR, ARMREG_PC);
ARM_LDR_IMM (code, ARMREG_PC, ins->sreg1, ins->inst_offset);
}
+ ins->flags |= MONO_INST_GC_CALLSITE;
+ ins->backend.pc_offset = code - cfg->native_code;
code = emit_move_return_value (cfg, ins, code);
break;
case OP_LOCALLOC: {
}
case OP_START_HANDLER: {
MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
+ int i, rot_amount;
+
+ /* Reserve a param area, see filter-stack.exe */
+ if (cfg->param_area) {
+ if ((i = mono_arm_is_rotated_imm8 (cfg->param_area, &rot_amount)) >= 0) {
+ ARM_SUB_REG_IMM (code, ARMREG_SP, ARMREG_SP, i, rot_amount);
+ } else {
+ code = mono_arm_emit_load_imm (code, ARMREG_IP, cfg->param_area);
+ ARM_SUB_REG_REG (code, ARMREG_SP, ARMREG_SP, ARMREG_IP);
+ }
+ }
if (arm_is_imm12 (spvar->inst_offset)) {
ARM_STR_IMM (code, ARMREG_LR, spvar->inst_basereg, spvar->inst_offset);
}
case OP_ENDFILTER: {
MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
+ int i, rot_amount;
+
+ /* Free the param area */
+ if (cfg->param_area) {
+ if ((i = mono_arm_is_rotated_imm8 (cfg->param_area, &rot_amount)) >= 0) {
+ ARM_ADD_REG_IMM (code, ARMREG_SP, ARMREG_SP, i, rot_amount);
+ } else {
+ code = mono_arm_emit_load_imm (code, ARMREG_IP, cfg->param_area);
+ ARM_ADD_REG_REG (code, ARMREG_SP, ARMREG_SP, ARMREG_IP);
+ }
+ }
if (ins->sreg1 != ARMREG_R0)
ARM_MOV_REG_REG (code, ARMREG_R0, ins->sreg1);
}
case OP_ENDFINALLY: {
MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
+ int i, rot_amount;
+
+ /* Free the param area */
+ if (cfg->param_area) {
+ if ((i = mono_arm_is_rotated_imm8 (cfg->param_area, &rot_amount)) >= 0) {
+ ARM_ADD_REG_IMM (code, ARMREG_SP, ARMREG_SP, i, rot_amount);
+ } else {
+ code = mono_arm_emit_load_imm (code, ARMREG_IP, cfg->param_area);
+ ARM_ADD_REG_REG (code, ARMREG_SP, ARMREG_SP, ARMREG_IP);
+ }
+ }
if (arm_is_imm12 (spvar->inst_offset)) {
ARM_LDR_IMM (code, ARMREG_IP, spvar->inst_basereg, spvar->inst_offset);
#ifdef ARM_FPU_FPA
case OP_R8CONST:
if (cfg->compile_aot) {
- ARM_LDFD (code, ins->dreg, ARMREG_PC, 0);
+ ARM_FPA_LDFD (code, ins->dreg, ARMREG_PC, 0);
ARM_B (code, 1);
*(guint32*)code = ((guint32*)(ins->inst_p0))[0];
code += 4;
* the displacement in LDFD (aligning to 512).
*/
code = mono_arm_emit_load_imm (code, ARMREG_LR, (guint32)ins->inst_p0);
- ARM_LDFD (code, ins->dreg, ARMREG_LR, 0);
+ ARM_FPA_LDFD (code, ins->dreg, ARMREG_LR, 0);
}
break;
case OP_R4CONST:
if (cfg->compile_aot) {
- ARM_LDFS (code, ins->dreg, ARMREG_PC, 0);
+ ARM_FPA_LDFS (code, ins->dreg, ARMREG_PC, 0);
ARM_B (code, 0);
*(guint32*)code = ((guint32*)(ins->inst_p0))[0];
code += 4;
} else {
code = mono_arm_emit_load_imm (code, ARMREG_LR, (guint32)ins->inst_p0);
- ARM_LDFS (code, ins->dreg, ARMREG_LR, 0);
+ ARM_FPA_LDFS (code, ins->dreg, ARMREG_LR, 0);
}
break;
case OP_STORER8_MEMBASE_REG:
if (!arm_is_fpimm8 (ins->inst_offset)) {
code = mono_arm_emit_load_imm (code, ARMREG_LR, ins->inst_offset);
ARM_ADD_REG_REG (code, ARMREG_LR, ARMREG_LR, ins->inst_destbasereg);
- ARM_STFD (code, ins->sreg1, ARMREG_LR, 0);
+ ARM_FPA_STFD (code, ins->sreg1, ARMREG_LR, 0);
} else {
- ARM_STFD (code, ins->sreg1, ins->inst_destbasereg, ins->inst_offset);
+ ARM_FPA_STFD (code, ins->sreg1, ins->inst_destbasereg, ins->inst_offset);
}
break;
case OP_LOADR8_MEMBASE:
if (!arm_is_fpimm8 (ins->inst_offset)) {
code = mono_arm_emit_load_imm (code, ARMREG_LR, ins->inst_offset);
ARM_ADD_REG_REG (code, ARMREG_LR, ARMREG_LR, ins->inst_basereg);
- ARM_LDFD (code, ins->dreg, ARMREG_LR, 0);
+ ARM_FPA_LDFD (code, ins->dreg, ARMREG_LR, 0);
} else {
- ARM_LDFD (code, ins->dreg, ins->inst_basereg, ins->inst_offset);
+ ARM_FPA_LDFD (code, ins->dreg, ins->inst_basereg, ins->inst_offset);
}
break;
case OP_STORER4_MEMBASE_REG:
g_assert (arm_is_fpimm8 (ins->inst_offset));
- ARM_STFS (code, ins->sreg1, ins->inst_destbasereg, ins->inst_offset);
+ ARM_FPA_STFS (code, ins->sreg1, ins->inst_destbasereg, ins->inst_offset);
break;
case OP_LOADR4_MEMBASE:
g_assert (arm_is_fpimm8 (ins->inst_offset));
- ARM_LDFS (code, ins->dreg, ins->inst_basereg, ins->inst_offset);
+ ARM_FPA_LDFS (code, ins->dreg, ins->inst_basereg, ins->inst_offset);
break;
case OP_ICONV_TO_R_UN: {
int tmpreg;
tmpreg = ins->dreg == 0? 1: 0;
ARM_CMP_REG_IMM8 (code, ins->sreg1, 0);
- ARM_FLTD (code, ins->dreg, ins->sreg1);
+ ARM_FPA_FLTD (code, ins->dreg, ins->sreg1);
ARM_B_COND (code, ARMCOND_GE, 8);
/* save the temp register */
ARM_SUB_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, 8);
- ARM_STFD (code, tmpreg, ARMREG_SP, 0);
- ARM_LDFD (code, tmpreg, ARMREG_PC, 12);
+ ARM_FPA_STFD (code, tmpreg, ARMREG_SP, 0);
+ ARM_FPA_LDFD (code, tmpreg, ARMREG_PC, 12);
ARM_FPA_ADFD (code, ins->dreg, ins->dreg, tmpreg);
- ARM_LDFD (code, tmpreg, ARMREG_SP, 0);
+ ARM_FPA_LDFD (code, tmpreg, ARMREG_SP, 0);
ARM_ADD_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, 8);
/* skip the constant pool */
ARM_B (code, 8);
break;
}
case OP_ICONV_TO_R4:
- ARM_FLTS (code, ins->dreg, ins->sreg1);
+ ARM_FPA_FLTS (code, ins->dreg, ins->sreg1);
break;
case OP_ICONV_TO_R8:
- ARM_FLTD (code, ins->dreg, ins->sreg1);
+ ARM_FPA_FLTD (code, ins->dreg, ins->sreg1);
break;
#elif defined(ARM_FPU_VFP)
ARM_FPA_DVFD (code, ins->dreg, ins->sreg1, ins->sreg2);
break;
case OP_FNEG:
- ARM_MNFD (code, ins->dreg, ins->sreg1);
+ ARM_FPA_MNFD (code, ins->dreg, ins->sreg1);
break;
#elif defined(ARM_FPU_VFP)
case OP_FADD:
g_assert_not_reached ();
break;
case OP_FCOMPARE:
-#ifdef ARM_FPU_FPA
- ARM_FCMP (code, ARM_FPA_CMF, ins->sreg1, ins->sreg2);
-#elif defined(ARM_FPU_VFP)
- ARM_CMPD (code, ins->sreg1, ins->sreg2);
- ARM_FMSTAT (code);
-#endif
+ if (IS_FPA) {
+ ARM_FPA_FCMP (code, ARM_FPA_CMF, ins->sreg1, ins->sreg2);
+ } else if (IS_VFP) {
+ ARM_CMPD (code, ins->sreg1, ins->sreg2);
+ ARM_FMSTAT (code);
+ }
break;
case OP_FCEQ:
-#ifdef ARM_FPU_FPA
- ARM_FCMP (code, ARM_FPA_CMF, ins->sreg1, ins->sreg2);
-#elif defined(ARM_FPU_VFP)
- ARM_CMPD (code, ins->sreg1, ins->sreg2);
- ARM_FMSTAT (code);
-#endif
+ if (IS_FPA) {
+ ARM_FPA_FCMP (code, ARM_FPA_CMF, ins->sreg1, ins->sreg2);
+ } else if (IS_VFP) {
+ ARM_CMPD (code, ins->sreg1, ins->sreg2);
+ ARM_FMSTAT (code);
+ }
ARM_MOV_REG_IMM8_COND (code, ins->dreg, 0, ARMCOND_NE);
ARM_MOV_REG_IMM8_COND (code, ins->dreg, 1, ARMCOND_EQ);
break;
case OP_FCLT:
-#ifdef ARM_FPU_FPA
- ARM_FCMP (code, ARM_FPA_CMF, ins->sreg1, ins->sreg2);
-#elif defined(ARM_FPU_VFP)
- ARM_CMPD (code, ins->sreg1, ins->sreg2);
- ARM_FMSTAT (code);
-#endif
+ if (IS_FPA) {
+ ARM_FPA_FCMP (code, ARM_FPA_CMF, ins->sreg1, ins->sreg2);
+ } else {
+ ARM_CMPD (code, ins->sreg1, ins->sreg2);
+ ARM_FMSTAT (code);
+ }
ARM_MOV_REG_IMM8 (code, ins->dreg, 0);
ARM_MOV_REG_IMM8_COND (code, ins->dreg, 1, ARMCOND_MI);
break;
case OP_FCLT_UN:
-#ifdef ARM_FPU_FPA
- ARM_FCMP (code, ARM_FPA_CMF, ins->sreg1, ins->sreg2);
-#elif defined(ARM_FPU_VFP)
- ARM_CMPD (code, ins->sreg1, ins->sreg2);
- ARM_FMSTAT (code);
-#endif
+ if (IS_FPA) {
+ ARM_FPA_FCMP (code, ARM_FPA_CMF, ins->sreg1, ins->sreg2);
+ } else if (IS_VFP) {
+ ARM_CMPD (code, ins->sreg1, ins->sreg2);
+ ARM_FMSTAT (code);
+ }
ARM_MOV_REG_IMM8 (code, ins->dreg, 0);
ARM_MOV_REG_IMM8_COND (code, ins->dreg, 1, ARMCOND_MI);
ARM_MOV_REG_IMM8_COND (code, ins->dreg, 1, ARMCOND_VS);
break;
case OP_FCGT:
/* swapped */
-#ifdef ARM_FPU_FPA
- ARM_FCMP (code, ARM_FPA_CMF, ins->sreg2, ins->sreg1);
-#elif defined(ARM_FPU_VFP)
- ARM_CMPD (code, ins->sreg2, ins->sreg1);
- ARM_FMSTAT (code);
-#endif
+ if (IS_FPA) {
+ ARM_FPA_FCMP (code, ARM_FPA_CMF, ins->sreg2, ins->sreg1);
+ } else if (IS_VFP) {
+ ARM_CMPD (code, ins->sreg2, ins->sreg1);
+ ARM_FMSTAT (code);
+ }
ARM_MOV_REG_IMM8 (code, ins->dreg, 0);
ARM_MOV_REG_IMM8_COND (code, ins->dreg, 1, ARMCOND_MI);
break;
case OP_FCGT_UN:
/* swapped */
-#ifdef ARM_FPU_FPA
- ARM_FCMP (code, ARM_FPA_CMF, ins->sreg2, ins->sreg1);
-#elif defined(ARM_FPU_VFP)
- ARM_CMPD (code, ins->sreg2, ins->sreg1);
- ARM_FMSTAT (code);
-#endif
+ if (IS_FPA) {
+ ARM_FPA_FCMP (code, ARM_FPA_CMF, ins->sreg2, ins->sreg1);
+ } else if (IS_VFP) {
+ ARM_CMPD (code, ins->sreg2, ins->sreg1);
+ ARM_FMSTAT (code);
+ }
ARM_MOV_REG_IMM8 (code, ins->dreg, 0);
ARM_MOV_REG_IMM8_COND (code, ins->dreg, 1, ARMCOND_MI);
ARM_MOV_REG_IMM8_COND (code, ins->dreg, 1, ARMCOND_VS);
g_assert_not_reached ();
break;
case OP_FBGE:
-#ifdef ARM_FPU_VFP
- EMIT_COND_BRANCH_FLAGS (ins, ARMCOND_GE);
-#else
- /* FPA requires EQ even thou the docs suggests that just CS is enough */
- EMIT_COND_BRANCH_FLAGS (ins, ARMCOND_EQ);
- EMIT_COND_BRANCH_FLAGS (ins, ARMCOND_CS);
-#endif
+ if (IS_VFP) {
+ EMIT_COND_BRANCH_FLAGS (ins, ARMCOND_GE);
+ } else {
+ /* FPA requires EQ even thou the docs suggests that just CS is enough */
+ EMIT_COND_BRANCH_FLAGS (ins, ARMCOND_EQ);
+ EMIT_COND_BRANCH_FLAGS (ins, ARMCOND_CS);
+ }
break;
case OP_FBGE_UN:
EMIT_COND_BRANCH_FLAGS (ins, ARMCOND_VS); /* V set */
break;
case OP_CKFINITE: {
-#ifdef ARM_FPU_FPA
- if (ins->dreg != ins->sreg1)
- ARM_MVFD (code, ins->dreg, ins->sreg1);
-#elif defined(ARM_FPU_VFP)
- ARM_ABSD (code, ARM_VFP_D1, ins->sreg1);
- ARM_FLDD (code, ARM_VFP_D0, ARMREG_PC, 0);
- ARM_B (code, 1);
- *(guint32*)code = 0xffffffff;
- code += 4;
- *(guint32*)code = 0x7fefffff;
- code += 4;
- ARM_CMPD (code, ARM_VFP_D1, ARM_VFP_D0);
- ARM_FMSTAT (code);
- EMIT_COND_SYSTEM_EXCEPTION_FLAGS (ARMCOND_GT, "ArithmeticException");
- ARM_CMPD (code, ins->sreg1, ins->sreg1);
- ARM_FMSTAT (code);
- EMIT_COND_SYSTEM_EXCEPTION_FLAGS (ARMCOND_VS, "ArithmeticException");
-
- ARM_CPYD (code, ins->dreg, ins->sreg1);
-#endif
+ if (IS_FPA) {
+ if (ins->dreg != ins->sreg1)
+ ARM_FPA_MVFD (code, ins->dreg, ins->sreg1);
+ } else if (IS_VFP) {
+ ARM_ABSD (code, ARM_VFP_D1, ins->sreg1);
+ ARM_FLDD (code, ARM_VFP_D0, ARMREG_PC, 0);
+ ARM_B (code, 1);
+ *(guint32*)code = 0xffffffff;
+ code += 4;
+ *(guint32*)code = 0x7fefffff;
+ code += 4;
+ ARM_CMPD (code, ARM_VFP_D1, ARM_VFP_D0);
+ ARM_FMSTAT (code);
+ EMIT_COND_SYSTEM_EXCEPTION_FLAGS (ARMCOND_GT, "ArithmeticException");
+ ARM_CMPD (code, ins->sreg1, ins->sreg1);
+ ARM_FMSTAT (code);
+ EMIT_COND_SYSTEM_EXCEPTION_FLAGS (ARMCOND_VS, "ArithmeticException");
+ ARM_CPYD (code, ins->dreg, ins->sreg1);
+ }
break;
}
+
+ case OP_GC_LIVENESS_DEF:
+ case OP_GC_LIVENESS_USE:
+ case OP_GC_PARAM_SLOT_LIVENESS_DEF:
+ ins->backend.pc_offset = code - cfg->native_code;
+ break;
+ case OP_GC_SPILL_SLOT_LIVENESS_DEF:
+ ins->backend.pc_offset = code - cfg->native_code;
+ bb->spill_slot_defs = g_slist_prepend_mempool (cfg->mempool, bb->spill_slot_defs, ins);
+ break;
+
default:
g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
g_assert_not_reached ();
MonoBasicBlock *bb;
MonoMethodSignature *sig;
MonoInst *inst;
- int alloc_size, pos, max_offset, i, rot_amount;
+ int alloc_size, orig_alloc_size, pos, max_offset, i, rot_amount;
guint8 *code;
CallInfo *cinfo;
int tracing = 0;
for (i = 0; i < 16; ++i) {
if ((cfg->used_int_regs & (1 << i))) {
mono_emit_unwind_op_offset (cfg, code, i, (- prev_sp_offset) + reg_offset);
+ mini_gc_set_slot_type_from_cfa (cfg, (- prev_sp_offset) + reg_offset, SLOT_NOREF);
reg_offset += 4;
}
}
if (iphone_abi) {
mono_emit_unwind_op_offset (cfg, code, ARMREG_LR, -4);
+ mini_gc_set_slot_type_from_cfa (cfg, -4, SLOT_NOREF);
} else {
mono_emit_unwind_op_offset (cfg, code, ARMREG_LR, -4);
+ mini_gc_set_slot_type_from_cfa (cfg, -4, SLOT_NOREF);
}
} else {
ARM_MOV_REG_REG (code, ARMREG_IP, ARMREG_SP);
lmf_offset = pos;
}
alloc_size += pos;
+ orig_alloc_size = alloc_size;
// align to MONO_ARCH_FRAME_ALIGNMENT bytes
if (alloc_size & (MONO_ARCH_FRAME_ALIGNMENT - 1)) {
alloc_size += MONO_ARCH_FRAME_ALIGNMENT - 1;
//g_print ("prev_sp_offset: %d, alloc_size:%d\n", prev_sp_offset, alloc_size);
prev_sp_offset += alloc_size;
+ for (i = 0; i < alloc_size - orig_alloc_size; i += 4)
+ mini_gc_set_slot_type_from_cfa (cfg, (- prev_sp_offset) + orig_alloc_size + i, SLOT_NOREF);
+
/* compute max_offset in order to use short forward jumps
* we could skip do it on arm because the immediate displacement
* for jumps is large enough, it may be useful later for constant pools
}
}
-guint8*
-mono_arch_get_ip_for_breakpoint (MonoJitInfo *ji, MonoContext *ctx)
-{
- guint8 *ip = MONO_CONTEXT_GET_IP (ctx);
-
- if (ji->from_aot)
- ip -= 6 * 4;
- else if (mini_get_debug_options ()->soft_breakpoints)
- ip -= 4;
- else
- ip -= 12;
-
- return ip;
-}
-
-guint8*
-mono_arch_get_ip_for_single_step (MonoJitInfo *ji, MonoContext *ctx)
-{
- guint8 *ip = MONO_CONTEXT_GET_IP (ctx);
-
- ip += 4;
-
- return ip;
-}
-
/*
* mono_arch_skip_breakpoint:
*