1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
|
/* Capstone Disassembly Engine */
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
// this tool is to generate arch/X86/X86GenDisassemblerTables2.inc
// NOTE: this requires updated X86GenDisassemblerTables2 & X86GenDisassemblerTables2
// generatedy by ./disassemblertables.py & disassemblertables_reduce.py
#include <stdio.h>
#include <stdint.h>
#include <string.h>
// X86DisassemblerDecoderCommon.h is copied from Capstone src
#include "../../arch/X86/X86DisassemblerDecoderCommon.h"
#define ARR_SIZE(a) (sizeof(a) / sizeof(a[0]))
/// Specifies whether a ModR/M byte is needed and (if so) which
/// instruction each possible value of the ModR/M byte corresponds to. Once
/// this information is known, we have narrowed down to a single instruction.
struct ModRMDecision {
uint8_t modrm_type;
uint16_t instructionIDs;
};
/// Specifies which set of ModR/M->instruction tables to look at
/// given a particular opcode.
struct OpcodeDecision {
struct ModRMDecision modRMDecisions[256];
};
/// Specifies which opcode->instruction tables to look at given
/// a particular context (set of attributes). Since there are many possible
/// contexts, the decoder first uses CONTEXTS_SYM to determine which context
/// applies given a specific set of attributes. Hence there are only IC_max
/// entries in this table, rather than 2^(ATTR_max).
struct ContextDecision {
struct OpcodeDecision opcodeDecisions[IC_max];
};
#ifdef CAPSTONE_X86_REDUCE
#include "X86GenDisassemblerTables_reduce2.inc"
#else
#include "X86GenDisassemblerTables2.inc"
#endif
static void index_OpcodeDecision(const struct OpcodeDecision *decisions, size_t size,
const struct OpcodeDecision *emptyDecision, unsigned int *index_table,
const char *opcodeTable,
const char *index_opcodeTable)
{
unsigned int i, count = 0;
for (i = 0; i < size; i++) {
if (memcmp((const void *)&decisions[i],
emptyDecision, sizeof(*emptyDecision)) != 0) {
// this is a non-zero entry
// index_table entry must be != 0
index_table[i] = count + 1;
count++;
} else
// empty entry
index_table[i] = 0;
}
printf("static const unsigned char %s[] = {\n", index_opcodeTable);
for (i = 0; i < size; i++) {
printf(" %u,\n", index_table[i]);
}
printf("};\n\n");
printf("static const struct OpcodeDecision %s[] = {\n", opcodeTable);
for (i = 0; i < size; i++) {
if (index_table[i]) {
unsigned int j;
const struct OpcodeDecision *decision;
// print out this non-zero entry
printf(" { {\n");
decision = &decisions[i];
for(j = 0; j < ARR_SIZE(emptyDecision->modRMDecisions); j++) {
const char *modrm;
switch(decision->modRMDecisions[j].modrm_type) {
default:
modrm = "MODRM_ONEENTRY";
break;
case 1:
modrm = "MODRM_SPLITRM";
break;
case 2:
modrm = "MODRM_SPLITMISC";
break;
case 3:
modrm = "MODRM_SPLITREG";
break;
case 4:
modrm = "MODRM_FULL";
break;
}
printf(" { %s, %u },\n",
modrm, decision->modRMDecisions[j].instructionIDs);
}
printf(" } },\n");
}
}
printf("};\n\n");
}
int main(int argc, char **argv)
{
unsigned int index_table[ARR_SIZE(x86DisassemblerOneByteOpcodes.opcodeDecisions)];
const struct OpcodeDecision emptyDecision;
memset((void *)&emptyDecision, 0, sizeof(emptyDecision));
printf("/* Capstone Disassembly Engine, http://www.capstone-engine.org */\n");
printf("/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */\n");
printf("\n");
index_OpcodeDecision(x86DisassemblerOneByteOpcodes.opcodeDecisions,
ARR_SIZE(x86DisassemblerOneByteOpcodes.opcodeDecisions),
&emptyDecision, index_table,
"x86DisassemblerOneByteOpcodes",
"index_x86DisassemblerOneByteOpcodes");
index_OpcodeDecision(x86DisassemblerTwoByteOpcodes.opcodeDecisions,
ARR_SIZE(x86DisassemblerTwoByteOpcodes.opcodeDecisions),
&emptyDecision, index_table,
"x86DisassemblerTwoByteOpcodes",
"index_x86DisassemblerTwoByteOpcodes");
index_OpcodeDecision(x86DisassemblerThreeByte38Opcodes.opcodeDecisions,
ARR_SIZE(x86DisassemblerThreeByte38Opcodes.opcodeDecisions),
&emptyDecision, index_table,
"x86DisassemblerThreeByte38Opcodes",
"index_x86DisassemblerThreeByte38Opcodes");
index_OpcodeDecision(x86DisassemblerThreeByte3AOpcodes.opcodeDecisions,
ARR_SIZE(x86DisassemblerThreeByte3AOpcodes.opcodeDecisions),
&emptyDecision, index_table,
"x86DisassemblerThreeByte3AOpcodes",
"index_x86DisassemblerThreeByte3AOpcodes");
#ifndef CAPSTONE_X86_REDUCE
index_OpcodeDecision(x86DisassemblerXOP8Opcodes.opcodeDecisions,
ARR_SIZE(x86DisassemblerXOP8Opcodes.opcodeDecisions),
&emptyDecision, index_table,
"x86DisassemblerXOP8Opcodes",
"index_x86DisassemblerXOP8Opcodes");
index_OpcodeDecision(x86DisassemblerXOP9Opcodes.opcodeDecisions,
ARR_SIZE(x86DisassemblerXOP9Opcodes.opcodeDecisions),
&emptyDecision, index_table,
"x86DisassemblerXOP9Opcodes",
"index_x86DisassemblerXOP9Opcodes");
index_OpcodeDecision(x86DisassemblerXOPAOpcodes.opcodeDecisions,
ARR_SIZE(x86DisassemblerXOPAOpcodes.opcodeDecisions),
&emptyDecision, index_table,
"x86DisassemblerXOPAOpcodes",
"index_x86DisassemblerXOPAOpcodes");
index_OpcodeDecision(x86Disassembler3DNowOpcodes.opcodeDecisions,
ARR_SIZE(x86Disassembler3DNowOpcodes.opcodeDecisions),
&emptyDecision, index_table,
"x86Disassembler3DNowOpcodes",
"index_x86Disassembler3DNowOpcodes");
#endif
return 0;
}
|