* 2) softfloat: the compiler emulates all the fp ops. Usually uses the
* ugly swapped double format (I guess a softfloat-vfp exists, too, though).
* 3) VFP: the new and actually sensible and useful FP support. Implemented
- * in HW or kernel-emulated, requires new tools. I think this ios what symbian uses.
+ * in HW or kernel-emulated, requires new tools. I think this is what symbian uses.
*
* The plan is to write the FPA support first. softfloat can be tested in a chroot.
*/
#define DEBUG_IMT 0
const char*
-mono_arch_regname (int reg) {
+mono_arch_regname (int reg)
+{
static const char * rnames[] = {
"arm_r0", "arm_r1", "arm_r2", "arm_r3", "arm_v1",
"arm_v2", "arm_v3", "arm_v4", "arm_v5", "arm_v6",
}
const char*
-mono_arch_fregname (int reg) {
+mono_arch_fregname (int reg)
+{
static const char * rnames[] = {
"arm_f0", "arm_f1", "arm_f2", "arm_f3", "arm_f4",
"arm_f5", "arm_f6", "arm_f7", "arm_f8", "arm_f9",
return code;
}
+static guint8*
+emit_move_return_value (MonoCompile *cfg, MonoInst *ins, guint8 *code)
+{
+ switch (ins->opcode) {
+ 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);
+#endif
+ break;
+ }
+
+ return code;
+}
+
/*
* mono_arch_get_argument_info:
* @csig: a method signature
ARM_CMP_REG_IMM (code, ins->sreg1, imm8, rot_amount);
break;
case OP_BREAK:
- *(int*)code = 0xe7f001f0;
- *(int*)code = 0xef9f0001;
- code += 4;
+ /*
+ * gdb does not like encountering the hw breakpoint ins in the debugged code.
+ * So instead of emitting a trap, we emit a call a C function and place a
+ * breakpoint there.
+ */
+ //*(int*)code = 0xef9f0001;
+ //code += 4;
//ARM_DBRK (code);
+ mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
+ (gpointer)"mono_break");
+ code = emit_call_seq (cfg, code);
break;
case OP_ADDCC:
ARM_ADDS_REG_REG (code, ins->dreg, ins->sreg1, ins->sreg2);
case OP_SHL_IMM:
if (ins->inst_imm)
ARM_SHL_IMM (code, ins->dreg, ins->sreg1, (ins->inst_imm & 0x1f));
+ else if (ins->dreg != ins->sreg1)
+ ARM_MOV_REG_REG (code, ins->dreg, ins->sreg1);
break;
case OP_ISHR:
ARM_SAR_REG (code, ins->dreg, ins->sreg1, ins->sreg2);
case OP_SHR_IMM:
if (ins->inst_imm)
ARM_SAR_IMM (code, ins->dreg, ins->sreg1, (ins->inst_imm & 0x1f));
+ else if (ins->dreg != ins->sreg1)
+ ARM_MOV_REG_REG (code, ins->dreg, ins->sreg1);
break;
case OP_SHR_UN_IMM:
if (ins->inst_imm)
ARM_SHR_IMM (code, ins->dreg, ins->sreg1, (ins->inst_imm & 0x1f));
+ else if (ins->dreg != ins->sreg1)
+ ARM_MOV_REG_REG (code, ins->dreg, ins->sreg1);
break;
case OP_ISHR_UN:
ARM_SHR_REG (code, ins->dreg, ins->sreg1, ins->sreg2);
else
mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_ABS, call->fptr);
code = emit_call_seq (cfg, code);
+ code = emit_move_return_value (cfg, ins, code);
break;
case OP_FCALL_REG:
case OP_LCALL_REG:
case OP_VOIDCALL_REG:
case OP_CALL_REG:
code = emit_call_reg (code, ins->sreg1);
+ code = emit_move_return_value (cfg, ins, code);
break;
case OP_FCALL_MEMBASE:
case OP_LCALL_MEMBASE:
ARM_MOV_REG_REG (code, ARMREG_LR, ARMREG_PC);
ARM_LDR_IMM (code, ARMREG_PC, ins->sreg1, ins->inst_offset);
}
+ code = emit_move_return_value (cfg, ins, code);
break;
case OP_OUTARG:
g_assert_not_reached ();
}
break;
case OP_STORER8_MEMBASE_REG:
- g_assert (arm_is_fpimm8 (ins->inst_offset));
- ARM_STFD (code, ins->sreg1, ins->inst_destbasereg, ins->inst_offset);
+ /* This is generated by the local regalloc pass which runs after the lowering pass */
+ if (!arm_is_fpimm8 (ins->inst_offset)) {
+ code = mono_arm_emit_load_imm (code, ARMREG_LR, ins->inst_offset);
+ ARM_STFD (code, ins->sreg1, ARMREG_LR, 0);
+ } else {
+ ARM_STFD (code, ins->sreg1, ins->inst_destbasereg, ins->inst_offset);
+ }
break;
case OP_LOADR8_MEMBASE:
- g_assert (arm_is_fpimm8 (ins->inst_offset));
- ARM_LDFD (code, ins->dreg, ins->inst_basereg, ins->inst_offset);
+ /* This is generated by the local regalloc pass which runs after the lowering pass */
+ if (!arm_is_fpimm8 (ins->inst_offset)) {
+ code = mono_arm_emit_load_imm (code, ARMREG_LR, ins->inst_offset);
+ ARM_LDFD (code, ins->dreg, ARMREG_LR, 0);
+ } else {
+ ARM_LDFD (code, ins->dreg, ins->inst_basereg, ins->inst_offset);
+ }
break;
case OP_STORER4_MEMBASE_REG:
g_assert (arm_is_fpimm8 (ins->inst_offset));