Major rework of API and improved documentation

This commit is contained in:
Alexis Engelke
2019-01-23 20:03:40 +01:00
parent a045588999
commit 3abf29d63e
6 changed files with 320 additions and 273 deletions

View File

@@ -1,22 +1,23 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <decode.h>
#include <fadec.h>
#define DECODE_TABLE_STRTAB1
#define FD_DECODE_TABLE_STRTAB1
static const char* _mnemonic_str =
#include <decode-table.inc>
;
#undef DECODE_TABLE_STRTAB1
#undef FD_DECODE_TABLE_STRTAB1
#define DECODE_TABLE_STRTAB2
#define FD_DECODE_TABLE_STRTAB2
static const uint16_t _mnemonic_offs[] = {
#include <decode-table.inc>
};
#undef DECODE_TABLE_STRTAB2
#undef FD_DECODE_TABLE_STRTAB2
#define FMT_CONCAT(buf, end, ...) do { \
buf += snprintf(buf, end - buf, __VA_ARGS__); \
@@ -25,79 +26,83 @@ static const uint16_t _mnemonic_offs[] = {
} while (0)
void
instr_format(const Instr* instr, char buffer[128])
fd_format(const FdInstr* instr, char* buffer, size_t len)
{
char* buf = buffer;
char* end = buffer + 128;
char* end = buffer + len;
FMT_CONCAT(buf, end, "[");
if (INSTR_HAS_REP(instr))
if (FD_HAS_REP(instr))
FMT_CONCAT(buf, end, "rep:");
if (INSTR_HAS_REPNZ(instr))
if (FD_HAS_REPNZ(instr))
FMT_CONCAT(buf, end, "repnz:");
if (INSTR_SEGMENT(instr) < 6)
FMT_CONCAT(buf, end, "%cs:", "ecsdfg"[INSTR_SEGMENT(instr)]);
if (INSTR_IS64(instr) && INSTR_ADDRSZ(instr) == 4)
if (FD_SEGMENT(instr) < 6)
FMT_CONCAT(buf, end, "%cs:", "ecsdfg"[FD_SEGMENT(instr)]);
if (FD_IS64(instr) && FD_ADDRSIZE(instr) == 4)
FMT_CONCAT(buf, end, "addr32:");
if (!INSTR_IS64(instr) && INSTR_ADDRSZ(instr) == 2)
if (!FD_IS64(instr) && FD_ADDRSIZE(instr) == 2)
FMT_CONCAT(buf, end, "addr16:");
if (INSTR_HAS_LOCK(instr))
if (FD_HAS_LOCK(instr))
FMT_CONCAT(buf, end, "lock:");
FMT_CONCAT(buf, end, "%s", &_mnemonic_str[_mnemonic_offs[instr->type]]);
if (INSTR_WIDTH(instr))
FMT_CONCAT(buf, end, "_%u", INSTR_WIDTH(instr));
FMT_CONCAT(buf, end, "%s", &_mnemonic_str[_mnemonic_offs[FD_TYPE(instr)]]);
if (FD_OPSIZE(instr))
FMT_CONCAT(buf, end, "_%u", FD_OPSIZE(instr));
for (int i = 0; i < 4; i++)
{
const struct Operand* operand = &instr->operands[i];
if (operand->type == OT_NONE)
FdOpType op_type = FD_OP_TYPE(instr, i);
if (op_type == FD_OP_NONE)
break;
const char* op_type_name = "reg\0imm\0mem" + operand->type * 4 - 4;
FMT_CONCAT(buf, end, " %s%u:", op_type_name, operand->size);
const char* op_type_name = "reg\0imm\0mem" + op_type * 4 - 4;
FMT_CONCAT(buf, end, " %s%u:", op_type_name, FD_OP_SIZE(instr, i));
switch (operand->type)
switch (op_type)
{
size_t immediate;
case OT_REG:
if (operand->size == 1 && !INSTR_HAS_REX(instr) &&
operand->reg >= 4 && operand->reg < 8)
FMT_CONCAT(buf, end, "r%uh", operand->reg - 4);
bool has_base;
bool has_idx;
bool has_disp;
case FD_OP_REG:
if (FD_OP_REG_HIGH(instr, i))
FMT_CONCAT(buf, end, "r%uh", FD_OP_REG(instr, i) - 4);
else
FMT_CONCAT(buf, end, "r%u", operand->reg);
FMT_CONCAT(buf, end, "r%u", FD_OP_REG(instr, i));
break;
case OT_IMM:
immediate = instr->immediate;
if (operand->size == 1)
case FD_OP_IMM:
immediate = FD_OP_IMM(instr, i);
if (FD_OP_SIZE(instr, i) == 1)
immediate &= 0xff;
else if (operand->size == 2)
else if (FD_OP_SIZE(instr, i) == 2)
immediate &= 0xffff;
else if (operand->size == 4)
else if (FD_OP_SIZE(instr, i) == 4)
immediate &= 0xffffffff;
FMT_CONCAT(buf, end, "0x%lx", immediate);
break;
case OT_MEM:
if (!reg_is_none(operand->reg))
case FD_OP_MEM:
has_base = FD_OP_BASE(instr, i) != FD_REG_NONE;
has_idx = FD_OP_INDEX(instr, i) != FD_REG_NONE;
has_disp = FD_OP_DISP(instr, i) != 0;
if (has_base)
{
FMT_CONCAT(buf, end, "r%u", operand->reg);
if (instr->scale != 0 || instr->disp > 0)
FMT_CONCAT(buf, end, "r%u", FD_OP_BASE(instr, i));
if (has_idx || has_disp)
FMT_CONCAT(buf, end, "+");
}
if (instr->scale != 0)
if (has_idx)
{
FMT_CONCAT(buf, end, "%u*r%u", 1 << (instr->scale - 1),
instr->sreg);
if (instr->disp > 0)
FMT_CONCAT(buf, end, "%u*r%u", 1 << FD_OP_SCALE(instr, i),
FD_OP_INDEX(instr, i));
if (has_disp)
FMT_CONCAT(buf, end, "+");
}
if (instr->disp < 0)
FMT_CONCAT(buf, end, "-0x%lx", -instr->disp);
else if ((reg_is_none(operand->reg) && instr->scale == 0) ||
instr->disp > 0)
FMT_CONCAT(buf, end, "0x%lx", instr->disp);
if (FD_OP_DISP(instr, i) < 0)
FMT_CONCAT(buf, end, "-0x%lx", -FD_OP_DISP(instr, i));
else if (has_disp || (!has_base && !has_idx))
FMT_CONCAT(buf, end, "0x%lx", FD_OP_DISP(instr, i));
break;
case OT_NONE:
case FD_OP_NONE:
default:
break;
}