aboutsummaryrefslogtreecommitdiffstats
path: root/capstone/suite/synctools/disassemblertables2.c
blob: f336da103be9b5b7316686d80a3aa28b415fdf00 (plain)
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;
}