diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/devices/cpu/drcbearm64.cpp | 108 | ||||
-rw-r--r-- | src/devices/cpu/drcbec.cpp | 95 | ||||
-rw-r--r-- | src/devices/cpu/drcbex64.cpp | 35 | ||||
-rw-r--r-- | src/devices/cpu/drcbex86.cpp | 19 | ||||
-rw-r--r-- | src/devices/cpu/uml.h | 2 |
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 ¶m = 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 ¶m, 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 ¶m) : 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) { } |