Browse Source

[video_core] Restrict macro JIT zero-register skips

Only apply the zero-register ALU skip when the operation is safe to elide without changing carry/result semantics.

This avoids invalid-instruction floods seen with Macro JIT enabled while keeping the optimization for operations where a zero source is harmless.
xbzk/hb-tico-support-part-2
xbzk 6 days ago
parent
commit
8ab9521cea
  1. 24
      src/video_core/macro.cpp

24
src/video_core/macro.cpp

@ -782,13 +782,17 @@ void MacroJITx64Impl::Compile_ALU(Core::System& system, Macro::Opcode opcode) {
const bool valid_operation = !is_a_zero && !is_b_zero; const bool valid_operation = !is_a_zero && !is_b_zero;
[[maybe_unused]] const bool is_move_operation = !is_a_zero && is_b_zero; [[maybe_unused]] const bool is_move_operation = !is_a_zero && is_b_zero;
const bool has_zero_register = is_a_zero || is_b_zero; const bool has_zero_register = is_a_zero || is_b_zero;
const bool no_zero_reg_skip = opcode.alu_operation == Macro::ALUOperation::AddWithCarry ||
opcode.alu_operation == Macro::ALUOperation::SubtractWithBorrow;
const bool zero_reg_skip =
optimizer.zero_reg_skip && !is_a_zero && is_b_zero &&
(opcode.alu_operation == Macro::ALUOperation::Xor ||
opcode.alu_operation == Macro::ALUOperation::Or ||
(optimizer.can_skip_carry && (opcode.alu_operation == Macro::ALUOperation::Add ||
opcode.alu_operation == Macro::ALUOperation::Subtract)));
Xbyak::Reg32 src_a; Xbyak::Reg32 src_a;
Xbyak::Reg32 src_b; Xbyak::Reg32 src_b;
if (!optimizer.zero_reg_skip || no_zero_reg_skip) {
if (!zero_reg_skip) {
src_a = Compile_GetRegister(opcode.src_a, RESULT); src_a = Compile_GetRegister(opcode.src_a, RESULT);
src_b = Compile_GetRegister(opcode.src_b, eax); src_b = Compile_GetRegister(opcode.src_b, eax);
} else { } else {
@ -804,7 +808,7 @@ void MacroJITx64Impl::Compile_ALU(Core::System& system, Macro::Opcode opcode) {
switch (opcode.alu_operation) { switch (opcode.alu_operation) {
case Macro::ALUOperation::Add: case Macro::ALUOperation::Add:
if (optimizer.zero_reg_skip) {
if (zero_reg_skip) {
if (valid_operation) { if (valid_operation) {
add(src_a, src_b); add(src_a, src_b);
} }
@ -822,7 +826,7 @@ void MacroJITx64Impl::Compile_ALU(Core::System& system, Macro::Opcode opcode) {
setc(byte[STATE + offsetof(JITState, carry_flag)]); setc(byte[STATE + offsetof(JITState, carry_flag)]);
break; break;
case Macro::ALUOperation::Subtract: case Macro::ALUOperation::Subtract:
if (optimizer.zero_reg_skip) {
if (zero_reg_skip) {
if (valid_operation) { if (valid_operation) {
sub(src_a, src_b); sub(src_a, src_b);
has_emitted = true; has_emitted = true;
@ -841,7 +845,7 @@ void MacroJITx64Impl::Compile_ALU(Core::System& system, Macro::Opcode opcode) {
setc(byte[STATE + offsetof(JITState, carry_flag)]); setc(byte[STATE + offsetof(JITState, carry_flag)]);
break; break;
case Macro::ALUOperation::Xor: case Macro::ALUOperation::Xor:
if (optimizer.zero_reg_skip) {
if (zero_reg_skip) {
if (valid_operation) { if (valid_operation) {
xor_(src_a, src_b); xor_(src_a, src_b);
} }
@ -850,7 +854,7 @@ void MacroJITx64Impl::Compile_ALU(Core::System& system, Macro::Opcode opcode) {
} }
break; break;
case Macro::ALUOperation::Or: case Macro::ALUOperation::Or:
if (optimizer.zero_reg_skip) {
if (zero_reg_skip) {
if (valid_operation) { if (valid_operation) {
or_(src_a, src_b); or_(src_a, src_b);
} }
@ -859,7 +863,7 @@ void MacroJITx64Impl::Compile_ALU(Core::System& system, Macro::Opcode opcode) {
} }
break; break;
case Macro::ALUOperation::And: case Macro::ALUOperation::And:
if (optimizer.zero_reg_skip) {
if (zero_reg_skip) {
if (!has_zero_register) { if (!has_zero_register) {
and_(src_a, src_b); and_(src_a, src_b);
} }
@ -868,7 +872,7 @@ void MacroJITx64Impl::Compile_ALU(Core::System& system, Macro::Opcode opcode) {
} }
break; break;
case Macro::ALUOperation::AndNot: case Macro::ALUOperation::AndNot:
if (optimizer.zero_reg_skip) {
if (zero_reg_skip) {
if (!is_a_zero) { if (!is_a_zero) {
not_(src_b); not_(src_b);
and_(src_a, src_b); and_(src_a, src_b);
@ -879,7 +883,7 @@ void MacroJITx64Impl::Compile_ALU(Core::System& system, Macro::Opcode opcode) {
} }
break; break;
case Macro::ALUOperation::Nand: case Macro::ALUOperation::Nand:
if (optimizer.zero_reg_skip) {
if (zero_reg_skip) {
if (!is_a_zero) { if (!is_a_zero) {
and_(src_a, src_b); and_(src_a, src_b);
not_(src_a); not_(src_a);

Loading…
Cancel
Save