summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/drcbex64.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/drcbex64.cpp')
-rw-r--r--src/devices/cpu/drcbex64.cpp35
1 files changed, 13 insertions, 22 deletions
diff --git a/src/devices/cpu/drcbex64.cpp b/src/devices/cpu/drcbex64.cpp
index 6124b6cd57a..7c8a8003644 100644
--- a/src/devices/cpu/drcbex64.cpp
+++ b/src/devices/cpu/drcbex64.cpp
@@ -1546,6 +1546,7 @@ void drcbe_x64::calculate_status_flags_mul_low(Assembler &a, uint32_t instsize,
void drcbe_x64::shift_op_param(Assembler &a, Inst::Id const opcode, size_t opsize, Operand const &dst, be_parameter const &param, u8 update_flags)
{
+ // caller must place non-immediate shift in ECX
// FIXME: upper bits may not be cleared for 32-bit form when shift count is zero
const bool carryin = (opcode == Inst::kIdRcl) || (opcode == Inst::kIdRcr);
@@ -1576,12 +1577,7 @@ void drcbe_x64::shift_op_param(Assembler &a, Inst::Id const opcode, size_t opsiz
const Gp shift = ecx;
if (carryin)
- {
- a.mov(r10, rax);
- a.lahf();
- }
-
- mov_reg_param(a, shift, param);
+ a.set(CondCode::kC, r10b);
a.and_(shift, (opsize * 8) - 1);
@@ -1593,14 +1589,9 @@ void drcbe_x64::shift_op_param(Assembler &a, Inst::Id const opcode, size_t opsiz
a.short_().jnz(calc);
if (carryin)
- {
- a.sahf(); // restore flags to keep carry in for rolc/rorc
- a.mov(rax, r10);
- }
+ a.shr(r10b, 1); // restore carry for rolc/rorc
else if (update_flags & FLAG_C)
- {
a.clc(); // throw away carry since it'll never be used
- }
a.short_().jmp(end);
@@ -1608,10 +1599,7 @@ void drcbe_x64::shift_op_param(Assembler &a, Inst::Id const opcode, size_t opsiz
}
if (carryin)
- {
- a.sahf(); // restore flags to keep carry in for rolc/rorc
- a.mov(rax, r10);
- }
+ a.shr(r10b, 1); // restore carry for rolc/rorc
a.emit(opcode, dst, cl);
@@ -1630,7 +1618,6 @@ void drcbe_x64::shift_op_param(Assembler &a, Inst::Id const opcode, size_t opsiz
}
else
{
- mov_reg_param(a, ecx, param);
a.emit(opcode, dst, cl);
}
}
@@ -4108,6 +4095,8 @@ void drcbe_x64::op_rolins(Assembler &a, const instruction &inst)
if (!maskimm)
mov_reg_param(a, maskreg, maskp);
+ if (!shiftp.is_immediate())
+ mov_reg_param(a, ecx, shiftp);
shift_op_param(a, Inst::kIdRol, inst.size(), srcreg, shiftp, 0);
mov_reg_param(a, dstreg, dstp);
@@ -5010,19 +4999,21 @@ void drcbe_x64::op_shift(Assembler &a, const uml::instruction &inst)
if (dstp.is_memory() && ((inst.size() == 8) || !dstp.is_cold_register()) && (dstp == src1p))
{
// dstp == src1p in memory
+ if (!src2p.is_immediate())
+ mov_reg_param(a, ecx, src2p, carryin);
shift_op_param(a, Opcode, inst.size(), MABS(dstp.memory(), inst.size()), src2p, inst.flags());
}
else
{
// general case
+ if (!src2p.is_immediate())
+ mov_reg_param(a, ecx, src2p, carryin); // do this first as shift and dst may be the same register
+
// pick a target register
- const Gp dstreg = dstp.select_register((inst.size() == 4) ? Gp(eax) : Gp(rax), src2p);
+ const Gp dstreg = dstp.select_register((inst.size() == 4) ? Gp(eax) : Gp(rax));
+ mov_reg_param(a, dstreg, src1p, carryin);
- if (carryin)
- mov_reg_param(a, dstreg, src1p, true);
- else
- mov_reg_param(a, dstreg, src1p);
shift_op_param(a, Opcode, inst.size(), dstreg, src2p, inst.flags());
mov_param_reg(a, dstp, dstreg);
}