Nasty, but jump over div/0. Value remains undefined, as on 360.
Fixes issue #135.
This commit is contained in:
parent
e3a4273ef3
commit
3573840c5f
|
@ -3289,6 +3289,9 @@ EMITTER_OPCODE_TABLE(
|
||||||
// TODO(benvanik): simplify code!
|
// TODO(benvanik): simplify code!
|
||||||
EMITTER(DIV_I8, MATCH(I<OPCODE_DIV, I8<>, I8<>, I8<>>)) {
|
EMITTER(DIV_I8, MATCH(I<OPCODE_DIV, I8<>, I8<>, I8<>>)) {
|
||||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||||
|
Xbyak::Label skip;
|
||||||
|
e.inLocalLabel();
|
||||||
|
|
||||||
// NOTE: RDX clobbered.
|
// NOTE: RDX clobbered.
|
||||||
bool clobbered_rcx = false;
|
bool clobbered_rcx = false;
|
||||||
if (i.src2.is_constant) {
|
if (i.src2.is_constant) {
|
||||||
|
@ -3303,6 +3306,10 @@ EMITTER(DIV_I8, MATCH(I<OPCODE_DIV, I8<>, I8<>, I8<>>)) {
|
||||||
e.idiv(e.cl);
|
e.idiv(e.cl);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// Skip if src2 is zero.
|
||||||
|
e.test(i.src2, i.src2);
|
||||||
|
e.jz(skip, CodeGenerator::T_SHORT);
|
||||||
|
|
||||||
if (i.instr->flags & ARITHMETIC_UNSIGNED) {
|
if (i.instr->flags & ARITHMETIC_UNSIGNED) {
|
||||||
if (i.src1.is_constant) {
|
if (i.src1.is_constant) {
|
||||||
e.mov(e.ax, static_cast<int16_t>(i.src1.constant()));
|
e.mov(e.ax, static_cast<int16_t>(i.src1.constant()));
|
||||||
|
@ -3319,6 +3326,9 @@ EMITTER(DIV_I8, MATCH(I<OPCODE_DIV, I8<>, I8<>, I8<>>)) {
|
||||||
e.idiv(i.src2);
|
e.idiv(i.src2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
e.L(skip);
|
||||||
|
e.outLocalLabel();
|
||||||
e.mov(i.dest, e.al);
|
e.mov(i.dest, e.al);
|
||||||
if (clobbered_rcx) {
|
if (clobbered_rcx) {
|
||||||
e.ReloadECX();
|
e.ReloadECX();
|
||||||
|
@ -3328,6 +3338,9 @@ EMITTER(DIV_I8, MATCH(I<OPCODE_DIV, I8<>, I8<>, I8<>>)) {
|
||||||
};
|
};
|
||||||
EMITTER(DIV_I16, MATCH(I<OPCODE_DIV, I16<>, I16<>, I16<>>)) {
|
EMITTER(DIV_I16, MATCH(I<OPCODE_DIV, I16<>, I16<>, I16<>>)) {
|
||||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||||
|
Xbyak::Label skip;
|
||||||
|
e.inLocalLabel();
|
||||||
|
|
||||||
// NOTE: RDX clobbered.
|
// NOTE: RDX clobbered.
|
||||||
bool clobbered_rcx = false;
|
bool clobbered_rcx = false;
|
||||||
if (i.src2.is_constant) {
|
if (i.src2.is_constant) {
|
||||||
|
@ -3347,6 +3360,10 @@ EMITTER(DIV_I16, MATCH(I<OPCODE_DIV, I16<>, I16<>, I16<>>)) {
|
||||||
e.idiv(e.cx);
|
e.idiv(e.cx);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// Skip if src2 is zero.
|
||||||
|
e.test(i.src2, i.src2);
|
||||||
|
e.jz(skip, CodeGenerator::T_SHORT);
|
||||||
|
|
||||||
if (i.instr->flags & ARITHMETIC_UNSIGNED) {
|
if (i.instr->flags & ARITHMETIC_UNSIGNED) {
|
||||||
if (i.src1.is_constant) {
|
if (i.src1.is_constant) {
|
||||||
e.mov(e.ax, i.src1.constant());
|
e.mov(e.ax, i.src1.constant());
|
||||||
|
@ -3368,6 +3385,9 @@ EMITTER(DIV_I16, MATCH(I<OPCODE_DIV, I16<>, I16<>, I16<>>)) {
|
||||||
e.idiv(i.src2);
|
e.idiv(i.src2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
e.L(skip);
|
||||||
|
e.outLocalLabel();
|
||||||
e.mov(i.dest, e.ax);
|
e.mov(i.dest, e.ax);
|
||||||
if (clobbered_rcx) {
|
if (clobbered_rcx) {
|
||||||
e.ReloadECX();
|
e.ReloadECX();
|
||||||
|
@ -3377,6 +3397,9 @@ EMITTER(DIV_I16, MATCH(I<OPCODE_DIV, I16<>, I16<>, I16<>>)) {
|
||||||
};
|
};
|
||||||
EMITTER(DIV_I32, MATCH(I<OPCODE_DIV, I32<>, I32<>, I32<>>)) {
|
EMITTER(DIV_I32, MATCH(I<OPCODE_DIV, I32<>, I32<>, I32<>>)) {
|
||||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||||
|
Xbyak::Label skip;
|
||||||
|
e.inLocalLabel();
|
||||||
|
|
||||||
// NOTE: RDX clobbered.
|
// NOTE: RDX clobbered.
|
||||||
bool clobbered_rcx = false;
|
bool clobbered_rcx = false;
|
||||||
if (i.src2.is_constant) {
|
if (i.src2.is_constant) {
|
||||||
|
@ -3396,6 +3419,10 @@ EMITTER(DIV_I32, MATCH(I<OPCODE_DIV, I32<>, I32<>, I32<>>)) {
|
||||||
e.idiv(e.ecx);
|
e.idiv(e.ecx);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// Skip if src2 is zero.
|
||||||
|
e.test(i.src2, i.src2);
|
||||||
|
e.jz(skip, CodeGenerator::T_SHORT);
|
||||||
|
|
||||||
if (i.instr->flags & ARITHMETIC_UNSIGNED) {
|
if (i.instr->flags & ARITHMETIC_UNSIGNED) {
|
||||||
if (i.src1.is_constant) {
|
if (i.src1.is_constant) {
|
||||||
e.mov(e.eax, i.src1.constant());
|
e.mov(e.eax, i.src1.constant());
|
||||||
|
@ -3417,6 +3444,9 @@ EMITTER(DIV_I32, MATCH(I<OPCODE_DIV, I32<>, I32<>, I32<>>)) {
|
||||||
e.idiv(i.src2);
|
e.idiv(i.src2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
e.L(skip);
|
||||||
|
e.outLocalLabel();
|
||||||
e.mov(i.dest, e.eax);
|
e.mov(i.dest, e.eax);
|
||||||
if (clobbered_rcx) {
|
if (clobbered_rcx) {
|
||||||
e.ReloadECX();
|
e.ReloadECX();
|
||||||
|
@ -3426,6 +3456,9 @@ EMITTER(DIV_I32, MATCH(I<OPCODE_DIV, I32<>, I32<>, I32<>>)) {
|
||||||
};
|
};
|
||||||
EMITTER(DIV_I64, MATCH(I<OPCODE_DIV, I64<>, I64<>, I64<>>)) {
|
EMITTER(DIV_I64, MATCH(I<OPCODE_DIV, I64<>, I64<>, I64<>>)) {
|
||||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||||
|
Xbyak::Label skip;
|
||||||
|
e.inLocalLabel();
|
||||||
|
|
||||||
// NOTE: RDX clobbered.
|
// NOTE: RDX clobbered.
|
||||||
bool clobbered_rcx = false;
|
bool clobbered_rcx = false;
|
||||||
if (i.src2.is_constant) {
|
if (i.src2.is_constant) {
|
||||||
|
@ -3445,6 +3478,10 @@ EMITTER(DIV_I64, MATCH(I<OPCODE_DIV, I64<>, I64<>, I64<>>)) {
|
||||||
e.idiv(e.rcx);
|
e.idiv(e.rcx);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// Skip if src2 is zero.
|
||||||
|
e.test(i.src2, i.src2);
|
||||||
|
e.jz(skip, CodeGenerator::T_SHORT);
|
||||||
|
|
||||||
if (i.instr->flags & ARITHMETIC_UNSIGNED) {
|
if (i.instr->flags & ARITHMETIC_UNSIGNED) {
|
||||||
if (i.src1.is_constant) {
|
if (i.src1.is_constant) {
|
||||||
e.mov(e.rax, i.src1.constant());
|
e.mov(e.rax, i.src1.constant());
|
||||||
|
@ -3466,6 +3503,9 @@ EMITTER(DIV_I64, MATCH(I<OPCODE_DIV, I64<>, I64<>, I64<>>)) {
|
||||||
e.idiv(i.src2);
|
e.idiv(i.src2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
e.L(skip);
|
||||||
|
e.outLocalLabel();
|
||||||
e.mov(i.dest, e.rax);
|
e.mov(i.dest, e.rax);
|
||||||
if (clobbered_rcx) {
|
if (clobbered_rcx) {
|
||||||
e.ReloadECX();
|
e.ReloadECX();
|
||||||
|
|
Loading…
Reference in New Issue