UML: Added TZCNT instruction (Trailing Zero Count) [Ville Linde]

This commit is contained in:
Ville Linde 2016-05-20 01:23:22 +03:00
parent 9ce1fbc54f
commit ec1f9b948c
9 changed files with 137 additions and 0 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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
//-------------------------------------------------

View File

@ -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);

View File

@ -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
//-------------------------------------------------

View File

@ -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);

View File

@ -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)

View File

@ -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))

View File

@ -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); }