+#if SIZEOF_VOID_P == 8
+ case OP_LDIV:
+ case OP_LREM:
+ case OP_LDIV_UN:
+ case OP_LREM_UN:
+ if (cfg->backend->emulate_div && mono_arch_opcode_needs_emulation (cfg, ins->opcode))
+ emulate = TRUE;
+ if (!emulate) {
+ if (cfg->backend->need_div_check) {
+ int reg1 = alloc_ireg (cfg);
+ int reg2 = alloc_ireg (cfg);
+ int reg3 = alloc_ireg (cfg);
+ /* b == 0 */
+ MONO_EMIT_NEW_LCOMPARE_IMM (cfg, ins->sreg2, 0);
+ MONO_EMIT_NEW_COND_EXC (cfg, IEQ, "DivideByZeroException");
+ if (ins->opcode == OP_LDIV || ins->opcode == OP_LREM) {
+ /* b == -1 && a == 0x80000000 */
+ MONO_EMIT_NEW_I8CONST (cfg, reg3, -1);
+ MONO_EMIT_NEW_BIALU (cfg, OP_LCOMPARE, -1, ins->sreg2, reg3);
+ MONO_EMIT_NEW_UNALU (cfg, OP_LCEQ, reg1, -1);
+ MONO_EMIT_NEW_I8CONST (cfg, reg3, 0x8000000000000000L);
+ MONO_EMIT_NEW_BIALU (cfg, OP_LCOMPARE, -1, ins->sreg1, reg3);
+ MONO_EMIT_NEW_UNALU (cfg, OP_LCEQ, reg2, -1);
+ MONO_EMIT_NEW_BIALU (cfg, OP_IAND, reg1, reg1, reg2);
+ MONO_EMIT_NEW_ICOMPARE_IMM (cfg, reg1, 1);
+ MONO_EMIT_NEW_COND_EXC (cfg, IEQ, "OverflowException");
+ }
+ }
+ MONO_EMIT_NEW_BIALU (cfg, ins->opcode, ins->dreg, ins->sreg1, ins->sreg2);
+ NULLIFY_INS (ins);
+ }
+ break;
+#endif
+
+ case OP_DIV_IMM:
+ case OP_REM_IMM:
+ case OP_IDIV_IMM:
+ case OP_IREM_IMM:
+ case OP_IDIV_UN_IMM:
+ case OP_IREM_UN_IMM:
+ if (cfg->backend->need_div_check) {
+ int reg1 = alloc_ireg (cfg);
+ /* b == 0 */
+ if (ins->inst_imm == 0) {
+ // FIXME: Optimize this
+ MONO_EMIT_NEW_ICONST (cfg, reg1, 0);
+ MONO_EMIT_NEW_ICOMPARE_IMM (cfg, reg1, 0);
+ MONO_EMIT_NEW_COND_EXC (cfg, IEQ, "DivideByZeroException");
+ }
+ if ((ins->opcode == OP_DIV_IMM || ins->opcode == OP_IDIV_IMM || ins->opcode == OP_REM_IMM || ins->opcode == OP_IREM_IMM) &&
+ (ins->inst_imm == -1)) {
+ /* b == -1 && a == 0x80000000 */
+ MONO_EMIT_NEW_ICOMPARE_IMM (cfg, ins->sreg1, 0x80000000);
+ MONO_EMIT_NEW_COND_EXC (cfg, IEQ, "OverflowException");
+ }
+ MONO_EMIT_NEW_BIALU_IMM (cfg, ins->opcode, ins->dreg, ins->sreg1, ins->inst_imm);
+ NULLIFY_INS (ins);
+ } else {
+ emulate = TRUE;
+ }
+ break;
+