mirror of
https://github.com/holub/mame
synced 2025-04-21 07:52:35 +03:00
UML: Added TZCNT instruction (Trailing Zero Count) [Ville Linde]
This commit is contained in:
parent
9ce1fbc54f
commit
ec1f9b948c
@ -1070,6 +1070,16 @@ int drcbe_c::execute(code_handle &entry)
|
||||
PARAM0 = temp32;
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_TZCNT, 4, 0): // TZCNT dst,src
|
||||
PARAM0 = tzcount32(PARAM1);
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_TZCNT, 4, 1):
|
||||
temp32 = tzcount32(PARAM1);
|
||||
flags = (temp32 == 32) ? FLAG_Z : 0;
|
||||
PARAM0 = temp32;
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_BSWAP, 4, 0): // BSWAP dst,src
|
||||
temp32 = PARAM1;
|
||||
PARAM0 = FLIPENDIAN_INT32(temp32);
|
||||
@ -1679,6 +1689,16 @@ int drcbe_c::execute(code_handle &entry)
|
||||
DPARAM0 = temp64;
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_TZCNT, 8, 0): // DTZCNT dst,src
|
||||
DPARAM0 = tzcount64(DPARAM1);
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_TZCNT, 8, 1):
|
||||
temp64 = tzcount64(DPARAM1);
|
||||
flags = (temp64 == 64) ? FLAG_Z : 0;
|
||||
DPARAM0 = temp64;
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_BSWAP, 8, 0): // DBSWAP dst,src
|
||||
temp64 = DPARAM1;
|
||||
DPARAM0 = FLIPENDIAN_INT64(temp64);
|
||||
@ -2289,3 +2309,23 @@ int drcbe_c::dmuls(UINT64 &dstlo, UINT64 &dsthi, INT64 src1, INT64 src2, int fla
|
||||
dstlo = lo;
|
||||
return ((hi >> 60) & FLAG_S) | ((dsthi != ((INT64)lo >> 63)) << 1);
|
||||
}
|
||||
|
||||
UINT32 drcbe_c::tzcount32(UINT32 value)
|
||||
{
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
if (value & (1 << i))
|
||||
return i;
|
||||
}
|
||||
return 32;
|
||||
}
|
||||
|
||||
UINT64 drcbe_c::tzcount64(UINT64 value)
|
||||
{
|
||||
for (int i = 0; i < 64; i++)
|
||||
{
|
||||
if (value & ((UINT64)(1) << i))
|
||||
return i;
|
||||
}
|
||||
return 64;
|
||||
}
|
||||
|
@ -44,6 +44,8 @@ private:
|
||||
void fixup_label(void *parameter, drccodeptr labelcodeptr);
|
||||
int dmulu(UINT64 &dstlo, UINT64 &dsthi, UINT64 src1, UINT64 src2, int flags);
|
||||
int dmuls(UINT64 &dstlo, UINT64 &dsthi, INT64 src1, INT64 src2, int flags);
|
||||
UINT32 tzcount32(UINT32 value);
|
||||
UINT64 tzcount64(UINT64 value);
|
||||
|
||||
// internal state
|
||||
drc_hash_table m_hash; // hash table state
|
||||
|
@ -361,6 +361,7 @@ const drcbe_x64::opcode_table_entry drcbe_x64::s_opcode_table_source[] =
|
||||
{ uml::OP_OR, &drcbe_x64::op_or }, // OR dst,src1,src2[,f]
|
||||
{ uml::OP_XOR, &drcbe_x64::op_xor }, // XOR dst,src1,src2[,f]
|
||||
{ uml::OP_LZCNT, &drcbe_x64::op_lzcnt }, // LZCNT dst,src[,f]
|
||||
{ uml::OP_TZCNT, &drcbe_x64::op_tzcnt }, // TZCNT dst,src[,f]
|
||||
{ uml::OP_BSWAP, &drcbe_x64::op_bswap }, // BSWAP dst,src
|
||||
{ uml::OP_SHL, &drcbe_x64::op_shl }, // SHL dst,src,count[,f]
|
||||
{ uml::OP_SHR, &drcbe_x64::op_shr }, // SHR dst,src,count[,f]
|
||||
@ -5360,6 +5361,45 @@ void drcbe_x64::op_lzcnt(x86code *&dst, const instruction &inst)
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// op_tzcnt - process a TZCNT opcode
|
||||
//-------------------------------------------------
|
||||
|
||||
void drcbe_x64::op_tzcnt(x86code *&dst, const instruction &inst)
|
||||
{
|
||||
// validate instruction
|
||||
assert(inst.size() == 4 || inst.size() == 8);
|
||||
assert_no_condition(inst);
|
||||
assert_flags(inst, FLAG_Z | FLAG_S);
|
||||
|
||||
// normalize parameters
|
||||
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
|
||||
be_parameter srcp(*this, inst.param(1), PTYPE_MRI);
|
||||
|
||||
// 32-bit form
|
||||
if (inst.size() == 4)
|
||||
{
|
||||
int dstreg = dstp.select_register(REG_EAX);
|
||||
emit_mov_r32_p32(dst, dstreg, srcp); // mov dstreg,srcp
|
||||
emit_mov_r32_imm(dst, REG_ECX, 32); // mov ecx,32
|
||||
emit_bsf_r32_r32(dst, dstreg, dstreg); // bsf dstreg,dstreg
|
||||
emit_cmovcc_r32_r32(dst, x64emit::COND_Z, dstreg, REG_ECX); // cmovz dstreg,ecx
|
||||
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
|
||||
}
|
||||
|
||||
// 64-bit form
|
||||
else if (inst.size() == 8)
|
||||
{
|
||||
int dstreg = dstp.select_register(REG_RAX);
|
||||
emit_mov_r64_p64(dst, dstreg, srcp); // mov dstreg,srcp
|
||||
emit_mov_r64_imm(dst, REG_RCX, 64); // mov rcx,64
|
||||
emit_bsf_r64_r64(dst, dstreg, dstreg); // bsf dstreg,dstreg
|
||||
emit_cmovcc_r64_r64(dst, x64emit::COND_Z, dstreg, REG_RCX); // cmovz dstreg,rcx
|
||||
emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// op_bswap - process a BSWAP opcode
|
||||
//-------------------------------------------------
|
||||
|
@ -179,6 +179,7 @@ private:
|
||||
void op_or(x86code *&dst, const uml::instruction &inst);
|
||||
void op_xor(x86code *&dst, const uml::instruction &inst);
|
||||
void op_lzcnt(x86code *&dst, const uml::instruction &inst);
|
||||
void op_tzcnt(x86code *&dst, const uml::instruction &inst);
|
||||
void op_bswap(x86code *&dst, const uml::instruction &inst);
|
||||
void op_shl(x86code *&dst, const uml::instruction &inst);
|
||||
void op_shr(x86code *&dst, const uml::instruction &inst);
|
||||
|
@ -243,6 +243,7 @@ const drcbe_x86::opcode_table_entry drcbe_x86::s_opcode_table_source[] =
|
||||
{ uml::OP_OR, &drcbe_x86::op_or }, // OR dst,src1,src2[,f]
|
||||
{ uml::OP_XOR, &drcbe_x86::op_xor }, // XOR dst,src1,src2[,f]
|
||||
{ uml::OP_LZCNT, &drcbe_x86::op_lzcnt }, // LZCNT dst,src[,f]
|
||||
{ uml::OP_TZCNT, &drcbe_x86::op_tzcnt }, // TZCNT dst,src[,f]
|
||||
{ uml::OP_BSWAP, &drcbe_x86::op_bswap }, // BSWAP dst,src
|
||||
{ uml::OP_SHL, &drcbe_x86::op_shl }, // SHL dst,src,count[,f]
|
||||
{ uml::OP_SHR, &drcbe_x86::op_shr }, // SHR dst,src,count[,f]
|
||||
@ -5475,6 +5476,51 @@ void drcbe_x86::op_lzcnt(x86code *&dst, const instruction &inst)
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// op_tzcnt - process a TZCNT opcode
|
||||
//-------------------------------------------------
|
||||
|
||||
void drcbe_x86::op_tzcnt(x86code *&dst, const instruction &inst)
|
||||
{
|
||||
// validate instruction
|
||||
assert(inst.size() == 4 || inst.size() == 8);
|
||||
assert_no_condition(inst);
|
||||
assert_flags(inst, FLAG_Z | FLAG_S);
|
||||
|
||||
// normalize parameters
|
||||
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
|
||||
be_parameter srcp(*this, inst.param(1), PTYPE_MRI);
|
||||
|
||||
int dstreg = dstp.select_register(REG_EAX);
|
||||
|
||||
// 32-bit form
|
||||
if (inst.size() == 4)
|
||||
{
|
||||
emit_mov_r32_p32(dst, dstreg, srcp); // mov dstreg,src1p
|
||||
emit_mov_r32_imm(dst, REG_ECX, 32); // mov ecx,32
|
||||
emit_bsf_r32_r32(dst, dstreg, dstreg); // bsf dstreg,dstreg
|
||||
emit_cmovcc_r32_r32(dst, x86emit::COND_Z, dstreg, REG_ECX); // cmovz dstreg,ecx
|
||||
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
|
||||
}
|
||||
|
||||
// 64-bit form
|
||||
else if (inst.size() == 8)
|
||||
{
|
||||
emit_link skip;
|
||||
emit_mov_r64_p64(dst, REG_EDX, dstreg, srcp); // mov dstreg:edx,srcp
|
||||
emit_bsf_r32_r32(dst, dstreg, dstreg); // bsf dstreg,dstreg
|
||||
emit_jcc_short_link(dst, x86emit::COND_NZ, skip); // jnz skip
|
||||
emit_mov_r32_imm(dst, REG_ECX, 32); // mov ecx,32
|
||||
emit_bsf_r32_r32(dst, dstreg, REG_EDX); // bsf dstreg,edx
|
||||
emit_cmovcc_r32_r32(dst, x86emit::COND_Z, dstreg, REG_ECX); // cmovz dstreg,ecx
|
||||
emit_add_r32_imm(dst, dstreg, 32); // add dstreg,32
|
||||
track_resolve_link(dst, skip); // skip:
|
||||
emit_xor_r32_r32(dst, REG_EDX, REG_EDX); // xor edx,edx
|
||||
emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,edx:dstreg
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// op_bswap - process a BSWAP opcode
|
||||
//-------------------------------------------------
|
||||
|
@ -180,6 +180,7 @@ private:
|
||||
void op_or(x86code *&dst, const uml::instruction &inst);
|
||||
void op_xor(x86code *&dst, const uml::instruction &inst);
|
||||
void op_lzcnt(x86code *&dst, const uml::instruction &inst);
|
||||
void op_tzcnt(x86code *&dst, const uml::instruction &inst);
|
||||
void op_bswap(x86code *&dst, const uml::instruction &inst);
|
||||
void op_shl(x86code *&dst, const uml::instruction &inst);
|
||||
void op_shr(x86code *&dst, const uml::instruction &inst);
|
||||
|
@ -87,6 +87,7 @@
|
||||
#define UML_OR(block, dst, src1, src2) do { block->append()._or(dst, src1, src2); } while (0)
|
||||
#define UML_XOR(block, dst, src1, src2) do { block->append()._xor(dst, src1, src2); } while (0)
|
||||
#define UML_LZCNT(block, dst, src) do { block->append().lzcnt(dst, src); } while (0)
|
||||
#define UML_TZCNT(block, dst, src) do { block->append().tzcnt(dst, src); } while (0)
|
||||
#define UML_BSWAP(block, dst, src) do { block->append().bswap(dst, src); } while (0)
|
||||
#define UML_SHL(block, dst, src, count) do { block->append().shl(dst, src, count); } while (0)
|
||||
#define UML_SHR(block, dst, src, count) do { block->append().shr(dst, src, count); } while (0)
|
||||
@ -126,6 +127,7 @@
|
||||
#define UML_DOR(block, dst, src1, src2) do { block->append().dor(dst, src1, src2); } while (0)
|
||||
#define UML_DXOR(block, dst, src1, src2) do { block->append().dxor(dst, src1, src2); } while (0)
|
||||
#define UML_DLZCNT(block, dst, src) do { block->append().dlzcnt(dst, src); } while (0)
|
||||
#define UML_DTZCNT(block, dst, src) do { block->append().dtzcnt(dst, src); } while (0)
|
||||
#define UML_DBSWAP(block, dst, src) do { block->append().dbswap(dst, src); } while (0)
|
||||
#define UML_DSHL(block, dst, src, count) do { block->append().dshl(dst, src, count); } while (0)
|
||||
#define UML_DSHR(block, dst, src, count) do { block->append().dshr(dst, src, count); } while (0)
|
||||
|
@ -55,6 +55,7 @@ using namespace uml;
|
||||
// opcode validation condition/flag valid bitmasks
|
||||
#define OPFLAGS_NONE 0x00
|
||||
#define OPFLAGS_C FLAG_C
|
||||
#define OPFLAGS_Z FLAG_Z
|
||||
#define OPFLAGS_SZ (FLAG_S | FLAG_Z)
|
||||
#define OPFLAGS_SZC (FLAG_S | FLAG_Z | FLAG_C)
|
||||
#define OPFLAGS_SZV (FLAG_S | FLAG_Z | FLAG_V)
|
||||
@ -182,6 +183,7 @@ const opcode_info instruction::s_opcode_info_table[OP_MAX] =
|
||||
OPINFO3(OR, "!or", 4|8, false, NONE, SZ, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
|
||||
OPINFO3(XOR, "!xor", 4|8, false, NONE, SZ, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
|
||||
OPINFO2(LZCNT, "!lzcnt", 4|8, false, NONE, SZ, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY))
|
||||
OPINFO2(TZCNT, "!tzcnt", 4|8, false, NONE, SZ, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY))
|
||||
OPINFO2(BSWAP, "!bswap", 4|8, false, NONE, SZ, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY))
|
||||
OPINFO3(SHL, "!shl", 4|8, false, NONE, SZC, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
|
||||
OPINFO3(SHR, "!shr", 4|8, false, NONE, SZC, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
|
||||
|
@ -189,6 +189,7 @@ namespace uml
|
||||
OP_OR, // OR dst,src1,src2[,f]
|
||||
OP_XOR, // XOR dst,src1,src2[,f]
|
||||
OP_LZCNT, // LZCNT dst,src
|
||||
OP_TZCNT, // TZCNT dst,src
|
||||
OP_BSWAP, // BSWAP dst,src
|
||||
OP_SHL, // SHL dst,src,count[,f]
|
||||
OP_SHR, // SHR dst,src,count[,f]
|
||||
@ -479,6 +480,7 @@ namespace uml
|
||||
void _or(parameter dst, parameter src1, parameter src2) { configure(OP_OR, 4, dst, src1, src2); }
|
||||
void _xor(parameter dst, parameter src1, parameter src2) { configure(OP_XOR, 4, dst, src1, src2); }
|
||||
void lzcnt(parameter dst, parameter src) { configure(OP_LZCNT, 4, dst, src); }
|
||||
void tzcnt(parameter dst, parameter src) { configure(OP_TZCNT, 4, dst, src); }
|
||||
void bswap(parameter dst, parameter src) { configure(OP_BSWAP, 4, dst, src); }
|
||||
void shl(parameter dst, parameter src, parameter count) { configure(OP_SHL, 4, dst, src, count); }
|
||||
void shr(parameter dst, parameter src, parameter count) { configure(OP_SHR, 4, dst, src, count); }
|
||||
@ -517,6 +519,7 @@ namespace uml
|
||||
void dor(parameter dst, parameter src1, parameter src2) { configure(OP_OR, 8, dst, src1, src2); }
|
||||
void dxor(parameter dst, parameter src1, parameter src2) { configure(OP_XOR, 8, dst, src1, src2); }
|
||||
void dlzcnt(parameter dst, parameter src) { configure(OP_LZCNT, 8, dst, src); }
|
||||
void dtzcnt(parameter dst, parameter src) { configure(OP_TZCNT, 8, dst, src); }
|
||||
void dbswap(parameter dst, parameter src) { configure(OP_BSWAP, 8, dst, src); }
|
||||
void dshl(parameter dst, parameter src, parameter count) { configure(OP_SHL, 8, dst, src, count); }
|
||||
void dshr(parameter dst, parameter src, parameter count) { configure(OP_SHR, 8, dst, src, count); }
|
||||
|
Loading…
Reference in New Issue
Block a user