The ROme OpTimistic Simulator  2.0.0
A General-Purpose Multithreaded Parallel/Distributed Simulation Platform
disassemble.c
Go to the documentation of this file.
1 
42 #if defined(__x86_64__) && defined(HAVE_ECS)
43 
44 #include <stdio.h>
45 #include <string.h>
46 #include <stdlib.h>
47 #include <stdint.h>
48 #include <stdbool.h>
49 
50 #include <arch/x86/disassemble.h>
51 
52 /* Prototipi delle funzioni */
53 
54 /* 0fxx - escape a due byte */
55 void esc_0f_opcode(struct disassembly_state *state);
56 
57 /* Escape al coprocessore */
58 void d8_opcode(struct disassembly_state *state);
59 void d9_opcode(struct disassembly_state *state);
60 void da_opcode(struct disassembly_state *state);
61 void db_opcode(struct disassembly_state *state);
62 void dc_opcode(struct disassembly_state *state);
63 void dd_opcode(struct disassembly_state *state);
64 void de_opcode(struct disassembly_state *state);
65 void df_opcode(struct disassembly_state *state);
66 
67 /* Vari gruppi */
68 void immed_grp_1(struct disassembly_state *state); /* opcodes 80-83 */
69 void shift_grp_2(struct disassembly_state *state); /* opcodes C0-C1, D0-D3 */
70 void unary_grp_3(struct disassembly_state *state); /* opcodes F6-F7 */
71 void grp_4(struct disassembly_state *state); /* opcode FE */
72 void grp_5(struct disassembly_state *state); /* opcode FF */
73 void grp_6(struct disassembly_state *state); /* opcode 0F00 */
74 void grp_7(struct disassembly_state *state); /* opcode 0F01 */
75 void grp_8(struct disassembly_state *state); /* opcode 0FBA */
76 void grp_9(struct disassembly_state *state); /* opcode 0FC7 */
77 void grp_10(struct disassembly_state *state); /* opcode 0FB9 */
78 void grp_11(struct disassembly_state *state); /* opcodes C6-C7 */
79 void grp_12(struct disassembly_state *state); /* opcode 0F71 */
80 void grp_13(struct disassembly_state *state); /* opcode 0F72 */
81 void grp_14(struct disassembly_state *state); /* opcode 0F73 */
82 void grp_15(struct disassembly_state *state); /* opcode 0FAE */
83 void grp_16(struct disassembly_state *state); /* opcode OF18 */
84 
85 /* escape MMX/SSE/SSE2 */
86 void esc_0f10_17 (struct disassembly_state *state);
87 void esc_0f28_2f (struct disassembly_state *state);
88 void esc_0f50_70 (struct disassembly_state *state);
89 void esc_0f74_76 (struct disassembly_state *state);
90 void esc_0f7e_7f (struct disassembly_state *state);
91 void esc_0fc2 (struct disassembly_state *state);
92 void esc_0fc4_c6 (struct disassembly_state *state);
93 void esc_0fd1_ef (struct disassembly_state *state);
94 void esc_0ff1_fe (struct disassembly_state *state);
95 
96 
97 /* Un array di opcode, dove l'indice è il primo byte dell'opcode */
98 insn one_byte_opcode_table[] = {
99  /* 00 */
100  { "add", { ADDR_E, ADDR_G, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL, I_MEMWR | I_MEMRD | I_ALU },
101  /* 01 */
102  { "add", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_MEMWR | I_MEMRD | I_ALU },
103  /* 02 */
104  { "add", { ADDR_G, ADDR_E, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL, I_MEMRD | I_ALU },
105  /* 03 */
106  { "add", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_MEMRD | I_ALU },
107  /* 04 */
108  { "add", { R_AL, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL, I_ALU },
109  /* 05 */
110  { "add", { R_AX, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL, I_ALU },
111  /* 06 */
112  { "push", { R_ES, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_PUSHPOP },
113  /* 07 */
114  { "pop", { R_ES, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_PUSHPOP },
115  /* 08 */
116  { "or", { ADDR_E, ADDR_G, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL, I_MEMWR | I_MEMRD | I_ALU },
117  /* 09 */
118  { "or", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_MEMWR | I_MEMRD | I_ALU },
119  /* 0A */
120  { "or", { ADDR_G, ADDR_E, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL, I_MEMRD | I_ALU },
121  /* 0B */
122  { "or", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_MEMRD | I_ALU },
123  /* 0C */
124  { "or", { R_AL, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL, I_ALU },
125  /* 0D */
126  { "or", { R_AX, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL, I_ALU },
127  /* 0E */
128  { "push", { R_CS, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_PUSHPOP },
129  /* 0F */
130  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f_opcode, 0 },
131  /* 10 */
132  { "adc", { ADDR_E, ADDR_G, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL, I_MEMWR | I_ALU },
133  /* 11 */
134  { "adc", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_MEMWR | I_ALU },
135  /* 12 */
136  { "adc", { ADDR_G, ADDR_E, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL, I_MEMRD | I_ALU },
137  /* 13 */
138  { "adc", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_MEMRD | I_ALU },
139  /* 14 */
140  { "adc", { R_AL, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL, I_ALU },
141  /* 15 */
142  { "adc", { R_AX, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL, I_ALU },
143  /* 16 */
144  { "push", { R_SS, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_PUSHPOP },
145  /* 17 */
146  { "pop", { R_SS, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_PUSHPOP },
147  /* 18 */
148  { "sbb", { ADDR_E, ADDR_G, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL, I_MEMWR | I_ALU },
149  /* 19 */
150  { "sbb", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_MEMWR | I_ALU },
151  /* 1A */
152  { "sbb", { ADDR_G, ADDR_E, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL, I_MEMWR | I_ALU },
153  /* 1B */
154  { "sbb", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_MEMRD | I_ALU },
155  /* 1C */
156  { "sbb", { R_AL, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL, I_ALU },
157  /* 1D */
158  { "sbb", { R_AX, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL, I_ALU },
159  /* 1E */
160  { "push", { R_DS, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_PUSHPOP },
161  /* 1F */
162  { "pop", { R_DS, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_PUSHPOP },
163  /* 20 */
164  { "and", { ADDR_E, ADDR_G, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL, I_MEMWR | I_ALU },
165  /* 21 */
166  { "and", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_MEMWR | I_ALU },
167  /* 22 */
168  { "and", { ADDR_G, ADDR_E, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL, I_MEMRD | I_ALU },
169  /* 23 */
170  { "and", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_MEMRD | I_ALU },
171  /* 24 */
172  { "and", { R_AL, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL, I_ALU },
173  /* 25 */
174  { "and", { R_AX, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL, I_ALU },
175  /* 26 */
176  { "es", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
177  /* 27 */
178  { "daa", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_ALU },
179  /* 28 */
180  { "sub", { ADDR_E, ADDR_G, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL, I_MEMWR | I_ALU },
181  /* 29 */
182  { "sub", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_MEMWR | I_ALU },
183  /* 2A */
184  { "sub", { ADDR_G, ADDR_E, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL, I_MEMRD | I_ALU },
185  /* 2B */
186  { "sub", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_MEMRD | I_ALU },
187  /* 2C */
188  { "sub", { R_AL, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL, I_ALU },
189  /* 2D */
190  { "sub", { R_AX, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL, I_ALU },
191  /* 2E */
192  { "cs", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
193  /* 2F */
194  { "das", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_ALU },
195  /* 30 */
196  { "xor", { ADDR_E, ADDR_G, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL, I_MEMWR | I_ALU },
197  /* 31 */
198  { "xor", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_MEMWR | I_ALU },
199  /* 32 */
200  { "xor", { ADDR_G, ADDR_E, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL, I_MEMRD | I_ALU },
201  /* 33 */
202  { "xor", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_MEMRD | I_ALU },
203  /* 34 */
204  { "xor", { R_AL, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL, I_ALU },
205  /* 35 */
206  { "xor", { R_AX, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL, I_ALU },
207  /* 36 */
208  { "ss", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
209  /* 37 */
210  { "aaa", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_ALU },
211  /* 38 */
212  { "cmp", { ADDR_E, ADDR_G, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL, I_MEMRD | I_ALU | I_CTRL },
213  /* 39 */
214  { "cmp", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_MEMRD | I_ALU | I_CTRL },
215  /* 3A */
216  { "cmp", { ADDR_G, ADDR_E, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL, I_MEMRD | I_ALU | I_CTRL },
217  /* 3B */
218  { "cmp", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_MEMRD | I_ALU | I_CTRL },
219  /* 3C */
220  { "cmp", { R_AL, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL, I_ALU | I_CTRL },
221  /* 3D */
222  { "cmp", { R_AX, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL, I_ALU | I_CTRL },
223  /* 3E */
224  { "ds", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
225  /* 3F */
226  { "aas", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_ALU },
227  /* 40 - La riga 40-4f è per il byte REX */
228  { "inc", { R_AX, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, I_ALU },
229  /* 41 */
230  { "inc", { R_CX, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, I_ALU },
231  /* 42 */
232  { "inc", { R_DX, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, I_ALU },
233  /* 43 */
234  { "inc", { R_BX, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, I_ALU },
235  /* 44 */
236  { "inc", { R_SP, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, I_ALU },
237  /* 45 */
238  { "inc", { R_BP, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, I_ALU },
239  /* 46 */
240  { "inc", { R_SI, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, I_ALU },
241  /* 47 */
242  { "inc", { R_DI, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, I_ALU },
243  /* 48 */
244  { "dec", { R_AX, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, I_ALU },
245  /* 49 */
246  { "dec", { R_CX, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, I_ALU },
247  /* 4A */
248  { "dec", { R_DX, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, I_ALU },
249  /* 4B */
250  { "dec", { R_BX, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, I_ALU },
251  /* 4C */
252  { "dec", { R_SP, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, I_ALU },
253  /* 4D */
254  { "dec", { R_BP, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, I_ALU },
255  /* 4E */
256  { "dec", { R_SI, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, I_ALU },
257  /* 4F */
258  { "dec", { R_DI, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, I_ALU },
259  /* 50 */
260  { "push", { R_AX, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, I_PUSHPOP },
261  /* 51 */
262  { "push", { R_CX, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, I_PUSHPOP },
263  /* 52 */
264  { "push", { R_DX, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, I_PUSHPOP },
265  /* 53 */
266  { "push", { R_BX, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, I_PUSHPOP },
267  /* 54 */
268  { "push", { R_SP, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, I_PUSHPOP },
269  /* 55 */
270  { "push", { R_BP, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, I_PUSHPOP },
271  /* 56 */
272  { "push", { R_SI, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, I_PUSHPOP },
273  /* 57 */
274  { "push", { R_DI, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, I_PUSHPOP },
275  /* 58 */
276  { "pop", { R_AX, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, I_PUSHPOP },
277  /* 59 */
278  { "pop", { R_CX, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, I_PUSHPOP },
279  /* 5A */
280  { "pop", { R_DX, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, I_PUSHPOP },
281  /* 5B */
282  { "pop", { R_BX, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, I_PUSHPOP },
283  /* 5C */
284  { "pop", { R_SP, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, I_PUSHPOP },
285  /* 5D */
286  { "pop", { R_BP, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, I_PUSHPOP },
287  /* 5E */
288  { "pop", { R_SI, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, I_PUSHPOP },
289  /* 5F */
290  { "pop", { R_DI, ADDR_0, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, I_PUSHPOP },
291  /* 60 */
292  { "pusha", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_PUSHPOP },
293  /* 61 */
294  { "popa", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_PUSHPOP },
295  /* 62 */
296  { "bound", { ADDR_G, ADDR_M, ADDR_0 }, { OP_V, OP_A, OP_0 }, NULL, I_MEMRD | I_CTRL | I_ALU },
297  /* 63 */
298  { "arpl", { ADDR_E, ADDR_G, ADDR_0 }, { OP_W, OP_W, OP_0 }, NULL, I_MEMRD | I_MEMWR | I_CTRL | I_ALU },
299  /* 64 */
300  { "fs", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
301  /* 65 */
302  { "gs", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
303  /* 66 - cambia la dimensione dell'operando */
304  { "opd-size", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
305  /* 67 - cambia la dimensione dell'operando */
306  { "addr-size", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
307  /* 68 */
308  { "push", { ADDR_I, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL, I_PUSHPOP },
309  /* 69 */
310  { "imul", { ADDR_G, ADDR_E, ADDR_I }, { OP_V, OP_V, OP_V }, NULL, I_MEMRD | I_ALU },
311  /* 6A */
312  { "push", { ADDR_I, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_PUSHPOP },
313  /* 6B */
314  { "imul", { ADDR_G, ADDR_E, ADDR_I }, { OP_V, OP_V, OP_B }, NULL, I_MEMRD | I_ALU },
315  /* 6C - SDM pgg 3-328-330 e 3-519-521 */
316  { "insb", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_MEMWR | I_STRING },
317  /* 6D */
318  { "insw", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_MEMWR | I_STRING },
319  /* 6E */
320  { "outsb", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_MEMRD | I_STRING },
321  /* 6F */
322  { "outsw", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_MEMRD | I_STRING },
323  /* 70 */
324  { "jo", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_JUMP | I_CONDITIONAL },
325  /* 71 */
326  { "jno", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_JUMP | I_CONDITIONAL },
327  /* 72 - quest'istruzione è jb/jnae/jc ed equivale a jump if carry set */
328  { "jc", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_JUMP | I_CONDITIONAL },
329  /* 73 - quest'istruzione è jnb/jnae/jnc ed equivale a jump if carry clear */
330  { "jnc", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_JUMP | I_CONDITIONAL },
331  /* 74 */
332  { "jz", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_JUMP | I_CONDITIONAL },
333  /* 75 */
334  { "jnz", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_JUMP | I_CONDITIONAL },
335  /* 76 */
336  { "jbe", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_JUMP | I_CONDITIONAL },
337  /* 77 */
338  { "ja", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_JUMP | I_CONDITIONAL },
339  /* 78 */
340  { "js", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_JUMP | I_CONDITIONAL },
341  /* 79 */
342  { "jns", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_JUMP | I_CONDITIONAL },
343  /* 7A */
344  { "jp", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_JUMP | I_CONDITIONAL },
345  /* 7B */
346  { "jnp", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_JUMP | I_CONDITIONAL },
347  /* 7C */
348  { "jl", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_JUMP | I_CONDITIONAL },
349  /* 7D */
350  { "jge", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_JUMP | I_CONDITIONAL },
351  /* 7E */
352  { "jle", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_JUMP | I_CONDITIONAL },
353  /* 7F */
354  { "jg", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_JUMP | I_CONDITIONAL },
355  /* 80 */
356  { NULL, { ADDR_E, ADDR_I, ADDR_0 }, { OP_B, OP_B, OP_0 }, immed_grp_1, 0 },
357  /* 81 */
358  { NULL, { ADDR_E, ADDR_I, ADDR_0 }, { OP_V, OP_V, OP_0 }, immed_grp_1, 0 },
359  /* 82 */
360  { NULL, { ADDR_E, ADDR_I, ADDR_0 }, { OP_B, OP_B, OP_0 }, immed_grp_1, 0 },
361  /* 83 */
362  { NULL, { ADDR_E, ADDR_I, ADDR_0 }, { OP_V, OP_B, OP_0 }, immed_grp_1, 0 },
363  /* 84 */
364  { "test", { ADDR_E, ADDR_G, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL, I_CTRL | I_ALU | I_MEMRD },
365  /* 85 */
366  { "test", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_CTRL | I_ALU | I_MEMRD },
367  /* 86 */
368  { "xchg", { ADDR_E, ADDR_G, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL, I_MEMRD | I_MEMWR },
369  /* 87 */
370  { "xchg", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_MEMRD | I_MEMWR },
371  /* 88 */
372  { "mov", { ADDR_E, ADDR_G, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL, I_MEMWR },
373  /* 89 */
374  { "mov", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_MEMWR },
375  /* 8A */
376  { "mov", { ADDR_G, ADDR_E, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL, I_MEMRD },
377  /* 8B */
378  { "mov", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_MEMRD },
379  /* 8C */
380  { "mov", { ADDR_E, ADDR_S, ADDR_0 }, { OP_W, OP_W, OP_0 }, NULL, I_MEMWR },
381  /* 8D */
382  { "lea", { ADDR_G, ADDR_M, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL, I_MEMIND },
383  /* 8E */
384  { "mov", { ADDR_S, ADDR_E, ADDR_0 }, { OP_W, OP_W, OP_0 }, NULL, I_MEMRD },
385  /* 8F */
386  { "pop", { ADDR_E, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL, I_PUSHPOP | I_MEMWR },
387  /* 90 */
388  { "nop", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
389  /* 91 */
390  { "xchg", { R_AX, R_CX, ADDR_0 }, { OP_E, OP_E, OP_0 }, NULL, 0 },
391  /* 92 */
392  { "xchg", { R_AX, R_DX, ADDR_0 }, { OP_E, OP_E, OP_0 }, NULL, 0 },
393  /* 93 */
394  { "xchg", { R_AX, R_BX, ADDR_0 }, { OP_E, OP_E, OP_0 }, NULL, 0 },
395  /* 94 */
396  { "xchg", { R_AX, R_SP, ADDR_0 }, { OP_E, OP_E, OP_0 }, NULL, 0 },
397  /* 95 */
398  { "xchg", { R_AX, R_BP, ADDR_0 }, { OP_E, OP_E, OP_0 }, NULL, 0 },
399  /* 96 */
400  { "xchg", { R_AX, R_SI, ADDR_0 }, { OP_E, OP_E, OP_0 }, NULL, 0 },
401  /* 97 */
402  { "xchg", { R_AX, R_DI, ADDR_0 }, { OP_E, OP_E, OP_0 }, NULL, 0 },
403  /* 98 - cbw/cwde dipendono dall'opsize */
404  { "cbw", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
405  /* 99 - cwd/cdq dipendono dall'opsize */
406  { "cwd", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
407  /* 9A */
408  { "callf", { ADDR_A, ADDR_0, ADDR_0 }, { OP_P, OP_0, OP_0 }, NULL, I_CALL},
409  /* 9B */
410  { "fwait", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_FPU | I_CTRL },
411  /* 9C */
412  { "pushf", { ADDR_F, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL, I_PUSHPOP | I_CTRL },
413  /* 9D */
414  { "popf", { ADDR_F, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL, I_PUSHPOP | I_CTRL },
415  /* 9E */
416  { "sahf", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_CTRL },
417  /* 9F */
418  { "lahf", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_CTRL },
419  /* A0 */
420  { "mov", { R_AL, ADDR_O, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL, I_MEMRD },
421  /* A1 */
422  { "mov", { R_AX, ADDR_O, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL, I_MEMRD },
423  /* A2 */
424  { "mov", { ADDR_O, R_AL, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_MEMWR },
425  /* A3 */
426  { "mov", { ADDR_O, R_AX, ADDR_0 }, { OP_V, OP_E, OP_0 }, NULL, I_MEMWR },
427  /* A4 */
428  { "movs", { ADDR_X, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_STRING | I_MEMRD | I_MEMWR },
429  /* A5 */
430  { "movs", { ADDR_Y, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL, I_STRING | I_MEMRD | I_MEMWR },
431  /* A6 */
432  { "cmps", { ADDR_X, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_STRING | I_CTRL | I_ALU | I_MEMRD },
433  /* A7 */
434  { "cmps", { ADDR_Y, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL, I_STRING | I_CTRL | I_ALU | I_MEMRD },
435  /* A8 */
436  { "test", { R_AL, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL, I_CTRL | I_ALU },
437  /* A9 */
438  { "test", { R_AX, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL, I_CTRL | I_ALU},
439  /* AA - stosb e stosw sono etichette per stos m8,16,32 */
440  { "stos", { ADDR_X, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_STRING | I_MEMWR },
441  /* AB - viene presentato come Yv, eAX, ma entrambi sono opzionali */
442  { "stos", { ADDR_Y, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL, I_STRING | I_MEMWR },
443 /* { "stosw", { ADDR_Y, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL, false }, */
444  /* AC */
445  { "lods", { ADDR_X, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_STRING | I_MEMRD },
446  /* AD */
447  { "lods", { ADDR_Y, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL, I_STRING | I_MEMRD },
448  /* AE */
449  { "scas", { ADDR_X, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_STRING | I_MEMRD | I_ALU | I_CTRL },
450  /* AF */
451  { "scas", { ADDR_Y, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL, I_STRING | I_MEMRD | I_ALU | I_CTRL },
452  /* B0 */
453  { "mov", { R_AL, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL, 0 },
454  /* B1 */
455  { "mov", { R_CL, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL, 0 },
456  /* B2 */
457  { "mov", { R_DL, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL, 0 },
458  /* B3 */
459  { "mov", { R_BL, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL, 0 },
460  /* B4 */
461  { "mov", { R_AH, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL, 0 },
462  /* B5 */
463  { "mov", { R_CH, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL, 0 },
464  /* B6 */
465  { "mov", { R_DH, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL, 0 },
466  /* B7 */
467  { "mov", { R_BH, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL, 0 },
468  /* B8 */
469  { "mov", { R_AX, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL, 0 },
470  /* B9 */
471  { "mov", { R_CX, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL, 0 },
472  /* BA */
473  { "mov", { R_DX, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL, 0 },
474  /* BB */
475  { "mov", { R_BX, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL, 0 },
476  /* BC */
477  { "mov", { R_SP, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL, 0 },
478  /* BD */
479  { "mov", { R_BP, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL, 0 },
480  /* BE */
481  { "mov", { R_SI, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL, 0 },
482  /* BF */
483  { "mov", { R_DI, ADDR_I, ADDR_0 }, { OP_E, OP_V, OP_0 }, NULL, 0 },
484  /* C0 */
485  { NULL, { ADDR_E, ADDR_I, ADDR_0 }, { OP_B, OP_B, OP_0 }, shift_grp_2, 0 },
486  /* C1 */
487  { NULL, { ADDR_E, ADDR_I, ADDR_0 }, { OP_V, OP_B, OP_0 }, shift_grp_2, 0 },
488  /* C2 */
489  { "ret", { ADDR_I, ADDR_0, ADDR_0 }, { OP_W, OP_0, OP_0 }, NULL, I_RET},
490  /* C3 */
491  { "ret", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_RET},
492  /* C4 */
493  { "les", { ADDR_G, ADDR_M, ADDR_0 }, { OP_V, OP_P, OP_0 }, NULL, I_MEMRD },
494  /* C5 */
495  { "lds", { ADDR_G, ADDR_M, ADDR_0 }, { OP_V, OP_P, OP_0 }, NULL, I_MEMRD },
496  /* C6 */
497  { NULL, { ADDR_E, ADDR_I, ADDR_0 }, { OP_B, OP_B, OP_0 }, grp_11, 0 },
498  /* C7 */
499  { NULL, { ADDR_E, ADDR_I, ADDR_0 }, { OP_V, OP_V, OP_0 }, grp_11, 0 },
500  /* C8 */
501  { "enter", { ADDR_I, ADDR_I, ADDR_0 }, { OP_W, OP_B, OP_0 }, NULL, 0 },
502  /* C9 */
503  { "leave", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_RET },
504  /* CA */
505  { "retf", { ADDR_I, ADDR_0, ADDR_0 }, { OP_W, OP_0, OP_0 }, NULL, I_RET},
506  /* CB */
507  { "retf", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_RET},
508  /* CC */
509  { "int\t3", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
510  /* CD */
511  { "int", { ADDR_I, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, 0 },
512  /* CE */
513  { "into", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
514  /* CF */
515  { "iret", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_RET },
516  /* D0 */
517  { NULL, { ADDR_E, IMMED_1, ADDR_0 }, { OP_B, OP_0, OP_0 }, shift_grp_2, I_MEMWR },
518  /* D1 */
519  { NULL, { ADDR_E, IMMED_1, ADDR_0 }, { OP_V, OP_0, OP_0 }, shift_grp_2, I_MEMWR },
520  /* D2 */
521  { NULL, { ADDR_E, R_CL, ADDR_0 }, { OP_B, OP_0, OP_0 }, shift_grp_2, I_MEMWR },
522  /* D3 */
523  { NULL, { ADDR_E, R_CL, ADDR_0 }, { OP_V, OP_0, OP_0 }, shift_grp_2, I_MEMWR },
524  /* D4 */
525  { "aam", { ADDR_I, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_ALU },
526  /* D5 */
527  { "aad", { ADDR_I, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_ALU },
528  /* D6 - istruzione non legale */
529  { "ill_d6", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
530  /* D7 */
531  { "xlatb", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_MEMRD },
532  /* D8 */
533  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, d8_opcode, 0 },
534  /* D9 */
535  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, d9_opcode, 0 },
536  /* DA */
537  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, da_opcode, 0 },
538  /* DB */
539  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, db_opcode, 0 },
540  /* DC */
541  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, dc_opcode, 0 },
542  /* DD */
543  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, dd_opcode, 0 },
544  /* DE */
545  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, de_opcode, 0 },
546  /* DF */
547  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, df_opcode, 0 },
548  /* E0 */
549  { "loopne", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_JUMP | I_CONDITIONAL },
550  /* E1 */
551  { "loope", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_JUMP | I_CONDITIONAL },
552  /* E2 */
553  { "loop", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_JUMP | I_CONDITIONAL },
554  /* E3 */
555  { "jcxz", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_JUMP | I_CONDITIONAL },
556  /* E4 */
557  { "in", { R_AL, ADDR_I, ADDR_0 }, { OP_0, OP_B, OP_0 }, NULL, 0 },
558  /* E5 */
559  { "in", { R_AX, ADDR_I, ADDR_0 }, { OP_E, OP_B, OP_0 }, NULL, 0 },
560  /* E6 */
561  { "out", { ADDR_I, R_AL, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, 0 },
562  /* E7 */
563  { "out", { ADDR_I, R_AX, ADDR_0 }, { OP_B, OP_E, OP_0 }, NULL, 0 },
564  /* E8 */
565  { "call", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL, I_CALL },
566  /* E9 - near jmp */
567  { "jmp", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL, I_JUMP },
568  /* EA - far jmp */
569  { "jmp", { ADDR_A, ADDR_0, ADDR_0 }, { OP_P, OP_0, OP_0 }, NULL, I_JUMP },
570  /* EB - short jmp */
571  { "jmp short", { ADDR_J, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_JUMP },
572  /* EC */
573  { "in", { R_AL, R_DX, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
574  /* ED */
575  { "in", { R_AX, R_DX, ADDR_0 }, { OP_E, OP_0, OP_0 }, NULL, 0 },
576  /* EE */
577  { "out", { R_DX, R_AL, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
578  /* EF */
579  { "out", { R_DX, R_AX, ADDR_0 }, { OP_0, OP_E, OP_0 }, NULL, 0 },
580  /* F0 */
581  { "lock", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
582  /* F1 */
583  { "ill_f1", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
584  /* F2 */
585  { "repne", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
586  /* F3 */
587  { "repe", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
588  /* F4 */
589  { "hlt", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
590  /* F5 */
591  { "cmc", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_CTRL },
592  /* F6 */
593  { NULL, { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, unary_grp_3, 0 },
594  /* F7 */
595  { NULL, { ADDR_E, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, unary_grp_3, 0 },
596  /* F8 */
597  { "clc", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_CTRL },
598  /* F9 */
599  { "stc", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_CTRL },
600  /* FA */
601  { "cli", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_CTRL },
602  /* FB */
603  { "sti", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_CTRL },
604  /* FC */
605  { "cld", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_CTRL },
606  /* FD */
607  { "std", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_CTRL },
608  /* FE - inc/dec */
609  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, grp_4, 0 },
610  /* FF - inc/dec */
611  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, grp_5, 0 },
612 };
613 
614 
615 /* tabella di escape opcode 0F */
616 insn esc_0f_opcode_table[] = {
617  /* 00 - grp 6 */
618  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, grp_6, 0 },
619  /* 01 - grp 7 */
620  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, grp_7, 0 },
621  /* 02 */
622  { "lar", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_W, OP_0 }, NULL, I_MEMRD | I_CTRL }, // [FV] Load Access Rights Byte
623  /* 03 */
624  { "lsl", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_W, OP_0 }, NULL, I_MEMRD | I_CTRL }, // [FV] Load Segment Limit
625  /* 04 */
626  { "ill_0f04", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
627  /* 05 */
628  { "ill_0f05", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
629  /* 06 */
630  { "clts", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
631  /* 07 */
632  { "ill_0f07", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
633  /* 08 */
634  { "invd", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
635  /* 09 */
636  { "wbinvd", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
637  /* 0A */
638  { "ill_0f0a", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
639  /* 0B */
640  { "ud2", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
641  /* 0C */
642  { "ill_0f0c", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
643  /* 0D */
644  { "ill_0f0d", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
645  /* 0E */
646  { "ill_0f0e", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
647  /* 0F */
648  { "ill_0f0f", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
649  /* 10 */
650  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f10_17, 0 },
651  /* 11 */
652  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f10_17, 0 },
653  /* 12 */
654  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f10_17, 0 },
655  /* 13 */
656  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f10_17, 0 },
657  /* 14 */
658  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f10_17, 0 },
659  /* 15 */
660  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f10_17, 0 },
661  /* 16 */
662  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f10_17, 0 },
663  /* 17 */
664  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f10_17, 0 },
665  /* 18 - prefetch */
666  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, grp_16, 0 },
667  /* 19 */
668  { "ill_0f19", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
669  /* 1A */
670  { "ill_0f1a", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
671  /* 1B */
672  { "ill_0f1b", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
673  /* 1C */
674  { "ill_0f1c", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
675  /* 1D */
676  { "ill_0f1d", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
677  /* 1E */
678  { "ill_0f1e", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
679  /* 1F */
680  { "nop", { ADDR_E, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL, 0 },
681  /* 20 */
682  { "mov", { ADDR_R, ADDR_C, ADDR_0 }, { OP_D, OP_D, OP_0 }, NULL, I_CTRL },
683  /* 21 */
684  { "mov", { ADDR_R, ADDR_D, ADDR_0 }, { OP_D, OP_D, OP_0 }, NULL, 0 },
685  /* 22 */
686  { "mov", { ADDR_C, ADDR_R, ADDR_0 }, { OP_D, OP_D, OP_0 }, NULL, I_CTRL },
687  /* 23 */
688  { "mov", { ADDR_D, ADDR_R, ADDR_0 }, { OP_D, OP_D, OP_0 }, NULL, 0 },
689  /* 24 */
690  { "mov", { ADDR_R, ADDR_T, ADDR_0 }, { OP_D, OP_D, OP_0 }, NULL, 0 }, // [FV] Viene riportata Illegal
691  /* 25 */
692  { "ill_0f25", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
693  /* 26 */
694  { "mov", { ADDR_T, ADDR_R, ADDR_0 }, { OP_D, OP_D, OP_0 }, NULL, 0 }, // [FV] Viene riportata Illegal
695  /* 27 */
696  { "ill_0f27", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
697  /* 28 */
698  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f28_2f, 0 },
699  /* 29 */
700  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f28_2f, 0 },
701  /* 2A */
702  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f28_2f, 0 },
703  /* 2B */
704  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f28_2f, 0 },
705  /* 2C */
706  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f28_2f, 0 },
707  /* 2D */
708  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f28_2f, 0 },
709  /* 2E */
710  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f28_2f, 0 },
711  /* 2F */
712  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f28_2f, 0 },
713  /* 30 */
714  { "wrmsr", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
715  /* 31 */
716  { "rdtsc", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
717  /* 32 */
718  { "rdmsr", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
719  /* 33 */
720  { "rdpmc", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
721  /* 34 */
722  { "sysenter", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
723  /* 35 */
724  { "sysexit", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
725  /* 36 */
726  { "ill_0f36", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
727  /* 37 */
728  { "ill_0f37", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
729  /* 38 */
730  { "ill_0f38", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
731  /* 39 */
732  { "ill_0f39", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
733  /* 3A */
734  { "ill_0f3a", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
735  /* 3B */
736  { "ill_0f3b", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
737  /* 3C */
738  { "ill_0f3c", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
739  /* 3D */
740  { "ill_0f3d", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
741  /* 3E */
742  { "ill_0f3e", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
743  /* 3F */
744  { "ill_0f3f", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
745  /* 40 */
746  { "cmovo", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_CONDITIONAL | I_MEMRD },
747  /* 41 */
748  { "cmovno", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_CONDITIONAL | I_MEMRD },
749  /* 42 - cmovb/cmovc/cmovnae */
750  { "cmovb", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_CONDITIONAL | I_MEMRD },
751  /* 43 - cmovae/cmovnb/cmovnc */
752  { "cmovnb", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_CONDITIONAL | I_MEMRD },
753  /* 44 - cmove/cmovz */
754  { "cmove", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_CONDITIONAL | I_MEMRD },
755  /* 45 - cmovne/cmovnz */
756  { "cmovne", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_CONDITIONAL | I_MEMRD },
757  /* 46 - cmovbe/cmovna */
758  { "cmovna", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_CONDITIONAL | I_MEMRD },
759  /* 47 - cmova/cmovnbe */
760  { "cmova", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_CONDITIONAL | I_MEMRD },
761  /* 48 */
762  { "cmovs", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_CONDITIONAL | I_MEMRD },
763  /* 49 */
764  { "cmovns", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_CONDITIONAL | I_MEMRD },
765  /* 4A - cmovp/cmovpe */
766  { "cmovp", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_CONDITIONAL | I_MEMRD },
767  /* 4B - cmovnp/cmovpo */
768  { "cmovnp", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_CONDITIONAL | I_MEMRD },
769  /* 4C - cmovl/cmovnge */
770  { "cmovl", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_CONDITIONAL | I_MEMRD },
771  /* 4D - cmovnl/cmovge */
772  { "cmovge", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_CONDITIONAL | I_MEMRD },
773  /* 4E - cmovle/cmovng */
774  { "cmovle", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_CONDITIONAL | I_MEMRD },
775  /* 4F - cmovnle/cmovg */
776  { "cmovg", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_CONDITIONAL | I_MEMRD },
777  /* 50 */
778  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
779  /* 51 */
780  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
781  /* 52 */
782  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
783  /* 53 */
784  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
785  /* 54 */
786  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
787  /* 55 */
788  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
789  /* 56 */
790  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
791  /* 57 */
792  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
793  /* 58 */
794  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
795  /* 59 */
796  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
797  /* 5A */
798  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
799  /* 5B */
800  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
801  /* 5C */
802  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
803  /* 5D */
804  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
805  /* 5E */
806  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
807  /* 5F */
808  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
809  /* 60 */
810  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
811  /* 61 */
812  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
813  /* 62 */
814  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
815  /* 63 */
816  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
817  /* 64 */
818  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
819  /* 65 */
820  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
821  /* 66 */
822  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
823  /* 67 */
824  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
825  /* 68 */
826  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
827  /* 69 */
828  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
829  /* 6A */
830  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
831  /* 6B */
832  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
833  /* 6C */
834  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
835  /* 6D */
836  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
837  /* 6E */
838  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
839  /* 6F */
840  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
841  /* 70 */
842  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f50_70, 0 },
843  /* 71 */
844  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, grp_12, 0 },
845  /* 72 */
846  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, grp_13, 0 },
847  /* 73 */
848  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, grp_14, 0 },
849  /* 74 */
850  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f74_76, 0 },
851  /* 75 */
852  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f74_76, 0 },
853  /* 76 */
854  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f74_76, 0 },
855  /* 77 */
856  { "emms", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_CTRL | I_FPU }, // [FV] Empty MMX Technology State
857  /* 78 */
858  { "mmxud", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }, // [FV] Non gestita
859  /* 79 */
860  { "mmxud", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }, // [FV] Non gestita
861  /* 7A */
862  { "mmxud", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }, // [FV] Non gestita
863  /* 7B */
864  { "mmxud", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }, // [FV] Non gestita
865  /* 7C */
866  { "mmxud", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }, // [FV] Non gestita
867  /* 7D */
868  { "mmxud", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }, // [FV] Non gestita
869  /* 7E */
870  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f7e_7f, 0 },
871  /* 7F */
872  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0f7e_7f, 0 },
873  /* 80 */
874  { "jo", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL, I_CONDITIONAL | I_JUMP },
875  /* 81 */
876  { "jno", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL, I_CONDITIONAL | I_JUMP },
877  /* 82 - jnae/jb/jc */
878  { "jb", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL, I_CONDITIONAL | I_JUMP },
879  /* 83 - jae/jnb/jnc */
880  { "jae", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL, I_CONDITIONAL | I_JUMP },
881  /* 84 - je/jz */
882  { "je", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL, I_CONDITIONAL | I_JUMP },
883  /* 85 - jne/jnz */
884  { "jne", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL, I_CONDITIONAL | I_JUMP },
885  /* 86 - jbe/jna */
886  { "jbe", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL, I_CONDITIONAL | I_JUMP },
887  /* 87 - ja/jnbe */
888  { "ja", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL, I_CONDITIONAL | I_JUMP },
889  /* 88 */
890  { "js", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL, I_CONDITIONAL | I_JUMP },
891  /* 89 */
892  { "jns", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL, I_CONDITIONAL | I_JUMP },
893  /* 8A - jp/jpe */
894  { "jp", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL, I_CONDITIONAL | I_JUMP },
895  /* 8B - jnp/jpo */
896  { "jnp", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL, I_CONDITIONAL | I_JUMP },
897  /* 8C - jl/jnge */
898  { "jl", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL, I_CONDITIONAL | I_JUMP },
899  /* 8D - jnl/jge */
900  { "jge", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL, I_CONDITIONAL | I_JUMP },
901  /* 8E - jle/jng */
902  { "jle", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL, I_CONDITIONAL | I_JUMP },
903  /* 8F - jnle/jg */
904  { "jg", { ADDR_J, ADDR_0, ADDR_0 }, { OP_V, OP_0, OP_0 }, NULL, I_CONDITIONAL | I_JUMP },
905  /* 90 */
906  { "seto", { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_CONDITIONAL | I_MEMWR },
907  /* 91 */
908  { "setno", { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_CONDITIONAL | I_MEMWR },
909  /* 92 - setb/setc/setnae */
910  { "setb", { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_CONDITIONAL | I_MEMWR },
911  /* 93 - setae/setnb/setnc */
912  { "setae", { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_CONDITIONAL | I_MEMWR },
913  /* 94 - sete/setz */
914  { "sete", { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_CONDITIONAL | I_MEMWR },
915  /* 95 - setne/setnz */
916  { "setne", { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_CONDITIONAL | I_MEMWR },
917  /* 96 - setbe/setna */
918  { "setbe", { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_CONDITIONAL | I_MEMWR },
919  /* 97 - seta/setnbe */
920  { "seta", { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_CONDITIONAL | I_MEMWR },
921  /* 98 */
922  { "sets", { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_CONDITIONAL | I_MEMWR },
923  /* 99 */
924  { "setns", { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_CONDITIONAL | I_MEMWR },
925  /* 9A - setp/setpe */
926  { "setp", { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_CONDITIONAL | I_MEMWR },
927  /* 9B - setnp/setpo */
928  { "setnp", { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_CONDITIONAL | I_MEMWR },
929  /* 9C - setl/setnge */
930  { "setl", { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_CONDITIONAL | I_MEMWR },
931  /* 9D - setnl/setge */
932  { "setge", { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_CONDITIONAL | I_MEMWR },
933  /* 9E - setle/setng */
934  { "setle", { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_CONDITIONAL | I_MEMWR },
935  /* 9F - setnle/setg */
936  { "setg", { ADDR_E, ADDR_0, ADDR_0 }, { OP_B, OP_0, OP_0 }, NULL, I_CONDITIONAL | I_MEMWR },
937  /* A0 */
938  { "push", { R_FS, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_PUSHPOP },
939  /* A1 */
940  { "pop", { R_FS, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_PUSHPOP },
941  /* A2 */
942  { "cpuid", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
943  /* A3 */
944  { "bt", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_MEMRD | I_CTRL },
945  /* A4 */
946  { "shld", { ADDR_E, ADDR_G, ADDR_I }, { OP_V, OP_V, OP_B }, NULL, I_MEMWR | I_MEMRD | I_ALU },
947  /* A5 */
948  { "shld", { ADDR_E, ADDR_G, R_CL }, { OP_V, OP_V, OP_0 }, NULL, I_MEMWR | I_MEMRD| I_ALU },
949  /* A6 */
950  { "ill_0fa6", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
951  /* A7 */
952  { "ill_0fa7", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
953  /* A8 */
954  { "push", { R_GS, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_PUSHPOP },
955  /* A9 */
956  { "pop", { R_GS, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, I_PUSHPOP },
957  /* AA */
958  { "rsm", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
959  /* AB */
960  { "bts", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_MEMRD | I_MEMWR | I_CTRL },
961  /* AC */
962  { "shrd", { ADDR_E, ADDR_G, ADDR_I }, { OP_V, OP_V, OP_B }, NULL, I_MEMWR | I_MEMRD | I_ALU },
963  /* AD */
964  { "shrd", { ADDR_E, ADDR_G, R_CL }, { OP_V, OP_V, OP_0 }, NULL, I_MEMWR | I_MEMRD | I_ALU },
965  /* AE */
966  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, grp_15, 0 },
967  /* AF */
968  { "imul", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_MEMRD | I_ALU },
969  /* B0 */
970  { "cmpxchg", { ADDR_E, ADDR_G, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL, I_MEMRD | I_MEMWR | I_CTRL | I_CONDITIONAL | I_ALU },
971  /* B1 */
972  { "cmpxchg", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_MEMRD | I_MEMWR | I_CTRL | I_CONDITIONAL | I_ALU },
973  /* B2 */
974  /* [FV] Mi pare fosse errata, riportava Mp, 00, 00 */
975  { "lss", { ADDR_G, ADDR_M, ADDR_0 }, { OP_V, OP_P, OP_0 }, NULL, I_MEMRD },
976  /* B3 */
977  { "btr", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_MEMRD | I_MEMWR | I_CTRL },
978  /* B4 */
979  /* [FV] Mi pare fosse errata, riportava Mp, 00, 00 */
980  { "lfs", { ADDR_G, ADDR_M, ADDR_0 }, { OP_V, OP_P, OP_0 }, NULL, I_MEMRD },
981  /* B5 */
982  /* [FV] Mi pare fosse errata, riportava Mp, 00, 00 */
983  { "lgs", { ADDR_G, ADDR_M, ADDR_0 }, { OP_V, OP_P, OP_0 }, NULL, I_MEMRD },
984  /* B6 */
985  { "movzx", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_B, OP_0 }, NULL, I_MEMRD },
986  /* B7 */
987  { "movzx", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_W, OP_0 }, NULL, I_MEMRD },
988  /* B8 */
989  { "ill_0fb8", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
990  /* B9 - è sia UD che group 10... boh! */
991  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, grp_10, 0 },
992  /* BA */
993  { NULL, { ADDR_E, ADDR_I, ADDR_0 }, { OP_V, OP_B, OP_0 }, grp_8, 0 },
994  /* BB */
995  { "btc", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_MEMRD | I_MEMWR | I_CTRL | I_ALU },
996  /* BC */
997  { "bsf", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_MEMRD | I_CTRL | I_ALU },
998  /* BD */
999  { "bsr", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_MEMRD | I_CTRL | I_ALU },
1000  /* BE */
1001  { "movsx", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_B, OP_0 }, NULL, I_MEMRD },
1002  /* BF */
1003  { "movsx", { ADDR_G, ADDR_E, ADDR_0 }, { OP_V, OP_W, OP_0 }, NULL, I_MEMRD },
1004  /* C0 */
1005  { "xadd", { ADDR_E, ADDR_G, ADDR_0 }, { OP_B, OP_B, OP_0 }, NULL, I_MEMRD | I_MEMWR | I_ALU },
1006  /* C1 */
1007  { "xadd", { ADDR_E, ADDR_G, ADDR_0 }, { OP_V, OP_V, OP_0 }, NULL, I_MEMRD | I_MEMWR | I_ALU },
1008  /* C2 */
1009  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fc2, 0 },
1010  /* C3 */
1011  /* [FV] Forse era sbagliato, riportava Ed, Gd, 00: inserita OP_Y nella select_operand_size e nella format_addr_g */
1012  { "movnti", { ADDR_M, ADDR_G, ADDR_0 }, { OP_Y, OP_Y, OP_0 }, NULL, I_MEMWR },
1013  /* C4 */
1014  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fc4_c6, 0 },
1015  /* C5 */
1016  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fc4_c6, 0 },
1017  /* C6 */
1018  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fc4_c6, 0 },
1019  /* C7 */
1020  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, grp_9, 0 },
1021  /* C8 */
1022  { "bswap", { R_EAX, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
1023  /* C9 */
1024  { "bswap", { R_ECX, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
1025  /* CA */
1026  { "bswap", { R_EDX, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
1027  /* CB */
1028  { "bswap", { R_EBX, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
1029  /* CC */
1030  { "bswap", { R_ESP, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
1031  /* CD */
1032  { "bswap", { R_EBP, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
1033  /* CE */
1034  { "bswap", { R_ESI, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
1035  /* CF */
1036  { "bswap", { R_EDI, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
1037  /* D0 */
1038  { "ill_0fd0", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
1039  /* D1 */
1040  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef, 0 },
1041  /* D2 */
1042  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef, 0 },
1043  /* D3 */
1044  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef, 0 },
1045  /* D4 */
1046  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef, 0 },
1047  /* D5 */
1048  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef, 0 },
1049  /* D6 */
1050  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef, 0 },
1051  /* D7 */
1052  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef, 0 },
1053  /* D8 */
1054  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef, 0 },
1055  /* D9 */
1056  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef, 0 },
1057  /* DA */
1058  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef, 0 },
1059  /* DB */
1060  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef, 0 },
1061  /* DC */
1062  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef, 0 },
1063  /* DD */
1064  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef, 0 },
1065  /* DE */
1066  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef, 0 },
1067  /* DF */
1068  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef, 0 },
1069  /* E0 */
1070  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef, 0 },
1071  /* E1 */
1072  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef, 0 },
1073  /* E2 */
1074  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef, 0 },
1075  /* E3 */
1076  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef, 0 },
1077  /* E4 */
1078  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef, 0 },
1079  /* E5 */
1080  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef, 0 },
1081  /* E6 */
1082  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef, 0 },
1083  /* E7 */
1084  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef, 0 },
1085  /* E8 */
1086  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef, 0 },
1087  /* E9 */
1088  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef, 0 },
1089  /* EA */
1090  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef, 0 },
1091  /* EB */
1092  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef, 0 },
1093  /* EC */
1094  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef, 0 },
1095  /* ED */
1096  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef, 0 },
1097  /* EE */
1098  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef, 0 },
1099  /* EF */
1100  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0fd1_ef, 0 },
1101  /* F0 */
1102  { "ill_0ff0", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
1103  /* F1 */
1104  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0ff1_fe, 0 },
1105  /* F2 */
1106  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0ff1_fe, 0 },
1107  /* F3 */
1108  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0ff1_fe, 0 },
1109  /* F4 */
1110  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0ff1_fe, 0 },
1111  /* F5 */
1112  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0ff1_fe, 0 },
1113  /* F6 */
1114  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0ff1_fe, 0 },
1115  /* F7 */
1116  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0ff1_fe, 0 },
1117  /* F8 */
1118  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0ff1_fe, 0 },
1119  /* F9 */
1120  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0ff1_fe, 0 },
1121  /* FA */
1122  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0ff1_fe, 0 },
1123  /* FB */
1124  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0ff1_fe, 0 },
1125  /* FC */
1126  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0ff1_fe, 0 },
1127  /* FD */
1128  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0ff1_fe, 0 },
1129  /* FE */
1130  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, esc_0ff1_fe, 0 },
1131  /* FF */
1132  { "ill_0fff", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
1133 };
1134 
1135 
1136 /* esc_0f_opcode
1137  * gestisce tutti gli opcode che iniziano con 0x0f
1138  */
1139 void esc_0f_opcode(struct disassembly_state *state)
1140 {
1141  unsigned char opcode;
1142  insn_table table = esc_0f_opcode_table;
1143 
1144  opcode = state->text[state->pos++];
1145 
1146  // Recupera gli operandi
1147  state->addr[0] = table[opcode].addr_method[0];
1148  state->addr[1] = table[opcode].addr_method[1];
1149  state->addr[2] = table[opcode].addr_method[2];
1150 
1151  state->op[0] = table[opcode].operand_type[0];
1152  state->op[1] = table[opcode].operand_type[1];
1153  state->op[2] = table[opcode].operand_type[2];
1154 
1155  state->opcode[1] = opcode;
1156 
1157  // Copia il mnemonico
1158  if(table[opcode].instruction != NULL) {
1159  strcpy(state->instrument->mnemonic, table[opcode].instruction);
1160  }
1161 
1162  // Preset some flags
1163  state->instrument->flags = table[opcode].flags;
1164 
1165  // Controlla se è un escape opcode
1166  if(table[opcode].instruction == NULL) { // È un escape opcode
1167  // Controllo di sicurezza
1168  if(table[opcode].esc_function == NULL) {
1169  fprintf(stderr, "%s:%d: Errore interno\n", __FILE__, __LINE__);
1170  abort();
1171  } else {
1172  table[opcode].esc_function(state);
1173  }
1174  } else { // Istruzione normale
1175  }
1176 }
1177 
1178 
1179 /* read_modrm
1180  * Salva il byte successivo in state->modrm ed incrementa state->pos
1181  */
1182 inline void read_modrm(struct disassembly_state *state)
1183 {
1184  state->modrm = state->text[state->pos];
1185  state->pos++;
1186  state->read_modrm = true;
1187 }
1188 
1189 
1190 /* d8_opcode
1191  * x87 escape.
1192  */
1193 void d8_opcode(struct disassembly_state *state)
1194 {
1195  // [FV] Dichiaro i seguenti campi
1196  char *instructions[4][2] = {{"fadd", "fmul"}, {"fcom", "fcomp"}, {"fsub", "fsubr"}, {"fdiv", "fdivr"}};
1197  int row, col;
1198  enum addr_method floatingPointRegisters[8] = {R_ST0, R_ST1, R_ST2, R_ST3, R_ST4, R_ST5, R_ST6, R_ST7};
1199 
1200  read_modrm(state);
1201 
1202  // [FV] Sono tutte istruzioni I_FPU
1203  state->instrument->flags |= I_FPU;
1204 
1205  if(state->modrm > 0xbf) {
1206  row = (state->modrm >> 4) - 0xC; // [FV] 0, 1, 2 o 3, a seconda (vedi tabelle manuale)
1207  col = ((state->modrm & 0x0F) < 0x8) ? 0 : 1;
1208 
1209  /* [FV]
1210  switch(state->modrm >> 4) {
1211  case 0xc: // (state->modrm & 0x0f) < 0x8 ? fadd : fmul
1212  case 0xd: // (state->modrm & 0x0f) < 0x8 ? fcom : fcomp
1213  case 0xe: // (state->modrm & 0x0f) < 0x8 ? fsub : fsubr
1214  case 0xf: // (state->modrm & 0x0f) < 0x8 ? fdiv : fdivr
1215  break;
1216  }
1217  */
1218 
1219  state->addr[0] = floatingPointRegisters[0];
1220  state->addr[1] = floatingPointRegisters[state->modrm & 0x07]; // [FV] Errore: nell'originale c'era 0x03!
1221 
1222  /* [FV]
1223  // Selettore registri
1224  switch(state->modrm & 0x03) { // In una tabella di lookup?
1225  case 0x0:
1226  state->addr[1] = R_ST0;
1227  break;
1228  case 0x1:
1229  state->addr[1] = R_ST1;
1230  break;
1231  case 0x2:
1232  state->addr[1] = R_ST2;
1233  break;
1234  case 0x3:
1235  state->addr[1] = R_ST3;
1236  break;
1237  case 0x4:
1238  state->addr[1] = R_ST4;
1239  break;
1240  case 0x5:
1241  state->addr[1] = R_ST5;
1242  break;
1243  case 0x6:
1244  state->addr[1] = R_ST6;
1245  break;
1246  case 0x7:
1247  state->addr[1] = R_ST7;
1248  }*/
1249  } else {
1250  // Il campo nnn del byte ModR/M seleziona l'istruzione
1251  row = ((state->modrm >> 3) & 0x07) / 2;
1252  col = ((state->modrm >> 3) & 0x07) % 2;
1253 
1254  switch((state->modrm >> 3) & 0x07) {
1255  case 0x0: // fadd
1256  strcpy(state->instrument->mnemonic, "fadd");
1257  break;
1258  case 0x1: // fmul
1259  strcpy(state->instrument->mnemonic, "fmul");
1260  break;
1261  case 0x2: // fcom
1262  strcpy(state->instrument->mnemonic, "fcom");
1263  break;
1264  case 0x3: // fcomp
1265  strcpy(state->instrument->mnemonic, "fcomp");
1266  break;
1267  case 0x4: // fsub
1268  strcpy(state->instrument->mnemonic, "fsub");
1269  break;
1270  case 0x5: // fsubr
1271  strcpy(state->instrument->mnemonic, "fsubr");
1272  break;
1273  case 0x6: // fdiv
1274  strcpy(state->instrument->mnemonic, "fdiv");
1275  break;
1276  case 0x7: // fdivr
1277  strcpy(state->instrument->mnemonic, "fdivr");
1278  break;
1279  }
1280 
1281  // L'operando è un float a 32 bit in memoria
1282  state->addr[0] = ADDR_M;
1283  state->op[0] = OP_D;
1284  // [FV] Effettua lettura in memoria
1285  state->instrument->flags |= I_MEMRD;
1286  }
1287 
1288  // [FV] Copio il mnemonico
1289  strcpy(state->instrument->mnemonic, instructions[row][col]);
1290 
1291  if(row == 1) { // [FV] L'istruzione e' una FCOM od una FCOMP
1292  state->instrument->flags |= I_CTRL;
1293  if(col == 1) // [FV] L'istruzione e' una FCOMP
1294  state->instrument->flags |= I_PUSHPOP;
1295  }
1296 }
1297 
1298 /* d9_opcode
1299  * x87 escape.
1300  */
1301 void d9_opcode(struct disassembly_state *state)
1302 {
1303  enum addr_method floatingPointRegisters[8] = {R_ST0, R_ST1, R_ST2, R_ST3, R_ST4, R_ST5, R_ST6, R_ST7};
1304 
1305  read_modrm(state);
1306  state->instrument->flags |= I_FPU;
1307 
1308  if(state->modrm > 0xbf) {
1309  switch(state->modrm >> 4) {
1310  case 0xc:
1311  strcpy(state->instrument->mnemonic, (state->modrm < 0xc8) ? "fld" : "fxch");
1312  state->addr[0] = floatingPointRegisters[state->modrm & 0x07];
1313  if(state->modrm < 0x8C) // [FV] La FLD effettua push di un registro nello FPU register stack
1314  state->instrument->flags |= I_PUSHPOP;
1315  break;
1316 
1317  case 0xd:
1318  if(state->modrm == 0xd0) {
1319  strcpy(state->instrument->mnemonic, "fnop");
1320  } else {
1321  strcpy(state->instrument->mnemonic, "ill_d9");
1322  state->instrument->flags &= ~I_FPU;
1323  }
1324  break; // TODO: Do we need a break here?!
1325 
1326  case 0xe:
1327  switch(state->modrm & 0x0f) {
1328  case 0x0: // fchs
1329  strcpy(state->instrument->mnemonic, "fchs");
1330  state->addr[0] = R_ST0;
1331  break;
1332  case 0x1: // fabs
1333  strcpy(state->instrument->mnemonic, "fabs");
1334  state->addr[0] = R_ST0;
1335  break;
1336  case 0x4: // ftst
1337  strcpy(state->instrument->mnemonic, "fchs");
1338  state->addr[0] = R_ST0;
1339  state->instrument->flags |= I_CTRL;
1340  break;
1341  case 0x5: // fxam
1342  strcpy(state->instrument->mnemonic, "fxam");
1343  state->addr[0] = R_ST0;
1344  state->instrument->flags |= I_CTRL;
1345  break;
1346  case 0x8: // fld1
1347  strcpy(state->instrument->mnemonic, "fld1");
1348  state->instrument->flags |= I_PUSHPOP;
1349  break;
1350  case 0x9: // fldl2t
1351  strcpy(state->instrument->mnemonic, "fldl2t");
1352  state->instrument->flags |= I_PUSHPOP;
1353  break;
1354  case 0xa: // fldl2e
1355  strcpy(state->instrument->mnemonic, "fldl2e");
1356  state->instrument->flags |= I_PUSHPOP;
1357  break;
1358  case 0xb: // fldpi
1359  strcpy(state->instrument->mnemonic, "flpi");
1360  state->instrument->flags |= I_PUSHPOP;
1361  break;
1362  case 0xc: // fldlg2
1363  strcpy(state->instrument->mnemonic, "fldlg2");
1364  state->instrument->flags |= I_PUSHPOP;
1365  break;
1366  case 0xd: // fldln2
1367  strcpy(state->instrument->mnemonic, "fldln2");
1368  state->instrument->flags |= I_PUSHPOP;
1369  break;
1370  case 0xe: // fldz
1371  strcpy(state->instrument->mnemonic, "fldz");
1372  state->instrument->flags |= I_PUSHPOP;
1373  break;
1374  default: // ill_d9
1375  strcpy(state->instrument->mnemonic, "ill_d9");
1376  state->instrument->flags &= ~I_FPU;
1377  break;
1378  }
1379  break;
1380 
1381  case 0xf:
1382  switch(state->modrm & 0X0f) {
1383  case 0x00: // f2xm1
1384  strcpy(state->instrument->mnemonic, "f2xm1");
1385  break;
1386  case 0x01: // fyl2x
1387  strcpy(state->instrument->mnemonic, "fyl2x");
1388  state->instrument->flags |= I_PUSHPOP;
1389  break;
1390  case 0x02: // fptan
1391  strcpy(state->instrument->mnemonic, "fptan");
1392  state->instrument->flags |= I_PUSHPOP;
1393  break;
1394  case 0x03: // fpatan
1395  strcpy(state->instrument->mnemonic, "fpatan");
1396  state->instrument->flags |= I_PUSHPOP;
1397  break;
1398  case 0x04: // fxtract
1399  strcpy(state->instrument->mnemonic, "fxtract");
1400  state->instrument->flags |= I_PUSHPOP;
1401  break;
1402  case 0x05: // fprem1
1403  strcpy(state->instrument->mnemonic, "fprem1");
1404  break;
1405  case 0x06: // fdecstp (Decrement Stack-Top Pointer)
1406  strcpy(state->instrument->mnemonic, "fdecstp");
1407  state->instrument->flags |= I_CTRL;
1408  break;
1409  case 0x07: // fincstp
1410  strcpy(state->instrument->mnemonic, "fincstp");
1411  state->instrument->flags |= I_CTRL;
1412  break;
1413  case 0x08: // fprem
1414  strcpy(state->instrument->mnemonic, "fprem");
1415  break;
1416  case 0x09: // fyl2xp1
1417  strcpy(state->instrument->mnemonic, "fyl2xp1");
1418  state->instrument->flags |= I_PUSHPOP;
1419  break;
1420  case 0x0a: // fsqrt
1421  strcpy(state->instrument->mnemonic, "fsqrt");
1422  break;
1423  case 0x0b: // fsincos
1424  strcpy(state->instrument->mnemonic, "fsincos");
1425  state->instrument->flags |= I_PUSHPOP;
1426  break;
1427  case 0x0c: // frndint
1428  strcpy(state->instrument->mnemonic, "frndint");
1429  break;
1430  case 0x0d: // fscale
1431  strcpy(state->instrument->mnemonic, "fscale");
1432  break;
1433  case 0x0e: // fsin
1434  strcpy(state->instrument->mnemonic, "fsin");
1435  break;
1436  case 0x0f: // fcos
1437  strcpy(state->instrument->mnemonic, "fcos");
1438  break;
1439  }
1440  break;
1441  }
1442  } else {
1443  state->addr[0] = ADDR_M;
1444  // [FV] state->op[0] = OP_B; // Non strettamente corretto, ma funziona!
1445 
1446  // Il campo nnn del byte ModR/M seleziona l'istruzione
1447  switch((state->modrm >> 3) & 0x07) {
1448 
1449  case 0x0: // fld
1450  strcpy(state->instrument->mnemonic, "fld");
1451  state->op[0] = OP_D;
1452  state->instrument->flags |= I_MEMRD | I_PUSHPOP;
1453  break;
1454 
1455  case 0x2: // fst
1456  strcpy(state->instrument->mnemonic, "fst");
1457  state->op[0] = OP_D;
1458  state->instrument->flags |= I_MEMWR;
1459  break;
1460 
1461  case 0x3: // fstp
1462  strcpy(state->instrument->mnemonic, "fstp");
1463  state->op[0] = OP_D;
1464  state->instrument->flags |= I_MEMWR | I_PUSHPOP;
1465  break;
1466 
1467  case 0x4: // fldenv
1468  strcpy(state->instrument->mnemonic, "fldenv");
1469  state->op[0] = OP_FS;
1470  state->instrument->flags |= I_MEMRD;
1471  break;
1472 
1473  case 0x5: // fldcw
1474  strcpy(state->instrument->mnemonic, "fldcw");
1475  state->op[0] = OP_W;
1476  state->instrument->flags |= I_MEMRD | I_CTRL;
1477  break;
1478 
1479  case 0x6: // fstenv
1480  strcpy(state->instrument->mnemonic, "fstenv");
1481  state->op[0] = OP_FS;
1482  state->instrument->flags |= I_MEMWR;
1483  break;
1484 
1485  case 0x7: // fstcw
1486  strcpy(state->instrument->mnemonic, "fstcw");
1487  state->op[0] = OP_W;
1488  state->instrument->flags |= I_MEMWR | I_CTRL;
1489  break;
1490 
1491  default: // ill_d9
1492  state->addr[0] = ADDR_0;
1493  state->op[0] = OP_0;
1494  state->instrument->flags &= ~I_FPU;
1495  }
1496  }
1497 }
1498 
1499 /* da_opcode
1500  * x87 escape.
1501  */
1502 void da_opcode(struct disassembly_state *state)
1503 {
1504  enum addr_method floatingPointRegisters[8] = {R_ST0, R_ST1, R_ST2, R_ST3, R_ST4, R_ST5, R_ST6, R_ST7};
1505 
1506  read_modrm(state);
1507  state->instrument->flags |= I_FPU;
1508 
1509  if(state->modrm > 0xbf) {
1510 
1511  if(state->modrm == 0xe9) {
1512  strcpy(state->instrument->mnemonic, "fucompp");
1513  state->instrument->flags |= I_CTRL | I_PUSHPOP;
1514  return;
1515  }
1516 
1517  switch(state->modrm >> 4) {
1518 
1519  case 0xc:
1520  strcpy(state->instrument->mnemonic, (state->modrm < 0xc8) ? "fcmovb" : "fcmove");
1521  break;
1522 
1523  case 0xd: // (state->modrm < 0xc8) ? fcmovbe : fcmovu
1524  strcpy(state->instrument->mnemonic, (state->modrm < 0xd8) ? "fcmovbe" : "fcmovu");
1525  break;
1526 
1527  default: // ill_da
1528  strcpy(state->instrument->mnemonic, "ill_da");
1529  state->instrument->flags &= ~I_FPU;
1530  return;
1531  }
1532 
1533 
1534 
1535  state->instrument->flags |= I_CONDITIONAL; // [FV] Testa EFLAGS
1536  state->addr[0] = R_ST0;
1537  state->addr[1] = floatingPointRegisters[state->modrm & 0x07];
1538  } else {
1539  // Md
1540  state->addr[0] = ADDR_M;
1541  state->op[0] = OP_D;
1542  state->instrument->flags |= I_MEMRD;
1543 
1544  switch((state->modrm >> 3) & 0x07) {
1545 
1546  case 0x0: // fiadd
1547  strcpy(state->instrument->mnemonic, "fiadd");
1548  break;
1549 
1550  case 0x1: // fimul
1551  strcpy(state->instrument->mnemonic, "fimul");
1552  break;
1553 
1554  case 0x2: // ficom
1555  strcpy(state->instrument->mnemonic, "ficom");
1556  state->instrument->flags |= I_CTRL;
1557  break;
1558 
1559  case 0x3: // ficomp
1560  strcpy(state->instrument->mnemonic, "ficomp");
1561  state->instrument->flags |= I_CTRL | I_PUSHPOP;
1562  break;
1563 
1564  case 0x4: // fisub
1565  strcpy(state->instrument->mnemonic, "fisub");
1566  break;
1567 
1568  case 0x5: // fisubr
1569  strcpy(state->instrument->mnemonic, "fisubr");
1570  break;
1571 
1572  case 0x6: // fidiv
1573  strcpy(state->instrument->mnemonic, "fidiv");
1574  break;
1575 
1576  case 0x7: // fidivr
1577  strcpy(state->instrument->mnemonic, "fidivr");
1578  break;
1579  }
1580 
1581  }
1582 }
1583 
1584 /* db_opcode
1585  * x87 escape.
1586  */
1587 void db_opcode(struct disassembly_state *state)
1588 {
1589  enum addr_method floatingPointRegisters[8] = {R_ST0, R_ST1, R_ST2, R_ST3, R_ST4, R_ST5, R_ST6, R_ST7};
1590 
1591  read_modrm(state);
1592  state->instrument->flags |= I_FPU;
1593 
1594  if(state->modrm > 0xbf) {
1595  if(state->modrm == 0xe2) {
1596  strcpy(state->instrument->mnemonic, "fclex");
1597  state->instrument->flags |= I_CTRL;
1598  return;
1599  } else if(state->modrm == 0xe3) {
1600  strcpy(state->instrument->mnemonic, "finit");
1601  state->instrument->flags |= I_CTRL;
1602  return;
1603  } else if(state->modrm > 0xf7 || (state->modrm > 0xdf && state->modrm < 0xe8)) { // [FV] Errore! C'era scritto "< 0xf0"!
1604  strcpy(state->instrument->mnemonic, "ill_db");
1605  state->instrument->flags &= ~I_FPU;
1606  } else {
1607  state->addr[0] = R_ST0;
1608  state->addr[1] = floatingPointRegisters[state->modrm && 0x07];
1609 
1610  switch(state->modrm >> 4) {
1611  case 0xc:
1612  strcpy(state->instrument->mnemonic, (state->modrm < 0xc8) ? "fcmovnb" : "fcmovne");
1613  state->instrument->flags |= I_CONDITIONAL;
1614  break;
1615  case 0xd:
1616  strcpy(state->instrument->mnemonic, (state->modrm < 0xc8) ? "fcmovnbe" : "fcmovnu");
1617  state->instrument->flags |= I_CONDITIONAL;
1618  break;
1619  case 0xe:
1620  strcpy(state->instrument->mnemonic, "fucomi");
1621  state->instrument->flags |= I_CTRL; // [FV] Affects EFLAGS register
1622  break;
1623  case 0xf: // fcomi
1624  strcpy(state->instrument->mnemonic, "fcomi");
1625  state->instrument->flags |= I_CTRL; // [FV] Affects EFLAGS register
1626  break;
1627  }
1628  }
1629  } else {
1630  state->addr[0] = ADDR_M;
1631 
1632  switch((state->modrm >> 3) & 0x07) {
1633  case 0x0:
1634  strcpy(state->instrument->mnemonic, "fild");
1635  state->op[0] = OP_W;
1636  state->instrument->flags |= I_MEMRD | I_PUSHPOP;
1637  break;
1638  case 0x1: // [FV] Questo case mancava!!!
1639  strcpy(state->instrument->mnemonic, "fisttp");
1640  state->op[0] = OP_W;
1641  state->instrument->flags |= I_MEMWR | I_PUSHPOP;
1642  break;
1643  case 0x2:
1644  strcpy(state->instrument->mnemonic, "fist");
1645  state->instrument->flags |= I_MEMWR;
1646  state->op[0] = OP_D;
1647  break;
1648  case 0x3:
1649  strcpy(state->instrument->mnemonic, "fistp");
1650  state->instrument->flags |= I_MEMWR | I_PUSHPOP;
1651  state->op[0] = OP_D;
1652  break;
1653  case 0x5:
1654  strcpy(state->instrument->mnemonic, "fld");
1655  state->instrument->flags |= I_MEMRD | I_PUSHPOP;
1656  state->op[0] = OP_M80; // [FV] Riportava OP_Q...
1657  break;
1658  case 0x7:
1659  strcpy(state->instrument->mnemonic, "fstp");
1660  state->instrument->flags |= I_MEMWR | I_PUSHPOP;
1661  state->op[0] = OP_M80; // [FV] Riportava OP_Q...
1662  break;
1663  default:
1664  state->addr[0] = ADDR_0;
1665  strcpy(state->instrument->mnemonic, "ill_db");
1666  state->instrument->flags &= ~I_FPU;
1667  }
1668  }
1669 }
1670 
1671 /* dc_opcode
1672  * x87 escape.
1673  */
1674 void dc_opcode(struct disassembly_state *state)
1675 {
1676  enum addr_method floatingPointRegisters[8] = {R_ST0, R_ST1, R_ST2, R_ST3, R_ST4, R_ST5, R_ST6, R_ST7};
1677 
1678  read_modrm(state);
1679  state->instrument->flags |= I_FPU;
1680 
1681  if(state->modrm > 0xbf) {
1682  if(state->modrm >> 4 == 0xd) {
1683  strcpy(state->instrument->mnemonic, "ill_dc");
1684  state->instrument->flags &= ~I_FPU;
1685  } else {
1686  state->addr[1] = R_ST0;
1687  state->addr[0] = floatingPointRegisters[state->modrm & 0x07];
1688 
1689  switch(state->modrm >> 4) {
1690  case 0xc:
1691  strcpy(state->instrument->mnemonic, (state->modrm < 0xc8) ? "fadd" : "fmul");
1692  break;
1693  case 0xe:
1694  strcpy(state->instrument->mnemonic, (state->modrm < 0xc8) ? "fsubr" : "fsub");
1695  break;
1696  case 0xf:
1697  strcpy(state->instrument->mnemonic, (state->modrm < 0xc8) ? "fdivr" : "fdiv");
1698  break;
1699  }
1700  }
1701  } else {
1702  state->addr[0] = ADDR_M;
1703  state->op[0] = OP_Q;
1704  state->instrument->flags |= I_MEMRD;
1705 
1706  switch((state->modrm >> 3) & 0x07) {
1707  case 0x00:
1708  strcpy(state->instrument->mnemonic, "fadd");
1709  break;
1710  case 0x01:
1711  strcpy(state->instrument->mnemonic, "fmul");
1712  break;
1713  case 0x02:
1714  strcpy(state->instrument->mnemonic, "fcom");
1715  state->instrument->flags |= I_CTRL;
1716  break;
1717  case 0x03:
1718  strcpy(state->instrument->mnemonic, "fcomp");
1719  state->instrument->flags |= I_CTRL | I_PUSHPOP;
1720  break;
1721  case 0x04:
1722  strcpy(state->instrument->mnemonic, "fsub");
1723  break;
1724  case 0x05:
1725  strcpy(state->instrument->mnemonic, "fsubr");
1726  break;
1727  case 0x06:
1728  strcpy(state->instrument->mnemonic, "fdiv");
1729  break;
1730  case 0x07:
1731  strcpy(state->instrument->mnemonic, "fdivr");
1732  break;
1733  }
1734  }
1735 }
1736 
1737 /* dd_opcode
1738  * x87 escape.
1739  */
1740 void dd_opcode(struct disassembly_state *state)
1741 {
1742  enum addr_method floatingPointRegisters[8] = {R_ST0, R_ST1, R_ST2, R_ST3, R_ST4, R_ST5, R_ST6, R_ST7};
1743 
1744  read_modrm(state);
1745  state->instrument->flags |= I_FPU;
1746 
1747  if(state->modrm > 0xbf) {
1748  if((state->modrm >= 0xc8 && state->modrm <= 0xcf) || state->modrm >= 0xf0) { // [FV] if(state->modrm < 0xc8 || state->modrm > 0xef) ???
1749  strcpy(state->instrument->mnemonic, "ill_dd");
1750  state->instrument->flags &= ~I_FPU;
1751  return;
1752  }
1753  else {
1754  if(state->modrm > 0xdf && state->modrm < 0xe8)
1755  state->addr[1] = R_ST0;
1756 
1757  state->addr[0] = floatingPointRegisters[state->modrm & 0x07];
1758 
1759  switch(state->modrm >> 4) {
1760  case 0xc:
1761  strcpy(state->instrument->mnemonic, "ffree");
1762  break;
1763  case 0xd:
1764  if(state->modrm < 0xd8) {
1765  strcpy(state->instrument->mnemonic, "fst");
1766  // [FV] state->instrument->to_instrument = true; - Perche'?
1767  } else { // fstp
1768  strcpy(state->instrument->mnemonic, "fstp");
1769  // [FV] state->instrument->to_instrument = true; - Perché?
1770  state->instrument->flags |= I_PUSHPOP;
1771  }
1772  break;
1773  case 0xe:
1774  if(state->modrm < 0xe8) {
1775  strcpy(state->instrument->mnemonic, "fucom");
1776  state->instrument->flags |= I_CTRL;
1777  } else {
1778  strcpy(state->instrument->mnemonic, "fucomp");
1779  state->instrument->flags |= I_PUSHPOP | I_CTRL;
1780  }
1781  break;
1782  }
1783  }
1784  } else {
1785  state->addr[0] = ADDR_M;
1786  state->op[0] = OP_Q; // [FV] C'era scritto OP_B...
1787 
1788  switch((state->modrm >> 3) & 0x07) {
1789  case 0x0: // fld
1790  strcpy(state->instrument->mnemonic, "fld");
1791  state->instrument->flags |= I_MEMRD | I_PUSHPOP;
1792  break;
1793  case 0x1: // [FV] Questo case mancava!!!
1794  strcpy(state->instrument->mnemonic, "fisttp");
1795  state->instrument->flags |= I_MEMWR | I_PUSHPOP;
1796  break;
1797  case 0x2: // fst
1798  strcpy(state->instrument->mnemonic, "fst");
1799  state->instrument->flags |= I_MEMWR;
1800  break;
1801  case 0x3: // fstp
1802  strcpy(state->instrument->mnemonic, "fstp");
1803  state->instrument->flags |= I_MEMWR | I_PUSHPOP;
1804  break;
1805  case 0x4: // frstor
1806  strcpy(state->instrument->mnemonic, "frstor");
1807  state->instrument->flags |= I_MEMRD | I_CTRL;
1808  state->op[0] = OP_FSR;
1809  break;
1810  case 0x6: // fsave
1811  strcpy(state->instrument->mnemonic, "fsave");
1812  state->instrument->flags |= I_MEMWR | I_CTRL;
1813  state->op[0] = OP_FSR;
1814  break;
1815  case 0x7: // fstsw
1816  strcpy(state->instrument->mnemonic, "fstsw");
1817  state->op[0] = OP_W; // [FV]
1818  state->instrument->flags |= I_MEMWR | I_CTRL;
1819  break;
1820  default: // ill_dd
1821  strcpy(state->instrument->mnemonic, "ill_dd");
1822  state->addr[0] = ADDR_0;
1823  state->op[0] = OP_0;
1824  state->instrument->flags &= ~I_FPU;
1825  }
1826  }
1827 }
1828 
1829 /* de_opcode
1830  * x87 escape.
1831  */
1832 void de_opcode(struct disassembly_state *state)
1833 {
1834  enum addr_method floatingPointRegisters[8] = {R_ST0, R_ST1, R_ST2, R_ST3, R_ST4, R_ST5, R_ST6, R_ST7};
1835 
1836  read_modrm(state);
1837  state->instrument->flags |= I_FPU;
1838 
1839  if(state->modrm > 0xbf) {
1840  state->instrument->flags |= I_PUSHPOP;
1841  if(state->modrm == 0xd9){ // fcompp
1842  strcpy(state->instrument->mnemonic, "fcompp");
1843  state->instrument->flags |= I_CTRL;
1844  }
1845  else if(state->modrm >> 4 == 0xd) {
1846  strcpy(state->instrument->mnemonic, "ill_de");
1847  state->instrument->flags &= ~I_PUSHPOP & ~I_FPU;
1848  }
1849  else {
1850  state->addr[1] = R_ST0;
1851  state->addr[0] = floatingPointRegisters[state->modrm & 0x07];
1852 
1853  switch(state->modrm & 0xf8) {
1854  case 0xc0:
1855  strcpy(state->instrument->mnemonic, "faddp");
1856  break;
1857  case 0xc8:
1858  strcpy(state->instrument->mnemonic, "fmulp");
1859  break;
1860  case 0xe0:
1861  strcpy(state->instrument->mnemonic, "fsubrp");
1862  break;
1863  case 0xe8:
1864  strcpy(state->instrument->mnemonic, "fsubp");
1865  break;
1866  case 0xf0:
1867  strcpy(state->instrument->mnemonic, "fdivrp");
1868  break;
1869  case 0xf8:
1870  strcpy(state->instrument->mnemonic, "fdivp");
1871  }
1872  }
1873  } else {
1874  state->addr[0] = ADDR_M;
1875  state->op[0] = OP_W;
1876  state->instrument->flags |= I_MEMRD;
1877 
1878  switch((state->modrm >> 3) & 0x07) {
1879  case 0x00:
1880  strcpy(state->instrument->mnemonic, "fiadd");
1881  break;
1882  case 0x01:
1883  strcpy(state->instrument->mnemonic, "fimul");
1884  break;
1885  case 0x02:
1886  strcpy(state->instrument->mnemonic, "ficom");
1887  break;
1888  case 0x03:
1889  strcpy(state->instrument->mnemonic, "ficomp");
1890  state->instrument->flags |= I_PUSHPOP;
1891  break;
1892  case 0x04:
1893  strcpy(state->instrument->mnemonic, "fisub");
1894  break;
1895  case 0x05:
1896  strcpy(state->instrument->mnemonic, "fisubr");
1897  break;
1898  case 0x06:
1899  strcpy(state->instrument->mnemonic, "fidiv");
1900  break;
1901  case 0x07:
1902  strcpy(state->instrument->mnemonic, "fidivr");
1903  break;
1904  }
1905  }
1906 }
1907 
1908 /* df_opcode
1909  * x87 escape.
1910  */
1911 void df_opcode(struct disassembly_state *state)
1912 {
1913  enum addr_method floatingPointRegisters[8] = {R_ST0, R_ST1, R_ST2, R_ST3, R_ST4, R_ST5, R_ST6, R_ST7};
1914 
1915  read_modrm(state);
1916  state->instrument->flags |= I_FPU;
1917 
1918  // TODO: da aggiungere che scrivono in memoria: fisttp
1919  // [FV] Fatto.
1920 
1921  if(state->modrm > 0xbf) {
1922  if(state->modrm == 0xe0) {
1923  strcpy(state->instrument->mnemonic, "fstsw");
1924  state->addr[0] = R_AX;
1925  state->instrument->flags |= I_CTRL;
1926  } else if(state->modrm < 0xe8 || state->modrm > 0xf7) {
1927  strcpy(state->instrument->mnemonic, "ill_df");
1928  state->instrument->flags &= ~I_FPU;
1929  }
1930  else {
1931  state->addr[0] = R_ST0;
1932  state->addr[1] = floatingPointRegisters[state->modrm & 0x07];
1933  state->instrument->flags |= I_CTRL | I_PUSHPOP; // [FV] EFALGS modificati
1934  strcpy(state->instrument->mnemonic, (state->modrm > 0xef) ? "fcomip" : "fucomip");
1935  }
1936  } else {
1937  unsigned char enc = (state->modrm >> 3) & 0x07;
1938  state->addr[0] = ADDR_M;
1939 
1940  // Scrivono in memoria soltanto fist, fistp, fbstp
1941  switch(enc) {
1942  case 0x00:
1943  strcpy(state->instrument->mnemonic, "fild");
1944  state->op[0] = OP_W;
1945  state->instrument->flags |= I_MEMRD | I_PUSHPOP;
1946  break;
1947  case 0x01:
1948  strcpy(state->instrument->mnemonic, "fisttp");
1949  state->op[0] = OP_W;
1950  state->instrument->flags |= I_MEMWR | I_PUSHPOP;
1951  break;
1952  case 0x02: // fist
1953  strcpy(state->instrument->mnemonic, "fist");
1954  state->op[0] = OP_W;
1955  state->instrument->flags |= I_MEMWR;
1956  break;
1957  case 0x03: // fistp
1958  strcpy(state->instrument->mnemonic, "fistp");
1959  state->op[0] = OP_W;
1960  state->instrument->flags |= I_MEMWR | I_PUSHPOP;
1961  break;
1962  case 0x04:
1963  strcpy(state->instrument->mnemonic, "fbld");
1964  state->op[0] = OP_M80;
1965  state->instrument->flags |= I_MEMRD;
1966  break;
1967  case 0x05:
1968  strcpy(state->instrument->mnemonic, "fild");
1969  state->op[0] = OP_Q;
1970  state->instrument->flags |= I_MEMRD | I_PUSHPOP;
1971  break;
1972  case 0x06: // fbstp
1973  strcpy(state->instrument->mnemonic, "fbstp");
1974  state->op[0] = OP_M80;
1975  state->instrument->flags |= I_MEMWR | I_PUSHPOP;
1976  break;
1977  case 0x07: // fistp
1978  strcpy(state->instrument->mnemonic, "fistp");
1979  state->op[0] = OP_Q;
1980  state->instrument->flags |= I_MEMWR | I_PUSHPOP;
1981  break;
1982  }
1983  }
1984 }
1985 
1986 /* Estensioni per gli opcode SSE/SSE2 - per queste istruzioni un terzo byte
1987  * opzionale specifica l'istruzione ed i suoi operandi. */
1988 
1989 /* sse_prefix_to_index
1990  * Converte un prefisso all'opcode SSE/SSE2 in un indice della tabella degli escape
1991  * opcode.
1992  */
1993 int sse_prefix_to_index (unsigned char sse_prefix)
1994 {
1995  int idx = 0;
1996 
1997  switch(sse_prefix) {
1998  case 0x00:
1999  idx = 0;
2000  break;
2001  case 0x66:
2002  idx = 1;
2003  break;
2004  case 0xf2:
2005  idx = 2;
2006  break;
2007  case 0xf3:
2008  idx = 3;
2009  break;
2010  default:
2011  fprintf(stderr, "%s:%d: Unexpected SSE prefix: %d\n", __FILE__, __LINE__, sse_prefix);
2012  }
2013 
2014  return idx;
2015 }
2016 
2017 
2018 /* sse_esc
2019  * Processa gli opcode con gli escape SSE/SSE2. L'istruzione è in:
2020  * table[state->opcode[1] - base][sse_prefix_to_index (state->sse_prefix)]
2021  * Vengono riempite tutte le informazioni di interessa in state.
2022  */
2023 void sse_esc(struct disassembly_state *state, insn table[][4], unsigned char base) {
2024  insn instruction;
2025 
2026  instruction = (table[state->opcode[1] - base][sse_prefix_to_index(state->sse_prefix)]);
2027 
2028  state->addr[0] = instruction.addr_method[0];
2029  state->addr[1] = instruction.addr_method[1];
2030  state->addr[2] = instruction.addr_method[2];
2031 
2032  state->op[0] = instruction.operand_type[0];
2033  state->op[1] = instruction.operand_type[1];
2034  state->op[2] = instruction.operand_type[2];
2035 
2036  state->instrument->flags = instruction.flags;
2037 
2038 }
2039 
2040 
2041 /* esc_0f10_17
2042  * Opcodes da 0f10 a 0f17.
2043  */
2044 void esc_0f10_17 (struct disassembly_state *state)
2045 {
2046  insn table[][4] = {
2047  /* 0F10 */
2048  {
2049  /* 00 */
2050  { "movups", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL, I_MEMRD | I_SSE | I_XMM },
2051  /* 66 */
2052  { "movupd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_PD, OP_0 }, NULL, I_MEMRD | I_SSE2 | I_XMM },
2053  /* F2 */
2054  { "movsd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SD, OP_SD, OP_0 }, NULL, I_MEMRD | I_SSE2 | I_XMM },
2055  /* F3 */
2056  { "movss", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SS, OP_SS, OP_0 }, NULL, I_MEMRD | I_SSE | I_XMM }
2057  },
2058  /* 0F11 */
2059  {
2060  /* 00 */
2061  { "movups", { ADDR_W, ADDR_V, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL, I_MEMWR | I_SSE | I_XMM },
2062  /* 66 */
2063  { "movupd", { ADDR_W, ADDR_V, ADDR_0 }, { OP_PD, OP_PD, OP_0 }, NULL, I_MEMWR | I_SSE2 | I_XMM },
2064  /* F2 */
2065  { "movsd", { ADDR_W, ADDR_V, ADDR_0 }, { OP_SD, OP_SD, OP_0 }, NULL, I_MEMWR | I_SSE2 | I_XMM },
2066  /* F3 */
2067  { "movss", { ADDR_W, ADDR_V, ADDR_0 }, { OP_SS, OP_SS, OP_0 }, NULL, I_MEMWR | I_SSE | I_XMM }
2068  },
2069  /* 0F12 */
2070  {
2071  /* 00 - situazione strana */
2072  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2073  /* 66 */
2074  { "movlpd", { ADDR_V, ADDR_M, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_MEMRD | I_SSE2 | I_XMM }, // [FV] Era segnata Vq, Ws?!
2075  /* F2 */
2076  { "ill_f20f12", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2077  /* F3 */
2078  { "ill_f20f13", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2079  },
2080  /* 0F13 */
2081  {
2082  /* 00 */
2083  { "movlps", { ADDR_M, ADDR_V, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_MEMWR | I_SSE | I_XMM }, // [FV] Era segnata Vq, Wq?
2084  /* 66 */
2085  { "movlpd", { ADDR_M, ADDR_V, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_MEMWR | I_SSE2 | I_XMM }, // [FV] Era segnata Vq, Wq?
2086  /* F2 */
2087  { "ill_f20f13", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2088  /* F3 */
2089  { "ill_f30f13", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2090  },
2091  /* 0F14 */
2092  {
2093  /* 00 */
2094  { "unpcklps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_Q, OP_0 }, NULL, I_MEMRD | I_SSE | I_XMM },
2095  /* 66 */
2096  { "unpcklpd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_Q, OP_0 }, NULL, I_MEMRD | I_SSE2 | I_XMM },
2097  /* F2 */
2098  { "ill_f20f14", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2099  /* F3 */
2100  { "ill_f30f14", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2101  },
2102  /* 0F15 */
2103  {
2104  /* 00 */
2105  { "unpckhps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_Q, OP_0 }, NULL, I_MEMRD | I_SSE | I_XMM },
2106  /* 66 */
2107  { "unpckhpd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_Q, OP_0 }, NULL, I_MEMRD | I_SSE2 | I_XMM },
2108  /* F2 */
2109  { "ill_f20f15", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2110  /* F3 */
2111  { "ill_f30f15", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2112  },
2113  /* 0F16 */
2114  {
2115  /* 00 - situazione strana */
2116  { NULL, { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2117  /* 66 */
2118  { "movhpd", { ADDR_V, ADDR_M, ADDR_0 }, { OP_DQ, OP_Q, OP_0 }, NULL, I_MEMRD | I_SSE2 }, // [FV] Era riportato Vq, Wq!?
2119  /* F2 */
2120  { "ill_f20f16", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2121  /* F3 */
2122  { "ill_f30f16", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2123  },
2124  /* 0F17 */
2125  {
2126  /* 00 */
2127  { "movhps", { ADDR_M, ADDR_V, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_MEMWR | I_SSE }, // [FV] Riportava addr[0] = ADDR_W!
2128  /* 66 */
2129  { "movhpd", { ADDR_M, ADDR_V, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_MEMWR | I_SSE2 }, // [FV] Riportava addr[0] = ADDR_W!
2130  /* F2 */
2131  { "ill_f20f17", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2132  /* F3 */
2133  { "ill_f30f17", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2134  }
2135  };
2136 
2137  if((state->opcode[1] == 0x12 || state->opcode[1] == 0x16) && state->sse_prefix == 0) {
2138  unsigned char opcode = state->opcode[1];
2139  int idx = 0;
2140  insn tbl[] = {
2141  /* 0f12 */
2142  /* mem->reg only */
2143  // [FV] Riportava Wq, Vq ed era segnata da non instrumentare !?
2144  { "movlps", { ADDR_V, ADDR_M, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_MEMWR | I_SSE },
2145  /* reg->reg only */
2146  { "movhlps", { ADDR_V, ADDR_V, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, 0 /* [FV] I_SSE3 */ },
2147  /* 0f16 */
2148  /* mem->reg only */
2149  // [FV] Riportava Vq, Wq
2150  { "movhps", { ADDR_V, ADDR_M, ADDR_0 }, { OP_DQ, OP_Q, OP_0 }, NULL, I_MEMRD | I_SSE },
2151  /* reg->reg only */
2152  // [FV] Riportava Vq, Vq
2153  { "movlhps", { ADDR_V, ADDR_V, ADDR_0 }, { OP_DQ, OP_Q, OP_0 }, NULL, I_SSE }
2154  };
2155 
2156  read_modrm(state);
2157 
2158  if(state->modrm >> 6 == 0x3) { // reg->reg
2159  if(opcode == 0x12)
2160  idx = 1;
2161  else
2162  idx = 3;
2163  } else { // mem->reg
2164  if(opcode == 0x12)
2165  idx = 0;
2166  else
2167  idx = 2;
2168  }
2169 
2170  state->addr[0] = tbl[idx].addr_method[0];
2171  state->addr[1] = tbl[idx].addr_method[1];
2172  state->addr[2] = tbl[idx].addr_method[2];
2173 
2174  state->op[0] = tbl[idx].operand_type[0];
2175  state->op[1] = tbl[idx].operand_type[1];
2176  state->op[2] = tbl[idx].operand_type[2];
2177 
2178  return;
2179  }
2180 
2181  sse_esc(state, table, 0x10);
2182 }
2183 
2184 void esc_0f28_2f (struct disassembly_state *state)
2185 {
2186  insn table[][4] = {
2187  /* 0F28 */
2188  {
2189  /* 00 */
2190  { "movaps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL, I_MEMRD | I_SSE | I_XMM },
2191  /* 66 */
2192  { "movapd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_PD, OP_0 }, NULL, I_MEMRD | I_SSE2 | I_XMM },
2193  /* F2 */
2194  { "ill_f20f28", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2195  /* F3 */
2196  { "ill_f30f28", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2197  },
2198  /* 0F29 */
2199  {
2200  /* 00 */
2201  { "movaps", { ADDR_W, ADDR_V, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL, I_MEMWR | I_SSE | I_XMM },
2202  /* 66 */
2203  { "movapd", { ADDR_W, ADDR_V, ADDR_0 }, { OP_PD, OP_PD, OP_0 }, NULL, I_MEMWR | I_SSE2 | I_XMM },
2204  /* F2 */
2205  { "ill_f20f29", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2206  /* F3 */
2207  { "ill_f30f29", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2208  },
2209  /* 0F2A */
2210  {
2211  /* 00 */
2212  { "cvtpi2ps", { ADDR_V, ADDR_Q, ADDR_0 }, { OP_PS, OP_PI, OP_0 }, NULL, I_MEMRD | I_MMX | I_XMM }, // [FV] Invece di OP_PI riportava OP_Q
2213  /* 66 */
2214  { "cvtpi2pd", { ADDR_V, ADDR_Q, ADDR_0 }, { OP_PD, OP_PI, OP_0 }, NULL, I_MEMRD | I_MMX | I_XMM }, // [FV] Riportava Vpd, Qdq!?
2215  /* F2 */
2216  { "cvtsi2sd", { ADDR_V, ADDR_E, ADDR_0 }, { OP_SD, OP_Y, OP_0 }, NULL, I_MEMRD | I_SSE2 | I_XMM }, // [FV] Riportava Vsd, Ed
2217  /* F3 */
2218  { "cvtsi2ss", { ADDR_V, ADDR_E, ADDR_0 }, { OP_SS, OP_Y, OP_0 }, NULL, I_MEMRD | I_SSE | I_XMM } // [FV] Riportava Vss, Ed
2219  },
2220  /* 0F2B */
2221  {
2222  /* 00 */
2223  { "movntps", { ADDR_M, ADDR_V, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL, I_MEMWR | I_SSE | I_XMM }, // [FV] Era segnato Wps, Vps
2224  /* 66 */
2225  { "movntpd", { ADDR_M, ADDR_V, ADDR_0 }, { OP_PD, OP_PD, OP_0 }, NULL, I_MEMWR | I_SSE2 | I_XMM }, // [FV] Era segnato Wpd, Vpd
2226  /* F2 */
2227  { "ill_f20f2b", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2228  /* F3 */
2229  { "ill_f30f2b", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2230  },
2231  /* 0F2C */
2232  {
2233  /* 00 */
2234  { "cvttps2pi", { ADDR_P, ADDR_W, ADDR_0 }, { OP_PI, OP_PS, OP_0 }, NULL, I_MEMRD | I_MMX | I_XMM }, // [FV] Riportava Qq, Wps
2235  /* 66 */
2236  { "cvttpd2pi", { ADDR_P, ADDR_W, ADDR_0 }, { OP_PI, OP_PD, OP_0}, NULL, I_MEMRD | I_MMX | I_XMM }, // [FV] Riportava Qdq, Wpd
2237  /* F2 */
2238  { "cvttsd2si", { ADDR_G, ADDR_W, ADDR_0 }, { OP_Y, OP_SD, OP_0 }, NULL, I_MEMRD | I_SSE2 | I_XMM }, // [FV] Riportava Gd, Wsd
2239  /* F3 */
2240  { "cvttss2si", { ADDR_G, ADDR_W, ADDR_0 }, { OP_Y, OP_SS, OP_0 }, NULL, I_MEMRD | I_SSE | I_XMM } // [FV] Riportava Gd, Wss
2241  },
2242  /* 0F2D */
2243  {
2244  /* 00 */
2245  { "cvtps2pi", { ADDR_P, ADDR_W, ADDR_0 }, { OP_PI, OP_PS, OP_0 }, NULL, I_MEMRD | I_MMX | I_XMM }, // [FV] Riportava Qq, Wps
2246  /* 66 */
2247  { "cvtpd2pi", { ADDR_P, ADDR_W, ADDR_0 }, { OP_PI, OP_PD, OP_0}, NULL, I_MEMRD | I_MMX | I_XMM }, // [FV] Riportava Qdq, Wpd (Mi pare sia Ppi ma il manuale riporta Qpi ?!?)
2248  /* F2 */
2249  { "cvtsd2si", { ADDR_G, ADDR_W, ADDR_0 }, { OP_Y, OP_SD, OP_0 }, NULL, I_MEMRD | I_SSE2 | I_XMM }, // [FV] Riportava Gd, Wsd
2250  /* F3 */
2251  { "cvtss2si", { ADDR_G, ADDR_W, ADDR_0 }, { OP_Y, OP_SS, OP_0 }, NULL, I_MEMRD | I_SSE | I_XMM } // [FV] Riportava Gd, Wss
2252  },
2253  /* OF2E */
2254  {
2255  /* 00 */
2256  { "ucomiss", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SS, OP_SS, OP_0 }, NULL, I_ALU | I_CTRL | I_MEMRD | I_SSE | I_XMM },
2257  /* 66 */
2258  { "ucomisd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SD, OP_SD, OP_0 }, NULL, I_ALU | I_CTRL | I_MEMRD | I_SSE2 | I_XMM },
2259  /* F2 */
2260  { "ill_f20f2e", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2261  /* F3 */
2262  { "ill_f30f2e", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2263  },
2264  /* 0F2F */
2265  {
2266  /* 00 */
2267  { "comiss", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL, I_ALU | I_CTRL | I_MEMRD | I_SSE | I_XMM },
2268  /* 66 */
2269  { "comisd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SD, OP_SD, OP_0 }, NULL, I_ALU | I_CTRL | I_MEMRD | I_SSE2 | I_XMM },
2270  /* F2 */
2271  { "ill_f20f2f", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2272  /* F3 */
2273  { "ill_f30f2f", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2274  }
2275  };
2276 
2277  sse_esc(state, table, 0x28);
2278 }
2279 
2280 void esc_0f50_70 (struct disassembly_state *state)
2281 {
2282 
2283  // TODO: 66 0f 3a 17: EXTRACTPS scrive in memoria
2284  // 66 0f 3a 14: PEXTRB
2285  // 66 0f 3a 16: PEXTRD
2286  // 66 0f 3a 16: PEXTRQ
2287  // 66 0f 3a 15: PEXTRW
2288 
2289  insn table[][4] = {
2290  /* 0F50 */
2291  {
2292  /* 00 */
2293  { "movmskps", { ADDR_G, ADDR_V, ADDR_0 }, { OP_Y, OP_PS, OP_0 }, NULL, I_SSE }, // [FV] Riportava Ed, Vps
2294  /* 66 */
2295  { "movmskpd", { ADDR_G, ADDR_V, ADDR_0 }, { OP_Y, OP_PD, OP_0 }, NULL, I_SSE2 }, // [FV] Riportava Ed, Vpd
2296  /* F2 */
2297  { "ill_f20f50", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2298  /* F3 */
2299  { "ill_f30f50", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2300  },
2301  /* 0F51 */
2302  {
2303  /* 00 */
2304  { "sqrtps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL, I_MEMRD | I_SSE | I_XMM },
2305  /* 66 */
2306  { "sqrtpd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_PD, OP_0 }, NULL, I_MEMRD | I_SSE2 | I_XMM },
2307  /* F2 */
2308  { "sqrtsd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SD, OP_SD, OP_0 }, NULL, I_MEMRD | I_SSE2 | I_XMM },
2309  /* F3 */
2310  { "sqrtss", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SS, OP_SS, OP_0 }, NULL, I_MEMRD | I_SSE | I_XMM }
2311  },
2312  /* 0F52 */
2313  {
2314  /* 00 */
2315  { "rsqrtps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL, I_MEMRD | I_SSE | I_XMM },
2316  /* 66 */
2317  { "ill_660f52", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2318  /* F2 */
2319  { "ill_f20f52", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2320  /* F3 */
2321  { "rsqrtss", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SS, OP_SS, OP_0 }, NULL, I_MEMRD | I_SSE | I_XMM }
2322  },
2323  /* 0F53 */
2324  {
2325  /* 00 */
2326  { "rcpps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL, I_MEMRD | I_SSE | I_XMM },
2327  /* 66 */
2328  { "ill_660f52", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2329  /* F2 */
2330  { "ill_f20f52", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2331  /* F3 */
2332  { "rcpss", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SS, OP_SS, OP_0 }, NULL, I_MEMRD | I_SSE | I_XMM }
2333  },
2334  /* 0F54 */
2335  {
2336  /* 00 */
2337  { "andps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL, I_MEMRD | I_ALU | I_SSE | I_XMM },
2338  /* 66 */
2339  { "andpd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_PD, OP_0 }, NULL, I_MEMRD | I_ALU | I_SSE2 | I_XMM }, // [FV] Il manuale riporta Wpd, Vpd
2340  /* F2 */
2341  { "ill_f20f54", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2342  /* F3 */
2343  { "ill_f30f54", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2344  },
2345  /* 0F55 */
2346  {
2347  /* 00 */
2348  { "andnps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL, I_MEMRD | I_ALU | I_SSE | I_XMM },
2349  /* 66 */
2350  { "andnpd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_PD, OP_0 }, NULL, I_MEMRD | I_ALU | I_SSE2 | I_XMM }, // [FV] Il manuale riporta Wpd, Vpd
2351  /* F2 */
2352  { "ill_f20f55", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2353  /* F3 */
2354  { "ill_f30f55", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2355  },
2356  /* 0F56 */
2357  {
2358  /* 00 */
2359  { "orps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL, I_MEMRD | I_ALU | I_SSE | I_XMM },
2360  /* 66 */
2361  { "orpd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_PD, OP_0 }, NULL, I_MEMRD | I_ALU | I_SSE2 | I_XMM }, // [FV] Il manuale riporta Wpd, Vpd
2362  /* F2 */
2363  { "ill_f20f56", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2364  /* F3 */
2365  { "ill_f30f56", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2366  },
2367  /* 0F57 */
2368  {
2369  /* 00 */
2370  { "xorps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL, I_MEMRD | I_ALU | I_SSE | I_XMM },
2371  /* 66 */
2372  { "xorpd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_PD, OP_0 }, NULL, I_MEMRD | I_ALU | I_SSE2 | I_XMM }, // [FV] Il manuale riporta Wpd, Vpd (controllare altre istanze, se presenti...)
2373  /* F2 */
2374  { "ill_f20f57", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2375  /* F3 */
2376  { "ill_f30f57", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2377  },
2378  /* 0F58 */
2379  {
2380  /* 00 */
2381  { "addps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL, I_MEMRD | I_ALU | I_SSE | I_XMM },
2382  /* 66 */
2383  { "addpd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_PD, OP_0 }, NULL, I_MEMRD | I_ALU | I_SSE2 | I_XMM },
2384  /* F2 */
2385  { "addsd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SD, OP_SD, OP_0 }, NULL, I_MEMRD | I_ALU | I_SSE2 | I_XMM },
2386  /* F3 */
2387  { "addss", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SS, OP_SS, OP_0 }, NULL, I_MEMRD | I_ALU | I_SSE | I_XMM }
2388  },
2389  /* 0F59 */
2390  {
2391  /* 00 */
2392  { "mulps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL, I_MEMRD | I_ALU | I_SSE | I_XMM },
2393  /* 66 */
2394  { "mulpd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_PD, OP_0 }, NULL, I_MEMRD | I_ALU | I_SSE2 | I_XMM },
2395  /* F2 */
2396  { "mulsd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SD, OP_SD, OP_0 }, NULL, I_MEMRD | I_ALU | I_SSE2 | I_XMM },
2397  /* F3 */
2398  { "mulss", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SS, OP_SS, OP_0 }, NULL, I_MEMRD | I_ALU | I_SSE | I_XMM }
2399  },
2400  /* 0F5A */
2401  {
2402  /* 00 */
2403  { "cvtps2pd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_PS, OP_0 }, NULL, I_MEMRD | I_SSE2 | I_XMM },
2404  /* 66 */
2405  { "cvtpd2ps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PD, OP_0 }, NULL, I_MEMRD | I_SSE2 | I_XMM },
2406  /* F2 */
2407  { "cvtsd2ss", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SS, OP_SD, OP_0 }, NULL, I_MEMRD | I_SSE2 | I_XMM },
2408  /* F3 */
2409  { "cvtss2sd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SD, OP_SS, OP_0 }, NULL, I_MEMRD | I_SSE2 | I_XMM }
2410  },
2411  /* 0F5B */
2412  {
2413  /* 00 */
2414  { "cvtdq2ps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_DQ, OP_0 }, NULL, I_MEMRD | I_SSE2 | I_XMM },
2415  /* 66 */
2416  { "cvtps2dq", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_PS, OP_0 }, NULL, I_MEMRD | I_SSE2 | I_XMM },
2417  /* F2 */
2418  { "ill_f20f5b", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2419  /* F3 */
2420  { "cvttps2dq", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_PS, OP_0}, NULL, I_MEMRD | I_SSE2 | I_XMM }
2421  },
2422  /* 0F5C */
2423  {
2424  /* 00 */
2425  { "subps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL, I_MEMRD | I_ALU | I_SSE | I_XMM },
2426  /* 66 */
2427  { "subpd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_PD, OP_0 }, NULL, I_MEMRD | I_ALU | I_SSE2 | I_XMM },
2428  /* F2 */
2429  { "subsd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SD, OP_SD, OP_0 }, NULL, I_MEMRD | I_ALU | I_SSE2 | I_XMM },
2430  /* F3 */
2431  { "subss", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SS, OP_SS, OP_0 }, NULL, I_MEMRD | I_ALU | I_SSE | I_XMM }
2432  },
2433  /* 0F5D */
2434  {
2435  /* 00 */
2436  { "minps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL, I_MEMRD | I_ALU | I_SSE | I_XMM },
2437  /* 66 */
2438  { "minpd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_PD, OP_0 }, NULL, I_MEMRD | I_ALU | I_SSE2 | I_XMM },
2439  /* F2 */
2440  { "minsd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SD, OP_SD, OP_0 }, NULL, I_MEMRD | I_ALU | I_SSE2 | I_XMM },
2441  /* F3 */
2442  { "minss", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SS, OP_SS, OP_0 }, NULL, I_MEMRD | I_ALU | I_SSE | I_XMM }
2443  },
2444  /* 0F5E */
2445  {
2446  /* 00 */
2447  { "divps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL, I_MEMRD | I_ALU | I_SSE | I_XMM },
2448  /* 66 */
2449  { "divpd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_PD, OP_0 }, NULL, I_MEMRD | I_ALU | I_SSE2 | I_XMM },
2450  /* F2 */
2451  { "divsd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SD, OP_SD, OP_0 }, NULL, I_MEMRD | I_ALU | I_SSE2 | I_XMM },
2452  /* F3 */
2453  { "divss", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SS, OP_SS, OP_0 }, NULL, I_MEMRD | I_ALU | I_SSE | I_XMM }
2454  },
2455  /* 0F5F */
2456  {
2457  /* 00 */
2458  { "maxps", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PS, OP_PS, OP_0 }, NULL, I_MEMRD | I_ALU | I_SSE | I_XMM },
2459  /* 66 */
2460  { "maxpd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_PD, OP_PD, OP_0 }, NULL, I_MEMRD | I_ALU | I_SSE2 | I_XMM },
2461  /* F2 */
2462  { "maxsd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SD, OP_SD, OP_0 }, NULL, I_MEMRD | I_ALU | I_SSE2 | I_XMM },
2463  /* F3 */
2464  { "maxss", { ADDR_V, ADDR_W, ADDR_0 }, { OP_SS, OP_SS, OP_0 }, NULL, I_MEMRD | I_ALU | I_SSE | I_XMM }
2465  },
2466  /* 0F60 */
2467  {
2468  /* 00 */
2469  { "punpcklbw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_D, OP_0 }, NULL, I_MEMRD | I_MMX },
2470  /* 66 */
2471  { "punpcklbw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0}, NULL, I_MEMRD | I_XMM | I_SSE2 },
2472  /* F2 */
2473  { "ill_f20f60", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2474  /* F3 */
2475  { "ill_f30f60", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2476  },
2477  /* 0F61 */
2478  {
2479  /* 00 */
2480  { "punpcklwd", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_D, OP_0 }, NULL, I_MEMRD | I_MMX },
2481  /* 66 */
2482  { "punpcklwd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0}, NULL, I_MEMRD | I_XMM | I_SSE2 },
2483  /* F2 */
2484  { "ill_f20f61", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2485  /* F3 */
2486  { "ill_f30f61", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2487  },
2488  /* 0F62 */
2489  {
2490  /* 00 */
2491  { "punpckldq", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_D, OP_0 }, NULL, I_MEMRD | I_MMX },
2492  /* 66 */
2493  { "punpckldq", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0}, NULL, I_MEMRD | I_XMM | I_SSE2 },
2494  /* F2 */
2495  { "ill_f20f62", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2496  /* F3 */
2497  { "ill_f30f62", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2498  },
2499  /* 0F63 */
2500  {
2501  /* 00 */
2502  { "packsswb", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_MEMRD | I_MMX },
2503  /* 66 */
2504  { "packsswb", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0}, NULL, I_MEMRD | I_XMM | I_SSE2 },
2505  /* F2 */
2506  { "ill_f20f63", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2507  /* F3 */
2508  { "ill_f30f63", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2509  },
2510  /* 0F64 */
2511  {
2512  /* 00 */
2513  { "pcmpgtb", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_CTRL | I_MEMRD | I_MMX },
2514  /* 66 */
2515  { "pcmpgtb", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_CTRL | I_MEMRD | I_SSE2 | I_XMM },
2516  /* F2 */
2517  { "ill_f20f64", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2518  /* F3 */
2519  { "ill_f30f64", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2520  },
2521  /* 0F65 */
2522  {
2523  /* 00 */
2524  { "pcmpgtw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_CTRL | I_MEMRD | I_MMX },
2525  /* 66 */
2526  { "pcmpgtw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_CTRL | I_MEMRD | I_SSE2 | I_XMM },
2527  /* F2 */
2528  { "ill_f20f65", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2529  /* F3 */
2530  { "ill_f30f65", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2531  },
2532  /* 0F66 */
2533  {
2534  /* 00 */
2535  { "pcmpgtd", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_CTRL | I_MEMRD | I_MMX },
2536  /* 66 */
2537  { "pcmpgtd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_CTRL | I_MEMRD | I_SSE2 | I_XMM },
2538  /* F2 */
2539  { "ill_f20f66", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2540  /* F3 */
2541  { "ill_f30f66", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2542  },
2543  /* 0F67 */
2544  {
2545  /* 00 */
2546  { "packuswb", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, 0 },
2547  /* 66 */
2548  { "packuswb", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0}, NULL, 0 },
2549  /* F2 */
2550  { "ill_f20f67", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2551  /* F3 */
2552  { "ill_f30f67", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2553  },
2554  /* 0F68 */
2555  {
2556  /* 00 */
2557  { "punpckhbw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_D, OP_0 }, NULL, I_MEMRD | I_MMX },
2558  /* 66 */
2559  { "punpckhbw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0}, NULL, I_MEMRD | I_XMM | I_SSE2 }, // [FV] Riportava Pdq, Qdq!
2560  /* F2 */
2561  { "ill_f20f68", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2562  /* F3 */
2563  { "ill_f30f68", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2564  },
2565  /* 0F69 */
2566  {
2567  /* 00 */
2568  { "punpckhwd", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_D, OP_0 }, NULL, I_MEMRD | I_MMX },
2569  /* 66 */
2570  { "punpckhwd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0}, NULL, I_MEMRD | I_XMM | I_SSE2 }, // [FV] Riportava Pdq, Qdq!
2571  /* F2 */
2572  { "ill_f20f69", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2573  /* F3 */
2574  { "ill_f30f69", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2575  },
2576  /* 0F6A */
2577  {
2578  /* 00 */
2579  { "punpckhdq", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_D, OP_0 }, NULL, I_MEMRD | I_MMX },
2580  /* 66 */
2581  { "punpckhdq", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0}, NULL, I_MEMRD | I_XMM | I_SSE2 }, // [FV] Riportava Pdq, Qdq!
2582  /* F2 */
2583  { "ill_f20f6a", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2584  /* F3 */
2585  { "ill_f30f6a", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2586  },
2587  /* 0F6B */
2588  {
2589  /* 00 */
2590  { "packssdw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_D, OP_0 }, NULL, I_MEMRD | I_MMX },
2591  /* 66 */
2592  { "packssdw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_DQ, OP_DQ, OP_0}, NULL, I_MEMRD | I_XMM | I_SSE2 },
2593  /* F2 */
2594  { "ill_f20f6b", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2595  /* F3 */
2596  { "ill_f30f6b", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2597  },
2598  /* 0F6C */
2599  {
2600  /* 00 */
2601  { "ill_0f6c", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2602  /* 66 */
2603  { "punpcklqdq", { ADDR_V, ADDR_W, ADDR_0}, { OP_DQ, OP_DQ, OP_0}, NULL, I_MEMRD | I_XMM | I_SSE2 },
2604  /* F2 */
2605  { "ill_f20f6c", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2606  /* F3 */
2607  { "ill_f30f6c", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2608  },
2609  /* 0F6D */
2610  {
2611  /* 00 */
2612  { "ill_0f6d", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2613  /* 66 */
2614  { "punpckhqdq", { ADDR_V, ADDR_W, ADDR_0}, { OP_DQ, OP_DQ, OP_0}, NULL, I_MEMRD | I_XMM | I_SSE2 },
2615  /* F2 */
2616  { "ill_f20f6d", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2617  /* F3 */
2618  { "ill_f30f6d", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2619  },
2620  /* 0F6E */
2621  {
2622  /* 00 */
2623  { "movd", { ADDR_P, ADDR_E, ADDR_0 }, { OP_D, OP_Y, OP_0 }, NULL, I_MEMRD | I_MMX | I_SSE2 }, // [FV] Riportava Pd, Ed ed era segnata da instrumentare!?
2624  /* 66 */
2625  { "movd", { ADDR_V, ADDR_E, ADDR_0 }, { OP_Y, OP_Y, OP_0 }, NULL, I_MEMRD | I_XMM | I_SSE2 }, // [FV] Riportava Vdq, Ed
2626  /* F2 */
2627  { "ill_f20f6e", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2628  /* F3 */
2629  { "ill_f30f6e", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2630  },
2631  /* 0F6F */
2632  {
2633  /* 00 */
2634  { "movq", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_MEMRD | I_MMX },
2635  /* 66 */
2636  { "movdqa", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_MEMRD | I_XMM | I_SSE2 },
2637  /* F2 */
2638  { "ill_f20f6f", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2639  /* F3 */
2640  { "movdqu", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_MEMRD | I_XMM | I_SSE2 },
2641  },
2642  /* 0F70 */
2643  {
2644  /* 00 */
2645  { "pshufw", { ADDR_P, ADDR_Q, ADDR_I }, { OP_Q, OP_Q, OP_B }, NULL, I_MEMRD | I_MMX },
2646  /* 66 */
2647  { "pshufd", { ADDR_V, ADDR_W, ADDR_I }, { OP_DQ, OP_DQ, OP_B }, NULL, I_MEMRD | I_XMM | I_SSE2 },
2648  /* F2 */
2649  { "pshuflw", { ADDR_V, ADDR_W, ADDR_I }, { OP_DQ, OP_DQ, OP_B }, NULL, I_MEMRD | I_XMM | I_SSE2 },
2650  /* F3 */
2651  { "pshufhw", { ADDR_V, ADDR_W, ADDR_I }, { OP_DQ, OP_DQ, OP_B }, NULL, I_MEMRD | I_XMM | I_SSE2 }
2652  }
2653  };
2654 
2655  sse_esc(state, table, 0x50);
2656 }
2657 
2658 void esc_0f74_76 (struct disassembly_state *state)
2659 {
2660  insn table[][4] = {
2661  /* 0F74 */
2662  {
2663  /* 00 */
2664  { "pcmpeqb", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_CTRL | I_MEMRD | I_MMX },
2665  /* 66 */
2666  { "pcmpeqb", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_CTRL | I_MEMRD | I_XMM | I_SSE2 },
2667  /* F2 */
2668  { "ill_f20f74", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2669  /* F3 */
2670  { "ill_f30f74", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2671  },
2672  /* 0F75 */
2673  {
2674  /* 00 */
2675  { "pcmpeqw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_CTRL | I_MEMRD | I_MMX },
2676  /* 66 */
2677  { "pcmpeqw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_CTRL | I_MEMRD | I_XMM | I_SSE2 },
2678  /* F2 */
2679  { "ill_f20f75", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2680  /* F3 */
2681  { "ill_f30f75", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2682  },
2683  /* 0F76 */
2684  {
2685  /* 00 */
2686  { "pcmpeqd", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_CTRL | I_MEMRD | I_MMX },
2687  /* 66 */
2688  { "pcmpeqd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_CTRL | I_MEMRD | I_XMM | I_SSE2 },
2689  /* F2 */
2690  { "ill_f20f76", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2691  /* F3 */
2692  { "ill_f30f76", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2693  }
2694  };
2695 
2696  sse_esc(state, table, 0x74);
2697 }
2698 
2699 void esc_0f7e_7f (struct disassembly_state *state)
2700 {
2701  insn table[][4] = {
2702  /* OF7E */
2703  {
2704  /* 00 */
2705  { "movd", { ADDR_E, ADDR_P, ADDR_0 }, { OP_Y, OP_D, OP_0 }, NULL, I_MEMWR | I_MMX | I_SSE2 }, // [FV] Riportava Ed, Pd
2706  /* 66 */
2707  { "movd", { ADDR_E, ADDR_V, ADDR_0 }, { OP_Y, OP_Y, OP_0 }, NULL, I_MEMWR | I_XMM | I_SSE2 }, // [FV] Riportava Ed, Vdq
2708  /* F2 */
2709  { "ill_f20f7e", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2710  /* F3 */
2711  { "movq", { ADDR_V, ADDR_W, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_MEMRD | I_XMM }
2712  },
2713  /* 0F7F */
2714  {
2715  /* 00 */
2716  { "movq", { ADDR_Q, ADDR_P, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_MEMWR | I_MMX },
2717  /* 66 */
2718  { "movdqa", { ADDR_W, ADDR_V, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_MEMWR | I_XMM | I_SSE2 },
2719  /* F2 */
2720  { "ill_f20f7f", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2721  /* F3 */
2722  { "movdqu", { ADDR_W, ADDR_V, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_MEMWR | I_XMM | I_SSE2 }
2723  }
2724  };
2725 
2726  sse_esc(state, table, 0x7e);
2727 }
2728 
2729 void esc_0fc2 (struct disassembly_state *state)
2730 {
2731  insn table[][4] = {
2732  /* 0FC2 */
2733  {
2734  /* 00 */
2735  { "cmpps", { ADDR_V, ADDR_W, ADDR_I }, { OP_PS, OP_PS, OP_B }, NULL, I_ALU | I_CTRL | I_MEMRD | I_SSE | I_XMM },
2736  /* 66 */
2737  { "cmppd", { ADDR_V, ADDR_W, ADDR_I }, { OP_PD, OP_PD, OP_B }, NULL, I_ALU | I_CTRL | I_MEMRD | I_SSE2 | I_XMM },
2738  /* F2 */
2739  { "cmpsd", { ADDR_V, ADDR_W, ADDR_I }, { OP_SD, OP_SD, OP_B }, NULL, I_ALU | I_CTRL | I_MEMRD | I_SSE2 | I_XMM },
2740  /* F3 */
2741  { "cmpss", { ADDR_V, ADDR_W, ADDR_I }, { OP_SS, OP_SS, OP_B }, NULL, I_ALU | I_CTRL | I_MEMRD | I_SSE | I_XMM },
2742  }
2743  };
2744 
2745  sse_esc(state, table, 0xc2);
2746 }
2747 
2748 void esc_0fc4_c6 (struct disassembly_state *state)
2749 {
2750  insn table[][4] = {
2751  /* 0FC4 */
2752  {
2753  /* 00 */
2754  { "pinsrw", { ADDR_P, ADDR_E, ADDR_I }, { OP_Q, OP_D, OP_B }, NULL, I_MEMRD | I_SSE | I_MMX },
2755  /* 66 */
2756  { "pinsrw", { ADDR_V, ADDR_E, ADDR_I }, { OP_DQ, OP_D, OP_B }, NULL, I_MEMRD | I_SSE2 | I_XMM },
2757  /* F2 */
2758  { "ill_f20fc4", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2759  /* F3 */
2760  { "ill_f30fc4", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2761  },
2762  /* 0FC5 */
2763  {
2764  /* 00 */
2765  { "pextrw", { ADDR_G, ADDR_N, ADDR_I }, { OP_D, OP_Q, OP_B }, NULL, I_SSE | I_MMX }, // [FV] Riportava Gd, Nq, Ib
2766  /* 66 */
2767  { "pextrw", { ADDR_G, ADDR_U, ADDR_I }, { OP_D, OP_DQ, OP_B }, NULL, I_SSE2 | I_XMM }, // [FV] Riportava Gd, Vdq, Ib
2768  /* F2 */
2769  { "ill_f20fc5", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2770  /* F3 */
2771  { "ill_f30fc5", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2772  },
2773  /* 0FC6 */
2774  {
2775  /* 00 */
2776  { "shufps", { ADDR_V, ADDR_W, ADDR_I }, { OP_PS, OP_PS, OP_B }, NULL, I_MEMRD | I_SSE2 | I_XMM },
2777  /* 66 */
2778  { "shufpd", { ADDR_V, ADDR_W, ADDR_I }, { OP_PD, OP_PD, OP_B }, NULL, I_MEMRD | I_SSE2 | I_XMM },
2779  /* F2 */
2780  { "ill_f20fc6", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2781  /* F3 */
2782  { "ill_f30fc6", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2783  }
2784  };
2785 
2786  sse_esc(state, table, 0xc4);
2787 }
2788 
2789 void esc_0fd1_ef (struct disassembly_state *state)
2790 {
2791  insn table[][4] = {
2792  /* 0FD1 */
2793  {
2794  /* 00 */
2795  { "psrlw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_MMX },
2796  /* 66 */
2797  { "psrlw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_XMM | I_SSE2 },
2798  /* F2 */
2799  { "ill_f20fd1", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2800  /* F3 */
2801  { "ill_f30fd1", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2802  },
2803  /* 0FD2 */
2804  {
2805  /* 00 */
2806  { "psrld", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_MMX },
2807  /* 66 */
2808  { "psrld", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_XMM | I_SSE2 },
2809  /* F2 */
2810  { "ill_f20fd2", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2811  /* F3 */
2812  { "ill_f30fd2", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2813  },
2814  /* 0FD3 */
2815  {
2816  /* 00 */
2817  { "psrlq", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_MMX },
2818  /* 66 */
2819  { "psrlq", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_XMM | I_SSE2 },
2820  /* F2 */
2821  { "ill_f20fd3", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2822  /* F3 */
2823  { "ill_f30fd3", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2824  },
2825  /* 0FD4 */
2826  {
2827  /* 00 */
2828  { "paddq", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_MMX },
2829  /* 66 */
2830  { "paddq", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_XMM },
2831  /* F2 */
2832  { "ill_f20fd4", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2833  /* F3 */
2834  { "ill_f30fd4", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2835  },
2836  /* 0FD5 */
2837  {
2838  /* 00 */
2839  { "pmulw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_MMX },
2840  /* 66 */
2841  { "pmulw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_MMX },
2842  /* F2 */
2843  { "ill_f20fd5", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2844  /* F3 */
2845  { "ill_f30fd5", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2846  },
2847  /* 0FD6 */
2848  {
2849  /* 00 */
2850  { "ill_0fd6", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2851  /* 66 */
2852  { "movq", { ADDR_W, ADDR_V, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_MEMWR | I_XMM },
2853  /* F2 */
2854  { "movdq2q", { ADDR_P, ADDR_U, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_MMX | I_XMM }, // [FV] Riportava Pq, Wq ed era segnata da instrumentare !?
2855  /* F3 */
2856  { "movq2dq", { ADDR_V, ADDR_N, ADDR_0 }, { OP_DQ, OP_Q, OP_0 }, NULL, I_MMX | I_XMM } // [FV] Riportava Vdq, Qq ed era segnata da instrumentare !?
2857  },
2858  /* 0FD7 */
2859  {
2860  /* 00 */
2861  { "pmovmskb", { ADDR_G, ADDR_N, ADDR_0 }, { OP_D, OP_Q, OP_0 }, NULL, I_MMX | I_SSE }, // [FV] Riportava Gd, Pq
2862  /* 66 */
2863  { "pmovmksb", { ADDR_G, ADDR_U, ADDR_0 }, { OP_D, OP_DQ, OP_0 }, NULL, I_XMM | I_SSE2 }, // [FV] Riportava Gd, Vdq
2864  /* F2 */
2865  { "ill_f20fd7", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2866  /* F3 */
2867  { "ill_f30fd7", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2868  },
2869  /* 0FD8 */
2870  {
2871  /* 00 */
2872  { "psubusb", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_MMX },
2873  /* 66 */
2874  { "psubusb", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_XMM },
2875  /* F2 */
2876  { "ill_f20fd8", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2877  /* F3 */
2878  { "ill_f30fd8", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2879  },
2880  /* 0FD9 */
2881  {
2882  /* 00 */
2883  { "psubusw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_MMX },
2884  /* 66 */
2885  { "psubusw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_XMM },
2886  /* F2 */
2887  { "ill_f20fd9", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2888  /* F3 */
2889  { "ill_f30fd9", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2890  },
2891  /* 0FDA */
2892  {
2893  /* 00 */
2894  { "pminub", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_CTRL | I_MEMRD | I_SSE | I_MMX },
2895  /* 66 */
2896  { "pminub", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_CTRL | I_MEMRD | I_SSE2 | I_XMM },
2897  /* F2 */
2898  { "ill_f20fda", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2899  /* F3 */
2900  { "ill_f30fda", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2901  },
2902  /* 0FDB */
2903  {
2904  /* 00 */
2905  { "pand", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_MMX },
2906  /* 66 */
2907  { "pand", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_XMM },
2908  /* F2 */
2909  { "ill_f20fdb", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2910  /* F3 */
2911  { "ill_f30fdb", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2912  },
2913  /* 0FDC */
2914  {
2915  /* 00 */
2916  { "paddusb", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_MMX },
2917  /* 66 */
2918  { "paddusb", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_XMM },
2919  /* F2 */
2920  { "ill_f20fdc", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2921  /* F3 */
2922  { "ill_f30fdc", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2923  },
2924  /* 0FDD */
2925  {
2926  /* 00 */
2927  { "paddusw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_MMX },
2928  /* 66 */
2929  { "paddusw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_XMM },
2930  /* F2 */
2931  { "ill_f20fdd", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2932  /* F3 */
2933  { "ill_f30fdd", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2934  },
2935  /* 0FDE */
2936  {
2937  /* 00 */
2938  { "pmaxub", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_CTRL | I_MEMRD | I_SSE | I_MMX },
2939  /* 66 */
2940  { "pmaxub", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_CTRL | I_MEMRD | I_SSE2 | I_XMM },
2941  /* F2 */
2942  { "ill_f20fde", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2943  /* F3 */
2944  { "ill_f30fde", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2945  },
2946  /* 0FDF */
2947  {
2948  /* 00 */
2949  { "pandn", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_MMX },
2950  /* 66 */
2951  { "pandn", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_XMM },
2952  /* F2 */
2953  { "ill_f20fdf", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2954  /* F3 */
2955  { "ill_f30fdf", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2956  },
2957  /* 0FE0 */
2958  {
2959  /* 00 */
2960  { "pavgb", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE | I_MMX },
2961  /* 66 */
2962  { "pavgb", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_XMM },
2963  /* F2 */
2964  { "ill_f20fe0", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2965  /* F3 */
2966  { "ill_f30fe0", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2967  },
2968  /* 0FE1 */
2969  {
2970  /* 00 */
2971  { "praw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_MMX },
2972  /* 66 */
2973  { "praw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_XMM },
2974  /* F2 */
2975  { "ill_f20fe1", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2976  /* F3 */
2977  { "ill_f30fe1", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2978  },
2979  /* 0FE2 */
2980  {
2981  /* 00 */
2982  { "prad", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_MMX },
2983  /* 66 */
2984  { "prad", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_XMM },
2985  /* F2 */
2986  { "ill_f20fe2", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2987  /* F3 */
2988  { "ill_f30fe2", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
2989  },
2990  /* 0FE3 */
2991  {
2992  /* 00 */
2993  { "pavgw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE | I_MMX },
2994  /* 66 */
2995  { "pavgw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_XMM },
2996  /* F2 */
2997  { "ill_f20fe3", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
2998  /* F3 */
2999  { "ill_f30fe3", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
3000  },
3001  /* 0FE4 */
3002  {
3003  /* 00 */
3004  { "pmulhuw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE | I_MMX },
3005  /* 66 */
3006  { "pmulhuw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_XMM },
3007  /* F2 */
3008  { "ill_f20fe4", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
3009  /* F3 */
3010  { "ill_f30fe4", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
3011  },
3012  /* 0FE5 */
3013  {
3014  /* 00 */
3015  { "pmulhw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_MMX },
3016  /* 66 */
3017  { "pmulhw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_XMM },
3018  /* F2 */
3019  { "ill_f20fe5", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
3020  /* F3 */
3021  { "ill_f30fe5", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
3022  },
3023  /* 0FE6 */
3024  {
3025  /* 00 */
3026  { "ill_0fe6", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
3027  /* 66 */
3028  { "cvttpd2dq", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_PD, OP_0}, NULL, I_MEMRD | I_SSE2 | I_XMM },
3029  /* F2 */
3030  { "cvtpd2dq", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_PD, OP_0 }, NULL, I_MEMRD | I_SSE2 | I_XMM },
3031  /* F3 */
3032  { "cvtdq2pd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_PD, OP_0 }, NULL, I_MEMRD | I_SSE2 | I_XMM } // [FV] Riportava Vpd, Wdq
3033  },
3034  /* 0FE7 */
3035  {
3036  /* 00 */
3037  { "movntq", { ADDR_M, ADDR_P, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_MEMWR | I_MMX }, // [FV] Riportava Gd, Pq
3038  /* 66 */
3039  { "movntdq", { ADDR_M, ADDR_V, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_MEMWR | I_SSE2 | I_XMM }, // [FV] Riportava Wdq, Vq
3040  /* F2 */
3041  { "ill_f20fe7", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
3042  /* F3 */
3043  { "ill_f30fe7", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
3044  },
3045  /* 0FE8 */
3046  {
3047  /* 00 */
3048  { "psubsb", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_MMX },
3049  /* 66 */
3050  { "psubsb", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_XMM },
3051  /* F2 */
3052  { "ill_f20fe8", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
3053  /* F3 */
3054  { "ill_f30fe8", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
3055  },
3056  /* 0FE9 */
3057  {
3058  /* 00 */
3059  { "psubsw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_MMX },
3060  /* 66 */
3061  { "psubsw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_XMM },
3062  /* F2 */
3063  { "ill_f20fe9", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
3064  /* F3 */
3065  { "ill_f30fe9", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
3066  },
3067  /* 0FEA */
3068  {
3069  /* 00 */
3070  { "pminusw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_CTRL | I_MEMRD | I_SSE | I_MMX },
3071  /* 66 */
3072  { "pminusw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_CTRL | I_MEMRD | I_SSE2 | I_XMM },
3073  /* F2 */
3074  { "ill_f20fea", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
3075  /* F3 */
3076  { "ill_f30fea", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
3077  },
3078  /* 0FEB */
3079  {
3080  /* 00 */
3081  { "por", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_MMX },
3082  /* 66 */
3083  { "por", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_XMM },
3084  /* F2 */
3085  { "ill_f20feb", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
3086  /* F3 */
3087  { "ill_f30feb", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
3088  },
3089  /* 0FEC */
3090  {
3091  /* 00 */
3092  { "paddsb", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_MMX },
3093  /* 66 */
3094  { "paddsb", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_XMM },
3095  /* F2 */
3096  { "ill_f20fec", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
3097  /* F3 */
3098  { "ill_f30fec", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
3099  },
3100  /* 0FED */
3101  {
3102  /* 00 */
3103  { "paddsw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_MMX },
3104  /* 66 */
3105  { "paddsw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_XMM },
3106  /* F2 */
3107  { "ill_f20fed", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
3108  /* F3 */
3109  { "ill_f30fed", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
3110  },
3111  /* 0FEE */
3112  {
3113  /* 00 */
3114  { "pmaxsw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_CTRL | I_MEMRD | I_SSE | I_MMX },
3115  /* 66 */
3116  { "pmaxsw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_CTRL | I_MEMRD | I_SSE2 | I_XMM },
3117  /* F2 */
3118  { "ill_f20fee", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
3119  /* F3 */
3120  { "ill_f30fee", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
3121  },
3122  /* 0FEF */
3123  {
3124  /* 00 */
3125  { "pxor", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_MMX },
3126  /* 66 */
3127  { "pxor", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_XMM },
3128  /* F2 */
3129  { "ill_f20fef", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
3130  /* F3 */
3131  { "ill_f30fef", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
3132  }
3133  };
3134 
3135  sse_esc(state, table, 0xd1);
3136 }
3137 
3138 void esc_0ff1_fe (struct disassembly_state *state)
3139 {
3140  insn table[][4] = {
3141  /* 0FF1 */
3142  {
3143  /* 00 */
3144  { "psllw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_MMX },
3145  /* 66 */
3146  { "psllw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_XMM },
3147  /* F2 */
3148  { "ill_f20ff1", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
3149  /* F3 */
3150  { "ill_f30ff1", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
3151  },
3152  /* 0FF2 */
3153  {
3154  /* 00 */
3155  { "pslld", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_MMX },
3156  /* 66 */
3157  { "pslld", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_XMM },
3158  /* F2 */
3159  { "ill_f20ff2", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
3160  /* F3 */
3161  { "ill_f30ff2", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
3162  },
3163  /* 0FF3 */
3164  {
3165  /* 00 */
3166  { "psllq", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_MMX },
3167  /* 66 */
3168  { "psllq", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_XMM },
3169  /* F2 */
3170  { "ill_f20ff3", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
3171  /* F3 */
3172  { "ill_f30ff3", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
3173  },
3174  /* 0FF4 */
3175  {
3176  /* 00 */
3177  { "pmuludq", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_MMX },
3178  /* 66 */
3179  { "pmuludq", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_XMM },
3180  /* F2 */
3181  { "ill_f20ff4", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
3182  /* F3 */
3183  { "ill_f30ff4", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
3184  },
3185  /* 0FF5 */
3186  {
3187  /* 00 */
3188  { "pmaddwd", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_MMX },
3189  /* 66 */
3190  { "pmaddwd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_XMM },
3191  /* F2 */
3192  { "ill_f20ff5", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
3193  /* F3 */
3194  { "ill_f30ff5", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
3195  },
3196  /* 0FF6 */
3197  {
3198  /* 00 */
3199  { "psadbw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE | I_MMX },
3200  /* 66 */
3201  { "psadbw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_XMM },
3202  /* F2 */
3203  { "ill_f20ff6", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
3204  /* F3 */
3205  { "ill_f30ff6", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
3206  },
3207  /* 0FF7 */
3208  {
3209  /* 00 */ // [FV] Scrive su DS:DI/EDI/RDI
3210  { "maskmovq", { ADDR_P, ADDR_N, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_MEMWR | I_MMX }, // [FV] Riportava Ppi, Qpi
3211  /* 66 */ // [FV] Scrive su DS:EDI/RDI
3212  { "maskmovdqu", { ADDR_V, ADDR_U, ADDR_0}, { OP_DQ, OP_DQ, OP_0}, NULL, I_MEMWR | I_SSE2 | I_XMM }, // [FV] Riportava Vdq, Wdq
3213  /* F2 */
3214  { "ill_f20ff7", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
3215  /* F3 */
3216  { "ill_f30ff7", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
3217  },
3218  /* 0FF8 */
3219  {
3220  /* 00 */
3221  { "psubb", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_MMX },
3222  /* 66 */
3223  { "psubb", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_XMM },
3224  /* F2 */
3225  { "ill_f20ff8", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
3226  /* F3 */
3227  { "ill_f30ff8", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
3228  },
3229  /* 0FF9 */
3230  {
3231  /* 00 */
3232  { "psubw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_MMX },
3233  /* 66 */
3234  { "psubw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_XMM },
3235  /* F2 */
3236  { "ill_f20ff9", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
3237  /* F3 */
3238  { "ill_f30ff9", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
3239  },
3240  /* 0FFA */
3241  {
3242  /* 00 */
3243  { "psubd", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_MMX },
3244  /* 66 */
3245  { "psubd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_XMM },
3246  /* F2 */
3247  { "ill_f20ffa", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
3248  /* F3 */
3249  { "ill_f30ffa", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
3250  },
3251  /* 0FFB */
3252  {
3253  /* 00 */
3254  { "psubq", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_MMX },
3255  /* 66 */
3256  { "psubq", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_XMM },
3257  /* F2 */
3258  { "ill_f20ffb", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
3259  /* F3 */
3260  { "ill_f30ffb", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
3261  },
3262  /* 0FFC */
3263  {
3264  /* 00 */
3265  { "paddb", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_MMX },
3266  /* 66 */
3267  { "paddb", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_XMM },
3268  /* F2 */
3269  { "ill_f20ffc", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
3270  /* F3 */
3271  { "ill_f30ffc", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
3272  },
3273  /* 0FFD */
3274  {
3275  /* 00 */
3276  { "paddw", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_MMX },
3277  /* 66 */
3278  { "paddw", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_XMM },
3279  /* F2 */
3280  { "ill_f20ffd", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
3281  /* F3 */
3282  { "ill_f30ffd", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
3283  },
3284  /* 0FFE */
3285  {
3286  /* 00 */
3287  { "paddd", { ADDR_P, ADDR_Q, ADDR_0 }, { OP_Q, OP_Q, OP_0 }, NULL, I_ALU | I_MEMRD | I_MMX },
3288  /* 66 */
3289  { "paddd", { ADDR_V, ADDR_W, ADDR_0 }, { OP_DQ, OP_DQ, OP_0 }, NULL, I_ALU | I_MEMRD | I_SSE2 | I_XMM },
3290  /* F2 */
3291  { "ill_f20ffe", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 },
3292  /* F3 */
3293  { "ill_f30ffe", { ADDR_0, ADDR_0, ADDR_0 }, { OP_0, OP_0, OP_0 }, NULL, 0 }
3294  }
3295  };
3296 
3297  sse_esc(state, table, 0xf1);
3298 }
3299 
3300 /* Gruppi di estensione degli opcode: usano i bit 5-3 del byte ModR/M per l'istruzione */
3301 
3302 /* immed_grp_1
3303  * L'opcode può andare da 0x80 a 0x83. L'istruzione è scelta in base ai bit 5-3 del byte
3304  * ModR/M.
3305  */
3306 void immed_grp_1(struct disassembly_state *state)
3307 {
3308  unsigned char encoding;
3309  char *instructions[] = { "add", "or", "adc", "sbb",
3310  "and", "sub", "xor", "cmp" };
3311 
3312  // Tutte queste istruzioni, tranne cmp, possono scrivere in memoria
3313 
3314  read_modrm(state);
3315 
3316  encoding = (state->modrm >> 3) & 0x07;
3317 
3318  strcpy(state->instrument->mnemonic, instructions[encoding]);
3319 
3320  if (encoding == 0b000 || encoding == 0b001 || encoding == 0b010 || encoding == 0b011 || encoding == 0b100 || encoding == 0b101 || encoding == 0b110)
3321  state->instrument->flags |= I_MEMRD | I_MEMWR | I_ALU;
3322 
3323  else if (encoding== 0b111)
3324  state->instrument->flags |= I_MEMRD | I_ALU | I_CTRL;
3325 
3326  switch(encoding) {
3327 
3328 
3329  case 0b000 ... 0b110: // ADD, ADC, SBB, AND, SUB, XOR ( ... e' una GNU extension)
3330 
3331  state->instrument->flags |= I_MEMRD | I_MEMWR | I_ALU;
3332  break;
3333  case 0b111: // CMP
3334  state->instrument->flags |= I_MEMRD | I_ALU | I_CTRL;
3335  }
3336 }
3337 
3338 /* opcodes C0-C1, D0-D3 */
3339 void shift_grp_2(struct disassembly_state *state)
3340 {
3341  unsigned char encoding;
3342 
3343  // Queste istruzioni possono scrivere tutte in memoria
3344 
3345  char *instructions[] = { "rol", "ror", "rcl", "rcr",
3346  "shl", "shr", "ill_grp_2", "sar" };
3347 
3348  read_modrm(state);
3349 
3350  encoding = (state->modrm >> 3) & 0x07;
3351 
3352  strcpy(state->instrument->mnemonic, instructions[encoding]);
3353 
3354  if(encoding != 0b110) {
3355  state->instrument->flags |= I_MEMRD | I_MEMWR | I_ALU;
3356  }
3357 }
3358 
3359 /* opcodes F6-F7 */
3360 void unary_grp_3(struct disassembly_state *state)
3361 {
3362  // Possono scrivere in memoria: not, neg
3363 
3364  unsigned char encoding, opcode;
3365  char *instructions[] = { "test", "ill_grp_3", "not", "neg",
3366  "mul", "imul", "div", "idiv" };
3367  enum addr_method addr[8][2] = { { ADDR_I, ADDR_I }, { ADDR_0, ADDR_0 },
3368  { ADDR_0, ADDR_0 }, { ADDR_0, ADDR_0 },
3369  { R_AL, R_AX }, { R_AL, R_AX },
3370  { R_AL, R_AX }, { R_AL, R_AX } };
3371  enum operand_type op[8][2] = { { OP_B, OP_V }, { OP_0, OP_0 },
3372  { OP_0, OP_0 }, { OP_0, OP_0 },
3373  { OP_0, OP_E }, { OP_0, OP_E },
3374  { OP_0, OP_E }, { OP_0, OP_E } };
3375 
3376  unsigned long flags[8] = { I_ALU | I_CTRL | I_MEMRD,
3377  0,
3378  I_ALU | I_MEMRD | I_MEMWR,
3379  I_ALU | I_MEMRD | I_MEMWR,
3380  I_ALU | I_MEMRD,
3381  I_ALU | I_MEMRD,
3382  I_ALU | I_MEMRD, I_ALU | I_MEMRD};
3383 
3384  read_modrm(state);
3385 
3386  encoding = (state->modrm >> 3) & 0x07;
3387  opcode = state->opcode[0] - 0xf6;
3388 
3389  strcpy(state->instrument->mnemonic, instructions[encoding]);
3390  state->addr[1] = addr[encoding][opcode];
3391  state->op[1] = op[encoding][opcode];
3392  state->instrument->flags = flags[encoding];
3393 }
3394 
3395 /* opcode FE */
3396 void grp_4(struct disassembly_state *state)
3397 {
3398  unsigned char encoding;
3399 
3400  read_modrm(state);
3401 
3402  encoding = (state->modrm >> 3) & 0x07;
3403  state->instrument->flags = I_MEMRD | I_MEMWR | I_ALU;
3404 
3405  switch(encoding) {
3406  case 0: // inc
3407  strcpy(state->instrument->mnemonic, "inc");
3408  break;
3409  case 1: // dec
3410  strcpy(state->instrument->mnemonic, "dec");
3411  break;
3412  default: // ill_grp_4
3413  strcpy(state->instrument->mnemonic, "ill_grp_4");
3414  state->instrument->flags = 0;
3415  break;
3416  }
3417 
3418  if(encoding < 2) {
3419  state->addr[0] = ADDR_E;
3420  state->op[0] = OP_B;
3421  }
3422 }
3423 
3424 /* opcode FF */
3425 void grp_5(struct disassembly_state *state)
3426 {
3427  unsigned char encoding;
3428  char *instructions[] = { "inc", "dec", "call", "call far",
3429  "jmp", "jmp far", "push", "ill_grp_5" };
3430 
3431  read_modrm(state);
3432 
3433  encoding = (state->modrm >> 3) & 0x07;
3434  strcpy(state->instrument->mnemonic, instructions[encoding]);
3435 
3436  switch(encoding) {
3437  case 0x00:
3438  case 0x01:
3439  state->instrument->flags = I_ALU | I_MEMRD | I_MEMWR;
3440  break;
3441  case 0x02:
3442  case 0x03:
3443  state->instrument->flags = I_CALLIND | I_CALL;
3444  break;
3445  case 0x04:
3446  case 0x05:
3447  state->instrument->flags = I_JUMPIND | I_JUMP;
3448  break;
3449  case 0x06:
3450  state->instrument->flags = I_PUSHPOP | I_MEMRD;
3451  break;
3452  case 0x07:
3453  return;
3454  }
3455 
3456  state->addr[0] = ADDR_E;
3457 
3458  if(encoding == 0x03 || encoding == 0x05)
3459  state->op[0] = OP_P;
3460  else
3461  state->op[0] = OP_V;
3462 }
3463 
3464 /* opcode 0F00 */
3465 void grp_6(struct disassembly_state *state)
3466 {
3467  unsigned char encoding;
3468 
3469  char *instructions[6] = { "sldt", "str", "lldt", "ltr", "verr", "verw" };
3470 
3471  read_modrm(state);
3472 
3473  encoding = (state->modrm >> 3) & 0x07;
3474  if(encoding > 0x05) {
3475  strcpy(state->instrument->mnemonic, "ill_grp_6");
3476  return;
3477  }
3478 
3479  strcpy(state->instrument->mnemonic, instructions[encoding]);
3480  state->addr[0] = ADDR_E;
3481  state->op[0] = OP_W; // [FV] Non corretto con dimensione registri per SLDT e STR!!!
3482 
3483  switch(encoding) {
3484  case 0x00: // SLDT
3485  state->instrument->flags = I_MEMWR;
3486  break;
3487  case 0x01: // STR
3488  state->instrument->flags = I_MEMWR;
3489  break;
3490  case 0x02: // LLDT
3491  state->instrument->flags = I_MEMRD;
3492  break;
3493  case 0x03: // LTR
3494  state->instrument->flags = I_MEMRD;
3495  break;
3496  case 0x04: // VERR
3497  state->instrument->flags = I_CTRL | I_MEMRD;
3498  break;
3499  case 0x05: // VERW
3500  state->instrument->flags = I_CTRL | I_MEMRD;
3501  break;
3502  }
3503 
3504  // [FV] state->op[0] = (encoding < 2) ? OP_V : OP_W; - Non penso funzioni... Ricontrollare!
3505 }
3506 
3507 /* opcode 0F01 */
3508 void grp_7(struct disassembly_state *state)
3509 {
3510  unsigned char encoding, lower_bits, mod_76;
3511  char *instructions[] = { "sgdt", "sidt", "lgdt", "lidt",
3512  "smsw", "ill_grp_7", "lmsw", "invlpg" };
3513 
3514  read_modrm(state);
3515 
3516  encoding = (state->modrm >> 3) & 0x07;
3517  lower_bits = state->modrm & 0x07;
3518  mod_76 = (state->modrm >> 6) & 0x03;
3519 
3520  // TODO: mod_76 dovrà essere reintrodotto prima o poi, quando questo modulo verrà esteso oltre le SSE2
3521  (void)mod_76;
3522  (void)lower_bits;
3523 
3524  /*if(mod_76 == 11b && encoding != 100b && encoding |= 110b) { // [FV] In realtà queste potremmo non gestirle...
3525  switch(encoding) {
3526  case 000b:
3527  switch(lower_bits) {
3528  case 001b:
3529  strcpy(state->instrument->mnemonic, "vmcall");
3530  break;
3531  case 010b:
3532  strcpy(state->instrument->mnemonic, "vmlaunch");
3533  break;
3534  case 011b:
3535  strcpy(state->instrument->mnemonic, "vmresume");
3536  break;
3537  case 100b:
3538  strcpy(state->instrument->mnemonic, "vmxoff");
3539  break;
3540  default:
3541  strcpy(state->instrument->mnemonic, "ill_grp_7");
3542  break;
3543  }
3544  break;
3545  case 001b:
3546  switch(lower_bits) {
3547  case 000b:
3548  strcpy(state->instrument->mnemonic, "trampoline");
3549  break;
3550  case 001b:
3551  strcpy(state->instrument->mnemonic, "mwait");
3552  break;
3553  default:
3554  strcpy(state->instrument->mnemonic, "ill_grp_7");
3555  break;
3556  }
3557  break;
3558  case 010b:
3559  switch(lower_bits) {
3560  case 000b:
3561  strcpy(state->instrument->mnemonic, "xgetbv");
3562  break;
3563  case 001b:
3564  strcpy(state->instrument->mnemonic, "xsetbv");
3565  break;
3566  default:
3567  strcpy(state->instrument->mnemonic, "ill_grp_7");
3568  break;
3569  }
3570  break;
3571  case 111b:
3572  switch(lower_bits) {
3573  case 000b:
3574  strcpy(state->instrument->mnemonic, "swapgs");
3575  break;
3576  case 001b:
3577  strcpy(state->instrument->mnemonic, "rdtscp");
3578  break;
3579  default:
3580  strcpy(state->instrument->mnemonic, "ill_grp_7");
3581  break;
3582  }
3583  break;
3584  default:
3585  strcpy(state->instrument->mnemonic, "ill_grp_7");
3586  break;
3587  //}
3588  }
3589  }*/
3590  //else {
3591  strcpy(state->instrument->mnemonic, instructions[encoding]);
3592 
3593  if(encoding == 5) // ill_grp_7
3594  return;
3595 
3596  if(encoding < 4) {
3597  state->addr[0] = ADDR_M;
3598  state->op[0] = OP_S;
3599  if(encoding < 2) // SGDT, SIDT
3600  state->instrument->flags = I_MEMWR;
3601  else // LGDT, LIDT
3602  state->instrument->flags = I_MEMRD;
3603  } else if(encoding == 0x07) { // INVLPG
3604  state->addr[0] = ADDR_M;
3605  state->op[0] = OP_B;
3606  } else {
3607  state->addr[0] = ADDR_E;
3608  state->op[0] = OP_W;
3609  if(encoding == 4) // SMSW
3610  state->instrument->flags = I_MEMWR;
3611  else // LMSW
3612  state->instrument->flags = I_MEMRD;
3613  }
3614  //}
3615 }
3616 
3617 /* opcode 0FBA */
3618 void grp_8(struct disassembly_state *state)
3619 {
3620  unsigned char encoding;
3621  char *instructions[] = { "bt", "bts", "btr", "btc" };
3622 
3623  read_modrm(state);
3624 
3625  encoding = (state->modrm >> 3) & 0x07;
3626 
3627  if(encoding < 4) {
3628  // ill_grp_8
3629  strcpy(state->instrument->mnemonic, "ill_grp_8");
3630  state->addr[0] = state->addr[1] = ADDR_0;
3631  state->op[0] = state->op[1] = OP_0;
3632  return;
3633  }
3634 
3635  encoding -= 4; // I valori a 0 a 3 in realtà non sono usati
3636 
3637  strcpy(state->instrument->mnemonic, instructions[encoding]);
3638  state->instrument->flags = I_MEMRD; // Tutte possono leggere dalla memoria
3639 
3640  if(encoding > 0) // BTS, BTR, BTC
3641  state->instrument->flags |= I_MEMWR;
3642 }
3643 
3644 /* opcode 0FC7 */ // [FV] Non tutte le istruzioni vengono gestite
3645 void grp_9(struct disassembly_state *state)
3646 {
3647  unsigned char encoding, mod;
3648 
3649  read_modrm(state);
3650 
3651  encoding = (state->modrm >> 3) & 0x07;
3652  mod = (state->modrm >> 6) & 0x03;
3653 
3654  if(mod != 0x03 && encoding == 0x01) { // cmpxch8b, scrive in memoria
3655  state->instrument->flags = I_CTRL | I_CONDITIONAL | I_ALU | I_MEMRD | I_MEMWR; // [FV]
3656  strcpy(state->instrument->mnemonic, "cmpxch8b");
3657  state->addr[0] = ADDR_M;
3658  if(REXW(state->rex))
3659  state->op[0] = OP_DQ; // [FV] Perche' questo non veniva gestito?
3660  else
3661  state->op[0] = OP_Q;
3662  } else
3663  strcpy(state->instrument->mnemonic, "ill_grp_9");
3664 }
3665 
3666 /* opcode 0FB9 */
3667 void grp_10(struct disassembly_state *state)
3668 {
3669  // UD e grp 10
3670  // Qui non c'è nulla da fare
3671  strcpy(state->instrument->mnemonic, "ill_grp_10");
3672 }
3673 
3674 /* opcodes C6-C7 */
3675 void grp_11(struct disassembly_state *state)
3676 {
3677  read_modrm(state);
3678 
3679  if((state->modrm >> 3) & 0x07) {
3680  strcpy(state->instrument->mnemonic, "ill_grp_11");
3681  return;
3682  }
3683 
3684  // In questo gruppo ci sono delle mov che possono scrivere a memoria,
3685  // ma il flag è stato già settato a true precedentemente
3686  strcpy(state->instrument->mnemonic, "mov");
3687  state->instrument->flags |= I_MEMWR;
3688 
3689  // [FV] La seguente porzione di codice mi pare ridondante
3690  /* [FV]
3691  * state->addr[0] = ADDR_E;
3692  * state->addr[1] = ADDR_I;
3693  *
3694  * if(state->opcode[0] == 0xc6)
3695  * state->op[0] = state->op[1] = OP_B;
3696  * else
3697  * state->op[0] = state->op[1] = OP_V;
3698  */
3699 }
3700 
3701 /* opcode 0F71 */
3702 void grp_12(struct disassembly_state *state)
3703 {
3704  unsigned char encoding, mod, sse_prefix;
3705  bool illegal = false;
3706  char *mnemonic;
3707 
3708  read_modrm(state);
3709 
3710  encoding = (state->modrm >> 3) & 0x07;
3711  mod = (state->modrm >> 6) & 0x03;
3712  sse_prefix = state->sse_prefix;
3713 
3714  state->prefix[0] = state->prefix[3] = 0x00; // cancella i prefissi grp 1 e 3
3715 
3716  if(mod != 0b11 || (sse_prefix != 0x66 && sse_prefix != 0x00))
3717  illegal = true;
3718 
3719  switch(encoding) {
3720  case 0x02: mnemonic = "psrlw"; break;
3721  case 0x04: mnemonic = "psraw"; break;
3722  case 0x06: mnemonic = "psllw"; break;
3723  default: illegal = true;
3724  }
3725 
3726  if(illegal == false) {
3727  strcpy(state->instrument->mnemonic, mnemonic);
3728  state->instrument->flags = I_ALU;
3729 
3730  if(sse_prefix == 0x66) {
3731  state->addr[0] = ADDR_W; // [FV] Errore!? Era riportato ADDR_P...
3732  state->op[0] = OP_DQ;
3733  state->instrument->flags |= I_SSE2 | I_XMM; // [FV] Controllare! Insieme ad istanze analoghe.
3734  }
3735  else {
3736  state->addr[0] = ADDR_P;
3737  state->op[0] = OP_Q;
3738  state->instrument->flags |= I_MMX; //Alice
3739  }
3740 
3741  state->addr[1] = ADDR_I;
3742  state->op[1] = OP_B;
3743  }
3744  else {
3745  strcpy(state->instrument->mnemonic, "ill_grp_12");
3746  }
3747 }
3748 
3749 /* opcode 0F72 */
3750 void grp_13(struct disassembly_state *state)
3751 {
3752  unsigned char encoding, mod, sse_prefix;
3753  bool illegal = false;
3754  char *mnemonic;
3755 
3756  read_modrm(state);
3757 
3758  encoding = (state->modrm >> 3) & 0x07;
3759  mod = (state->modrm >> 6) & 0x03;
3760  sse_prefix = state->sse_prefix;
3761 
3762  state->prefix[0] = state->prefix[2] = 0x00; // cancella i prefissi grp 1 e 3
3763 
3764  if(mod != 0x03 || (sse_prefix != 0x66 && sse_prefix != 0x00))
3765  illegal = true;
3766 
3767  switch(encoding) {
3768  case 0x02: mnemonic = "psrld"; break;
3769  case 0x04: mnemonic = "psrad"; break;
3770  case 0x06: mnemonic = "pslld"; break;
3771  default: illegal = true;
3772  }
3773 
3774  if(illegal == false) {
3775  strcpy(state->instrument->mnemonic, mnemonic);
3776  state->instrument->flags = I_ALU;
3777 
3778  state->addr[0] = ADDR_P;
3779  state->addr[1] = ADDR_I;
3780 
3781  if(sse_prefix == 0x66) {
3782  state->op[0] = OP_DQ;
3783  state->instrument->flags |= I_SSE2 | I_XMM;
3784  }
3785  else { // [FV] In questo caso riportava addr[0] = ADDR_W. Errore!?
3786  state->op[0] = OP_Q;
3787  state->instrument->flags |= I_MMX; //Alice
3788  }
3789 
3790  state->op[1] = OP_B;
3791  }
3792  else {
3793  strcpy(state->instrument->mnemonic, "ill_grp_13");
3794  }
3795 }
3796 
3797 /* opcode 0F73 */
3798 void grp_14(struct disassembly_state *state)
3799 {
3800  unsigned char encoding, mod, sse_prefix;
3801  char *mnemonic;
3802 
3803  read_modrm(state);
3804 
3805  encoding = (state->modrm >> 3) & 0x07;
3806  mod = (state->modrm >> 6) & 0x03;
3807  sse_prefix = state->sse_prefix;
3808 
3809  state->prefix[0] = state->prefix[3] = 0x00; // Cancella pref grp 1 e 3
3810 
3811  // Per codificare 0x02 e 0x06, i prefissi sse validi sono 0x00 e 0x66.
3812  // Per codificare 0x03 e 0x07, l'unico prefisso valido è 0x66
3813  if(mod != 0b11 ||
3814  (
3815  (!((encoding == 0x02 || encoding == 0x06) && ((sse_prefix == 0x00) || (sse_prefix == 0x66)))) ||
3816  (!((encoding == 0x03 || encoding == 0x07) && (sse_prefix == 0x66)))) // [FV] Attenzione! I controlli erano errati perché mancava la negazione su sse_prefix
3817  ) {
3818  strcpy(state->instrument->mnemonic, "ill_grp_14");
3819  return;
3820  }
3821 
3822  // [FV] pslldq solo quando encoding == 7
3823  mnemonic = (encoding == 2) ? "psrlq" : (encoding == 3) ? "psrldq" : (encoding == 6) ? "psllq" : "pslldq";
3824  strcpy(state->instrument->mnemonic, mnemonic);
3825 
3826  state->instrument->flags = I_ALU;
3827 
3828  if(sse_prefix == 0x66) {
3829  state->addr[0] = ADDR_W;
3830  state->op[0] = OP_DQ;
3831  state->instrument->flags |= I_XMM | I_SSE2;
3832  } else {
3833  state->addr[0] = ADDR_P;
3834  state->op[0] = OP_Q;
3835  state->instrument->flags |= I_MMX;
3836  }
3837 
3838  state->addr[1] = ADDR_I;
3839  state->op[1] = OP_B; // [FV] Errore, c'era scritto op[0] !
3840 }
3841 
3842 /* opcode 0FAE */ // [FV] Non tutte le istruzioni sono gestite
3843 void grp_15(struct disassembly_state *state)
3844 {
3845  unsigned char encoding, mod;
3846  char *mnemonic;
3847 
3848  read_modrm(state);
3849 
3850  encoding = (state->modrm >> 3) & 0x07;
3851  mod = (state->modrm >> 6) & 0x03;
3852 
3853  if((mod == 0b11 && encoding < 5) || (mod != 0b11 && (encoding < 7 && encoding > 3))) { // XSAVE, XRSTOR, XSAVEOPT
3854  strcpy(state->instrument->mnemonic, "ill_grp_15");
3855  return;
3856  }
3857 
3858  if(mod == 0b11) { //Alice
3859  switch(encoding) {
3860  case 0x05: mnemonic = "lfence"; break;
3861  case 0x06: mnemonic = "mfence"; break;
3862  case 0x07: mnemonic = "sfence"; break;
3863  }
3864  } else {
3865  state->addr[0] = ADDR_M;
3866 
3867  switch(encoding) {
3868  case 0x00: // fxsave
3869  mnemonic = "fxsave";
3870  state->instrument->flags = I_MEMWR | I_CTRL | I_MMX | I_XMM | I_FPU;
3871  state->op[0] = OP_M512byte;
3872  break;
3873  case 0x01: // fxrstor
3874  mnemonic = "fxrstor";
3875  state->instrument->flags = I_MEMRD | I_CTRL | I_MMX | I_XMM | I_FPU;
3876  state->op[0] = OP_M512byte;
3877  break;
3878  case 0x02: // ldmxcsr
3879  mnemonic = "ldmxcsr";
3880  state->instrument->flags = I_MEMRD | I_SSE;
3881  state->op[0] = OP_D;
3882  break;
3883  case 0x03: // stmxcsr
3884  mnemonic = "stmxcsr";
3885  state->instrument->flags = I_MEMWR | I_SSE;
3886  state->op[0] = OP_D;
3887  break;
3888  case 0x07: // clflush
3889  mnemonic = "clflush";
3890  state->instrument->flags = I_SSE2; // [FV] SSE2 cacheability instruction, ma ha un proprio CPUID Feature flag
3891  state->op[0] = OP_B;
3892  break;
3893  }
3894 
3895  strcpy(state->instrument->mnemonic, mnemonic);
3896  // Imposto Addr/Op più probabili
3897  // [FV] state->addr[0] = ADDR_M;
3898  // [FV] state->op[0] = OP_B;
3899  }
3900 }
3901 
3902 /* opcode OF18 */
3903 void grp_16(struct disassembly_state *state)
3904 {
3905  unsigned char encoding, mod;
3906  char *mnemonic;
3907 
3908  read_modrm(state);
3909 
3910  encoding = (state->modrm >> 3) & 0x07;
3911  mod = (state->modrm >> 6) & 0x03;
3912 
3913  if(mod == 0x03 || encoding > 0x03) {
3914  strcpy(state->instrument->mnemonic, "ill_grp_16");
3915  return;
3916  }
3917 
3918  switch(encoding) {
3919  case 0x00: mnemonic = "prefetchnta"; break;
3920  case 0x01: mnemonic = "prefetcht0"; break;
3921  case 0x02: mnemonic = "prefetcht1"; break;
3922  case 0x03: mnemonic = "prefetcht2"; break;
3923  }
3924 
3925  state->instrument->flags = I_MEMRD;
3926  strcpy(state->instrument->mnemonic, mnemonic);
3927  state->addr[0] = ADDR_M;
3928  state->op[0] = OP_B;
3929 }
3930 
3931 /* select_operand_size
3932  * Determina quanti dati verranno scritti in memoria, utilizzando le
3933  * dimensioni degli operandi
3934  */
3935 void select_operand_size(struct disassembly_state *state, enum operand_type op)
3936 {
3937  unsigned long size;
3938 
3939  // Eccezione per la modalità a 64bit:
3940  // Se c'è il prefisso 66H e REX.W = 0, la dimensione è 16 bit
3941  if(state->prefix[3] == 0x66 && !REXW(state->rex)) {
3942  state->instrument->span = 2;
3943  return;
3944  }
3945 
3946  switch(op) {
3947  case OP_M512byte:
3948  size = 512;
3949  break;
3950  case OP_FSR:
3951  if(state->opd_size == SIZE_16)
3952  size = 94;
3953  else
3954  size = 108;
3955  break;
3956  case OP_FS:
3957  if(state->opd_size == SIZE_16)
3958  size = 14;
3959  else
3960  size = 24;
3961  break;
3962  case OP_A:
3963  /* Istruzione BOUND: se lavoriamo con operandi a 16 bit, vengono letti dalla memoria due interi word
3964  * con segno adiacenti, mentre se lavoriamo a 32 bit, vengono letti dalla memoria due interi doubleword
3965  * con segno adiacenti. L'istruzione BOUND non è permessa in 64-bit mode.
3966  */
3967  if(state->opd_size == SIZE_16) {
3968  size = 4;
3969  }
3970  else {
3971  size = 8;
3972  }
3973  break;
3974  case OP_0:
3975  case OP_E:
3976  size = 0;
3977  break;
3978  case OP_C: /* byte/word/qword */
3979  if(REXW(state->rex)) {
3980  size = 8;
3981  break;
3982  }
3983  if(state->opd_size == SIZE_16) {
3984  size = 2;
3985  break;
3986  }
3987  /* fallthrough */
3988  case OP_B: /* byte, a prescindere da tutti gli altri parametri */
3989  size = 1;
3990  break;
3991  case OP_Y:
3992  if(REXW(state->rex)) {
3993  size = 8; // [FV] e.g. istruzione MOVNTI
3994  break;
3995  }
3996  /* fallthrough */
3997  case OP_D: /* double word */
3998  /* fallthrough */
3999  case OP_SI:
4000  size = 4;
4001  break;
4002  case OP_PD: /* double quad word */
4003  case OP_DQ:
4004  size = 16;
4005  break;
4006  case OP_P: /* 6 byte o double word */ // [FV] Od anche 10 byte
4007  if(REXW(state->rex)) {
4008  size = 10; // [FV] e.g. istruzione LSS
4009  break;
4010  }
4011  if(state->opd_size == SIZE_16) { // [FV] C'era scritto "SIZE_32" invece di "SIZE_16"?
4012  size = 4;
4013  break;
4014  }
4015  size = 6;
4016  break;
4017  case OP_S: /* 6 byte*/ // [FV] Non dovrebbe riportare 10 byte per IA-32e mode? eg istruzione SGDT?
4018  if(state->mode64 == true) // [FV] Da rivedere!
4019  size = 10;
4020  else
4021  size = 6;
4022  break;
4023  case OP_PS: /* double quad word */
4024  size = 16;
4025  break;
4026  case OP_M80:
4027  size = 10;
4028  break;
4029  case OP_Q: /* quad word */
4030  case OP_PI:
4031  size = 8;
4032  break;
4033  case OP_SS: /* double word */
4034  case OP_SD:
4035  size = 4;
4036  break;
4037  case OP_V: /* word o double word o quad word*/ // [FV] Rivedere, pero', istruzioni come la SLDT
4038  if(REXW(state->rex)) {
4039  size = 8;
4040  break;
4041  }
4042  if(state->opd_size == SIZE_32) {
4043  size = 4;
4044  break;
4045  }
4046  /* fallthrough */
4047  case OP_W: /* word */
4048  size = 2;
4049  }
4050 
4051  state->instrument->span = size;
4052 }
4053 
4054 
4055 void format_addr_m (struct disassembly_state *state, enum addr_method addr, enum operand_type op);
4056 
4057 /* Le funzioni di formato usano l'istruzione, il metodo di accesso ed il tipo
4058  * di operando per estrarre informazioni sul tipo di dati gestiti dalle
4059  * istruzioni
4060  */
4061 
4062 /* format_addr_a
4063  * Accesso diretto. Nessun byte ModR/M, nessun registro di base, nessun indice nei
4064  * registri, nessun fattore di scala. Decisamente semplice!
4065  */
4066 void format_addr_a (struct disassembly_state *state, enum addr_method addr, enum operand_type op)
4067 {
4068  (void)addr;
4069 
4070  // Questo formato è proprio della jmp far e della call far.
4071  // La jmp imposta il flag to_instrument a true, mentre la
4072  // call no. Pertanto, soltanto la jmp far sarà intercettata.
4073 
4074  // [FV] state->instrument->is_jmp = true;
4075 
4076  uint16_t segment, short_offset;
4077  uint32_t long_offset, offset;
4078 
4079  if(op == OP_P) { // Recupera il segmento
4080  memcpy(&segment, state->text + state->pos, 2);
4081  state->pos += 2;
4082 
4083  // Recupera l'offset
4084  if(state->opd_size == SIZE_16) { // 16 bit
4085  memcpy(&short_offset, state->text + state->pos, 2);
4086  state->pos += 2;
4087  offset = short_offset;
4088  } else { // 32 o 64 bit
4089  memcpy(&long_offset, state->text + state->pos, 4);
4090  state->pos += 4;
4091  offset = long_offset;
4092  }
4093 
4094  // Memorizza l'indirizzo assoluto
4095  state->instrument->addr = segment;
4096 
4097  // TODO: ricontrollare a cosa serviva qui offset...
4098  (void)offset;
4099  } else {
4100  fprintf(stderr, "%s:%d: Errore interno\n", __FILE__, __LINE__);
4101  abort();
4102  }
4103 }
4104 
4105 /* format_addr_c
4106  * I bit 5-3 del byte ModR/M identificano un registro di controllo
4107  */
4108 void format_addr_c (struct disassembly_state *state, enum addr_method addr, enum operand_type op)
4109 {
4110  (void)addr;
4111  (void)op;
4112 
4113  // Da qui non si può recuperare alcuna informazione interessante...
4114 
4115  char modrm = (state->modrm >> 3) & 0x07;
4116 
4117  // Estende i registri di controllo a 64bit
4118  if(state->mode64) {
4119  if(REXR(state->rex))
4120  modrm |= 0x08;
4121  }
4122 
4123  switch(modrm) {
4124  case 0: // cr0
4125  case 1: // cr1
4126  case 2: // cr2
4127  case 3: // cr3
4128  case 4: // cr4
4129  case 8: // cr8 [Task Priority Register]
4130  default: // cr_undef
4131  break;
4132  }
4133 }
4134 
4135 /* format_addr_d
4136  * I bit 5-3 del byte ModR/M selezionano un registro di debug
4137  */
4138 void format_addr_d (struct disassembly_state *state, enum addr_method addr, enum operand_type op)
4139 {
4140  (void)addr;
4141  (void)op;
4142 
4143  // Niente di interessante...
4144 
4145  char modrm = (state->modrm >> 3) & 0x07;
4146 
4147  // Estende i registri di controllo a 64bit
4148  if(state->mode64) {
4149  if(REXR(state->rex))
4150  modrm |= 0x08;
4151  }
4152 
4153  switch(modrm) {
4154  case 0: // dr0
4155  case 1: // dr1
4156  case 2: // dr2
4157  case 3: // dr3
4158  case 4: // dr4
4159  case 5: // dr5
4160  case 6: // dr6
4161  case 7: // dr7
4162  case 8: // dr8
4163  case 9: // dr9
4164  case 10: // dr10
4165  case 11: // dr11
4166  case 12: // dr12
4167  case 13: // dr13
4168  case 14: // dr14
4169  case 15: // dr15
4170  default: // dr_undef
4171  break;
4172  }
4173 }
4174 
4175 /* format_addr_e
4176  * A seconda del byte ModR/M, l'operando o è un registro, o è un
4177  * indirizzo di memoria con un registro di base opzionale, registro
4178  * di indice, fattore di scala e displacement...
4179  */
4180 void format_addr_e (struct disassembly_state *state, enum addr_method addr, enum operand_type op)
4181 {
4182 
4183  /* Se ModR/M specifica un registro, allora OP specifica la sua dimensione,
4184  come la differenza tra ax, eax o rax. Se ModR/M specifica un indirizzo,
4185  allora OP specifica il tipo di dato puntato (byte, word, ...) */
4186  unsigned char rm;
4187  enum reg_size reg_size = REG_SIZE_128;
4188 
4189  (void)addr;
4190 
4191  rm = state->modrm & 0x07;
4192 
4193  switch(op) {
4194  case OP_B: /* 1 */
4195  reg_size = REG_SIZE_8;
4196  break;
4197  case OP_C: /* 1/2 */
4198  if(state->opd_size != SIZE_16) {
4199  reg_size = REG_SIZE_8;
4200  break;
4201  }
4202  /* fallthrough */
4203  case OP_W: /* 2 */
4204  reg_size = REG_SIZE_16;
4205  break;
4206  case OP_V: /* 2/4/8 */ // [FV] Controllare, tuttavia, la SLDT
4207  if(state->opd_size == SIZE_64) {
4208  if(REXW(state->rex)) {
4209  reg_size = REG_SIZE_64;
4210  break;
4211  }
4212  }
4213  if(state->opd_size == SIZE_16) {
4214  reg_size = REG_SIZE_16;
4215  break;
4216  }
4217  /* fallthrough */
4218  case OP_D: /* 4 */
4219  case OP_SI: /* 4 */
4220  reg_size = REG_SIZE_32;
4221  break;
4222  case OP_Q: /* 8 */
4223  case OP_PI: /* 8 */
4224  reg_size = REG_SIZE_64;
4225  break;
4226  case OP_DQ: /* 16 */
4227  case OP_PS: /* 16 */
4228  case OP_PD: /* 16 */
4229  reg_size = REG_SIZE_128;
4230  break;
4231  case OP_Y: /* RICONTROLLARE ASSOLUTAMENTE */
4232  if(state->opd_size == SIZE_64) {
4233  reg_size = REG_SIZE_64;
4234  }
4235  reg_size = REG_SIZE_32;
4236  break;
4237  default:
4238  fprintf(stderr, "%s: %d: Unexpected operand %d\n", __FILE__, __LINE__, op);
4239  break;
4240  }
4241 
4242  if(state->modrm >> 6 == 0x3) { // Specifica un registro
4243  /* [FV] Potrebbe sia leggere che scrivere la memoria e, se lo fa, e' soltanto tramite questo operando */
4244  state->instrument->flags &= ~(I_MEMWR | I_MEMRD);
4245 
4246  if(!state->read_dest) {
4247  // È a registro: non scrive in memoria
4248  // [FV] state->instrument->to_memory = false;
4249 
4250  // Nel caso di una jump, potrebbe essere una indirect branch:
4251  // salva il valore del registro come fosse un registro di base
4252  state->instrument->has_base_register = true;
4253  state->instrument->breg = rm;
4254  }
4255  } else {
4256  switch(reg_size) {
4257  case REG_SIZE_8: // byte
4258  case REG_SIZE_16: // word
4259  case REG_SIZE_32: // dword
4260  case REG_SIZE_64: // qword
4261  case REG_SIZE_128: // oword
4262  default: // ?
4263  break;
4264  }
4265 
4266  if(state->addr[0] != ADDR_G
4267  && state->addr[1] != ADDR_G
4268  && state->addr[2] != ADDR_G) {
4269  // Se siamo a 64 bit, REX.R estende il campo reg
4270  if(state->mode64 && REXR(state->rex)) {
4271  ; // Qui andrebbe esteso il campo reg
4272  }
4273  }
4274 
4275  if(state->op[0] == 0x0F && state->op[1] == 0xC4) // [FV] Eccezione istruzioni PINSRW
4276  op = OP_W;
4277  format_addr_m(state, addr, op); // passa il riferimento a memoria
4278  }
4279 }
4280 
4281 /* format_addr_g
4282  * Il campo Reg del byte ModR/M specifica un registro
4283  */
4284 void format_addr_g (struct disassembly_state *state, enum addr_method addr, enum operand_type op)
4285 {
4286  enum reg_size reg_size;
4287  int reg_field;
4288  (void)addr;
4289 
4290  // Tipo predefinito - molto probabilmente è quello sbagliato...
4291  reg_size = REG_SIZE_128;
4292  reg_field = (state->modrm >> 3) & 0x07;
4293 
4294  // Estende ai registri a 64 bit, se esegue in modalità a 64 bit
4295  if(state->mode64 && REXR(state->rex)) {
4296  reg_field |= 0x08;
4297  }
4298 
4299  switch(op) {
4300  case OP_B: /* 8 */
4301  reg_size = REG_SIZE_8;
4302  break;
4303  case OP_C: /* 8/16 */
4304  if(state->opd_size != SIZE_16) {
4305  reg_size = REG_SIZE_8;
4306  break;
4307  }
4308  /* fallthrough */
4309  case OP_W: /* 16 */
4310  reg_size = REG_SIZE_16;
4311  break;
4312  case OP_V: /* 16/32/64 */
4313  if(state->opd_size == SIZE_64) {
4314  if(REXW(state->rex)) {
4315  reg_size = REG_SIZE_64;
4316  break;
4317  }
4318  }
4319  if(state->opd_size == SIZE_16) {
4320  reg_size = REG_SIZE_16;
4321  break;
4322  }
4323  /* fallthrough */
4324  case OP_D: /* 32 */
4325  reg_size = REG_SIZE_32;
4326  break;
4327  case OP_Y:
4328  if(state->opd_size == SIZE_64) {
4329  if(REXW(state->rex)) {
4330  reg_size = REG_SIZE_64;
4331  break;
4332  }
4333  }
4334  /* fallthrough */
4335  case OP_SI: /* 32 */
4336  reg_size = REG_SIZE_32;
4337  break;
4338  default:
4339  fprintf(stderr, "%s: %d: Unexpected operand %d\n", __FILE__, __LINE__, op);
4340  break;
4341  }
4342 
4343  // TODO: reg_field mantiene il codice del registro, a questo punto
4344  // potremmo aggiungere un campo che ne tiene traccia per l'emissione
4345  // dell'istruzione assembly inversa
4346  //
4347  // TODO: (2) Questa cosa scritta qui sopra è quanto ha implementato Simone
4348  // qui sotto
4349  //
4350  // Il campo reg_size può essere usato per discriminare la dimensione del
4351  // registro e quindi impostare il nome del registro correttamente
4352  (void)reg_size;
4353 
4354  // [SE] Hack terribile per ottenere il codice del registro destinazione
4355  state->instrument->reg_dest = reg_field;
4356 }
4357 
4358 /* format_addr_i
4359  * Dati immediati
4360  */
4361 void format_addr_i (struct disassembly_state *state, enum addr_method addr, enum operand_type op)
4362 {
4363  // I dati immediati sono di 1, 2 o 4 byte
4364  int immed_size = 0;
4365  uint8_t byte;
4366  uint16_t word;
4367  uint32_t dword;
4368  uint64_t qword, immed_data = 0;
4369  (void)addr;
4370 
4371  switch(op) {
4372  case OP_B: /* 8 */
4373  immed_size = 1;
4374  break;
4375  case OP_C: /* 8/16 */
4376  if(state->opd_size != SIZE_16) {
4377  immed_size = 1;
4378  break;
4379  }
4380  /* fallthrough */
4381  case OP_W: /* 16 */
4382  immed_size = 2;
4383  break;
4384  case OP_V: /* 16/32 */
4385  // Eccezione al funzionamento dei dati immediati: le mov con opcode 0xb8 - 0xbf permettodono di avere
4386  // come operando anche un dato immediato a 64 bit, qualora REX.W = 1.
4387  if(state->opcode[0] >= 0xb8 && state->opcode[0] <= 0xbf) {
4388  if(state->mode64 && REXW(state->rex)) {
4389  immed_size = 8;
4390  break;
4391  }
4392  }
4393  if(state->opd_size == SIZE_16) {
4394  immed_size = 2;
4395  break;
4396  }
4397  /* fallthrough */
4398  case OP_D: /* 32 */
4399  immed_size = 4;
4400  break;
4401  default:
4402  fprintf(stderr, "%s: %d: Unexpected operand %d\n", __FILE__, __LINE__, op);
4403  break;
4404  }
4405 
4406 
4407  switch(immed_size) {
4408  case 1:
4409  memcpy(&byte, state->text + state->pos, immed_size);
4410  immed_data = byte;
4411  break;
4412  case 2:
4413  memcpy(&word, state->text + state->pos, immed_size);
4414  immed_data = word;
4415  break;
4416  case 4:
4417  memcpy(&dword, state->text + state->pos, immed_size);
4418  immed_data = dword;
4419  break;
4420  case 8:
4421  memcpy(&qword, state->text + state->pos, immed_size);
4422  immed_data = qword;
4423  break;
4424  default:
4425  fprintf(stderr, "%s: %d: Unexpected size %d\n", __FILE__, __LINE__, immed_size);
4426  break;
4427  }
4428 
4429  // A questo punto immed_data contiene i dati immediati dell'istruzione
4430  // [SE] Populating immed_* fields
4431  state->instrument->immed_offset = state->immed_offset = state->pos;
4432  state->instrument->immed_size = state->immed_size = immed_size;
4433  state->instrument->immed = immed_data;
4434 
4435  state->pos += immed_size; // Salta i dati immediati appena gestiti
4436 }
4437 
4438 /* format_addr_j
4439  * L'istruzione contiene un offset relativo a EIP
4440  */
4441 void format_addr_j (struct disassembly_state *state, enum addr_method addr, enum operand_type op)
4442 {
4443  int off_size = 0, jump_size = 0;
4444  int8_t byte_jump;
4445  int16_t word_jump;
4446  int32_t dword_jump;
4447  (void)addr;
4448 
4449  switch(op) {
4450  case OP_B: /* 8 */
4451  off_size = 1;
4452  break;
4453  case OP_C: /* 8/16 */
4454  if(state->opd_size != SIZE_16) {
4455  off_size = 1;
4456  break;
4457  }
4458  /* fallthrough */
4459  case OP_W: /* 16 */
4460  off_size = 2;
4461  break;
4462  case OP_V: /* 16/32 */
4463  if(state->opd_size == SIZE_16) {
4464  off_size = 2;
4465  break;
4466  }
4467  /* fallthrough */
4468  case OP_D: /* 32 */
4469  off_size = 4;
4470  break;
4471  default:
4472  fprintf(stderr, "%s: %d: Unexpected operand %d\n", __FILE__, __LINE__, op);
4473  break;
4474  }
4475 
4476  jump_size = off_size;
4477 
4478  switch(off_size) {
4479  case 4:
4480  memcpy(&dword_jump, state->text + state->pos, off_size);
4481  break;
4482  case 2:
4483  memcpy(&word_jump, state->text + state->pos, off_size);
4484  break;
4485  case 1:
4486  memcpy(&byte_jump, state->text + state->pos, off_size);
4487  if(state->opd_size == SIZE_16) { // Estensione del segno
4488  word_jump = (int16_t)byte_jump;
4489  jump_size = 2;
4490  } else {
4491  dword_jump = (int32_t)byte_jump;
4492  jump_size = 4;
4493  }
4494  break;
4495  default:
4496  fprintf(stderr, "%s: errore interno alla riga %d: %d\n", __FILE__, __LINE__, jump_size);
4497  return;
4498  }
4499 
4500  state->pos += off_size;
4501 
4502  if(jump_size == 2) { // Indirizzi a 16 bit
4503  state->instrument->jump_dest = (int32_t)word_jump;
4504  } else { // Indirizzi a 32 bit
4505  state->instrument->jump_dest = dword_jump;
4506  }
4507 }
4508 
4509 /* format_addr_m
4510  * Il byte ModR/M può riferirsi soltanto a memoria, e il formato della memoria è terribile:
4511  * [base + index * scale + displacement]
4512  * Tutti gli elementi sono opzionali, anche se ci deve essere almeno "qualcosa".
4513  * Per i 16 e i 32 bit, nel volume 2A del SDM ci sono delle tabelle molto utili, a metà
4514  * del capitolo 2. Per i 64bit, la spiegazione è un po' meno accurata, ma il funzionamento
4515  * è più o meno simile all'indirizzamento per i 32 bit.
4516  */
4517 void format_addr_m (struct disassembly_state *state, enum addr_method addr, enum operand_type op)
4518 {
4519  bool no_sib_base = false;
4520  unsigned char mod, rm;
4521  unsigned long mem_ref;
4522 
4523  // Determina la dimensione della scrittura/lettura in memoria
4524  select_operand_size(state, op);
4525 
4526  if(addr == ADDR_M && op == OP_P) {
4527  format_addr_a(state, addr, op);
4528  return;
4529  }
4530 
4531  mod = state->modrm >> 6;
4532  rm = state->modrm & 0x07;
4533 
4534  if(mod == 0x3) { // Non dovrebbe verificarsi qui. Ma un po' di paranoia è buona
4535  /* Potrebbe accadere con l'opcode 62
4536  * 62 f8 per esattezza
4537  * mod = 11
4538  * reg = 111
4539  * r/m = 000
4540  */
4541  fprintf(stderr, "%s: errore interno alla riga %d: ModR/M %#02x\n", __FILE__, __LINE__, state->modrm);
4542  return;
4543  }
4544 
4545  // Gestisce separatamente i 16 e i 32 bit
4546  if(state->addr_size == SIZE_16) {
4547  uint8_t disp8;
4548  uint16_t disp16;
4549  char *eff_addr[] = { "bx + si", "bx + di", "bp + si", "bp + di",
4550  "si", "di", "bp", "bx" };
4551 
4552  // Se Mod è 00b e R/M è 110b, allora c'è solo uno spiazzamento a 16 bit
4553  if(mod == 0x0 && rm == 0x6) {
4554  memcpy(&disp16, state->text + state->disp_offset, 2);
4555 
4556  // Riferimento in memoria
4557  mem_ref = (unsigned long)disp16;
4558 
4559  state->instrument->addr = mem_ref;
4560 
4561  return;
4562  }
4563 
4564  // Copia il registro di base
4565  // [FV] if(!state->read_dest) {
4566 
4567  state->instrument->has_base_register = true;
4568  state->instrument->breg = rm;
4569  strcpy(state->instrument->breg_mnem, eff_addr[rm]);
4570 
4571  //Alice
4572  // Controlla se si sta accedendo a un indirizzo a partire dallo stack
4573  if(rm == 0x2 || rm == 0x3 || rm == 0x6) {
4574 
4575  state->instrument->flags |= I_STACK;
4576  }
4577 
4578 
4579  // [FV] }
4580 
4581  // Se Mod è 01b o 10b allora c'è, rispettivamente, uno spiazzamento di 8 o 16 bit
4582 
4583  // [FV] if(!state->read_dest) {
4584 
4585  if(mod == 0x1) {
4586  memcpy (&disp8, state->text + state->disp_offset, 1);
4587  state->instrument->addr = (int16_t)disp8;
4588  } else if(mod == 0x2) {
4589  memcpy (&disp16, state->text + state->disp_offset, 2);
4590  state->instrument->addr = disp16;
4591  }
4592 
4593  // [FV] }
4594 
4595  } else { // Indirizzi a 32 o 64 bit
4596  uint8_t disp8;
4597  uint32_t disp32;
4598  char *eff_addr_32[] = { "eax", "ecx", "edx", "ebx",
4599  "", "ebp", "esi", "edi" };
4600  char *eff_addr_64[] = { "rax", "rcx", "rdx", "rbx",
4601  "", "rbp", "rsi", "rdi",
4602  "r8", "r9", "r10", "r11",
4603  "r12", "r13", "r14", "r15"};
4604  char **eff_addr = eff_addr_32;
4605 
4606  // Determina se si indirizzano registri a 32 o a 64 bit
4607  if(state->mode64)
4608  eff_addr = eff_addr_64;
4609 
4610  // Se Mod è 00b e R/M è 101b, c'è solo uno spiazzamento di 32 bit
4611  if(mod == 0x0 && rm == 0x5) {
4612 
4613  // A 64 bit è RIP-Relative: non va instrumentato
4614  if(state->mode64) {
4615  state->uses_rip = true;
4616  } else {
4617 
4618  memcpy (&disp32, state->text + state->disp_offset, 4);
4619 
4620  // Riferimento in memoria
4621  mem_ref = (unsigned long)disp32;
4622 
4623  state->instrument->addr = mem_ref;
4624  }
4625 
4626  return;
4627  }
4628 
4629  // Se R/M è 100b, allora c'è il SIB che specifica l'operando
4630  if(rm == 0x4) {
4631  unsigned char ss, idx, base;
4632  char *base_r_32[] = { "eax", "ecx", "edx", "ebx",
4633  "esp", "", "esi", "edi" };
4634  char *idx_r_32[] = { "eax", "ecx", "edx", "ebx",
4635  "", "ebp", "esi", "edi" };
4636  char *base_r_64[] = { "rax", "rcx", "rdx", "rbx",
4637  "rsp", "", "rsi", "rdi",
4638  "r8", "r9", "r10", "r11",
4639  "r12", "r13", "r14", "r15" };
4640  char *idx_r_64[] = { "rax", "rcx", "rdx", "rbx",
4641  "", "rbp", "rsi", "rdi",
4642  "r8", "r9", "r10", "r11",
4643  "r12", "r13", "r14", "r15" };
4644 
4645  char **base_r = base_r_32;
4646  char **idx_r = idx_r_32;
4647 
4648  // Determina se si indirizzano registri a 32 o 64 bit
4649  if(state->mode64) {
4650  base_r = base_r_64;
4651  idx_r = idx_r_64;
4652  }
4653 
4654  ss = state->sib >> 6;
4655  idx = (state->sib >> 3) & 0x07;
4656  base = state->sib & 0x07;
4657 
4658  // Gestisce i registri estesi a 64 bit
4659  if(state->addr_size == SIZE_64) {
4660  // Estensione di idx
4661  if(REXX(state->rex))
4662  idx |= 0x08;
4663  // Estensione di base
4664  if(REXB(state->rex))
4665  base |= 0x08;
4666  }
4667 
4668  // Determina il registro base
4669  if(mod == 0x0 && (base == 0x5 || base == 0xd))
4670  no_sib_base = true;
4671  else {
4672  // [FV] if(!state->read_dest) {
4673 
4674  strcpy(state->instrument->breg_mnem, base_r[base]);
4675  state->instrument->breg = base;
4676  state->instrument->has_base_register = true;
4677 
4678  //Alice
4679  if(base == 0x04) { // esp
4680 
4681  state->instrument->flags |= I_STACK;
4682  }
4683 
4684  // [FV] }
4685  }
4686 
4687  // Se c'è un registro indice
4688  if(idx != 0x4 && idx != 0xc) {
4689 
4690  // Controlla la scala
4691  // [FV] if(!state->read_dest) {
4692 
4693  switch(ss) {
4694  case 1:
4695  state->instrument->has_scale = true;
4696  state->instrument->scale = 2;
4697  break;
4698  case 2:
4699  state->instrument->has_scale = true;
4700  state->instrument->scale = 4;
4701  break;
4702  case 3:
4703  state->instrument->has_scale = true;
4704  state->instrument->scale = 8;
4705  }
4706 
4707  // [FV] }
4708 
4709  // Copia il registro indice
4710  // [FV] if(!state->read_dest) {
4711 
4712  state->instrument->has_index_register = true;
4713  state->instrument->ireg = idx;
4714  strcat(state->instrument->ireg_mnem, idx_r[idx]);
4715 
4716  //Alice
4717  if(idx == 0x05) { // ebp
4718 
4719  state->instrument->flags |= I_STACK;
4720  }
4721 
4722 
4723  // [FV] }
4724  }
4725  } else { // Non c'è SIB
4726 
4727  // Gestisce i registri estesi a 64 bit
4728  if(state->addr_size == SIZE_64) {
4729  // Estensione di base
4730  if(REXB(state->rex))
4731  rm |= 0x08;
4732  }
4733 
4734  // [FV] if(!state->read_dest) {
4735 
4736  strcpy(state->instrument->breg_mnem, eff_addr[rm]);
4737  state->instrument->breg = rm;
4738  state->instrument->has_base_register = true;
4739 
4740  //Alice
4741  if(rm == 0x05) { // ebp
4742 
4743 
4744  state->instrument->flags |= I_STACK;
4745  }
4746 
4747 
4748  // [FV] }
4749  }
4750 
4751  // Se Mod è 01b o 10b allora c'è, rispettivamente, uno spiazzamento
4752  // di 8 o 32 bit
4753 
4754  if(mod == 0x1) {
4755  memcpy(&disp8, state->text + state->disp_offset, 1);
4756  state->instrument->addr = (unsigned long)disp8;
4757  } else if(mod == 0x2) {
4758  memcpy(&disp32, state->text + state->disp_offset, 4);
4759  state->instrument->addr = disp32;
4760  } else if(no_sib_base) {
4761  memcpy(&disp32, state->text + state->pos, 4);
4762  state->instrument->addr = disp32;
4763  state->disp_offset = state->pos; // TODO: questa roba andrebbe spostata in disp_size, anche se è una delle uniche due eccezioni...
4764  state->pos += 4;
4765  }
4766  }
4767 }
4768 
4769 /* format_addr_o
4770  * Byte ModR/M non presente. C'è un offset di dimensione ADDR_SIZE subito dopo l'istruzione
4771  */
4772 void format_addr_o (struct disassembly_state *state, enum addr_method addr, enum operand_type op)
4773 {
4774  uint8_t boff;
4775  uint16_t woff;
4776  uint32_t doff;
4777  uint64_t qoff;
4778  int offsize = 0;
4779 
4780  (void)addr;
4781 
4782  // Determina la dimensione della scrittura/lettura in memoria
4783  // [FV] if(!state->read_dest)
4784 
4785  select_operand_size(state, op);
4786 
4787  switch(state->addr_size) {
4788  // [FV] Aggiunto un case
4789  case SIZE_8:
4790  offsize = 1;
4791  break;
4792  case SIZE_16:
4793  offsize = 2;
4794  break;
4795  case SIZE_32:
4796  offsize = 4;
4797  break;
4798  case SIZE_64:
4799  offsize = 8;
4800  break;
4801  default:
4802  printf("Caso di default...\n");
4803  }
4804 
4805  if(offsize == 8)
4806  memcpy(&qoff, state->text + state->pos, offsize);
4807  else if(offsize == 4)
4808  memcpy(&doff, state->text + state->pos, offsize);
4809  else if(offsize == 2)
4810  memcpy(&woff, state->text + state->pos, offsize);
4811  // [FV] Aggiunto il seguente else
4812  else
4813  memcpy(&boff, state->text + state->pos, offsize);
4814 
4815  // TODO: La gestione del disp_offset andrebbe spostata alla macro disp_size,
4816  // anche se qui non viene utilizzato il byte ModR/M
4817  state->disp_offset = state->pos;
4818 
4819  // Fa avanzare il puntatore del parser
4820  state->pos += offsize;
4821 
4822  // Memorizza l'indirizzo in memoria
4823  switch(offsize) {
4824  case 8:
4825  state->instrument->addr = qoff;
4826  break;
4827  case 4:
4828  state->instrument->addr = doff;
4829  break;
4830  case 2:
4831  state->instrument->addr = woff;
4832  break;
4833  // [FV] Aggiunto il seguente case
4834  case 1:
4835  state->instrument->addr = boff;
4836  }
4837 }
4838 
4839 /* format_addr_p
4840  * Il campo reg del byte ModR/M seleziona un registro MMX.
4841  */
4842 void format_addr_p (struct disassembly_state *state, enum addr_method addr, enum operand_type op)
4843 {
4844  (void)state;
4845  (void)addr;
4846  (void)op;
4847 
4848  // Questo è il numero del registro a 64 bit: (state->modrm >> 3) & 0x07
4849 }
4850 
4851 /* format_addr_n [FV]
4852  * Il campo R/M del byte ModR/M seleziona un registro MMX.
4853  */
4854 void format_addr_n (struct disassembly_state *state, enum addr_method addr, enum operand_type op)
4855 {
4856  (void)state;
4857  (void)addr;
4858  (void)op;
4859 
4860  // Questo è il numero del registro a 64 bit: (state->modrm & 0x07)
4861 }
4862 
4863 /* format_addr_q
4864  * Il byte ModR/M specifica una posizione in memoria oppure un registro MMX
4865  */
4866 void format_addr_q (struct disassembly_state *state, enum addr_method addr, enum operand_type op)
4867 {
4868  if(state->modrm >> 6 == 0x3) { // Specifica un registro a 64 bit
4869  // [FV] Non legge, né scrive
4870  state->instrument->flags &= ~I_MEMRD & ~I_MEMWR; //Alice: state => flags
4871  }
4872  else {
4873  // [FV] Altrimenti non è I_MMX
4874  if(state->addr[0] != ADDR_P && state->addr[1] != ADDR_P && // [FV] Finora presenti solo ai primi due operandi
4875  state->addr[0] != ADDR_N && state->addr[1] != ADDR_N)
4876  state->instrument->flags &= ~I_MMX;
4877  format_addr_m (state, addr, op);
4878  }
4879 }
4880 
4881 /* format_addr_r
4882  * Il campo Mod del byte ModR/M può soltanto riferirsi ad un registro general purpose
4883  */
4884 void format_addr_r (struct disassembly_state *state, enum addr_method addr, enum operand_type op)
4885 {
4886  (void)addr;
4887 
4888  // Viene usato soltanto da OP_D
4889  if(op != OP_D) {
4890  fprintf(stderr, "%s:%d: Errore interno\n", __FILE__, __LINE__);
4891  abort();
4892  }
4893 
4894  // Identifica il registro
4895  char reg = state->modrm & 0x07;
4896  if(state->mode64 && REXR(state->rex))
4897  reg |= 0x08;
4898 
4899  // A questo punto, reg identifica il registro per la modalità d'esecuzione corrente
4900 }
4901 
4902 /* format_addr_s
4903  * Il campo Reg del byte ModR/M seleziona un segment register
4904  */
4905 void format_addr_s (struct disassembly_state *state, enum addr_method addr, enum operand_type op)
4906 {
4907  (void)state;
4908  (void)addr;
4909  (void)op;
4910 
4911  // I segment register sono:
4912  // es, cs, ss, ds, fs, gs, r_reg, r_seg
4913  // Gli r_seg sono segment register riservati
4914  // Il numero di registro è selezionato da: (state->modrm >> 3) & 0x07
4915 }
4916 
4917 /* format_addr_t
4918  * Il campo Reg del byte ModR/M sleziona un registro di test. Dopo un po'
4919  * di tempo passato sul SDM, ho capito che i registri di test erano usati
4920  * soltanto nell'80486, sono stati soppiantati dal Pentium in poi dai MSR
4921  * e con l'avvento dell'architettura P6, un'istruzione di mov che coinvolge
4922  * un registro di test genera un'eccezione UD. In ogni caso, li prendo
4923  * comunque in considerazione, anche se è abbastanza inutile. Molto probabilmente
4924  * questa funzione (e tutte le chiamate ad essa) possono essere cancellate senza
4925  * problemi.
4926  */
4927 void format_addr_t (struct disassembly_state *state, enum addr_method addr, enum operand_type op)
4928 {
4929  (void)state;
4930  (void)addr;
4931  (void)op;
4932 
4933  // Il registro di test (se presente) è selezionato da (state->modrm >> 3) & 0x07
4934 }
4935 
4936 /* format_addr_v
4937  * Il campo Reg del byte ModR/M seleziona un registro XMM
4938  */
4939 void format_addr_v (struct disassembly_state *state, enum addr_method addr, enum operand_type op)
4940 {
4941  (void)addr;
4942  (void)op;
4943 
4944  char reg = (state->modrm >> 3) & 0x07;
4945  if(state->mode64 && REXR(state->rex))
4946  reg |= 0x08;
4947 
4948 }
4949 
4950 /* format_addr_u [FV]
4951  * Il campo R/M del byte ModR/M seleziona un registro XMM
4952  */
4953 void format_addr_u (struct disassembly_state *state, enum addr_method addr, enum operand_type op)
4954 {
4955  (void)addr;
4956  (void)op;
4957 
4958  char reg = state->modrm & 0x07;
4959  if(state->mode64 && REXR(state->rex))
4960  reg |= 0x08;
4961 }
4962 
4963 /* format_addr_w
4964  * Il byte ModR/M specifica o un registro XMM o la memoria
4965  */
4966 void format_addr_w (struct disassembly_state *state, enum addr_method addr, enum operand_type op)
4967 {
4968  if(state->modrm >> 6 == 0x3) {
4969  char reg = (state->modrm >> 3) & 0x07;
4970 
4971  // [FV] Ne' legge, ne' scrive (da verificare)
4972  state->instrument->flags &= ~I_MEMRD & ~I_MEMWR;
4973 
4974  if(state->mode64 && REXR(state->rex))
4975  reg |= 0x08;
4976  } else {
4977  if(state->addr[0] != ADDR_U && state->addr[0] != ADDR_V && /* state->addr[0] != ADDR_L &&*/
4978  state->addr[1] != ADDR_U && state->addr[1] != ADDR_V /*&& state->addr[1] != ADDR_L */)
4979  // [FV] Finora tali addressing methods sono presenti solo ai primi due operandi
4980  state->instrument->flags &= ~I_XMM;
4981  format_addr_m(state, addr, op);
4982  }
4983 }
4984 
4985 /* format_addr_x
4986  * X è un operando implicito, il suffisso nell'istruzione è b
4987  */
4988 void format_addr_x (struct disassembly_state *state, enum addr_method addr, enum operand_type op)
4989 {
4990  (void)addr;
4991  (void)op;
4992 
4993  // La dimensione è sicuramente 1 byte
4994  state->instrument->span = 1;
4995 
4996  // È un'istruzione che lavora sulle stringhe
4997  // [FV] state->instrument->is_string_insn = true;
4998 }
4999 
5000 /* format_addr_y
5001  * Y è un operando implicito, il suffisso nell'istruzione è l o w o q a seconda
5002  */
5003 void format_addr_y (struct disassembly_state *state, enum addr_method addr, enum operand_type op)
5004 {
5005  (void)addr;
5006 
5007  // Determina la dimensione della scrittura/lettura in memoria
5008  // [FV] if(!state->read_dest)
5009  select_operand_size(state, op);
5010 
5011  // È un'istruzione che lavora sulle stringhe
5012  // [FV] state->instrument->is_string_insn = true;
5013 }
5014 
5015 
5016 /* format_addr_op
5017  * Questa funzione decide quale tipo di indirizzamento viene usato dall'istruzione
5018  * (se a registro o a memoria, qual è la dimensione dei dati, ...)
5019  */
5020 void format_addr_op (struct disassembly_state *state, enum addr_method addr, enum operand_type op)
5021 {
5022 
5023  switch(addr) {
5024 
5025  case ADDR_N:
5026  format_addr_n(state, addr, op);
5027  break;
5028 
5029  case ADDR_U:
5030  format_addr_u(state, addr, op);
5031  break;
5032 
5033  case ADDR_A:
5034  format_addr_a(state, addr, op);
5035  break;
5036 
5037  case ADDR_C:
5038  format_addr_c(state, addr, op);
5039  break;
5040 
5041  case ADDR_D:
5042  format_addr_d(state, addr, op);
5043  break;
5044 
5045  case ADDR_E: // Può esserci accesso a memoria
5046  format_addr_e(state, addr, op);
5047  break;
5048 
5049  case ADDR_F:
5050  // Non occorre fare nulla per questo metodo di indirizzamento.
5051  // È utilizzato soltanto da pushf/popf e si riferisce sempre e solo ad eflags
5052  break;
5053 
5054  case ADDR_G:
5055  // [FV] Si tratta di un registro
5056  format_addr_g(state, addr, op);
5057  break;
5058 
5059  case ADDR_I:
5060  // [FV] Si tratta di un dato immediato
5061  format_addr_i(state, addr, op);
5062  break;
5063 
5064  case ADDR_J:
5065  // [FV] state->instrument->is_jmp = true;
5066  format_addr_j(state, addr, op);
5067  break;
5068 
5069  case ADDR_M:
5070  format_addr_m(state, addr, op);
5071  break;
5072 
5073  case ADDR_O: // Ci sono due mov (A2 e A3) che scrivono su memoria
5074  // [FV] ... mentre A0 e A1 leggono dalla memoria
5075  format_addr_o(state, addr, op);
5076  break;
5077 
5078  case ADDR_P:
5079  format_addr_p(state, addr, op);
5080  break;
5081 
5082  case ADDR_Q: // Può esserci accesso a memoria
5083  format_addr_q(state, addr, op);
5084  break;
5085 
5086  case ADDR_R:
5087  format_addr_r(state, addr, op);
5088  break;
5089 
5090  case ADDR_S:
5091  format_addr_s(state, addr, op);
5092  break;
5093 
5094  case ADDR_T:
5095  break;
5096 
5097  case ADDR_V:
5098  format_addr_v(state, addr, op);
5099  break;
5100 
5101  case ADDR_W: // Può esserci accesso a memoria...
5102  format_addr_w(state, addr, op);
5103  break;
5104 
5105  case ADDR_X: // Può esserci accesso a memoria
5106  format_addr_x(state, addr, op);
5107  break;
5108 
5109  case ADDR_Y: // Può esserci accesso a memoria
5110  format_addr_y(state, addr, op);
5111  break;
5112 
5113  case R_START ... R_END:
5114  // I registri possono avere dimensioni diverse (es: [e]ax)
5115  // Per le dimensioni a 64 bit vale il fatto che se REX.B == 1, allora reg |= 0x08
5116  break;
5117 
5118  case IMMED_1:
5119  // Il valore 1...
5120  break;
5121 
5122  default:
5123  fprintf(stderr, "%s:%d: Unexpected address format %d\n", __FILE__, __LINE__, addr);
5124  }
5125 }
5126 
5127 /* x86_disassemble_instruction
5128  * Disassembla l'istruzione a text + *pos e restituisce una
5129  * riga di assembly dopo aver aggiornato *pos
5130  */
5131 void x86_disassemble_instruction (unsigned char *text, unsigned long *pos, insn_info_x86 *instrument, char flags)
5132 {
5133  int k = 0;
5134  bool print_prefixes = false; // Shall this become useful in the future?
5135  unsigned char opcode;
5136  insn_table table = one_byte_opcode_table;
5137  struct disassembly_state state;
5138 
5139  state.text = text;
5140  state.pos = *pos;
5141  state.disp_offset = 0;
5142 
5143  state.opcode[0] = 0x00;
5144  state.opcode[1] = 0x00;
5145 
5146  state.instrument = instrument;
5147  state.instrument->initial = *pos;
5148 
5149  // In realtà è un'affermazione un po' forte dire che se non è né a 64 né a 32 è a 16
5150  // Pare che gli ELF non prevedano codice a 16 bit...
5151  // In questo caso, probabilmente molto del lavoro fatto per supportare i 16
5152  // bit è stato inutile, ma devo ricontrollare in quali casi gli opcode
5153  // specificano i dati a 16 bit... E soprattutto, devo controllare
5154  // se GAS genera mai quegli opcode...
5155  // Credo che Linux non tratti più codice a 16 bit (e in effetti avrebbe ragione,
5156  // visto che è dall'8088 che non ci sono più processori a 16 bit).
5157  // Immagino che questo sproloquio corrisponda a un TODO.
5158  state.opd_size = D64(flags) || D32(flags) ? SIZE_32 : SIZE_16;
5159  state.addr_size = A64(flags) || A32(flags) ? SIZE_32 : SIZE_16;
5160 
5161  state.mode64 = D64(flags) ? true : false;
5162 
5163  // [FV] Imposto inizialmente a false il flag "uses_rip"
5164  state.uses_rip = false;
5165 
5166  state.rex = 0;
5167  state.modrm = 0;
5168  state.read_modrm = false;
5169  state.sib = 0;
5170 
5171  state.read_dest = false;
5172 
5173  state.sse_prefix = 0;
5174  state.prefix[0] = 0;
5175  state.prefix[1] = 0;
5176  state.prefix[2] = 0;
5177  state.prefix[3] = 0;
5178 
5179  state.orig_pos = *pos;
5180 
5181  /* Controlla e gestisce prefissi - alcune istruzioni xmm ed SSE hanno prefissi
5182  che non sono prefissi, pertanto bisogna rinviare la gestione dei prefissi
5183  quanto più possibile... */
5184  while(true) {
5185  opcode = state.text[state.pos++]; // Legge l'opcode
5186 // printf("x86.c_POS: %02x byte: %#02x\n", state.text[state.pos]-1, opcode);
5187 
5188  if(!is_prefix(opcode)) break; // I prefissi SSE sono anche prefissi normali (con significato diverso)
5189 
5190  // 66, F2, F3 - Prefissi SSE
5191  // Controlla il byte 3 dell'opcode
5192  if(is_sse_prefix(opcode))
5193  state.sse_prefix = opcode;
5194 
5195  // C'è un prefisso. Occorre capire di che tipo
5196  if(p_is_group1(opcode)) { /* lock/repne/repe */
5197  if(!state.prefix[0]) // Ignora prefissi addizionali
5198  state.prefix[0] = opcode;
5199  } else if(p_is_group2(opcode)) { /* segment override/branch hint */
5200  if(!state.prefix[1]) // Ignora prefissi addizionali
5201  state.prefix[1] = opcode;
5202  } else if(p_is_group3(opcode)) { /* operand size override prefix */
5203  if(!state.prefix[2]) // Ignora prefissi addizionali
5204  state.prefix[2] = opcode;
5205  } else if(p_is_group4(opcode)) { /* address size override prefix */
5206  if(!state.prefix[3]) // Ignora prefissi addizionali
5207  state.prefix[3] = opcode;
5208  } else { // mmm...
5209  fprintf(stderr, "%s:%d: Errore interno\n", __FILE__, __LINE__);
5210  abort();
5211  }
5212 
5213  }
5214 
5215  // Controlla se è presente il prefisso REX. Il byte REX, se presente, si trova
5216  // sempre tra i legacy-prefixes e l'opcode. Ce ne può essere più d'uno. In questo
5217  // caso, ha valore soltanto l'ultimo, gli altri vengono ignorati.
5218  while(true) {
5219  if(is_rex_prefix(opcode, state.mode64)) {
5220  state.rex = opcode;
5221  opcode = state.text[state.pos++];
5222  continue;
5223  }
5224  break;
5225  }
5226 
5227  // Recupera gli operandi e i metodi di indirizzamento dell'istruzione
5228  state.addr[0] = table[opcode].addr_method[0];
5229  state.addr[1] = table[opcode].addr_method[1];
5230  state.addr[2] = table[opcode].addr_method[2];
5231 
5232  state.op[0] = table[opcode].operand_type[0];
5233  state.op[1] = table[opcode].operand_type[1];
5234  state.op[2] = table[opcode].operand_type[2];
5235 
5236 
5237  // Controlla se l'istruzione è da instrumentare
5238  state.instrument->flags = table[opcode].flags;
5239 
5240  state.opcode[0] = opcode;
5241 
5242  // Salva l'istruzione
5243  if(table[opcode].instruction != NULL)
5244  strcpy(state.instrument->mnemonic, table[opcode].instruction);
5245 
5246  // Controlla opcode di escape
5247  if(table[opcode].instruction == NULL) { // byte di escape
5248  // Controllo di sicurezza
5249  if(table[opcode].esc_function == NULL) {
5250  fprintf(stderr, "%s:%d: Errore interno\n", __FILE__, __LINE__);
5251  abort();
5252  } else {
5253  table[opcode].esc_function(&state);
5254  }
5255  } else { // Istruzione normale
5256  }
5257 
5258  // Se c'è un prefisso di gruppo 2, controlla se c'è un'istruzione Jcc
5259  if(state.prefix[1]) {
5260  if(is_jcc_insn (state.opcode[0]) // branch hint prefix
5261  || (state.opcode[0] == 0x0f && is_esc_jcc_insn(state.opcode[1]))) {
5262  if(print_prefixes) {
5263  if(state.prefix[1] == 0x2e) {// branch not taken
5264  }
5265  else if(state.prefix[1] == 0x3e) { // branch taken
5266  }
5267  else { // invalid branch hint
5268  fprintf(stderr, "%s:%d: Errore interno\n", __FILE__, __LINE__);
5269  abort();
5270  }
5271  }
5272  state.prefix[1] = 0;
5273  } else { // segment override prefix
5274  }
5275  }
5276  if(state.prefix[2] == 0x66) {
5277  state.opd_size = ((state.opd_size == SIZE_32) || (state.opd_size == SIZE_64)) ? SIZE_16 : SIZE_32;
5278  }
5279  if(state.prefix[3] == 0x67) {
5280  state.addr_size = ((state.addr_size == SIZE_32) || (state.addr_size == SIZE_64)) ? SIZE_16 : SIZE_32;
5281  }
5282 
5283  /* Cerca gli offset di varie parti dell'istruzione */
5284 
5285  // Controlla il byte ModR/M
5286  if(!state.read_modrm && (has_modrm(state.addr[0])
5287  || has_modrm(state.addr[1]) || has_modrm(state.addr[2]))) {
5288  state.modrm = state.text[state.pos];
5289  state.pos++;
5290  }
5291 
5292  // Controlla il byte SIB
5293  if(has_sib(state.modrm, state.addr_size)) {
5294  state.sib = state.text[state.pos];
5295  state.pos++;
5296  }
5297 
5298  // Controlla il displacement
5299  state.disp_size = disp_size(state.modrm, state.addr_size);
5300 
5301  // [DC] Registra la dimensione dell'opcode, del prefisso, R/M e SIB delle istruzioni per gestire correttamente
5302  // la rilocazione nella fase di emissione del file instrumentato
5303  state.instrument->opcode_size = (state.pos - state.orig_pos);
5304 
5305  switch(state.disp_size) {
5306  case 8:
5307  state.instrument->disp = (long long) *(int64_t *)(state.text + state.pos);
5308  state.disp_offset = state.pos;
5309  state.pos += state.disp_size;
5310  break;
5311  case 4:
5312  state.instrument->disp = (long long) *(int32_t *)(state.text + state.pos);
5313  state.disp_offset = state.pos;
5314  state.pos += state.disp_size;
5315  break;
5316  case 2:
5317  state.instrument->disp = (long long) *(int16_t *)(state.text + state.pos);
5318  state.disp_offset = state.pos;
5319  state.pos += state.disp_size;
5320  break;
5321  case 1:
5322  state.instrument->disp = (long long) *(int8_t *)(state.text + state.pos);
5323  state.disp_offset = state.pos;
5324  state.pos += state.disp_size;
5325  break;
5326  }
5327 
5328  //state.instrument->opcode_size = (state.pos - state.orig_pos);
5329 
5330  // A questo punto, state.pos o è l'offset dei dati immediati, oppure
5331  // l'offset dell'istruzione seguente
5332  // I dati immediati vengono smaltiti dalle funzioni di formattazione.
5333 
5334  // Gestisce addr/op
5335  for(k = 0; k < 3; k++) {
5336 
5337  if(state.addr[k] == ADDR_0) break; // Finito!
5338 
5339  // Ogni istruzione può avere fino a tre operandi. Tipicamente il primo
5340  // è l'operando di destinazione. Effettuiamo un controllo su questo
5341  // operando per vedere se l'istruzione accede in memoria!
5342  format_addr_op(&state, state.addr[k], state.op[k]);
5343  state.read_dest = true;
5344 
5345  // [SE] Hack terribile per capire se un registro è usato come destinazione
5346  if (k == 0 && state.addr[k] == ADDR_G) {
5347  state.instrument->dest_is_reg = true;
5348  }
5349  }
5350 
5351  // Copia i byte dell'istruzione
5352  memcpy(state.instrument->insn, &(state.text[*pos]), state.pos - *pos);
5353 
5354  // Copia il displacement (se l'istruzione è da instrumentare ed accede a memoria)
5355  // [FV] Adesso copio il displacement indipendentemente da alcuna condizione
5356  // [FV] if(state.instrument->to_instrument && state.instrument->to_memory)
5357  state.instrument->disp_offset = state.disp_offset;
5358  state.instrument->disp_size = state.disp_size;
5359 
5360 
5361  // [FV] Copia il flag "uses_rip"
5362  state.instrument->uses_rip = state.uses_rip;
5363 
5364 
5365  // Copia i byte dell'opcode
5366  memcpy(state.instrument->opcode, state.opcode, 2);
5367 
5368  // [SE] Copia i rimanenti campi
5369  state.instrument->rex = state.rex;
5370  state.instrument->modrm = state.modrm;
5371  state.instrument->sib = state.sib;
5372  state.instrument->sse_prefix = state.sse_prefix;
5373  memcpy(state.instrument->prefix, state.prefix, 4);
5374 
5375  state.instrument->insn_size = (state.pos - *pos);
5376  *pos = state.pos;
5377 
5378 }
5379 
5380 #endif /* defined(__x86_64__) && defined(HAVE_ECS) */
5381 
x86 ISA disassembler header
Definition: mm.h:39