encode: Support FD/TD encodings
This commit is contained in:
17
encode.c
17
encode.c
@@ -291,8 +291,8 @@ const struct EncodingInfo encoding_infos[ENC_MAX] = {
|
|||||||
[ENC_S] = { 0 },
|
[ENC_S] = { 0 },
|
||||||
[ENC_A] = { .zregidx = 0^3, .zregval = 0 },
|
[ENC_A] = { .zregidx = 0^3, .zregval = 0 },
|
||||||
[ENC_D] = { .immctl = 6, .immidx = 0 },
|
[ENC_D] = { .immctl = 6, .immidx = 0 },
|
||||||
[ENC_FD] = { .immctl = 2, .immidx = 1 },
|
[ENC_FD] = { .zregidx = 0^3, .zregval = 0, .immctl = 2, .immidx = 1 },
|
||||||
[ENC_TD] = { .immctl = 2, .immidx = 0 },
|
[ENC_TD] = { .zregidx = 1^3, .zregval = 0, .immctl = 2, .immidx = 0 },
|
||||||
[ENC_RVM] = { .modrm = 2^3, .modreg = 0^3, .vexreg = 1^3 },
|
[ENC_RVM] = { .modrm = 2^3, .modreg = 0^3, .vexreg = 1^3 },
|
||||||
[ENC_RVMI] = { .modrm = 2^3, .modreg = 0^3, .vexreg = 1^3, .immctl = 4, .immidx = 3 },
|
[ENC_RVMI] = { .modrm = 2^3, .modreg = 0^3, .vexreg = 1^3, .immctl = 4, .immidx = 3 },
|
||||||
[ENC_RVMR] = { .modrm = 2^3, .modreg = 0^3, .vexreg = 1^3, .immctl = 3, .immidx = 3 },
|
[ENC_RVMR] = { .modrm = 2^3, .modreg = 0^3, .vexreg = 1^3, .immctl = 3, .immidx = 3 },
|
||||||
@@ -330,6 +330,7 @@ fe_enc64_impl(uint8_t** restrict buf, uint64_t mnem, FeOp op0, FeOp op1,
|
|||||||
const struct EncodingInfo* ei = &encoding_infos[desc->enc];
|
const struct EncodingInfo* ei = &encoding_infos[desc->enc];
|
||||||
uint64_t opc = desc->opc;
|
uint64_t opc = desc->opc;
|
||||||
int64_t imm = 0xcc;
|
int64_t imm = 0xcc;
|
||||||
|
unsigned immsz = desc->immsz;
|
||||||
|
|
||||||
if (UNLIKELY(desc->enc == ENC_INVALID)) goto fail;
|
if (UNLIKELY(desc->enc == ENC_INVALID)) goto fail;
|
||||||
|
|
||||||
@@ -362,14 +363,18 @@ fe_enc64_impl(uint8_t** restrict buf, uint64_t mnem, FeOp op0, FeOp op1,
|
|||||||
|
|
||||||
if (ei->immctl > 0) {
|
if (ei->immctl > 0) {
|
||||||
imm = ops[ei->immidx];
|
imm = ops[ei->immidx];
|
||||||
|
if (ei->immctl == 2) {
|
||||||
|
immsz = UNLIKELY(mnem & FE_ADDR32) ? 4 : 8;
|
||||||
|
if (immsz == 4) imm = (int32_t) imm; // address are zero-extended
|
||||||
|
}
|
||||||
if (ei->immctl == 3)
|
if (ei->immctl == 3)
|
||||||
imm = op_reg_idx(imm) << 4;
|
imm = op_reg_idx(imm) << 4;
|
||||||
if (ei->immctl == 6) {
|
if (ei->immctl == 6) {
|
||||||
if (UNLIKELY(mnem & FE_JMPL) && desc->alt) goto next;
|
if (UNLIKELY(mnem & FE_JMPL) && desc->alt) goto next;
|
||||||
imm -= (int64_t) *buf + opc_size(opc) + desc->immsz;
|
imm -= (int64_t) *buf + opc_size(opc) + immsz;
|
||||||
}
|
}
|
||||||
if (UNLIKELY(ei->immctl == 1) && imm != 1) goto next;
|
if (UNLIKELY(ei->immctl == 1) && imm != 1) goto next;
|
||||||
if (ei->immctl >= 4 && !op_imm_n(imm, desc->immsz)) goto next;
|
if (ei->immctl >= 2 && !op_imm_n(imm, immsz)) goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOP has no operands, so this must be the 32-bit OA XCHG
|
// NOP has no operands, so this must be the 32-bit OA XCHG
|
||||||
@@ -380,7 +385,7 @@ fe_enc64_impl(uint8_t** restrict buf, uint64_t mnem, FeOp op0, FeOp op1,
|
|||||||
|
|
||||||
if (ei->modrm) {
|
if (ei->modrm) {
|
||||||
FeOp modreg = ei->modreg ? ops[ei->modreg^3] : (opc & 0xff00) >> 8;
|
FeOp modreg = ei->modreg ? ops[ei->modreg^3] : (opc & 0xff00) >> 8;
|
||||||
if (enc_mr(buf, opc, ops[ei->modrm^3], modreg, desc->immsz)) goto fail;
|
if (enc_mr(buf, opc, ops[ei->modrm^3], modreg, immsz)) goto fail;
|
||||||
} else if (ei->modreg) {
|
} else if (ei->modreg) {
|
||||||
if (enc_o(buf, opc, ops[ei->modreg^3])) goto fail;
|
if (enc_o(buf, opc, ops[ei->modreg^3])) goto fail;
|
||||||
} else {
|
} else {
|
||||||
@@ -388,7 +393,7 @@ fe_enc64_impl(uint8_t** restrict buf, uint64_t mnem, FeOp op0, FeOp op1,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ei->immctl >= 2)
|
if (ei->immctl >= 2)
|
||||||
if (enc_imm(buf, imm, desc->immsz)) goto fail;
|
if (enc_imm(buf, imm, immsz)) goto fail;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ class InstrDesc(NamedTuple):
|
|||||||
for ot, op in zip(ots, self.operands):
|
for ot, op in zip(ots, self.operands):
|
||||||
if ot == "m":
|
if ot == "m":
|
||||||
tys.append(0xf)
|
tys.append(0xf)
|
||||||
elif ot in "io":
|
elif ot in "ioa":
|
||||||
tys.append(0)
|
tys.append(0)
|
||||||
elif op.kind == "GP":
|
elif op.kind == "GP":
|
||||||
if (self.mnemonic == "MOVSX" or self.mnemonic == "MOVZX" or
|
if (self.mnemonic == "MOVSX" or self.mnemonic == "MOVZX" or
|
||||||
|
|||||||
@@ -159,6 +159,48 @@ main(int argc, char** argv)
|
|||||||
TEST("\x66\x0f\x3a\x14\xc1\x02", FE_SSE_PEXTRBrri, FE_CX, FE_XMM0, 2);
|
TEST("\x66\x0f\x3a\x14\xc1\x02", FE_SSE_PEXTRBrri, FE_CX, FE_XMM0, 2);
|
||||||
TEST("", FE_SSE_PEXTRBrri, FE_CH, FE_XMM0, 2);
|
TEST("", FE_SSE_PEXTRBrri, FE_CH, FE_XMM0, 2);
|
||||||
|
|
||||||
|
// Test FD/TD encodings
|
||||||
|
TEST("\xa0\x00\x00\x00\x00\x00\x00\x00\x00", FE_MOV8ra, FE_AX, 0);
|
||||||
|
TEST("\x67\xa0\x00\x00\x00\x00", FE_MOV8ra|FE_ADDR32, FE_AX, 0);
|
||||||
|
TEST("\x66\xa1\x00\x00\x00\x00\x00\x00\x00\x00", FE_MOV16ra, FE_AX, 0);
|
||||||
|
TEST("\x67\x66\xa1\x00\x00\x00\x00", FE_MOV16ra|FE_ADDR32, FE_AX, 0);
|
||||||
|
TEST("\x66\xa1\x10\x32\x54\x76\x98\xba\xdc\xfe", FE_MOV16ra, FE_AX, 0xfedcba9876543210);
|
||||||
|
TEST("\x67\x66\xa1\x98\xba\xdc\xfe", FE_MOV16ra|FE_ADDR32, FE_AX, 0xfedcba98);
|
||||||
|
TEST("\xa1\x10\x32\x54\x76\x98\xba\xdc\xfe", FE_MOV32ra, FE_AX, 0xfedcba9876543210);
|
||||||
|
TEST("\x67\xa1\x98\xba\xdc\xfe", FE_MOV32ra|FE_ADDR32, FE_AX, 0xfedcba98);
|
||||||
|
TEST("\x48\xa1\x10\x32\x54\x76\x98\xba\xdc\xfe", FE_MOV64ra, FE_AX, 0xfedcba9876543210);
|
||||||
|
TEST("\x67\x48\xa1\x98\xba\xdc\xfe", FE_MOV64ra|FE_ADDR32, FE_AX, 0xfedcba98);
|
||||||
|
TEST("\xa2\x00\x00\x00\x00\x00\x00\x00\x00", FE_MOV8ar, 0, FE_AX);
|
||||||
|
TEST("\x67\xa2\x00\x00\x00\x00", FE_MOV8ar|FE_ADDR32, 0, FE_AX);
|
||||||
|
TEST("\x66\xa3\x00\x00\x00\x00\x00\x00\x00\x00", FE_MOV16ar, 0, FE_AX);
|
||||||
|
TEST("\x67\x66\xa3\x00\x00\x00\x00", FE_MOV16ar|FE_ADDR32, 0, FE_AX);
|
||||||
|
TEST("\x66\xa3\x10\x32\x54\x76\x98\xba\xdc\xfe", FE_MOV16ar, 0xfedcba9876543210, FE_AX);
|
||||||
|
TEST("\x67\x66\xa3\x98\xba\xdc\xfe", FE_MOV16ar|FE_ADDR32, 0xfedcba98, FE_AX);
|
||||||
|
TEST("\xa3\x10\x32\x54\x76\x98\xba\xdc\xfe", FE_MOV32ar, 0xfedcba9876543210, FE_AX);
|
||||||
|
TEST("\x67\xa3\x98\xba\xdc\xfe", FE_MOV32ar|FE_ADDR32, 0xfedcba98, FE_AX);
|
||||||
|
TEST("\x48\xa3\x10\x32\x54\x76\x98\xba\xdc\xfe", FE_MOV64ar, 0xfedcba9876543210, FE_AX);
|
||||||
|
TEST("\x67\x48\xa3\x98\xba\xdc\xfe", FE_MOV64ar|FE_ADDR32, 0xfedcba98, FE_AX);
|
||||||
|
TEST("", FE_MOV8ra, FE_CX, 0);
|
||||||
|
TEST("", FE_MOV8ra|FE_ADDR32, FE_CX, 0);
|
||||||
|
TEST("", FE_MOV16ra, FE_CX, 0);
|
||||||
|
TEST("", FE_MOV16ra|FE_ADDR32, FE_CX, 0);
|
||||||
|
TEST("", FE_MOV16ra, FE_CX, 0xfedcba9876543210);
|
||||||
|
TEST("", FE_MOV16ra|FE_ADDR32, FE_CX, 0xfedcba98);
|
||||||
|
TEST("", FE_MOV32ra, FE_CX, 0xfedcba9876543210);
|
||||||
|
TEST("", FE_MOV32ra|FE_ADDR32, FE_CX, 0xfedcba98);
|
||||||
|
TEST("", FE_MOV64ra, FE_CX, 0xfedcba9876543210);
|
||||||
|
TEST("", FE_MOV64ra|FE_ADDR32, FE_CX, 0xfedcba98);
|
||||||
|
TEST("", FE_MOV8ar, 0, FE_CX);
|
||||||
|
TEST("", FE_MOV8ar|FE_ADDR32, 0, FE_CX);
|
||||||
|
TEST("", FE_MOV16ar, 0, FE_CX);
|
||||||
|
TEST("", FE_MOV16ar|FE_ADDR32, 0, FE_CX);
|
||||||
|
TEST("", FE_MOV16ar, 0xfedcba9876543210, FE_CX);
|
||||||
|
TEST("", FE_MOV16ar|FE_ADDR32, 0xfedcba98, FE_CX);
|
||||||
|
TEST("", FE_MOV32ar, 0xfedcba9876543210, FE_CX);
|
||||||
|
TEST("", FE_MOV32ar|FE_ADDR32, 0xfedcba98, FE_CX);
|
||||||
|
TEST("", FE_MOV64ar, 0xfedcba9876543210, FE_CX);
|
||||||
|
TEST("", FE_MOV64ar|FE_ADDR32, 0xfedcba98, FE_CX);
|
||||||
|
|
||||||
// Test VEX encoding
|
// Test VEX encoding
|
||||||
TEST("\xc5\xfc\x77", FE_VZEROALL);
|
TEST("\xc5\xfc\x77", FE_VZEROALL);
|
||||||
TEST("\xc5\xf8\x77", FE_VZEROUPPER);
|
TEST("\xc5\xf8\x77", FE_VZEROUPPER);
|
||||||
|
|||||||
Reference in New Issue
Block a user