diff options
author | 2025-04-03 02:40:43 +1100 | |
---|---|---|
committer | 2025-04-03 02:40:43 +1100 | |
commit | 436431d99b4f2d8a502fd4fc911830ac0d237db5 (patch) | |
tree | 145b752c16ac0ad2c217162da4e21d10e1bc385c /src/devices/cpu/drcbex64.cpp | |
parent | 9349b16a17d6395e301c719af14b4428fee73421 (diff) |
-cpu/e132xs: Miscellaneous fixes/optimisation:
* Fixed behaviour of delayed branches, trace exceptions, and saved PC
calculation for error exceptions in delay slots for the interpreter.
All instructions in delay slots, branching instructions that can raise
exceptions and tracing shoud now (mis)behave properly for the
interpreter, including things the manual says you shouldn't do.
* Fixed and optimised flag updates for left shifts for the recompiler.
* Optimised ROL instruction for the recompiler and made flag calculation
equivalent to the interpreter both with and without the "Missioncraft
flags" compile-time option.
* Only block interrupts for one instruction following a delayed branch.
* Optimised the SOFTWARE instruction a little for the recompiler.
* Added more SDRAM configuration logging and cleaned up code a bit.
-cpu/drcbearm64.cpp: Apply the change from 7efe37938f9dd6a366e to OR and
XOR instructions as well, and fix some cases where a 32-bit logical
operation would fail to clear the upper bits of a register.
-cpu/drcbex64.cpp: Avoid more conditional branches on conditional MOV.
Diffstat (limited to 'src/devices/cpu/drcbex64.cpp')
-rw-r--r-- | src/devices/cpu/drcbex64.cpp | 43 |
1 files changed, 28 insertions, 15 deletions
diff --git a/src/devices/cpu/drcbex64.cpp b/src/devices/cpu/drcbex64.cpp index 45d442e8576..f95a3700804 100644 --- a/src/devices/cpu/drcbex64.cpp +++ b/src/devices/cpu/drcbex64.cpp @@ -3661,26 +3661,28 @@ void drcbe_x64::op_mov(Assembler &a, const instruction &inst) // add a conditional branch unless a conditional move is possible Label skip; - if (inst.condition() != uml::COND_ALWAYS && !(dstp.is_int_register() && !srcp.is_immediate())) + const bool need_skip = (inst.condition() != uml::COND_ALWAYS) && !dstp.is_int_register(); + if (need_skip) { skip = a.newLabel(); a.short_().j(X86_NOT_CONDITION(inst.condition()), skip); } - // register to memory if (dstp.is_memory() && srcp.is_int_register()) { + // register to memory Gp const src = Gp::fromTypeAndId((inst.size() == 4) ? RegType::kX86_Gpd : RegType::kX86_Gpq, srcp.ireg()); a.mov(MABS(dstp.memory()), src); } - // immediate to memory else if (dstp.is_memory() && srcp.is_immediate() && short_immediate(srcp.immediate())) + { + // immediate to memory a.mov(MABS(dstp.memory(), inst.size()), s32(srcp.immediate())); - - // conditional memory to register + } else if (dstp.is_int_register() && srcp.is_memory()) { + // conditional memory to register Gp const dst = Gp::fromTypeAndId((inst.size() == 4) ? RegType::kX86_Gpd : RegType::kX86_Gpq, dstp.ireg()); if (inst.condition() != uml::COND_ALWAYS) @@ -3688,30 +3690,41 @@ void drcbe_x64::op_mov(Assembler &a, const instruction &inst) else a.mov(dst, MABS(srcp.memory())); } - - // conditional register to register - else if (dstp.is_int_register() && srcp.is_int_register()) + else if (dstp.is_int_register()) { - Gp const src = Gp::fromTypeAndId((inst.size() == 4) ? RegType::kX86_Gpd : RegType::kX86_Gpq, srcp.ireg()); + // conditional register to register Gp const dst = Gp::fromTypeAndId((inst.size() == 4) ? RegType::kX86_Gpd : RegType::kX86_Gpq, dstp.ireg()); if (inst.condition() != uml::COND_ALWAYS) - a.cmov(X86_CONDITION(inst.condition()), dst, src); + { + if (srcp.is_int_register()) + { + Gp const src = Gp::fromTypeAndId((inst.size() == 4) ? RegType::kX86_Gpd : RegType::kX86_Gpq, srcp.ireg()); + a.cmov(X86_CONDITION(inst.condition()), dst, src); + } + else + { + Gp const src = (inst.size() == 4) ? Gp(eax) : Gp(rax); + mov_reg_param(a, src, srcp, true); + a.cmov(X86_CONDITION(inst.condition()), dst, src); + } + } else - a.mov(dst, src); + { + mov_reg_param(a, dst, srcp, true); + } } - - // general case else { - Gp dstreg = (inst.size() == 4) ? dstp.select_register(eax) : dstp.select_register(rax); + // general case + Gp const dstreg = (inst.size() == 4) ? dstp.select_register(eax) : dstp.select_register(rax); mov_reg_param(a, dstreg, srcp, true); mov_param_reg(a, dstp, dstreg); } // resolve the jump - if (inst.condition() != uml::COND_ALWAYS && !(dstp.is_int_register() && !srcp.is_immediate())) + if (need_skip) a.bind(skip); } |