mirror of
https://github.com/holub/mame
synced 2025-06-05 20:33:45 +03:00
Even more recompiler fixes:
* cpu/drcbearm64.cpp: Fixed ROLAND, ROLINS and CARRY clobbering the shift input when it's a a register. * cpu/drcbex86.cpp: Fixed DROLINS clobbering source in I0 and miscalculating flags when destination is I0. * cpu/uml.h: Removed assertion that's no longer valid. * cpu/drcbearm64.cpp: Added minimal operand swizzling to allow AND, OR and XOR to work without the simplifier. * cpu/drcbex64.cpp: Optimised shift operations slightly. * cpu/drcbec.cpp: Added stub implementations for TEST with no flag outputs to allow running with simplifier disabled. * cpu/drcbec.cpp: Implemented DREADM/DWRITEM with byte size access. * cpu/drcbec.cpp: Store pointer to address space directly in instruction stream. * cpu/drcbearm64.cpp: Removed some special cases for situations the simplifier deals with for ROLAND and ROLINS. * cpu/drcbec.cpp: Added some actual detail to error messages on encountering unexpected instructions.
This commit is contained in:
parent
9fd9257ac5
commit
5785f30e7f
@ -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());
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
||||
// pick a target register
|
||||
const Gp dstreg = dstp.select_register((inst.size() == 4) ? Gp(eax) : Gp(rax), src2p);
|
||||
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));
|
||||
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);
|
||||
}
|
||||
|
@ -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]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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) { }
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user