summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/devices/cpu/drcbearm64.cpp108
-rw-r--r--src/devices/cpu/drcbec.cpp95
-rw-r--r--src/devices/cpu/drcbex64.cpp35
-rw-r--r--src/devices/cpu/drcbex86.cpp19
-rw-r--r--src/devices/cpu/uml.h2
5 files changed, 109 insertions, 150 deletions
diff --git a/src/devices/cpu/drcbearm64.cpp b/src/devices/cpu/drcbearm64.cpp
index a8a679c3d07..b9eee3fd6b8 100644
--- a/src/devices/cpu/drcbearm64.cpp
+++ b/src/devices/cpu/drcbearm64.cpp
@@ -2906,12 +2906,13 @@ void drcbe_arm64::op_carry(a64::Assembler &a, const uml::instruction &inst)
}
else
{
- const a64::Gp shift = bitp.select_register(TEMP_REG2, inst.size());
+ const a64::Gp bitreg = bitp.select_register(TEMP_REG2, inst.size());
+ const a64::Gp shift = select_register(TEMP_REG2, inst.size());
- mov_reg_param(a, inst.size(), shift, bitp);
+ mov_reg_param(a, inst.size(), bitreg, bitp);
mov_reg_param(a, inst.size(), src, srcp);
- a.and_(shift, shift, inst.size() * 8 - 1);
+ a.and_(shift, bitreg, (inst.size() * 8) - 1);
// move carry bit to lsb
a.lsr(scratch, src, shift);
@@ -3135,44 +3136,11 @@ void drcbe_arm64::op_roland(a64::Assembler &a, const uml::instruction &inst)
const a64::Gp output = dstp.select_register(TEMP_REG1, inst.size());
const a64::Gp shift = shiftp.select_register(TEMP_REG2, inst.size());
- const a64::Gp scratch = shiftp.select_register(FUNC_SCRATCH_REG, inst.size());
+ const a64::Gp scratch = select_register(FUNC_SCRATCH_REG, inst.size());
const uint64_t instbits = inst.size() * 8;
- if (maskp.is_immediate() && maskp.is_immediate_value(0))
- {
- // A zero mask will always result in zero so optimize it out
- const a64::Gp zero = select_register(a64::xzr, inst.size());
-
- mov_param_reg(a, inst.size(), dstp, zero);
-
- if (inst.flags())
- {
- a.tst(zero, zero);
- m_carry_state = carry_state::POISON;
- }
-
- return;
- }
-
bool optimized = false;
- if (srcp.is_immediate() && shiftp.is_immediate() && maskp.is_immediate())
- {
- // Optimize all constant inputs into a single mov
- uint64_t result = srcp.immediate();
-
- if (shiftp.immediate() != 0)
- {
- if (inst.size() == 4)
- result = rotl_32(result, shiftp.immediate());
- else
- result = rotl_64(result, shiftp.immediate());
- }
-
- a.mov(output, result & maskp.immediate());
-
- optimized = true;
- }
- else if (maskp.is_immediate() && shiftp.is_immediate() && !maskp.is_immediate_value(util::make_bitmask<uint64_t>(instbits)))
+ if (maskp.is_immediate() && shiftp.is_immediate() && !maskp.is_immediate_value(util::make_bitmask<uint64_t>(instbits)))
{
// A mask of all 1s will be handled efficiently in the unoptimized path, so only optimize for the other cases if possible
const auto pop = population_count_64(maskp.immediate());
@@ -3284,20 +3252,6 @@ void drcbe_arm64::op_rolins(a64::Assembler &a, const uml::instruction &inst)
a64::Gp dst;
- if (maskp.is_immediate() && maskp.is_immediate_value(0))
- {
- // A zero mask means no bits will be inserted so it can be optimized out
- if (inst.flags())
- {
- dst = dstp.select_register(TEMP_REG2, inst.size());
- mov_reg_param(a, inst.size(), dst, dstp);
- a.tst(dst, dst);
- m_carry_state = carry_state::POISON;
- }
-
- return;
- }
-
bool can_use_dst_reg = dstp.is_int_register();
if (can_use_dst_reg && srcp.is_int_register())
can_use_dst_reg = srcp.ireg() != dstp.ireg();
@@ -3307,35 +3261,7 @@ void drcbe_arm64::op_rolins(a64::Assembler &a, const uml::instruction &inst)
can_use_dst_reg = shiftp.ireg() != dstp.ireg();
bool optimized = false;
- if (srcp.is_immediate() && maskp.is_immediate() && shiftp.is_immediate() && maskp.is_immediate_value(util::make_bitmask<uint64_t>(instbits)))
- {
- dst = dstp.select_register(TEMP_REG2, inst.size());
-
- uint64_t result = 0;
- if (inst.size() == 4)
- result = rotl_32(srcp.immediate(), shiftp.immediate());
- else
- result = rotl_64(srcp.immediate(), shiftp.immediate());
-
- a.mov(dst, result);
-
- optimized = true;
- }
- else if (maskp.is_immediate() && shiftp.is_immediate() && maskp.is_immediate_value(util::make_bitmask<uint64_t>(instbits)))
- {
- // a mask of all 1s means that the result of the rol will completely overwrite
- // the output value, so just load the source value into the output register and rol on that
- dst = dstp.select_register(TEMP_REG2, inst.size());
- mov_reg_param(a, inst.size(), dst, srcp);
-
- const auto shift = -int64_t(shiftp.immediate()) & (instbits - 1);
-
- if (shift != 0)
- a.ror(dst, dst, shift);
-
- optimized = true;
- }
- else if (maskp.is_immediate() && shiftp.is_immediate())
+ if (maskp.is_immediate() && shiftp.is_immediate())
{
const auto pop = population_count_64(maskp.immediate());
const auto lz = count_leading_zeros_64(maskp.immediate()) & (instbits - 1);
@@ -3452,7 +3378,7 @@ void drcbe_arm64::op_rolins(a64::Assembler &a, const uml::instruction &inst)
else
{
const a64::Gp shift = shiftp.select_register(SCRATCH_REG2, inst.size());
- const a64::Gp scratch2 = shiftp.select_register(FUNC_SCRATCH_REG, inst.size());
+ const a64::Gp scratch2 = select_register(FUNC_SCRATCH_REG, inst.size());
mov_reg_param(a, inst.size(), shift, shiftp);
a.mov(scratch, inst.size() * 8);
@@ -4087,6 +4013,12 @@ void drcbe_arm64::op_and(a64::Assembler &a, const uml::instruction &inst)
be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
+ if (inst.param(0) == inst.param(2))
+ {
+ using std::swap;
+ swap(src1p, src2p);
+ }
+
const a64::Gp dst = dstp.select_register(TEMP_REG3, inst.size());
const a64::Gp src1 = src1p.select_register(dst, inst.size());
@@ -4194,6 +4126,12 @@ void drcbe_arm64::op_or(a64::Assembler &a, const uml::instruction &inst)
be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
+ if (inst.param(0) == inst.param(2))
+ {
+ using std::swap;
+ swap(src1p, src2p);
+ }
+
const a64::Gp dst = dstp.select_register(TEMP_REG3, inst.size());
const a64::Gp src1 = src1p.select_register(dst, inst.size());
@@ -4235,6 +4173,12 @@ void drcbe_arm64::op_xor(a64::Assembler &a, const uml::instruction &inst)
be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
+ if (inst.param(0) == inst.param(2))
+ {
+ using std::swap;
+ swap(src1p, src2p);
+ }
+
const a64::Gp dst = dstp.select_register(TEMP_REG3, inst.size());
const a64::Gp src1 = src1p.select_register(dst, inst.size());
diff --git a/src/devices/cpu/drcbec.cpp b/src/devices/cpu/drcbec.cpp
index 7b2b9818db2..5ec9a0b94e4 100644
--- a/src/devices/cpu/drcbec.cpp
+++ b/src/devices/cpu/drcbec.cpp
@@ -191,6 +191,11 @@ enum
#define FDPARAM2 (*inst[2].pdouble)
#define FDPARAM3 (*inst[3].pdouble)
+#define SPACEPARAM0 (*inst[0].space)
+#define SPACEPARAM1 (*inst[1].space)
+#define SPACEPARAM2 (*inst[2].space)
+#define SPACEPARAM3 (*inst[3].space)
+
// compute C and V flags for 32-bit add/subtract
#define FLAGS32_C_ADD(a,b) ((uint32_t)~(a) < (uint32_t)(b))
#define FLAGS32_C_SUB(a,b) ((uint32_t)(b) > (uint32_t)(a))
@@ -354,6 +359,7 @@ union drcbec_instruction
int64_t * pint64;
float * pfloat;
double * pdouble;
+ address_space * space;
void (*cfunc)(void *);
drcuml_machine_state *state;
const code_handle * handle;
@@ -614,9 +620,7 @@ void drcbe_c::generate(drcuml_block &block, const instruction *instlist, uint32_
for (int pnum = 0; pnum < inst.numparams(); pnum++)
{
auto const &param = inst.param(pnum);
- if (param.is_mapvar() ||
- (param.is_immediate() && (param.immediate() != 0)) ||
- (param.is_size_space() && (param.space() != 0)))
+ if (param.is_mapvar() || (param.is_immediate() && (param.immediate() != 0)))
{
int const align = (psize[pnum] == 4) ? alignof(uint32_t) : alignof(uint64_t);
int const misalign = immedbytes % align;
@@ -751,7 +755,7 @@ int drcbe_c::execute(code_handle &entry)
case MAKE_OPCODE_SHORT(OP_MAPVAR, 4, 0): // MAPVAR mapvar,value
// these opcodes should be processed at compile-time only
- fatalerror("Unexpected opcode\n");
+ fatalerror("Unexpected opcode %08x %d %d %d\n", opcode, OPCODE_GET_SHORT(opcode) >> 2, BIT(opcode, 0) ? 8 : 4, BIT(opcode, 1));
case MAKE_OPCODE_SHORT(OP_BREAK, 4, 0):
osd_break_into_debugger("break from drc");
@@ -1031,51 +1035,51 @@ int drcbe_c::execute(code_handle &entry)
break;
case MAKE_OPCODE_SHORT(OP_READ1, 4, 0): // READ dst,src1,space_BYTE
- PARAM0 = m_space[PARAM2]->read_byte(PARAM1);
+ PARAM0 = SPACEPARAM2.read_byte(PARAM1);
break;
case MAKE_OPCODE_SHORT(OP_READ2, 4, 0): // READ dst,src1,space_WORD
- PARAM0 = m_space[PARAM2]->read_word(PARAM1);
+ PARAM0 = SPACEPARAM2.read_word(PARAM1);
break;
case MAKE_OPCODE_SHORT(OP_READ4, 4, 0): // READ dst,src1,space_DWORD
- PARAM0 = m_space[PARAM2]->read_dword(PARAM1);
+ PARAM0 = SPACEPARAM2.read_dword(PARAM1);
break;
case MAKE_OPCODE_SHORT(OP_READM1, 4, 0): // READM dst,src1,mask,space_BYTE
- PARAM0 = m_space[PARAM3]->read_byte(PARAM1, PARAM2);
+ PARAM0 = SPACEPARAM3.read_byte(PARAM1, PARAM2);
break;
case MAKE_OPCODE_SHORT(OP_READM2, 4, 0): // READM dst,src1,mask,space_WORD
- PARAM0 = m_space[PARAM3]->read_word(PARAM1, PARAM2);
+ PARAM0 = SPACEPARAM3.read_word(PARAM1, PARAM2);
break;
case MAKE_OPCODE_SHORT(OP_READM4, 4, 0): // READM dst,src1,mask,space_DWORD
- PARAM0 = m_space[PARAM3]->read_dword(PARAM1, PARAM2);
+ PARAM0 = SPACEPARAM3.read_dword(PARAM1, PARAM2);
break;
case MAKE_OPCODE_SHORT(OP_WRITE1, 4, 0): // WRITE dst,src1,space_BYTE
- m_space[PARAM2]->write_byte(PARAM0, PARAM1);
+ SPACEPARAM2.write_byte(PARAM0, PARAM1);
break;
case MAKE_OPCODE_SHORT(OP_WRITE2, 4, 0): // WRITE dst,src1,space_WORD
- m_space[PARAM2]->write_word(PARAM0, PARAM1);
+ SPACEPARAM2.write_word(PARAM0, PARAM1);
break;
case MAKE_OPCODE_SHORT(OP_WRITE4, 4, 0): // WRITE dst,src1,space_DWORD
- m_space[PARAM2]->write_dword(PARAM0, PARAM1);
+ SPACEPARAM2.write_dword(PARAM0, PARAM1);
break;
case MAKE_OPCODE_SHORT(OP_WRITEM1, 4, 0): // WRITEM dst,src1,mask,space_BYTE
- m_space[PARAM3]->write_byte(PARAM0, PARAM1, PARAM2);
+ SPACEPARAM3.write_byte(PARAM0, PARAM1, PARAM2);
break;
case MAKE_OPCODE_SHORT(OP_WRITEM2, 4, 0): // WRITEM dst,src1,mask,space_WORD
- m_space[PARAM3]->write_word(PARAM0, PARAM1, PARAM2);
+ SPACEPARAM3.write_word(PARAM0, PARAM1, PARAM2);
break;
case MAKE_OPCODE_SHORT(OP_WRITEM4, 4, 0): // WRITEM dst,src1,mask,space_DWORD
- m_space[PARAM3]->write_dword(PARAM0, PARAM1, PARAM2);
+ SPACEPARAM3.write_dword(PARAM0, PARAM1, PARAM2);
break;
case MAKE_OPCODE_SHORT(OP_CARRY, 4, 0): // CARRY src,bitnum
@@ -1302,7 +1306,10 @@ int drcbe_c::execute(code_handle &entry)
PARAM0 = temp32;
break;
- case MAKE_OPCODE_SHORT(OP_TEST, 4, 1): // TEST src1,src2[,f]
+ case MAKE_OPCODE_SHORT(OP_TEST, 4, 0): // TEST src1,src2[,f]
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_TEST, 4, 1):
temp32 = PARAM0 & PARAM1;
flags = FLAGS32_NZ(temp32);
break;
@@ -1663,59 +1670,67 @@ int drcbe_c::execute(code_handle &entry)
break;
case MAKE_OPCODE_SHORT(OP_READ1, 8, 0): // DREAD dst,src1,space_BYTE
- DPARAM0 = m_space[PARAM2]->read_byte(PARAM1);
+ DPARAM0 = SPACEPARAM2.read_byte(PARAM1);
break;
case MAKE_OPCODE_SHORT(OP_READ2, 8, 0): // DREAD dst,src1,space_WORD
- DPARAM0 = m_space[PARAM2]->read_word(PARAM1);
+ DPARAM0 = SPACEPARAM2.read_word(PARAM1);
break;
case MAKE_OPCODE_SHORT(OP_READ4, 8, 0): // DREAD dst,src1,space_DWORD
- DPARAM0 = m_space[PARAM2]->read_dword(PARAM1);
+ DPARAM0 = SPACEPARAM2.read_dword(PARAM1);
break;
case MAKE_OPCODE_SHORT(OP_READ8, 8, 0): // DREAD dst,src1,space_QWORD
- DPARAM0 = m_space[PARAM2]->read_qword(PARAM1);
+ DPARAM0 = SPACEPARAM2.read_qword(PARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_READM1, 8, 0): // DREADM dst,src1,mask,space_BYTE
+ DPARAM0 = SPACEPARAM3.read_byte(PARAM1, DPARAM2);
break;
case MAKE_OPCODE_SHORT(OP_READM2, 8, 0): // DREADM dst,src1,mask,space_WORD
- DPARAM0 = m_space[PARAM3]->read_word(PARAM1, DPARAM2);
+ DPARAM0 = SPACEPARAM3.read_word(PARAM1, DPARAM2);
break;
case MAKE_OPCODE_SHORT(OP_READM4, 8, 0): // DREADM dst,src1,mask,space_DWORD
- DPARAM0 = m_space[PARAM3]->read_dword(PARAM1, DPARAM2);
+ DPARAM0 = SPACEPARAM3.read_dword(PARAM1, DPARAM2);
break;
case MAKE_OPCODE_SHORT(OP_READM8, 8, 0): // DREADM dst,src1,mask,space_QWORD
- DPARAM0 = m_space[PARAM3]->read_qword(PARAM1, DPARAM2);
+ DPARAM0 = SPACEPARAM3.read_qword(PARAM1, DPARAM2);
break;
case MAKE_OPCODE_SHORT(OP_WRITE1, 8, 0): // DWRITE dst,src1,space_BYTE
- m_space[PARAM2]->write_byte(PARAM0, PARAM1);
+ SPACEPARAM2.write_byte(PARAM0, PARAM1);
break;
case MAKE_OPCODE_SHORT(OP_WRITE2, 8, 0): // DWRITE dst,src1,space_WORD
- m_space[PARAM2]->write_word(PARAM0, PARAM1);
+ SPACEPARAM2.write_word(PARAM0, PARAM1);
break;
case MAKE_OPCODE_SHORT(OP_WRITE4, 8, 0): // DWRITE dst,src1,space_DWORD
- m_space[PARAM2]->write_dword(PARAM0, PARAM1);
+ SPACEPARAM2.write_dword(PARAM0, PARAM1);
break;
case MAKE_OPCODE_SHORT(OP_WRITE8, 8, 0): // DWRITE dst,src1,space_QWORD
- m_space[PARAM2]->write_qword(PARAM0, DPARAM1);
+ SPACEPARAM2.write_qword(PARAM0, DPARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_WRITEM1, 8, 0): // DWRITEM dst,src1,mask,space_BYTE
+ SPACEPARAM3.write_byte(PARAM0, DPARAM1, DPARAM2);
break;
case MAKE_OPCODE_SHORT(OP_WRITEM2, 8, 0): // DWRITEM dst,src1,mask,space_WORD
- m_space[PARAM3]->write_word(PARAM0, DPARAM1, DPARAM2);
+ SPACEPARAM3.write_word(PARAM0, DPARAM1, DPARAM2);
break;
case MAKE_OPCODE_SHORT(OP_WRITEM4, 8, 0): // DWRITEM dst,src1,mask,space_DWORD
- m_space[PARAM3]->write_dword(PARAM0, DPARAM1, DPARAM2);
+ SPACEPARAM3.write_dword(PARAM0, DPARAM1, DPARAM2);
break;
case MAKE_OPCODE_SHORT(OP_WRITEM8, 8, 0): // DWRITEM dst,src1,mask,space_QWORD
- m_space[PARAM3]->write_qword(PARAM0, DPARAM1, DPARAM2);
+ SPACEPARAM3.write_qword(PARAM0, DPARAM1, DPARAM2);
break;
case MAKE_OPCODE_SHORT(OP_CARRY, 8, 0): // DCARRY src,bitnum
@@ -1920,7 +1935,10 @@ int drcbe_c::execute(code_handle &entry)
DPARAM0 = temp64;
break;
- case MAKE_OPCODE_SHORT(OP_TEST, 8, 1): // DTEST src1,src2[,f]
+ case MAKE_OPCODE_SHORT(OP_TEST, 8, 0): // DTEST src1,src2[,f]
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_TEST, 8, 1):
temp64 = DPARAM0 & DPARAM1;
flags = FLAGS64_NZ(temp64);
break;
@@ -2097,11 +2115,11 @@ int drcbe_c::execute(code_handle &entry)
break;
case MAKE_OPCODE_SHORT(OP_FREAD, 4, 0): // FSREAD dst,src1,space
- PARAM0 = m_space[PARAM2]->read_dword(PARAM1);
+ PARAM0 = SPACEPARAM2.read_dword(PARAM1);
break;
case MAKE_OPCODE_SHORT(OP_FWRITE, 4, 0): // FSWRITE dst,src1,space
- m_space[PARAM2]->write_dword(PARAM0, PARAM1);
+ SPACEPARAM2.write_dword(PARAM0, PARAM1);
break;
case MAKE_OPCODE_SHORT(OP_FMOV, 4, 1): // FSMOV dst,src[,c]
@@ -2240,11 +2258,11 @@ int drcbe_c::execute(code_handle &entry)
break;
case MAKE_OPCODE_SHORT(OP_FREAD, 8, 0): // FDREAD dst,src1,space
- DPARAM0 = m_space[PARAM2]->read_qword(PARAM1);
+ DPARAM0 = SPACEPARAM2.read_qword(PARAM1);
break;
case MAKE_OPCODE_SHORT(OP_FWRITE, 8, 0): // FDWRITE dst,src1,space
- m_space[PARAM2]->write_qword(PARAM0, DPARAM1);
+ SPACEPARAM2.write_qword(PARAM0, DPARAM1);
break;
case MAKE_OPCODE_SHORT(OP_FMOV, 8, 1): // FDMOV dst,src[,c]
@@ -2376,7 +2394,7 @@ int drcbe_c::execute(code_handle &entry)
break;
default:
- fatalerror("Unexpected opcode!\n");
+ fatalerror("Unexpected opcode! %08x %d %d %d\n", opcode, OPCODE_GET_SHORT(opcode) >> 2, BIT(opcode, 0) ? 8 : 4, BIT(opcode, 1));
}
// advance past the parameters and immediates
@@ -2450,7 +2468,8 @@ void drcbe_c::output_parameter(drcbec_instruction **dstptr, void *immed, int imm
// space/size parameters; sizes are built into our opcodes, but space needs to be encoded
case parameter::PTYPE_SIZE_SPACE:
- return output_parameter(dstptr, immed, immoffset, size, param.space());
+ (dst++)->space = m_space[param.space()];
+ break;
// code handle just points to the handle
case parameter::PTYPE_CODE_HANDLE:
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);
}
diff --git a/src/devices/cpu/drcbex86.cpp b/src/devices/cpu/drcbex86.cpp
index 43f4c69b233..e06f92350b2 100644
--- a/src/devices/cpu/drcbex86.cpp
+++ b/src/devices/cpu/drcbex86.cpp
@@ -4633,9 +4633,9 @@ void drcbe_x86::op_rolins(Assembler &a, const instruction &inst)
// pick a target register for the general case
Gp const dstreg = dstp.select_register(ecx, shiftp, maskp);
- // 32-bit form
if (inst.size() == 4)
{
+ // 32-bit form
emit_mov_r32_p32(a, eax, srcp); // mov eax,srcp
shift_op_param(a, Inst::kIdRol, inst.size(), eax, shiftp, // rol eax,shiftp
[inst](Assembler &a, Operand const &dst, be_parameter const &src)
@@ -4662,10 +4662,9 @@ void drcbe_x86::op_rolins(Assembler &a, const instruction &inst)
if (inst.flags())
a.test(dstreg, dstreg);
}
-
- // 64-bit form
else if (inst.size() == 8)
{
+ // 64-bit form
emit_mov_r64_p64(a, eax, edx, srcp); // mov edx:eax,srcp
emit_rol_r64_p64(a, eax, edx, shiftp, inst); // rol edx:eax,shiftp
if (maskp.is_immediate())
@@ -4697,9 +4696,15 @@ void drcbe_x86::op_rolins(Assembler &a, const instruction &inst)
a.not_(ecx); // not ecx
if (dstp.is_int_register())
{
- a.and_(Gpd(dstp.ireg()), ebx); // and dstp.lo,ebx
+ if (dstp.ireg() == Gp::kIdBx)
+ a.and_(ptr(esp, -8), ebx); // and dstp.lo,ebx
+ else
+ a.and_(Gpd(dstp.ireg()), ebx); // and dstp.lo,ebx
a.and_(MABS(m_reghi[dstp.ireg()]), ecx); // and dstp.hi,ecx
- a.or_(Gpd(dstp.ireg()), eax); // or dstp.lo,eax
+ if (dstp.ireg() == Gp::kIdBx)
+ a.or_(ptr(esp, -8), eax); // or dstp.lo,eax
+ else
+ a.or_(Gpd(dstp.ireg()), eax); // or dstp.lo,eax
a.or_(MABS(m_reghi[dstp.ireg()]), edx); // or dstp.hi,edx
}
else
@@ -4710,6 +4715,8 @@ void drcbe_x86::op_rolins(Assembler &a, const instruction &inst)
a.or_(MABS(dstp.memory(4)), edx); // or dstp.hi,edx
}
+ a.mov(ebx, ptr(esp, -8)); // mov ebx,[esp-8]
+
if (inst.flags())
{
if (dstp.is_int_register())
@@ -4726,8 +4733,6 @@ void drcbe_x86::op_rolins(Assembler &a, const instruction &inst)
emit_combine_z_flags(a);
}
-
- a.mov(ebx, ptr(esp, -8)); // mov ebx,[esp-8]
}
}
}
diff --git a/src/devices/cpu/uml.h b/src/devices/cpu/uml.h
index effeb2c22a3..cbc4a82a205 100644
--- a/src/devices/cpu/uml.h
+++ b/src/devices/cpu/uml.h
@@ -298,7 +298,7 @@ namespace uml
constexpr parameter(parameter const &param) : m_type(param.m_type), m_value(param.m_value) { }
constexpr parameter(u64 val) : m_type(PTYPE_IMMEDIATE), m_value(val) { }
parameter(operand_size size, memory_scale scale) : m_type(PTYPE_SIZE_SCALE), m_value((scale << 4) | size) { assert(size >= SIZE_BYTE && size <= SIZE_QWORD); assert(scale >= SCALE_x1 && scale <= SCALE_x8); }
- parameter(operand_size size, memory_space space) : m_type(PTYPE_SIZE_SPACE), m_value((space << 4) | size) { assert(size >= SIZE_BYTE && size <= SIZE_QWORD); assert(space >= SPACE_PROGRAM && space <= SPACE_IO); }
+ parameter(operand_size size, memory_space space) : m_type(PTYPE_SIZE_SPACE), m_value((space << 4) | size) { assert(size >= SIZE_BYTE && size <= SIZE_QWORD); }
parameter(code_handle &handle) : m_type(PTYPE_CODE_HANDLE), m_value(reinterpret_cast<parameter_value>(&handle)) { }
constexpr parameter(code_label const &label) : m_type(PTYPE_CODE_LABEL), m_value(label) { }