MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_UN_IMM, ins->dreg, ins->sreg1, 0);
ins->opcode = OP_NOP;
break;
+#if defined(__ppc__) || defined(__powerpc__)
+ case OP_LADD_OVF:
+ /* ADC sets the condition code */
+ MONO_EMIT_NEW_BIALU (cfg, OP_ADDCC, ins->dreg + 1, ins->sreg1 + 1, ins->sreg2 + 1);
+ MONO_EMIT_NEW_BIALU (cfg, OP_ADD_OVF_CARRY, ins->dreg + 2, ins->sreg1 + 2, ins->sreg2 + 2);
+ ins->opcode = OP_NOP;
+ g_assert_not_reached ();
+ break;
+ case OP_LADD_OVF_UN:
+ /* ADC sets the condition code */
+ MONO_EMIT_NEW_BIALU (cfg, OP_ADDCC, ins->dreg + 1, ins->sreg1 + 1, ins->sreg2 + 1);
+ MONO_EMIT_NEW_BIALU (cfg, OP_ADD_OVF_UN_CARRY, ins->dreg + 2, ins->sreg1 + 2, ins->sreg2 + 2);
+ ins->opcode = OP_NOP;
+ g_assert_not_reached ();
+ break;
+ case OP_LSUB_OVF:
+ /* SBB sets the condition code */
+ MONO_EMIT_NEW_BIALU (cfg, OP_SUBCC, ins->dreg + 1, ins->sreg1 + 1, ins->sreg2 + 1);
+ MONO_EMIT_NEW_BIALU (cfg, OP_SUB_OVF_CARRY, ins->dreg + 2, ins->sreg1 + 2, ins->sreg2 + 2);
+ ins->opcode = OP_NOP;
+ g_assert_not_reached ();
+ break;
+ case OP_LSUB_OVF_UN:
+ /* SBB sets the condition code */
+ MONO_EMIT_NEW_BIALU (cfg, OP_SUBCC, ins->dreg + 1, ins->sreg1 + 1, ins->sreg2 + 1);
+ MONO_EMIT_NEW_BIALU (cfg, OP_SUB_OVF_UN_CARRY, ins->dreg + 2, ins->sreg1 + 2, ins->sreg2 + 2);
+ ins->opcode = OP_NOP;
+ g_assert_not_reached ();
+ break;
+#else
case OP_LADD_OVF:
MONO_EMIT_NEW_BIALU (cfg, OP_ADDCC, ins->dreg, ins->sreg1, ins->sreg2);
MONO_EMIT_NEW_COND_EXC (cfg, OV, "OverflowException");
MONO_EMIT_NEW_COND_EXC (cfg, C, "OverflowException");
ins->opcode = OP_NOP;
break;
+#endif
case OP_ICONV_TO_OVF_I8:
case OP_ICONV_TO_OVF_I:
MONO_EMIT_NEW_BIALU (cfg, OP_ISUBCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
MONO_EMIT_NEW_BIALU (cfg, OP_ISBB, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
break;
+
+#if defined(__ppc__) || defined(__powerpc__)
+ case OP_LADD_OVF:
+ /* ADC sets the condition code */
+ MONO_EMIT_NEW_BIALU (cfg, OP_ADDCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
+ MONO_EMIT_NEW_BIALU (cfg, OP_ADD_OVF_CARRY, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
+ break;
+ case OP_LADD_OVF_UN:
+ /* ADC sets the condition code */
+ MONO_EMIT_NEW_BIALU (cfg, OP_ADDCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
+ MONO_EMIT_NEW_BIALU (cfg, OP_ADD_OVF_UN_CARRY, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
+ break;
+ case OP_LSUB_OVF:
+ /* SBB sets the condition code */
+ MONO_EMIT_NEW_BIALU (cfg, OP_SUBCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
+ MONO_EMIT_NEW_BIALU (cfg, OP_SUB_OVF_CARRY, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
+ break;
+ case OP_LSUB_OVF_UN:
+ /* SBB sets the condition code */
+ MONO_EMIT_NEW_BIALU (cfg, OP_SUBCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
+ MONO_EMIT_NEW_BIALU (cfg, OP_SUB_OVF_UN_CARRY, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
+ break;
+#else
case OP_LADD_OVF:
/* ADC sets the condition code */
MONO_EMIT_NEW_BIALU (cfg, OP_IADDCC, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
MONO_EMIT_NEW_BIALU (cfg, OP_ISBB, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
MONO_EMIT_NEW_COND_EXC (cfg, C, "OverflowException");
break;
+#endif
case OP_LAND:
MONO_EMIT_NEW_BIALU (cfg, OP_IAND, tree->dreg + 1, tree->sreg1 + 1, tree->sreg2 + 1);
MONO_EMIT_NEW_BIALU (cfg, OP_IAND, tree->dreg + 2, tree->sreg1 + 2, tree->sreg2 + 2);
#elif defined(__arm__)
MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ARM_RSBS_IMM, tree->dreg + 1, tree->sreg1 + 1, 0);
MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ARM_RSC_IMM, tree->dreg + 2, tree->sreg1 + 2, 0);
+#elif defined(__ppc__) || defined(__powerpc__)
+ /* This is the old version from inssel-long32.brg */
+ MONO_EMIT_NEW_UNALU (cfg, OP_INOT, tree->dreg + 1, tree->sreg1 + 1);
+ MONO_EMIT_NEW_UNALU (cfg, OP_INOT, tree->dreg + 2, tree->sreg1 + 2);
+ /* ADC sets the condition codes */
+ MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADC_IMM, tree->dreg + 1, tree->dreg + 1, 1);
+ MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADC_IMM, tree->dreg + 2, tree->dreg + 2, 0);
#else
NOT_IMPLEMENTED;
#endif
case OP_VCALL_REG:
case OP_VCALL_MEMBASE: {
MonoCallInst *call = (MonoCallInst*)ins;
+ int size;
if (call->vret_in_reg) {
MonoCallInst *call2;
/* Compute the vtype location */
dest_var = get_vreg_to_inst (cfg, call->inst.dreg);
- /* This was already created when OP_OUTARG_VTRETADDR was processed */
- g_assert (dest_var);
+ if (!dest_var)
+ dest_var = mono_compile_create_var_for_vreg (cfg, call->signature->ret, OP_LOCAL, call->inst.dreg);
EMIT_NEW_VARLOADA (cfg, dest, dest_var, dest_var->inst_vtype);
/* Save the result */
- /* This assumes the vtype is sizeof (gpointer) long */
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
+ if (dest_var->backend.is_pinvoke)
+ size = mono_class_native_size (dest->inst_vtype->data.klass, NULL);
+ else
+ size = mono_type_size (dest_var->inst_vtype, NULL);
+ switch (size) {
+ case 1:
+ MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI1_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
+ break;
+ case 2:
+ MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI2_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
+ break;
+ case 4:
+ MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
+ break;
+ case 8:
+ MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI8_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
+ break;
+ default:
+ /* This assumes the vtype is sizeof (gpointer) long */
+ MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, dest->dreg, 0, call2->inst.dreg);
+ break;
+ }
} else {
switch (ins->opcode) {
case OP_VCALL: