Skip to content

Commit da3fb7b

Browse files
committed
Add a few missing instructions/tests
1 parent 9d766af commit da3fb7b

36 files changed

Lines changed: 1736 additions & 31 deletions

File tree

include/remill/Arch/Runtime/HyperCall.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ class SyncHyperCall {
3232
kX86ReadTSCP,
3333
kX86LoadGlobalDescriptorTable,
3434
kX86LoadInterruptDescriptorTable,
35+
kX86LoadAccessRights,
36+
kX86VerifySegmentReadable,
3537
kX86ReadModelSpecificRegister,
3638
kX86WriteModelSpecificRegister,
3739
kX86WriteBackInvalidate,

lib/Arch/Runtime/HyperCall.cpp

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ Memory *__remill_sync_hyper_call(State &state, Memory *mem,
7878

7979
case SyncHyperCall::kX86ReadTSC:
8080
asm volatile("rdtsc"
81-
: "=a"(state.gpr.rax.dword), "=d"(state.gpr.rdx.dword));
81+
: "=a"(state.gpr.rax.aword), "=d"(state.gpr.rdx.aword));
8282
break;
8383

8484
case SyncHyperCall::kX86ReadTSCP:
@@ -113,6 +113,38 @@ Memory *__remill_sync_hyper_call(State &state, Memory *mem,
113113
break;
114114
}
115115

116+
case SyncHyperCall::kX86LoadAccessRights: {
117+
const auto selector = static_cast<uint16_t>(state.addr_to_load);
118+
uint8_t zf = 0;
119+
#if REMILL_HYPERCALL_X86
120+
uint32_t result = 0;
121+
#else
122+
uint64_t result = 0;
123+
#endif
124+
asm volatile("lar %[src], %[dst] \n\t"
125+
"setz %[zf]"
126+
: [dst] "=r"(result), [zf] "=qm"(zf)
127+
: [src] "rm"(selector)
128+
: "cc");
129+
state.addr_to_store = result;
130+
state.rflag.zf = zf;
131+
state.aflag.zf = zf;
132+
break;
133+
}
134+
135+
case SyncHyperCall::kX86VerifySegmentReadable: {
136+
const auto selector = static_cast<uint16_t>(state.addr_to_load);
137+
uint8_t zf = 0;
138+
asm volatile("verr %[src] \n\t"
139+
"setz %[zf]"
140+
: [zf] "=qm"(zf)
141+
: [src] "rm"(selector)
142+
: "cc");
143+
state.rflag.zf = zf;
144+
state.aflag.zf = zf;
145+
break;
146+
}
147+
116148
case SyncHyperCall::kX86ReadModelSpecificRegister:
117149
asm volatile("rdmsr"
118150
: "=c"(state.gpr.rcx.dword)

lib/Arch/X86/Semantics/BINARY.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,8 +402,12 @@ IF_64BIT(DEF_ISEL(MUL_GPRv_64) = MULrax<R64>;)
402402

403403
DEF_ISEL(MULX_GPR32d_GPR32d_GPR32d) = MULX<R32W, R32>;
404404
DEF_ISEL(MULX_GPR32d_GPR32d_MEMd) = MULX<R32W, M32>;
405+
DEF_ISEL(MULX_VGPR32d_VGPR32d_VGPR32d) = MULX<R32W, R32>;
406+
DEF_ISEL(MULX_VGPR32d_VGPR32d_MEMd) = MULX<R32W, M32>;
405407
IF_64BIT(DEF_ISEL(MULX_GPR64q_GPR64q_GPR64q) = MULX<R64W, R64>;)
406408
IF_64BIT(DEF_ISEL(MULX_GPR64q_GPR64q_MEMq) = MULX<R64W, M64>;)
409+
IF_64BIT(DEF_ISEL(MULX_VGPR64q_VGPR64q_VGPR64q) = MULX<R64W, R64>;)
410+
IF_64BIT(DEF_ISEL(MULX_VGPR64q_VGPR64q_MEMq) = MULX<R64W, M64>;)
407411

408412
DEF_ISEL(MULPS_XMMps_MEMps) = MULPS<V128W, V128, MV128>;
409413
DEF_ISEL(MULPS_XMMps_XMMps) = MULPS<V128W, V128, V128>;

lib/Arch/X86/Semantics/BITBYTE.cpp

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ DEF_ISEL(SETP_MEMb) = SETP<M8W>;
123123
DEF_ISEL(SETP_GPR8) = SETP<R8W>;
124124
DEF_ISEL(SETZ_MEMb) = SETZ<M8W>;
125125
DEF_ISEL(SETZ_GPR8) = SETZ<R8W>;
126+
DEF_ISEL(SETE_MEMb) = SETZ<M8W>;
127+
DEF_ISEL(SETE_GPR8) = SETZ<R8W>;
126128
DEF_ISEL(SETS_MEMb) = SETS<M8W>;
127129
DEF_ISEL(SETS_GPR8) = SETS<R8W>;
128130
DEF_ISEL(SETNO_MEMb) = SETNO<M8W>;
@@ -323,6 +325,159 @@ DEF_SEM(LZCNT, D dst, S src) {
323325
return memory;
324326
}
325327

328+
template <typename T>
329+
ALWAYS_INLINE static T LowBitMask(T count, T bit_size) {
330+
if (UCmpEq(count, 0)) {
331+
return Literal<T>(0);
332+
}
333+
if (!UCmpLt(count, bit_size)) {
334+
return Maximize(Literal<T>(0));
335+
}
336+
return USub(UShl(Literal<T>(1), count), Literal<T>(1));
337+
}
338+
339+
template <typename T>
340+
ALWAYS_INLINE static T PopulationCount(T val) {
341+
auto count = Literal<T>(0);
342+
for (unsigned i = 0; i < (sizeof(T) * 8U); ++i) {
343+
count = UAdd(count, UAnd(UShr(val, Literal<T>(i)), Literal<T>(1)));
344+
}
345+
return count;
346+
}
347+
348+
ALWAYS_INLINE static uint32_t CRC32Byte(uint32_t crc, uint8_t byte) {
349+
crc = UXor(crc, ZExtTo<uint32_t>(byte));
350+
for (unsigned i = 0; i < 8U; ++i) {
351+
auto low_bit_set = UCmpNeq(UAnd(crc, Literal<uint32_t>(1)), 0U);
352+
crc = UShr(crc, 1U);
353+
crc = Select(low_bit_set, UXor(crc, Literal<uint32_t>(0x82F63B78U)), crc);
354+
}
355+
return crc;
356+
}
357+
358+
template <typename T>
359+
ALWAYS_INLINE static uint32_t CRC32Value(uint32_t crc, T val) {
360+
for (unsigned i = 0; i < sizeof(T); ++i) {
361+
crc = CRC32Byte(crc,
362+
TruncTo<uint8_t>(UShr(val, Literal<T>(i * 8U))));
363+
}
364+
return crc;
365+
}
366+
367+
template <typename D, typename S1, typename S2>
368+
DEF_SEM(BEXTR, D dst, S1 src1, S2 src2) {
369+
auto val = Read(src1);
370+
auto control = Read(src2);
371+
auto bit_size = BitSizeOf(src1);
372+
auto start = ZExtTo<S1>(TruncTo<uint8_t>(control));
373+
auto length =
374+
ZExtTo<S1>(TruncTo<uint8_t>(UShr(control, Literal<decltype(control)>(8))));
375+
auto res = Literal<S1>(0);
376+
377+
if (UCmpLt(start, bit_size) && UCmpNeq(length, 0)) {
378+
auto avail = USub(bit_size, start);
379+
auto use_len = Select(UCmpLt(avail, length), avail, length);
380+
auto mask = LowBitMask(use_len, bit_size);
381+
res = UAnd(UShr(val, start), mask);
382+
}
383+
384+
WriteZExt(dst, res);
385+
Write(FLAG_CF, false);
386+
Write(FLAG_OF, false);
387+
Write(FLAG_ZF, ZeroFlag(res));
388+
Write(FLAG_SF, false);
389+
UndefFlag(af);
390+
UndefFlag(pf);
391+
return memory;
392+
}
393+
394+
template <typename D, typename S1, typename S2>
395+
DEF_SEM(BZHI, D dst, S1 src1, S2 src2) {
396+
auto val = Read(src1);
397+
auto count = ZExtTo<S1>(TruncTo<uint8_t>(Read(src2)));
398+
auto bit_size = BitSizeOf(src1);
399+
auto out_of_range = !UCmpLt(count, bit_size);
400+
auto mask = LowBitMask(count, bit_size);
401+
auto res = Select(out_of_range, val, UAnd(val, mask));
402+
403+
WriteZExt(dst, res);
404+
Write(FLAG_CF, out_of_range);
405+
Write(FLAG_OF, false);
406+
Write(FLAG_ZF, ZeroFlag(res));
407+
Write(FLAG_SF, SignFlag(res));
408+
UndefFlag(af);
409+
UndefFlag(pf);
410+
return memory;
411+
}
412+
413+
template <typename D, typename S>
414+
DEF_SEM(POPCNT, D dst, S src) {
415+
auto val = Read(src);
416+
auto count = PopulationCount(val);
417+
WriteZExt(dst, count);
418+
Write(FLAG_CF, false);
419+
Write(FLAG_PF, false);
420+
Write(FLAG_AF, false);
421+
Write(FLAG_ZF, ZeroFlag(val));
422+
Write(FLAG_SF, false);
423+
Write(FLAG_OF, false);
424+
return memory;
425+
}
426+
427+
template <typename D, typename S1, typename S2>
428+
DEF_SEM(PDEP, D dst, S1 src1, S2 src2) {
429+
auto src = Read(src1);
430+
auto mask = Read(src2);
431+
auto res = Literal<S1>(0);
432+
unsigned src_index = 0;
433+
434+
for (unsigned i = 0; i < (sizeof(decltype(src)) * 8U); ++i) {
435+
auto mask_bit = UShl(Literal<S1>(1), Literal<decltype(src)>(i));
436+
if (UCmpNeq(UAnd(mask, mask_bit), 0)) {
437+
auto src_bit =
438+
UAnd(UShr(src, Literal<decltype(src)>(src_index)), Literal<S1>(1));
439+
if (UCmpNeq(src_bit, 0)) {
440+
res = UOr(res, mask_bit);
441+
}
442+
++src_index;
443+
}
444+
}
445+
446+
WriteZExt(dst, res);
447+
return memory;
448+
}
449+
450+
template <typename D, typename S1, typename S2>
451+
DEF_SEM(PEXT, D dst, S1 src1, S2 src2) {
452+
auto src = Read(src1);
453+
auto mask = Read(src2);
454+
auto res = Literal<S1>(0);
455+
unsigned dst_index = 0;
456+
457+
for (unsigned i = 0; i < (sizeof(decltype(src)) * 8U); ++i) {
458+
auto mask_bit = UShl(Literal<S1>(1), Literal<decltype(src)>(i));
459+
if (UCmpNeq(UAnd(mask, mask_bit), 0)) {
460+
auto src_bit = UAnd(UShr(src, Literal<decltype(src)>(i)), Literal<S1>(1));
461+
if (UCmpNeq(src_bit, 0)) {
462+
res = UOr(res, UShl(Literal<S1>(1), Literal<decltype(src)>(dst_index)));
463+
}
464+
++dst_index;
465+
}
466+
}
467+
468+
WriteZExt(dst, res);
469+
return memory;
470+
}
471+
472+
template <typename D, typename S1, typename S2>
473+
DEF_SEM(CRC32, D dst, S1 src1, S2 src2) {
474+
auto seed = TruncTo<uint32_t>(Read(src1));
475+
auto val = Read(src2);
476+
auto crc = CRC32Value(seed, val);
477+
WriteZExt(dst, crc);
478+
return memory;
479+
}
480+
326481
} // namespace
327482

328483
DEF_ISEL(BSWAP_GPRv_16) = BSWAP_16;
@@ -335,6 +490,40 @@ DEF_ISEL_RnW_Rn(TZCNT_GPRv_GPRv, TZCNT);
335490
DEF_ISEL_RnW_Mn(LZCNT_GPRv_MEMv, LZCNT);
336491
DEF_ISEL_RnW_Rn(LZCNT_GPRv_GPRv, LZCNT);
337492

493+
DEF_ISEL(BEXTR_VGPR32d_MEMd_VGPR32d) = BEXTR<R32W, M32, R32>;
494+
DEF_ISEL(BEXTR_VGPR32d_VGPR32d_VGPR32d) = BEXTR<R32W, R32, R32>;
495+
IF_64BIT(DEF_ISEL(BEXTR_VGPR64q_MEMq_VGPR64q) = BEXTR<R64W, M64, R64>;)
496+
IF_64BIT(DEF_ISEL(BEXTR_VGPR64q_VGPR64q_VGPR64q) = BEXTR<R64W, R64, R64>;)
497+
498+
DEF_ISEL(BZHI_VGPR32d_MEMd_VGPR32d) = BZHI<R32W, M32, R32>;
499+
DEF_ISEL(BZHI_VGPR32d_VGPR32d_VGPR32d) = BZHI<R32W, R32, R32>;
500+
IF_64BIT(DEF_ISEL(BZHI_VGPR64q_MEMq_VGPR64q) = BZHI<R64W, M64, R64>;)
501+
IF_64BIT(DEF_ISEL(BZHI_VGPR64q_VGPR64q_VGPR64q) = BZHI<R64W, R64, R64>;)
502+
503+
DEF_ISEL_RnW_Mn(POPCNT_GPRv_MEMv, POPCNT);
504+
DEF_ISEL_RnW_Rn(POPCNT_GPRv_GPRv, POPCNT);
505+
506+
DEF_ISEL(PDEP_VGPR32d_VGPR32d_MEMd) = PDEP<R32W, R32, M32>;
507+
DEF_ISEL(PDEP_VGPR32d_VGPR32d_VGPR32d) = PDEP<R32W, R32, R32>;
508+
IF_64BIT(DEF_ISEL(PDEP_VGPR64q_VGPR64q_MEMq) = PDEP<R64W, R64, M64>;)
509+
IF_64BIT(DEF_ISEL(PDEP_VGPR64q_VGPR64q_VGPR64q) = PDEP<R64W, R64, R64>;)
510+
511+
DEF_ISEL(PEXT_VGPR32d_VGPR32d_MEMd) = PEXT<R32W, R32, M32>;
512+
DEF_ISEL(PEXT_VGPR32d_VGPR32d_VGPR32d) = PEXT<R32W, R32, R32>;
513+
IF_64BIT(DEF_ISEL(PEXT_VGPR64q_VGPR64q_MEMq) = PEXT<R64W, R64, M64>;)
514+
IF_64BIT(DEF_ISEL(PEXT_VGPR64q_VGPR64q_VGPR64q) = PEXT<R64W, R64, R64>;)
515+
516+
DEF_ISEL(CRC32_GPRyy_MEMb_32) = CRC32<R32W, R32, M8>;
517+
IF_64BIT(DEF_ISEL(CRC32_GPRyy_MEMb_64) = CRC32<R64W, R64, M8>;)
518+
DEF_ISEL(CRC32_GPRyy_GPR8b_32) = CRC32<R32W, R32, R8>;
519+
IF_64BIT(DEF_ISEL(CRC32_GPRyy_GPR8b_64) = CRC32<R64W, R64, R8>;)
520+
DEF_ISEL(CRC32_GPRyy_MEMv_16) = CRC32<R32W, R32, M16>;
521+
DEF_ISEL(CRC32_GPRyy_MEMv_32) = CRC32<R32W, R32, M32>;
522+
IF_64BIT(DEF_ISEL(CRC32_GPRyy_MEMv_64) = CRC32<R64W, R64, M64>;)
523+
DEF_ISEL(CRC32_GPRyy_GPRv_16) = CRC32<R32W, R32, R16>;
524+
DEF_ISEL(CRC32_GPRyy_GPRv_32) = CRC32<R32W, R32, R32>;
525+
IF_64BIT(DEF_ISEL(CRC32_GPRyy_GPRv_64) = CRC32<R64W, R64, R64>;)
526+
338527
namespace {
339528
template <typename D, typename S>
340529
DEF_SEM(BSR, D dst, S src) {

lib/Arch/X86/Semantics/CMOV.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ DEF_SEM(CMOVNZ, D dst, S1 src1) {
5252
return memory;
5353
}
5454

55+
template <typename D, typename S1>
56+
DEF_SEM(CMOVNE, D dst, S1 src1) {
57+
return CMOVNZ<D, S1>(dst, src1);
58+
}
59+
5560
template <typename D, typename S1>
5661
DEF_SEM(CMOVNB, D dst, S1 src1) {
5762
WriteZExt(dst, Select(__remill_compare_uge(BNot(FLAG_CF)), Read(src1),
@@ -94,6 +99,11 @@ DEF_SEM(CMOVZ, D dst, S1 src1) {
9499
return memory;
95100
}
96101

102+
template <typename D, typename S1>
103+
DEF_SEM(CMOVE, D dst, S1 src1) {
104+
return CMOVZ<D, S1>(dst, src1);
105+
}
106+
97107
template <typename D, typename S1>
98108
DEF_SEM(CMOVP, D dst, S1 src1) {
99109
WriteZExt(dst, Select(FLAG_PF, Read(src1), TruncTo<S1>(Read(dst))));
@@ -151,6 +161,10 @@ DEF_ISEL_RnW_Mn(CMOVO_GPRv_MEMv, CMOVO);
151161
DEF_ISEL_RnW_Rn(CMOVO_GPRv_GPRv, CMOVO);
152162
DEF_ISEL_RnW_Mn(CMOVZ_GPRv_MEMv, CMOVZ);
153163
DEF_ISEL_RnW_Rn(CMOVZ_GPRv_GPRv, CMOVZ);
164+
DEF_ISEL_RnW_Mn(CMOVE_GPRv_MEMv, CMOVZ);
165+
DEF_ISEL_RnW_Rn(CMOVE_GPRv_GPRv, CMOVZ);
166+
DEF_ISEL_RnW_Mn(CMOVNE_GPRv_MEMv, CMOVNZ);
167+
DEF_ISEL_RnW_Rn(CMOVNE_GPRv_GPRv, CMOVNZ);
154168
DEF_ISEL_RnW_Mn(CMOVP_GPRv_MEMv, CMOVP);
155169
DEF_ISEL_RnW_Rn(CMOVP_GPRv_GPRv, CMOVP);
156170
DEF_ISEL_RnW_Mn(CMOVS_GPRv_MEMv, CMOVS);

lib/Arch/X86/Semantics/COND_BR.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,13 +213,25 @@ DEF_ISEL(JNZ_RELBRz_16) = JNZ;
213213
DEF_ISEL(JNZ_RELBRz_32) = JNZ;
214214
IF_64BIT(DEF_ISEL(JNZ_RELBRz_64) = JNZ;)
215215
DEF_ISEL(JNZ_RELBRd) = JNZ;
216+
DEF_ISEL(JNE_RELBRb) = JNZ;
217+
DEF_ISEL(JNE_RELBRz_8) = JNZ;
218+
DEF_ISEL(JNE_RELBRz_16) = JNZ;
219+
DEF_ISEL(JNE_RELBRz_32) = JNZ;
220+
IF_64BIT(DEF_ISEL(JNE_RELBRz_64) = JNZ;)
221+
DEF_ISEL(JNE_RELBRd) = JNZ;
216222

217223
DEF_ISEL(JNB_RELBRb) = JNB;
218224
DEF_ISEL(JNB_RELBRz_8) = JNB;
219225
DEF_ISEL(JNB_RELBRz_16) = JNB;
220226
DEF_ISEL(JNB_RELBRz_32) = JNB;
221227
IF_64BIT(DEF_ISEL(JNB_RELBRz_64) = JNB;)
222228
DEF_ISEL(JNB_RELBRd) = JNB;
229+
DEF_ISEL(JAE_RELBRb) = JNB;
230+
DEF_ISEL(JAE_RELBRz_8) = JNB;
231+
DEF_ISEL(JAE_RELBRz_16) = JNB;
232+
DEF_ISEL(JAE_RELBRz_32) = JNB;
233+
IF_64BIT(DEF_ISEL(JAE_RELBRz_64) = JNB;)
234+
DEF_ISEL(JAE_RELBRd) = JNB;
223235

224236
DEF_ISEL(JNO_RELBRb) = JNO;
225237
DEF_ISEL(JNO_RELBRz_8) = JNO;
@@ -255,6 +267,12 @@ DEF_ISEL(JZ_RELBRz_16) = JZ;
255267
DEF_ISEL(JZ_RELBRz_32) = JZ;
256268
IF_64BIT(DEF_ISEL(JZ_RELBRz_64) = JZ;)
257269
DEF_ISEL(JZ_RELBRd) = JZ;
270+
DEF_ISEL(JE_RELBRb) = JZ;
271+
DEF_ISEL(JE_RELBRz_8) = JZ;
272+
DEF_ISEL(JE_RELBRz_16) = JZ;
273+
DEF_ISEL(JE_RELBRz_32) = JZ;
274+
IF_64BIT(DEF_ISEL(JE_RELBRz_64) = JZ;)
275+
DEF_ISEL(JE_RELBRd) = JZ;
258276

259277
DEF_ISEL(JP_RELBRb) = JP;
260278
DEF_ISEL(JP_RELBRz_8) = JP;

lib/Arch/X86/Semantics/LOGICAL.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,18 @@ DEF_SEM(AND, D dst, S1 src1, S2 src2) {
3838
return memory;
3939
}
4040

41+
template <typename D, typename S1, typename S2>
42+
DEF_SEM(ANDN, D dst, S1 src1, S2 src2) {
43+
auto lhs = Read(src1);
44+
auto rhs = Read(src2);
45+
auto res = UAnd(UNot(lhs), rhs);
46+
WriteZExt(dst, res);
47+
SetFlagsLogical(state, lhs, rhs, res);
48+
UndefFlag(af);
49+
UndefFlag(pf);
50+
return memory;
51+
}
52+
4153
template <typename D, typename S1, typename S2>
4254
DEF_SEM(OR, D dst, S1 src1, S2 src2) {
4355
auto lhs = Read(src1);
@@ -97,6 +109,11 @@ DEF_ISEL_RnW_Rn_Mn(AND_GPRv_MEMv, AND);
97109
DEF_ISEL(AND_AL_IMMb) = AND<R8W, R8, I8>;
98110
DEF_ISEL_RnW_Rn_In(AND_OrAX_IMMz, AND);
99111

112+
DEF_ISEL(ANDN_VGPR32d_VGPR32d_MEMd) = ANDN<R32W, R32, M32>;
113+
DEF_ISEL(ANDN_VGPR32d_VGPR32d_VGPR32d) = ANDN<R32W, R32, R32>;
114+
IF_64BIT(DEF_ISEL(ANDN_VGPR64q_VGPR64q_MEMq) = ANDN<R64W, R64, M64>;)
115+
IF_64BIT(DEF_ISEL(ANDN_VGPR64q_VGPR64q_VGPR64q) = ANDN<R64W, R64, R64>;)
116+
100117
DEF_ISEL(OR_MEMb_IMMb_80r1) = OR<M8W, M8, I8>;
101118
DEF_ISEL(OR_GPR8_IMMb_80r1) = OR<R8W, R8, I8>;
102119
DEF_ISEL_MnW_Mn_In(OR_MEMv_IMMz, OR);

0 commit comments

Comments
 (0)