Rizin
unix-like reverse engineering framework and cli tools
asm_x86_nz.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2008-2020 pancake
2 // SPDX-FileCopyrightText: 2008-2020 unlogic
3 // SPDX-FileCopyrightText: 2008-2020 emvivre
4 // SPDX-License-Identifier: LGPL-3.0-only
5 
6 #include <rz_flag.h>
7 #include <rz_core.h>
8 #include <rz_asm.h>
9 #include <rz_lib.h>
10 #include <rz_types.h>
11 #include <stdio.h>
12 #include <string.h>
13 
14 static ut64 getnum(RzAsm *a, const char *s);
15 
16 #define ENCODING_SHIFT 0
17 #define OPTYPE_SHIFT 6
18 #define REGMASK_SHIFT 16
19 #define OPSIZE_SHIFT 24
20 
21 // How to encode the operand?
22 #define OT_REGMEM (1 << (ENCODING_SHIFT + 0))
23 #define OT_SPECIAL (1 << (ENCODING_SHIFT + 1))
24 #define OT_IMMEDIATE (1 << (ENCODING_SHIFT + 2))
25 #define OT_JMPADDRESS (1 << (ENCODING_SHIFT + 3))
26 
27 // Register indices - by default, we allow all registers
28 #define OT_REGALL (0xff << REGMASK_SHIFT)
29 
30 // Memory or register operands: how is the operand written in assembly code?
31 #define OT_MEMORY (1 << (OPTYPE_SHIFT + 0))
32 #define OT_CONSTANT (1 << (OPTYPE_SHIFT + 1))
33 #define OT_GPREG ((1 << (OPTYPE_SHIFT + 2)) | OT_REGALL)
34 #define OT_SEGMENTREG ((1 << (OPTYPE_SHIFT + 3)) | OT_REGALL)
35 #define OT_FPUREG ((1 << (OPTYPE_SHIFT + 4)) | OT_REGALL)
36 #define OT_MMXREG ((1 << (OPTYPE_SHIFT + 5)) | OT_REGALL)
37 #define OT_XMMREG ((1 << (OPTYPE_SHIFT + 6)) | OT_REGALL)
38 #define OT_CONTROLREG ((1 << (OPTYPE_SHIFT + 7)) | OT_REGALL)
39 #define OT_DEBUGREG ((1 << (OPTYPE_SHIFT + 8)) | OT_REGALL)
40 #define OT_SREG ((1 << (OPTYPE_SHIFT + 9)) | OT_REGALL)
41 // more?
42 
43 #define OT_REGTYPE ((OT_GPREG | OT_SEGMENTREG | OT_FPUREG | OT_MMXREG | OT_XMMREG | OT_CONTROLREG | OT_DEBUGREG) & ~OT_REGALL)
44 
45 // Register mask
46 #define OT_REG(num) ((1 << (REGMASK_SHIFT + (num))) | OT_REGTYPE)
47 
48 #define OT_UNKNOWN (0 << OPSIZE_SHIFT)
49 #define OT_BYTE (1 << OPSIZE_SHIFT)
50 #define OT_WORD (2 << OPSIZE_SHIFT)
51 #define OT_DWORD (4 << OPSIZE_SHIFT)
52 #define OT_QWORD (8 << OPSIZE_SHIFT)
53 #define OT_OWORD (16 << OPSIZE_SHIFT)
54 #define OT_TBYTE (32 << OPSIZE_SHIFT)
55 
56 #define ALL_SIZE (OT_BYTE | OT_WORD | OT_DWORD | OT_QWORD | OT_OWORD)
57 
58 // For register operands, we mostl don't care about the size.
59 // So let's just set all relevant flags.
60 #define OT_FPUSIZE (OT_DWORD | OT_QWORD | OT_TBYTE)
61 #define OT_XMMSIZE (OT_DWORD | OT_QWORD | OT_OWORD)
62 
63 // Macros for encoding
64 #define OT_REGMEMOP(type) (OT_##type##REG | OT_MEMORY | OT_REGMEM)
65 #define OT_REGONLYOP(type) (OT_##type##REG | OT_REGMEM)
66 #define OT_MEMONLYOP (OT_MEMORY | OT_REGMEM)
67 #define OT_MEMIMMOP (OT_MEMORY | OT_IMMEDIATE)
68 #define OT_REGSPECOP(type) (OT_##type##REG | OT_SPECIAL)
69 #define OT_IMMOP (OT_CONSTANT | OT_IMMEDIATE)
70 #define OT_MEMADDROP (OT_MEMORY | OT_IMMEDIATE)
71 
72 // Some operations are encoded via opcode + spec field
73 #define SPECIAL_SPEC 0x00010000
74 #define SPECIAL_MASK 0x00000007
75 
76 #define MAX_OPERANDS 3
77 #define MAX_REPOP_LENGTH 20
78 
79 #define is_valid_registers(op) \
80  if (is_debug_or_control(op->operands[0]) || is_debug_or_control(op->operands[1])) \
81  return -1;
82 
83 const ut8 SEG_REG_PREFIXES[] = { 0x26, 0x2e, 0x36, 0x3e, 0x64, 0x65 };
84 
85 typedef enum tokentype_t {
91 
92 typedef enum register_t {
94  X86R_EAX = 0,
103  X86R_AX = 0,
111  X86R_AL = 0,
119  X86R_RAX = 0,
128  X86R_R8 = 0,
136  X86R_CS = 0,
141  X86R_GS, // Is this the right order?
142  X86R_CR0 = 0,
150  X86R_DR0 = 0,
157  X86R_DR7
159 
160 typedef struct operand_t {
163  struct {
165  bool extended;
166  };
167  union {
168  struct {
172  int scale[2];
173  };
174  struct {
175  ut64 immediate;
177  };
178  struct {
180  };
181  };
186 
187 typedef struct Opcode_t {
188  char *mnemonic;
189  ut32 op[3];
190  size_t op_len;
191  bool is_short;
192  ut8 opcode[3];
193  int operands_count;
195  bool has_bnd;
197 
198 static inline bool is_debug_or_control(Operand op) {
199  return (op.type & OT_REGTYPE) & (OT_CONTROLREG | OT_DEBUGREG);
200 }
201 
202 static ut8 getsib(const ut8 sib) {
203  if (!sib) {
204  return 0;
205  }
206  return (sib & 0x8) ? 3 : getsib((sib << 1) | 1) - 1;
207 }
208 
209 static int is_al_reg(const Operand *op) {
210  if (op->type & OT_MEMORY) {
211  return 0;
212  }
213  if (op->reg == X86R_AL && op->type & OT_BYTE) {
214  return 1;
215  }
216  return 0;
217 }
218 
219 static int oprep(RzAsm *a, ut8 *data, const Opcode *op);
220 
221 static int process_16bit_group_1(RzAsm *a, ut8 *data, const Opcode *op, int op1) {
223  int l = 0;
224  int immediate = op->operands[1].immediate * op->operands[1].sign;
225 
226  data[l++] = 0x66;
227  if (op->operands[1].immediate < 128) {
228  data[l++] = 0x83;
229  data[l++] = op->operands[0].reg | (0xc0 + op1 + op->operands[0].reg);
230  } else {
231  if (op->operands[0].reg == X86R_AX) {
232  data[l++] = 0x05 + op1;
233  } else {
234  data[l++] = 0x81;
235  data[l++] = (0xc0 + op1) | op->operands[0].reg;
236  }
237  }
238  data[l++] = immediate;
239  if (op->operands[1].immediate > 127) {
240  data[l++] = immediate >> 8;
241  }
242 
243  return l;
244 }
245 
246 static int process_group_1(RzAsm *a, ut8 *data, const Opcode *op) {
248  int l = 0;
249  int modrm = 0;
250  int mod_byte = 0;
251  int offset = 0;
252  int mem_ref = 0;
253  st32 immediate = 0;
254 
255  if (!op->operands[1].is_good_flag) {
256  return -1;
257  }
258  if (a->bits == 64 && op->operands[0].type & OT_QWORD) {
259  data[l++] = 0x48;
260  }
261  if (!strcmp(op->mnemonic, "adc")) {
262  modrm = 2;
263  } else if (!strcmp(op->mnemonic, "add")) {
264  modrm = 0;
265  } else if (!strcmp(op->mnemonic, "or")) {
266  modrm = 1;
267  } else if (!strcmp(op->mnemonic, "and")) {
268  modrm = 4;
269  } else if (!strcmp(op->mnemonic, "xor")) {
270  modrm = 6;
271  } else if (!strcmp(op->mnemonic, "sbb")) {
272  modrm = 3;
273  } else if (!strcmp(op->mnemonic, "sub")) {
274  modrm = 5;
275  } else if (!strcmp(op->mnemonic, "cmp")) {
276  modrm = 7;
277  }
278  immediate = op->operands[1].immediate * op->operands[1].sign;
279 
280  if (op->operands[0].type & OT_DWORD ||
281  op->operands[0].type & OT_QWORD) {
282  if (op->operands[1].immediate < 128) {
283  data[l++] = 0x83;
284  } else if (op->operands[0].reg != X86R_EAX ||
285  op->operands[0].type & OT_MEMORY) {
286  data[l++] = 0x81;
287  }
288  } else if (op->operands[0].type & OT_BYTE) {
289  if (op->operands[1].immediate > 255) {
290  RZ_LOG_ERROR("assembler: x86.nz: %s: the immediate value exceeds bounds (imm > 255)\n", op->mnemonic);
291  return -1;
292  }
293  data[l++] = 0x80;
294  }
295  if (op->operands[0].type & OT_MEMORY) {
296  offset = op->operands[0].offset * op->operands[0].offset_sign;
297  if (op->operands[0].offset || op->operands[0].regs[0] == X86R_EBP) {
298  mod_byte = 1;
299  }
301  mod_byte = 2;
302  }
303  int reg0 = op->operands[0].regs[0];
304  if (reg0 == -1) {
305  mem_ref = 1;
306  reg0 = 5;
307  mod_byte = 0;
308  }
309  data[l++] = mod_byte << 6 | modrm << 3 | reg0;
310  if (op->operands[0].regs[0] == X86R_ESP) {
311  data[l++] = 0x24;
312  }
313  if (mod_byte || mem_ref) {
314  data[l++] = offset;
315  if (mod_byte == 2 || mem_ref) {
316  data[l++] = offset >> 8;
317  data[l++] = offset >> 16;
318  data[l++] = offset >> 24;
319  }
320  }
321  } else {
322  if (op->operands[1].immediate > 127 && op->operands[0].reg == X86R_EAX) {
323  data[l++] = 5 | modrm << 3 | op->operands[0].reg;
324  } else {
325  mod_byte = 3;
326  data[l++] = mod_byte << 6 | modrm << 3 | op->operands[0].reg;
327  }
328  }
329 
330  data[l++] = immediate;
331  if ((immediate > 127 || immediate < -128) &&
332  ((op->operands[0].type & OT_DWORD) || (op->operands[0].type & OT_QWORD))) {
333  data[l++] = immediate >> 8;
334  data[l++] = immediate >> 16;
335  data[l++] = immediate >> 24;
336  }
337  return l;
338 }
339 
340 static int process_group_2(RzAsm *a, ut8 *data, const Opcode *op) {
342  int l = 0;
343  int modrm = 0;
344  int mod_byte = 0;
345  int reg0 = 0;
346 
347  if (a->bits == 64 && op->operands[0].type & OT_QWORD) {
348  data[l++] = 0x48;
349  }
350 
351  if (!strcmp(op->mnemonic, "rol")) {
352  modrm = 0;
353  } else if (!strcmp(op->mnemonic, "ror")) {
354  modrm = 1;
355  } else if (!strcmp(op->mnemonic, "rcl")) {
356  modrm = 2;
357  } else if (!strcmp(op->mnemonic, "rcr")) {
358  modrm = 3;
359  } else if (!strcmp(op->mnemonic, "shl")) {
360  modrm = 4;
361  } else if (!strcmp(op->mnemonic, "shr")) {
362  modrm = 5;
363  } else if (!strcmp(op->mnemonic, "sal")) {
364  modrm = 6;
365  } else if (!strcmp(op->mnemonic, "sar")) {
366  modrm = 7;
367  }
368 
369  st32 immediate = op->operands[1].immediate * op->operands[1].sign;
370  if (immediate > 255 || immediate < -128) {
371  RZ_LOG_ERROR("assembler: x86.nz: %s: the immediate value exceeds bounds (imm > 255 or imm < -128)\n", op->mnemonic);
372  return -1;
373  }
374 
375  if (op->operands[0].type & (OT_DWORD | OT_QWORD)) {
376  if (op->operands[1].type & (OT_GPREG | OT_BYTE)) {
377  data[l++] = 0xd3;
378  } else if (immediate == 1) {
379  data[l++] = 0xd1;
380  } else {
381  data[l++] = 0xc1;
382  }
383  } else if (op->operands[0].type & OT_BYTE) {
384  const Operand *o = &op->operands[0];
385  if (o->regs[0] != -1 && o->regs[1] != -1) {
386  data[l++] = 0xc0;
387  data[l++] = 0x44;
388  data[l++] = o->regs[0] | (o->regs[1] << 3);
389  data[l++] = (ut8)((o->offset * o->offset_sign) & 0xff);
390  data[l++] = immediate;
391  return l;
392  } else if (op->operands[1].type & (OT_GPREG | OT_WORD)) {
393  data[l++] = 0xd2;
394  } else if (immediate == 1) {
395  data[l++] = 0xd0;
396  } else {
397  data[l++] = 0xc0;
398  }
399  }
400  if (op->operands[0].type & OT_MEMORY) {
401  reg0 = op->operands[0].regs[0];
402  mod_byte = 0;
403  } else {
404  reg0 = op->operands[0].reg;
405  mod_byte = 3;
406  }
407  data[l++] = mod_byte << 6 | modrm << 3 | reg0;
408  if (immediate != 1 && !(op->operands[1].type & OT_GPREG)) {
409  data[l++] = immediate;
410  }
411  return l;
412 }
413 
414 static int process_1byte_op(RzAsm *a, ut8 *data, const Opcode *op, int op1) {
416  int l = 0;
417  int mod_byte = 0;
418  int reg = 0;
419  int rm = 0;
420  int rex = 0;
421  int mem_ref = 0;
422  st32 offset = 0;
423  int ebp_reg = 0;
424 
425  if (!op->operands[1].is_good_flag) {
426  return -1;
427  }
428 
429  if (op->operands[0].reg == X86R_AL && op->operands[1].type & OT_CONSTANT) {
430  data[l++] = op1 + 4;
431  data[l++] = op->operands[1].immediate * op->operands[1].sign;
432  return l;
433  }
434 
435  if (a->bits == 64) {
436  if (!(op->operands[0].type & op->operands[1].type)) {
437  return -1;
438  }
439  }
440 
441  if (a->bits == 64 && ((op->operands[0].type & OT_QWORD) | (op->operands[1].type & OT_QWORD))) {
442  if (op->operands[0].extended) {
443  rex = 1;
444  }
445  if (op->operands[1].extended) {
446  rex += 4;
447  }
448  data[l++] = 0x48 | rex;
449  }
450 
451  if (op->operands[0].type & OT_MEMORY && op->operands[1].type & OT_REGALL) {
452  if (a->bits == 64 && (op->operands[0].type & OT_DWORD) &&
453  (op->operands[1].type & OT_DWORD)) {
454  data[l++] = 0x67;
455  }
456  if (op->operands[0].type & OT_BYTE && op->operands[1].type & OT_BYTE) {
457  data[l++] = op1;
458  } else if (op->operands[0].type & (OT_DWORD | OT_QWORD) &&
459  op->operands[1].type & (OT_DWORD | OT_QWORD)) {
460  data[l++] = op1 + 0x1;
461  } else {
462  RZ_LOG_ERROR("assembler: x86.nz: %s: mismatched operand sizes\n", op->mnemonic);
463  return -1;
464  }
465  reg = op->operands[1].reg;
466  rm = op->operands[0].regs[0];
467  offset = op->operands[0].offset * op->operands[0].offset_sign;
468  if (rm == -1) {
469  rm = 5;
470  mem_ref = 1;
471  } else {
472  if (offset) {
473  mod_byte = 1;
475  mod_byte = 2;
476  }
477  } else if (op->operands[0].regs[1] != X86R_UNDEFINED) {
478  rm = 4;
479  offset = op->operands[0].regs[1] << 3;
480  }
481  }
482  } else if (op->operands[0].type & OT_REGALL) {
483  if (op->operands[1].type & OT_MEMORY) {
484  if (op->operands[0].type & OT_BYTE && op->operands[1].type & OT_BYTE) {
485  data[l++] = op1 + 0x2;
486  } else if (op->operands[0].type & (OT_DWORD | OT_QWORD) &&
487  op->operands[1].type & (OT_DWORD | OT_QWORD)) {
488  data[l++] = op1 + 0x3;
489  } else {
490  RZ_LOG_ERROR("assembler: x86.nz: %s: mismatched operand sizes\n", op->mnemonic);
491  return -1;
492  }
493  reg = op->operands[0].reg;
494  rm = op->operands[1].regs[0];
495 
496  if (op->operands[1].scale[0] > 1) {
497  if (op->operands[1].regs[1] != X86R_UNDEFINED) {
498  data[l++] = op->operands[0].reg << 3 | 4;
499  data[l++] = getsib(op->operands[1].scale[0]) << 6 |
500  op->operands[1].regs[0] << 3 |
501  op->operands[1].regs[1];
502  return l;
503  }
504  data[l++] = op->operands[0].reg << 3 | 4; // 4 = SIB
505  data[l++] = getsib(op->operands[1].scale[0]) << 6 | op->operands[1].regs[0] << 3 | 5;
506  data[l++] = op->operands[1].offset * op->operands[1].offset_sign;
507  data[l++] = 0;
508  data[l++] = 0;
509  data[l++] = 0;
510  return l;
511  }
512  offset = op->operands[1].offset * op->operands[1].offset_sign;
513  if (offset) {
514  mod_byte = 1;
516  mod_byte = 2;
517  }
518  }
519 
520  } else if (op->operands[1].type & OT_REGALL) {
521  if (op->operands[0].type & OT_BYTE && op->operands[1].type & OT_BYTE) {
522  data[l++] = op1;
523  } else if (op->operands[0].type & OT_DWORD && op->operands[1].type & OT_DWORD) {
524  data[l++] = op1 + 0x1;
525  }
526  if (a->bits == 64) {
527  if (op->operands[0].type & OT_QWORD &&
528  op->operands[1].type & OT_QWORD) {
529  data[l++] = op1 + 0x1;
530  }
531  }
532 
533  mod_byte = 3;
534  reg = op->operands[1].reg;
535  rm = op->operands[0].reg;
536  }
537  }
538  if (op->operands[0].regs[0] == X86R_EBP ||
539  op->operands[1].regs[0] == X86R_EBP) {
540  // reg += 8;
541  ebp_reg = 1;
542  }
543  data[l++] = mod_byte << 6 | reg << 3 | rm;
544 
545  if (op->operands[0].regs[0] == X86R_ESP ||
546  op->operands[1].regs[0] == X86R_ESP) {
547  data[l++] = 0x24;
548  }
549  if (offset || mem_ref || ebp_reg) {
550  // if ((mod_byte > 0 && mod_byte < 3) || mem_ref) {
551  data[l++] = offset;
552  if (mod_byte == 2 || mem_ref) {
553  data[l++] = offset >> 8;
554  data[l++] = offset >> 16;
555  data[l++] = offset >> 24;
556  }
557  }
558  return l;
559 }
560 
561 static int opadc(RzAsm *a, ut8 *data, const Opcode *op) {
562  if (op->operands[1].type & OT_CONSTANT) {
563  if (op->operands[0].type & OT_GPREG &&
564  op->operands[0].type & OT_WORD) {
565  return process_16bit_group_1(a, data, op, 0x10);
566  }
567  if (!is_al_reg(&op->operands[0])) {
568  return process_group_1(a, data, op);
569  }
570  }
571  return process_1byte_op(a, data, op, 0x10);
572 }
573 
574 static int opadd(RzAsm *a, ut8 *data, const Opcode *op) {
575  if (op->operands[1].type & OT_CONSTANT) {
576  if (op->operands[0].type & OT_GPREG &&
577  op->operands[0].type & OT_WORD) {
578  return process_16bit_group_1(a, data, op, 0x00);
579  }
580  if (!is_al_reg(&op->operands[0])) {
581  return process_group_1(a, data, op);
582  }
583  }
584  return process_1byte_op(a, data, op, 0x00);
585 }
586 
587 static int opand(RzAsm *a, ut8 *data, const Opcode *op) {
588  if (op->operands[1].type & OT_CONSTANT) {
589  if (op->operands[0].type & OT_GPREG &&
590  op->operands[0].type & OT_WORD) {
591  return process_16bit_group_1(a, data, op, 0x20);
592  }
593  if (!is_al_reg(&op->operands[0])) {
594  return process_group_1(a, data, op);
595  }
596  }
597  return process_1byte_op(a, data, op, 0x20);
598 }
599 
600 static int opcmp(RzAsm *a, ut8 *data, const Opcode *op) {
601  if (op->operands[1].type & OT_CONSTANT) {
602  if (op->operands[0].type & OT_GPREG &&
603  op->operands[0].type & OT_WORD) {
604  return process_16bit_group_1(a, data, op, 0x38);
605  }
606  if (!is_al_reg(&op->operands[0])) {
607  return process_group_1(a, data, op);
608  }
609  }
610  return process_1byte_op(a, data, op, 0x38);
611 }
612 
613 static int opsub(RzAsm *a, ut8 *data, const Opcode *op) {
614  if (op->operands[1].type & OT_CONSTANT) {
615  if (op->operands[0].type & OT_GPREG &&
616  op->operands[0].type & OT_WORD) {
617  return process_16bit_group_1(a, data, op, 0x28);
618  }
619  if (!is_al_reg(&op->operands[0])) {
620  return process_group_1(a, data, op);
621  }
622  }
623  return process_1byte_op(a, data, op, 0x28);
624 }
625 
626 static int opor(RzAsm *a, ut8 *data, const Opcode *op) {
627  if (op->operands[1].type & OT_CONSTANT) {
628  if (op->operands[0].type & OT_GPREG &&
629  op->operands[0].type & OT_WORD) {
630  return process_16bit_group_1(a, data, op, 0x08);
631  }
632  if (!is_al_reg(&op->operands[0])) {
633  return process_group_1(a, data, op);
634  }
635  }
636  return process_1byte_op(a, data, op, 0x08);
637 }
638 
639 static int opxadd(RzAsm *a, ut8 *data, const Opcode *op) {
641  int i = 0;
642  if (op->operands_count < 2) {
643  return -1;
644  }
645  if (a->bits == 64) {
646  data[i++] = 0x48;
647  };
648  data[i++] = 0x0f;
649  if (op->operands[0].type & OT_BYTE &&
650  op->operands[1].type & OT_BYTE) {
651  data[i++] = 0xc0;
652  } else {
653  data[i++] = 0xc1;
654  }
655  if (op->operands[0].type & OT_REGALL &&
656  op->operands[1].type & OT_REGALL) { // TODO memory modes
657  data[i] |= 0xc0;
658  data[i] |= (op->operands[1].reg << 3);
659  data[i++] |= op->operands[0].reg;
660  }
661  return i;
662 }
663 
664 static int opxor(RzAsm *a, ut8 *data, const Opcode *op) {
666  if (op->operands_count < 2) {
667  return -1;
668  }
669  if (op->operands[0].type == 0x80 && op->operands[0].reg == X86R_UNDEFINED) {
670  return -1;
671  }
672  if (op->operands[1].type == 0x80 && op->operands[0].reg == X86R_UNDEFINED) {
673  return -1;
674  }
675  if (op->operands[1].type & OT_CONSTANT) {
676  if (op->operands[0].type & OT_GPREG &&
677  op->operands[0].type & OT_WORD) {
678  return process_16bit_group_1(a, data, op, 0x30);
679  }
680  if (!is_al_reg(&op->operands[0])) {
681  return process_group_1(a, data, op);
682  }
683  }
684  return process_1byte_op(a, data, op, 0x30);
685 }
686 
687 static int opneg(RzAsm *a, ut8 *data, const Opcode *op) {
689  int l = 0;
690 
691  if (op->operands[0].type & OT_GPREG) {
692  if (op->operands[0].type & OT_WORD) {
693  data[l++] = 0x66;
694  } else if (op->operands[0].type & OT_QWORD) {
695  data[l++] = 0x48;
696  }
697 
698  if (op->operands[0].type & OT_BYTE) {
699  data[l++] = 0xf6;
700  } else {
701  data[l++] = 0xf7;
702  }
703  data[l++] = 0xd8 | op->operands[0].reg;
704  return l;
705  }
706  return -1;
707 }
708 
709 static int endbr64(RzAsm *a, ut8 *data, const Opcode *op) {
710  memcpy(data, "\xf3\x0f\x1e\xfa", 4);
711  return 4;
712 }
713 
714 static int endbr32(RzAsm *a, ut8 *data, const Opcode *op) {
715  memcpy(data, "\xf3\x0f\x1e\xfb", 4);
716  return 4;
717 }
718 
719 static int opnot(RzAsm *a, ut8 *data, const Opcode *op) {
721  int l = 0;
722 
723  if (op->operands[0].reg == X86R_UNDEFINED) {
724  return -1;
725  }
726 
727  int size = op->operands[0].type & ALL_SIZE;
728  if (op->operands[0].explicit_size) {
729  size = op->operands[0].dest_size;
730  }
731  // rex prefix
732  int rex = 1 << 6;
733  bool use_rex = false;
734  if (size & OT_QWORD) { // W field
735  use_rex = true;
736  rex |= 1 << 3;
737  }
738  if (op->operands[0].extended) { // B field
739  use_rex = true;
740  rex |= 1;
741  }
742 
743  if (use_rex) {
744  data[l++] = rex;
745  }
746  data[l++] = 0xf7;
747  data[l++] = 0xd0 | op->operands[0].reg;
748 
749  return l;
750 }
751 
752 static int opsbb(RzAsm *a, ut8 *data, const Opcode *op) {
753  if (op->operands[1].type & OT_CONSTANT) {
754  if (op->operands[0].type & OT_GPREG &&
755  op->operands[0].type & OT_WORD) {
756  return process_16bit_group_1(a, data, op, 0x18);
757  }
758  if (!is_al_reg(&op->operands[0])) {
759  return process_group_1(a, data, op);
760  }
761  }
762  return process_1byte_op(a, data, op, 0x18);
763 }
764 
765 static int opbs(RzAsm *a, ut8 *data, const Opcode *op) {
766  int l = 0;
767  if (a->bits >= 32 && op->operands[1].type & OT_MEMORY && op->operands[1].reg_size & OT_WORD) {
768  return -1;
769  }
770  if (!(op->operands[1].type & OT_MEMORY) &&
771  !((op->operands[0].type & ALL_SIZE) == (op->operands[1].type & ALL_SIZE))) {
772  return -1;
773  }
774  if (op->operands[0].type & OT_GPREG && !(op->operands[0].type & OT_MEMORY)) {
775  if (a->bits == 64) {
776  if (op->operands[1].type & OT_MEMORY &&
777  op->operands[1].reg_size & OT_DWORD) {
778  data[l++] = 0x67;
779  }
780  if (op->operands[0].type & OT_WORD) {
781  data[l++] = 0x66;
782  }
783  if (op->operands[0].type & OT_QWORD) {
784  data[l++] = 0x48;
785  }
786  } else if (op->operands[0].type & OT_WORD) {
787  data[l++] = 0x66;
788  }
789  data[l++] = 0x0f;
790  if (!strcmp(op->mnemonic, "bsf")) {
791  data[l++] = 0xbc;
792  } else {
793  data[l++] = 0xbd;
794  }
795  if (op->operands[1].type & OT_GPREG && !(op->operands[1].type & OT_MEMORY)) {
796  data[l] = 0xc0;
797  } else if (!(op->operands[1].type & OT_MEMORY)) {
798  return -1;
799  }
800  data[l] += op->operands[0].reg << 3;
801  data[l++] += op->operands[1].reg;
802  }
803  return l;
804 }
805 
806 static int opbswap(RzAsm *a, ut8 *data, const Opcode *op) {
807  int l = 0;
808  if (op->operands[0].type & OT_REGALL) {
810  if (op->operands[0].reg == X86R_UNDEFINED) {
811  return -1;
812  }
813 
814  if (op->operands[0].type & OT_QWORD) {
815  if (op->operands[0].extended) {
816  data[l++] = 0x49;
817  } else {
818  data[l++] = 0x48;
819  }
820  data[l++] = 0x0f;
821  data[l++] = 0xc8 + op->operands[0].reg;
822  } else if (op->operands[0].type & OT_DWORD) {
823  if (op->operands[0].extended) {
824  data[l++] = 0x41;
825  }
826  data[l++] = 0x0f;
827  data[l++] = 0xc8 + op->operands[0].reg;
828  } else {
829  return -1;
830  }
831  }
832  return l;
833 }
834 
835 static int opcall(RzAsm *a, ut8 *data, const Opcode *op) {
837  int l = 0;
838  int immediate = 0;
839  int offset = 0;
840  int mod = 0;
841 
842  if (op->operands[0].type & OT_GPREG) {
843  if (op->operands[0].reg == X86R_UNDEFINED) {
844  return -1;
845  }
846  if (a->bits == 64 && op->operands[0].extended) {
847  data[l++] = 0x41;
848  }
849  data[l++] = 0xff;
850  mod = 3;
851  data[l++] = mod << 6 | 2 << 3 | op->operands[0].reg;
852  } else if (op->operands[0].type & OT_MEMORY) {
853  if (op->operands[0].regs[0] == X86R_UNDEFINED) {
854  return -1;
855  }
856  data[l++] = 0xff;
857  offset = op->operands[0].offset * op->operands[0].offset_sign;
858  if (offset) {
859  mod = 1;
860  if (offset > 127 || offset < -128) {
861  mod = 2;
862  }
863  }
864  data[l++] = mod << 6 | 2 << 3 | op->operands[0].regs[0];
865  if (mod) {
866  data[l++] = offset;
867  if (mod == 2) {
868  data[l++] = offset >> 8;
869  data[l++] = offset >> 16;
870  data[l++] = offset >> 24;
871  }
872  }
873  } else {
874  ut64 instr_offset = a->pc;
875  data[l++] = 0xe8;
876  immediate = op->operands[0].immediate * op->operands[0].sign;
877  immediate -= instr_offset + 5;
878  data[l++] = immediate;
879  data[l++] = immediate >> 8;
880  data[l++] = immediate >> 16;
881  data[l++] = immediate >> 24;
882  }
883  return l;
884 }
885 
886 static int opcmov(RzAsm *a, ut8 *data, const Opcode *op) {
888  int l = 0;
889  int mod_byte = 0;
890  int offset = 0;
891 
892  if (op->operands[0].type & OT_MEMORY ||
893  op->operands[1].type & OT_CONSTANT) {
894  return -1;
895  }
896 
897  data[l++] = 0x0f;
898  char *cmov = op->mnemonic + 4;
899  if (!strcmp(cmov, "o")) {
900  data[l++] = 0x40;
901  } else if (!strcmp(cmov, "no")) {
902  data[l++] = 0x41;
903  } else if (!strcmp(cmov, "b") ||
904  !strcmp(cmov, "c") ||
905  !strcmp(cmov, "nae")) {
906  data[l++] = 0x42;
907  } else if (!strcmp(cmov, "ae") ||
908  !strcmp(cmov, "nb") ||
909  !strcmp(cmov, "nc")) {
910  data[l++] = 0x43;
911  } else if (!strcmp(cmov, "e") ||
912  !strcmp(cmov, "z")) {
913  data[l++] = 0x44;
914  } else if (!strcmp(cmov, "ne") ||
915  !strcmp(cmov, "nz")) {
916  data[l++] = 0x45;
917  } else if (!strcmp(cmov, "be") ||
918  !strcmp(cmov, "na")) {
919  data[l++] = 0x46;
920  } else if (!strcmp(cmov, "a") ||
921  !strcmp(cmov, "nbe")) {
922  data[l++] = 0x47;
923  } else if (!strcmp(cmov, "s")) {
924  data[l++] = 0x48;
925  } else if (!strcmp(cmov, "ns")) {
926  data[l++] = 0x49;
927  } else if (!strcmp(cmov, "p") ||
928  !strcmp(cmov, "pe")) {
929  data[l++] = 0x4a;
930  } else if (!strcmp(cmov, "np") ||
931  !strcmp(cmov, "po")) {
932  data[l++] = 0x4b;
933  } else if (!strcmp(cmov, "l") ||
934  !strcmp(cmov, "nge")) {
935  data[l++] = 0x4c;
936  } else if (!strcmp(cmov, "ge") ||
937  !strcmp(cmov, "nl")) {
938  data[l++] = 0x4d;
939  } else if (!strcmp(cmov, "le") ||
940  !strcmp(cmov, "ng")) {
941  data[l++] = 0x4e;
942  } else if (!strcmp(cmov, "g") ||
943  !strcmp(cmov, "nle")) {
944  data[l++] = 0x4f;
945  }
946 
947  if (op->operands[0].type & OT_REGALL) {
948  if (op->operands[1].type & OT_MEMORY) {
949  if (op->operands[1].scale[0] > 1) {
950  if (op->operands[1].regs[1] != X86R_UNDEFINED) {
951  data[l++] = op->operands[0].reg << 3 | 4;
952  data[l++] = getsib(op->operands[1].scale[0]) << 6 |
953  op->operands[1].regs[0] << 3 |
954  op->operands[1].regs[1];
955  return l;
956  }
957  offset = op->operands[1].offset * op->operands[1].offset_sign;
958 
959  if (op->operands[1].scale[0] == 2 && offset) {
960  data[l++] = 0x40 | op->operands[0].reg << 3 | 4; // 4 = SIB
961  } else {
962  data[l++] = op->operands[0].reg << 3 | 4; // 4 = SIB
963  }
964 
965  if (op->operands[1].scale[0] == 2) {
966  data[l++] = op->operands[1].regs[0] << 3 | op->operands[1].regs[0];
967 
968  } else {
969  data[l++] = getsib(op->operands[1].scale[0]) << 6 |
970  op->operands[1].regs[0] << 3 | 5;
971  }
972 
973  if (offset) {
974  data[l++] = offset;
976  data[l++] = offset >> 8;
977  data[l++] = offset >> 16;
978  data[l++] = offset >> 24;
979  }
980  }
981  return l;
982  }
983  if (op->operands[1].regs[1] != X86R_UNDEFINED) {
984  data[l++] = op->operands[0].reg << 3 | 4;
985  data[l++] = op->operands[1].regs[1] << 3 | op->operands[1].regs[0];
986  return l;
987  }
988 
989  offset = op->operands[1].offset * op->operands[1].offset_sign;
990  if (op->operands[1].offset || op->operands[1].regs[0] == X86R_EBP) {
991  mod_byte = 1;
992  }
994  mod_byte = 2;
995  }
996 
997  data[l++] = mod_byte << 6 | op->operands[0].reg << 3 | op->operands[1].regs[0];
998 
999  if (mod_byte) {
1000  data[l++] = offset;
1001  if (mod_byte == 2) {
1002  data[l++] = offset >> 8;
1003  data[l++] = offset >> 16;
1004  data[l++] = offset >> 24;
1005  }
1006  }
1007  } else {
1008  data[l++] = 0xc0 | op->operands[0].reg << 3 | op->operands[1].reg;
1009  }
1010  }
1011 
1012  return l;
1013 }
1014 
1015 static int opmovx(RzAsm *a, ut8 *data, const Opcode *op) {
1017  int l = 0;
1018  int word = 0;
1019  char *movx = op->mnemonic + 3;
1020 
1021  if (!(op->operands[0].type & OT_REGTYPE && op->operands[1].type & OT_MEMORY)) {
1022  return -1;
1023  }
1024  if (op->operands[1].type & OT_WORD) {
1025  word = 1;
1026  }
1027 
1028  data[l++] = 0x0f;
1029  if (!strcmp(movx, "zx")) {
1030  data[l++] = 0xb6 + word;
1031  } else if (!strcmp(movx, "sx")) {
1032  data[l++] = 0xbe + word;
1033  }
1034  data[l++] = op->operands[0].reg << 3 | op->operands[1].regs[0];
1035  if (op->operands[1].regs[0] == X86R_ESP) {
1036  data[l++] = 0x24;
1037  }
1038 
1039  return l;
1040 }
1041 
1042 static int opaam(RzAsm *a, ut8 *data, const Opcode *op) {
1044  int l = 0;
1045  int immediate = op->operands[0].immediate * op->operands[0].sign;
1046  data[l++] = 0xd4;
1047  if (immediate == 0) {
1048  data[l++] = 0x0a;
1049  } else if (immediate < 256 && immediate > -129) {
1050  data[l++] = immediate;
1051  }
1052  return l;
1053 }
1054 
1055 static int opdec(RzAsm *a, ut8 *data, const Opcode *op) {
1056  if (op->operands[1].type) {
1057  RZ_LOG_ERROR("assembler: x86.nz: %s: invalid operands\n", op->mnemonic);
1058  return -1;
1059  }
1061  int l = 0;
1062  int size = op->operands[0].type & ALL_SIZE;
1063  if (op->operands[0].explicit_size) {
1064  size = op->operands[0].dest_size;
1065  }
1066 
1067  if (size & OT_WORD) {
1068  data[l++] = 0x66;
1069  }
1070 
1071  // rex prefix
1072  int rex = 1 << 6;
1073  bool use_rex = false;
1074  if (size & OT_QWORD) { // W field
1075  use_rex = true;
1076  rex |= 1 << 3;
1077  }
1078  if (op->operands[0].extended) { // B field
1079  use_rex = true;
1080  rex |= 1;
1081  }
1082 
1083  // opcode selection
1084  int opcode;
1085  if (size & OT_BYTE) {
1086  opcode = 0xfe;
1087  } else {
1088  opcode = 0xff;
1089  }
1090 
1091  if (!(op->operands[0].type & OT_MEMORY)) {
1092  if (use_rex) {
1093  data[l++] = rex;
1094  }
1095  if (a->bits > 32 || size & OT_BYTE) {
1096  data[l++] = opcode;
1097  }
1098  if (a->bits == 32 && size & (OT_DWORD | OT_WORD)) {
1099  data[l++] = 0x48 | op->operands[0].reg;
1100  } else {
1101  data[l++] = 0xc8 | op->operands[0].reg;
1102  }
1103  return l;
1104  }
1105 
1106  // modrm and SIB selection
1107  bool rip_rel = op->operands[0].regs[0] == X86R_RIP;
1108  int offset = op->operands[0].offset * op->operands[0].offset_sign;
1109  int modrm = 0;
1110  int mod;
1111  int reg = 0;
1112  int rm;
1113  bool use_sib = false;
1114  int sib = 0;
1115  // mod
1116  if (offset == 0) {
1117  mod = 0;
1118  } else if (offset < 128 && offset > -129) {
1119  mod = 1;
1120  } else {
1121  mod = 2;
1122  }
1123 
1124  if (op->operands[0].regs[0] & OT_WORD) {
1125  if (op->operands[0].regs[0] == X86R_BX && op->operands[0].regs[1] == X86R_SI) {
1126  rm = B0000;
1127  } else if (op->operands[0].regs[0] == X86R_BX && op->operands[0].regs[1] == X86R_DI) {
1128  rm = B0001;
1129  } else if (op->operands[0].regs[0] == X86R_BP && op->operands[0].regs[1] == X86R_SI) {
1130  rm = B0010;
1131  } else if (op->operands[0].regs[0] == X86R_BP && op->operands[0].regs[1] == X86R_DI) {
1132  rm = B0011;
1133  } else if (op->operands[0].regs[0] == X86R_SI && op->operands[0].regs[1] == -1) {
1134  rm = B0100;
1135  } else if (op->operands[0].regs[0] == X86R_DI && op->operands[0].regs[1] == -1) {
1136  rm = B0101;
1137  } else if (op->operands[0].regs[0] == X86R_BX && op->operands[0].regs[1] == -1) {
1138  rm = B0111;
1139  } else {
1140  // TODO allow for displacement only when parser is reworked
1141  return -1;
1142  }
1143  modrm = (mod << 6) | (reg << 3) | rm;
1144  } else {
1145  // rm
1146  if (op->operands[0].extended) {
1147  rm = op->operands[0].reg;
1148  } else {
1149  rm = op->operands[0].regs[0];
1150  }
1151  //[epb] alone is illegal, so we need to fake a [ebp+0]
1152  if (rm == 5 && mod == 0) {
1153  mod = 1;
1154  }
1155 
1156  // sib
1157  int index = op->operands[0].regs[1];
1158  int scale = getsib(op->operands[0].scale[1]);
1159  if (index != -1) {
1160  use_sib = true;
1161  sib = (scale << 6) | (index << 3) | rm;
1162  } else if (rm == 4) {
1163  use_sib = true;
1164  sib = 0x24;
1165  }
1166  if (use_sib) {
1167  rm = B0100;
1168  }
1169  if (rip_rel) {
1170  modrm = (B0000 << 6) | (reg << 3) | B0101;
1171  sib = (scale << 6) | (B0100 << 3) | B0101;
1172  } else {
1173  modrm = (mod << 6) | (reg << 3) | rm;
1174  }
1175  modrm |= 1 << 3;
1176  }
1177 
1178  if (use_rex) {
1179  data[l++] = rex;
1180  }
1181  data[l++] = opcode;
1182  data[l++] = modrm;
1183  if (use_sib) {
1184  data[l++] = sib;
1185  }
1186  // offset
1187  if (mod == 1) {
1188  data[l++] = offset;
1189  } else if (op->operands[0].regs[0] & OT_WORD && mod == 2) {
1190  data[l++] = offset;
1191  data[l++] = offset >> 8;
1192  } else if (mod == 2 || rip_rel) {
1193  data[l++] = offset;
1194  data[l++] = offset >> 8;
1195  data[l++] = offset >> 16;
1196  data[l++] = offset >> 24;
1197  }
1198 
1199  return l;
1200 }
1201 
1202 static int opidiv(RzAsm *a, ut8 *data, const Opcode *op) {
1204  int l = 0;
1205 
1206  if (op->operands[0].type & OT_QWORD) {
1207  data[l++] = 0x48;
1208  }
1209  switch (op->operands_count) {
1210  case 1:
1211  if (op->operands[0].type & OT_WORD) {
1212  data[l++] = 0x66;
1213  }
1214  if (op->operands[0].type & OT_BYTE) {
1215  data[l++] = 0xf6;
1216  } else {
1217  data[l++] = 0xf7;
1218  }
1219  if (op->operands[0].type & OT_MEMORY) {
1220  data[l++] = 0x38 | op->operands[0].regs[0];
1221  } else {
1222  data[l++] = 0xf8 | op->operands[0].reg;
1223  }
1224  break;
1225  default:
1226  return -1;
1227  }
1228  return l;
1229 }
1230 
1231 static int opdiv(RzAsm *a, ut8 *data, const Opcode *op) {
1233  int l = 0;
1234 
1235  if (op->operands[0].type & OT_QWORD) {
1236  data[l++] = 0x48;
1237  }
1238  switch (op->operands_count) {
1239  case 1:
1240  if (op->operands[0].type & OT_WORD) {
1241  data[l++] = 0x66;
1242  }
1243  if (op->operands[0].type & OT_BYTE) {
1244  data[l++] = 0xf6;
1245  } else {
1246  data[l++] = 0xf7;
1247  }
1248  if (op->operands[0].type & OT_MEMORY) {
1249  data[l++] = 0x30 | op->operands[0].regs[0];
1250  } else {
1251  data[l++] = 0xf0 | op->operands[0].reg;
1252  }
1253  break;
1254  default:
1255  return -1;
1256  }
1257  return l;
1258 }
1259 
1260 static int opimul(RzAsm *a, ut8 *data, const Opcode *op) {
1262  int l = 0;
1263  int offset = 0;
1264  st64 immediate = 0;
1265 
1266  if (op->operands[0].type & OT_QWORD) {
1267  data[l++] = 0x48;
1268  }
1269  switch (op->operands_count) {
1270  case 1:
1271  if (op->operands[0].type & OT_WORD) {
1272  data[l++] = 0x66;
1273  }
1274  if (op->operands[0].type & OT_BYTE) {
1275  data[l++] = 0xf6;
1276  } else {
1277  data[l++] = 0xf7;
1278  }
1279  if (op->operands[0].type & OT_MEMORY) {
1280  data[l++] = 0x28 | op->operands[0].regs[0];
1281  } else {
1282  data[l++] = 0xe8 | op->operands[0].reg;
1283  }
1284  break;
1285  case 2:
1286  if (op->operands[0].type & OT_GPREG) {
1287  if (op->operands[1].type & OT_CONSTANT) {
1288  if (op->operands[1].immediate == -1) {
1289  RZ_LOG_ERROR("assembler: x86.nz: %s: immediate operand exceeds max value (imm == -1)\n", op->mnemonic);
1290  return -1;
1291  }
1292  immediate = op->operands[1].immediate * op->operands[1].sign;
1293  if (op->operands[0].type & OT_GPREG) {
1294  if (immediate >= 128) {
1295  data[l++] = 0x69;
1296  } else {
1297  data[l++] = 0x6b;
1298  }
1299  data[l++] = 0xc0 | op->operands[0].reg << 3 | op->operands[0].reg;
1300  data[l++] = immediate;
1301  if (immediate >= 128) {
1302  data[l++] = immediate >> 8;
1303  data[l++] = immediate >> 16;
1304  data[l++] = immediate >> 24;
1305  }
1306  if (a->bits == 64 && immediate > UT32_MAX) {
1307  data[l++] = immediate >> 32;
1308  data[l++] = immediate >> 40;
1309  data[l++] = immediate >> 48;
1310  data[l++] = immediate >> 56;
1311  }
1312  }
1313  } else if (op->operands[1].type & OT_MEMORY) {
1314  data[l++] = 0x0f;
1315  data[l++] = 0xaf;
1316  if (op->operands[1].regs[0] != X86R_UNDEFINED) {
1317  offset = op->operands[1].offset * op->operands[1].offset_sign;
1318  if (offset != 0) {
1319  if (offset >= 128 || offset <= -128) {
1320  data[l] = 0x80;
1321  } else {
1322  data[l] = 0x40;
1323  }
1324  data[l++] |= op->operands[0].reg << 3 | op->operands[1].regs[0];
1325  data[l++] = offset;
1326  if (offset >= 128 || offset <= -128) {
1327  data[l++] = offset >> 8;
1328  data[l++] = offset >> 16;
1329  data[l++] = offset >> 24;
1330  }
1331  } else {
1332  if (op->operands[1].regs[1] != X86R_UNDEFINED) {
1333  data[l++] = 0x04 | op->operands[0].reg << 3;
1334  data[l++] = op->operands[1].regs[1] << 3 | op->operands[1].regs[0];
1335  } else {
1336  data[l++] = op->operands[0].reg << 3 | op->operands[1].regs[0];
1337  }
1338  }
1339  } else {
1340  immediate = op->operands[1].immediate * op->operands[1].sign;
1341  data[l++] = op->operands[0].reg << 3 | 0x5;
1342  data[l++] = immediate;
1343  data[l++] = immediate >> 8;
1344  data[l++] = immediate >> 16;
1345  data[l++] = immediate >> 24;
1346  }
1347  } else if (op->operands[1].type & OT_GPREG) {
1348  data[l++] = 0x0f;
1349  data[l++] = 0xaf;
1350  data[l++] = 0xc0 | op->operands[0].reg << 3 | op->operands[1].reg;
1351  }
1352  }
1353  break;
1354  case 3:
1355  if (op->operands[0].type & OT_GPREG &&
1356  (op->operands[1].type & OT_GPREG || op->operands[1].type & OT_MEMORY) &&
1357  op->operands[2].type & OT_CONSTANT) {
1358  data[l++] = 0x6b;
1359  if (op->operands[1].type & OT_MEMORY) {
1360  if (op->operands[1].regs[1] != X86R_UNDEFINED) {
1361  data[l++] = 0x04 | op->operands[0].reg << 3;
1362  data[l++] = op->operands[1].regs[0] | op->operands[1].regs[1] << 3;
1363  } else {
1364  offset = op->operands[1].offset * op->operands[1].offset_sign;
1365  if (offset != 0) {
1366  if (offset >= 128 || offset <= -128) {
1367  data[l] = 0x80;
1368  } else {
1369  data[l] = 0x40;
1370  }
1371  data[l++] |= op->operands[0].reg << 3;
1372  data[l++] = offset;
1373  if (offset >= 128 || offset <= -128) {
1374  data[l++] = offset >> 8;
1375  data[l++] = offset >> 16;
1376  data[l++] = offset >> 24;
1377  }
1378  } else {
1379  data[l++] = 0x00 | op->operands[0].reg << 3 | op->operands[1].regs[0];
1380  }
1381  }
1382  } else {
1383  data[l++] = 0xc0 | op->operands[0].reg << 3 | op->operands[1].reg;
1384  }
1385  immediate = op->operands[2].immediate * op->operands[2].sign;
1386  data[l++] = immediate;
1387  if (immediate >= 128 || immediate <= -128) {
1388  data[l++] = immediate >> 8;
1389  data[l++] = immediate >> 16;
1390  data[l++] = immediate >> 24;
1391  }
1392  }
1393  break;
1394  default:
1395  return -1;
1396  }
1397  return l;
1398 }
1399 
1400 static int opin(RzAsm *a, ut8 *data, const Opcode *op) {
1402  int l = 0;
1403  st32 immediate = 0;
1404  if (op->operands[1].reg == X86R_DX) {
1405  if (op->operands[0].reg == X86R_AL &&
1406  op->operands[0].type & OT_BYTE) {
1407  data[l++] = 0xec;
1408  return l;
1409  }
1410  if (op->operands[0].reg == X86R_AX &&
1411  op->operands[0].type & OT_WORD) {
1412  data[l++] = 0x66;
1413  data[l++] = 0xed;
1414  return l;
1415  }
1416  if (op->operands[0].reg == X86R_EAX &&
1417  op->operands[0].type & OT_DWORD) {
1418  data[l++] = 0xed;
1419  return l;
1420  }
1421  } else if (op->operands[1].type & OT_CONSTANT) {
1422  immediate = op->operands[1].immediate * op->operands[1].sign;
1423  if (immediate > 255 || immediate < -128) {
1424  return -1;
1425  }
1426  if (op->operands[0].reg == X86R_AL &&
1427  op->operands[0].type & OT_BYTE) {
1428  data[l++] = 0xe4;
1429  } else if (op->operands[0].reg == X86R_AX &&
1430  op->operands[0].type & OT_BYTE) {
1431  data[l++] = 0x66;
1432  data[l++] = 0xe5;
1433  } else if (op->operands[0].reg == X86R_EAX &&
1434  op->operands[0].type & OT_DWORD) {
1435  data[l++] = 0xe5;
1436  }
1437  data[l++] = immediate;
1438  }
1439  return l;
1440 }
1441 
1442 static int opclflush(RzAsm *a, ut8 *data, const Opcode *op) {
1444  int l = 0;
1445  int offset = 0;
1446  int mod_byte = 0;
1447 
1448  if (op->operands[0].type & OT_MEMORY) {
1449  data[l++] = 0x0f;
1450  data[l++] = 0xae;
1451  offset = op->operands[0].offset * op->operands[0].offset_sign;
1452  if (offset) {
1454  mod_byte = 2;
1455  } else {
1456  mod_byte = 1;
1457  }
1458  }
1459  data[l++] = (mod_byte << 6) | (7 << 3) | op->operands[0].regs[0];
1460  if (mod_byte) {
1461  data[l++] = offset;
1462  if (mod_byte == 2) {
1463  data[l++] = offset >> 8;
1464  data[l++] = offset >> 16;
1465  data[l++] = offset >> 24;
1466  }
1467  }
1468  }
1469  return l;
1470 }
1471 
1472 static int opinc(RzAsm *a, ut8 *data, const Opcode *op) {
1473  if (op->operands[1].type) {
1474  RZ_LOG_ERROR("assembler: x86.nz: %s: invalid operands\n", op->mnemonic);
1475  return -1;
1476  }
1478  int l = 0;
1479  int size = op->operands[0].type & ALL_SIZE;
1480  if (op->operands[0].explicit_size) {
1481  size = op->operands[0].dest_size;
1482  }
1483 
1484  if (size & OT_WORD) {
1485  data[l++] = 0x66;
1486  }
1487 
1488  // rex prefix
1489  int rex = 1 << 6;
1490  bool use_rex = false;
1491  if (size & OT_QWORD) { // W field
1492  use_rex = true;
1493  rex |= 1 << 3;
1494  }
1495  if (op->operands[0].extended) { // B field
1496  use_rex = true;
1497  rex |= 1;
1498  }
1499 
1500  // opcode selection
1501  int opcode;
1502  if (size & OT_BYTE) {
1503  opcode = 0xfe;
1504  } else {
1505  opcode = 0xff;
1506  }
1507 
1508  if (!(op->operands[0].type & OT_MEMORY)) {
1509  if (use_rex) {
1510  data[l++] = rex;
1511  }
1512  if (a->bits > 32 || size & OT_BYTE) {
1513  data[l++] = opcode;
1514  }
1515  if (a->bits == 32 && size & (OT_DWORD | OT_WORD)) {
1516  data[l++] = 0x40 | op->operands[0].reg;
1517  } else {
1518  data[l++] = 0xc0 | op->operands[0].reg;
1519  }
1520  return l;
1521  }
1522 
1523  // modrm and SIB selection
1524  bool rip_rel = op->operands[0].regs[0] == X86R_RIP;
1525  int offset = op->operands[0].offset * op->operands[0].offset_sign;
1526  int modrm = 0;
1527  int mod;
1528  int reg = 0;
1529  int rm;
1530  bool use_sib = false;
1531  int sib = 0;
1532  // mod
1533  if (offset == 0) {
1534  mod = 0;
1535  } else if (offset < 128 && offset > -129) {
1536  mod = 1;
1537  } else {
1538  mod = 2;
1539  }
1540 
1541  if (op->operands[0].regs[0] & OT_WORD) {
1542  if (op->operands[0].regs[0] == X86R_BX && op->operands[0].regs[1] == X86R_SI) {
1543  rm = B0000;
1544  } else if (op->operands[0].regs[0] == X86R_BX && op->operands[0].regs[1] == X86R_DI) {
1545  rm = B0001;
1546  } else if (op->operands[0].regs[0] == X86R_BP && op->operands[0].regs[1] == X86R_SI) {
1547  rm = B0010;
1548  } else if (op->operands[0].regs[0] == X86R_BP && op->operands[0].regs[1] == X86R_DI) {
1549  rm = B0011;
1550  } else if (op->operands[0].regs[0] == X86R_SI && op->operands[0].regs[1] == -1) {
1551  rm = B0100;
1552  } else if (op->operands[0].regs[0] == X86R_DI && op->operands[0].regs[1] == -1) {
1553  rm = B0101;
1554  } else if (op->operands[0].regs[0] == X86R_BX && op->operands[0].regs[1] == -1) {
1555  rm = B0111;
1556  } else {
1557  // TODO allow for displacement only when parser is reworked
1558  return -1;
1559  }
1560  modrm = (mod << 6) | (reg << 3) | rm;
1561  } else {
1562  // rm
1563  if (op->operands[0].extended) {
1564  rm = op->operands[0].reg;
1565  } else {
1566  rm = op->operands[0].regs[0];
1567  }
1568  //[epb] alone is illegal, so we need to fake a [ebp+0]
1569  if (rm == 5 && mod == 0) {
1570  mod = 1;
1571  }
1572 
1573  // sib
1574  int index = op->operands[0].regs[1];
1575  int scale = getsib(op->operands[0].scale[1]);
1576  if (index != -1) {
1577  use_sib = true;
1578  sib = (scale << 6) | (index << 3) | rm;
1579  } else if (rm == 4) {
1580  use_sib = true;
1581  sib = 0x24;
1582  }
1583  if (use_sib) {
1584  rm = B0100;
1585  }
1586  if (rip_rel) {
1587  modrm = (B0000 << 6) | (reg << 3) | B0101;
1588  sib = (scale << 6) | (B0100 << 3) | B0101;
1589  } else {
1590  modrm = (mod << 6) | (reg << 3) | rm;
1591  }
1592  }
1593 
1594  if (use_rex) {
1595  data[l++] = rex;
1596  }
1597  data[l++] = opcode;
1598  data[l++] = modrm;
1599  if (use_sib) {
1600  data[l++] = sib;
1601  }
1602  // offset
1603  if (mod == 1) {
1604  data[l++] = offset;
1605  } else if (op->operands[0].regs[0] & OT_WORD && mod == 2) {
1606  data[l++] = offset;
1607  data[l++] = offset >> 8;
1608  } else if (mod == 2 || rip_rel) {
1609  data[l++] = offset;
1610  data[l++] = offset >> 8;
1611  data[l++] = offset >> 16;
1612  data[l++] = offset >> 24;
1613  }
1614 
1615  return l;
1616 }
1617 
1618 static int opint(RzAsm *a, ut8 *data, const Opcode *op) {
1619  int l = 0;
1620  if (op->operands[0].type & OT_CONSTANT) {
1621  st32 immediate = op->operands[0].immediate * op->operands[0].sign;
1622  if (immediate <= 255 && immediate >= -128) {
1623  data[l++] = 0xcd;
1624  data[l++] = immediate;
1625  }
1626  }
1627  return l;
1628 }
1629 
1630 static int opjc(RzAsm *a, ut8 *data, const Opcode *op) {
1632  int l = 0;
1633  bool is_short = op->is_short;
1634  // st64 bigimm = op->operands[0].immediate * op->operands[0].sign;
1635  st64 immediate = op->operands[0].immediate * op->operands[0].sign;
1636  if (is_short && (immediate > ST8_MAX || immediate < ST8_MIN)) {
1637  return l;
1638  }
1639  immediate -= a->pc;
1640  if (immediate > ST32_MAX || immediate < -ST32_MAX) {
1641  return -1;
1642  }
1643  if (!strcmp(op->mnemonic, "jmp")) {
1644  if (op->operands[0].type & OT_GPREG) {
1645  data[l++] = 0xff;
1646  if (op->operands[0].type & OT_MEMORY) {
1647  if (op->operands[0].offset) {
1648  int offset = op->operands[0].offset * op->operands[0].offset_sign;
1649  if (offset >= 128 || offset <= -129) {
1650  data[l] = 0xa0;
1651  } else {
1652  data[l] = 0x60;
1653  }
1654  data[l++] |= op->operands[0].regs[0];
1655  if (op->operands[0].regs[0] == X86R_ESP) {
1656  data[l++] = 0x24;
1657  }
1658  data[l++] = offset;
1659  if (op->operands[0].offset >= 0x80) {
1660  data[l++] = offset >> 8;
1661  data[l++] = offset >> 16;
1662  data[l++] = offset >> 24;
1663  }
1664  } else {
1665  data[l++] = 0x20 | op->operands[0].regs[0];
1666  }
1667  } else {
1668  data[l++] = 0xe0 | op->operands[0].reg;
1669  }
1670  } else {
1671  if (-0x80 <= (immediate - 2) && (immediate - 2) <= 0x7f) {
1672  /* relative byte address */
1673  data[l++] = 0xeb;
1674  data[l++] = immediate - 2;
1675  } else {
1676  /* relative address */
1677  immediate -= 5;
1678  data[l++] = 0xe9;
1679  data[l++] = immediate;
1680  data[l++] = immediate >> 8;
1681  data[l++] = immediate >> 16;
1682  data[l++] = immediate >> 24;
1683  }
1684  }
1685  return l;
1686  }
1687  if (immediate <= 0x81 && immediate > -0x7f) {
1688  is_short = true;
1689  }
1690  if (a->bits == 16 && (immediate > 0x81 || immediate < -0x7e)) {
1691  data[l++] = 0x66;
1692  is_short = false;
1693  immediate--;
1694  }
1695 
1696  if (!is_short) {
1697  data[l++] = 0x0f;
1698  }
1699  if (!strcmp(op->mnemonic, "ja") ||
1700  !strcmp(op->mnemonic, "jnbe")) {
1701  data[l++] = 0x87;
1702  } else if (!strcmp(op->mnemonic, "jae") ||
1703  !strcmp(op->mnemonic, "jnb") ||
1704  !strcmp(op->mnemonic, "jnc")) {
1705  data[l++] = 0x83;
1706  } else if (!strcmp(op->mnemonic, "jz") ||
1707  !strcmp(op->mnemonic, "je")) {
1708  data[l++] = 0x84;
1709  } else if (!strcmp(op->mnemonic, "jb") ||
1710  !strcmp(op->mnemonic, "jnae") ||
1711  !strcmp(op->mnemonic, "jc")) {
1712  data[l++] = 0x82;
1713  } else if (!strcmp(op->mnemonic, "jbe") ||
1714  !strcmp(op->mnemonic, "jna")) {
1715  data[l++] = 0x86;
1716  } else if (!strcmp(op->mnemonic, "jg") ||
1717  !strcmp(op->mnemonic, "jnle")) {
1718  data[l++] = 0x8f;
1719  } else if (!strcmp(op->mnemonic, "jge") ||
1720  !strcmp(op->mnemonic, "jnl")) {
1721  data[l++] = 0x8d;
1722  } else if (!strcmp(op->mnemonic, "jl") ||
1723  !strcmp(op->mnemonic, "jnge")) {
1724  data[l++] = 0x8c;
1725  } else if (!strcmp(op->mnemonic, "jle") ||
1726  !strcmp(op->mnemonic, "jng")) {
1727  data[l++] = 0x8e;
1728  } else if (!strcmp(op->mnemonic, "jne") ||
1729  !strcmp(op->mnemonic, "jnz")) {
1730  data[l++] = 0x85;
1731  } else if (!strcmp(op->mnemonic, "jno")) {
1732  data[l++] = 0x81;
1733  } else if (!strcmp(op->mnemonic, "jnp") ||
1734  !strcmp(op->mnemonic, "jpo")) {
1735  data[l++] = 0x8b;
1736  } else if (!strcmp(op->mnemonic, "jns")) {
1737  data[l++] = 0x89;
1738  } else if (!strcmp(op->mnemonic, "jo")) {
1739  data[l++] = 0x80;
1740  } else if (!strcmp(op->mnemonic, "jp") ||
1741  !strcmp(op->mnemonic, "jpe")) {
1742  data[l++] = 0x8a;
1743  } else if (!strcmp(op->mnemonic, "js") ||
1744  !strcmp(op->mnemonic, "jz")) {
1745  data[l++] = 0x88;
1746  }
1747  if (is_short) {
1748  data[l - 1] -= 0x10;
1749  }
1750 
1751  immediate -= is_short ? 2 : 6;
1752  data[l++] = immediate;
1753  if (!is_short) {
1754  data[l++] = immediate >> 8;
1755  data[l++] = immediate >> 16;
1756  data[l++] = immediate >> 24;
1757  }
1758  return l;
1759 }
1760 
1761 static int oplea(RzAsm *a, ut8 *data, const Opcode *op) {
1762  int l = 0;
1763  int mod = 0;
1764  st32 offset = 0;
1765  int reg = 0;
1766  int rm = 0;
1767  if (op->operands[0].type & OT_REGALL &&
1768  op->operands[1].type & (OT_MEMORY | OT_CONSTANT)) {
1769  if (a->bits == 64) {
1770  data[l++] = 0x48;
1771  }
1772  data[l++] = 0x8d;
1773  if (op->operands[1].regs[0] == X86R_UNDEFINED) {
1774  // RIP-relative LEA
1775  ut64 offset = op->operands[1].offset - a->pc;
1776  if (data[0] == 0x48) {
1777  offset -= 7;
1778  }
1779  ut32 high = 0xff00 & offset;
1780  data[l++] = op->operands[0].reg << 3 | 5;
1781  data[l++] = offset;
1782  data[l++] = high >> 8;
1783  data[l++] = offset >> 16;
1784  data[l++] = offset >> 24;
1785  return l;
1786  } else {
1787  reg = op->operands[0].reg;
1788  rm = op->operands[1].regs[0];
1789 
1790  offset = op->operands[1].offset * op->operands[1].offset_sign;
1791  if (op->operands[1].regs[0] == X86R_RIP) {
1792  // RIP-relative LEA (not caught above, so "offset" is already relative)
1793  data[l++] = reg << 3 | 5;
1794  data[l++] = offset;
1795  data[l++] = offset >> 8;
1796  data[l++] = offset >> 16;
1797  data[l++] = offset >> 24;
1798  return l;
1799  }
1800  if (offset != 0 || op->operands[1].regs[0] == X86R_EBP) {
1801  mod = 1;
1802  if (offset >= 128 || offset < -128) {
1803  mod = 2;
1804  }
1805  data[l++] = mod << 6 | reg << 3 | rm;
1806  if (op->operands[1].regs[0] == X86R_ESP) {
1807  data[l++] = 0x24;
1808  }
1809  data[l++] = offset;
1810  if (mod == 2) {
1811  data[l++] = offset >> 8;
1812  data[l++] = offset >> 16;
1813  data[l++] = offset >> 24;
1814  }
1815  } else {
1816  data[l++] = op->operands[0].reg << 3 | op->operands[1].regs[0];
1817  if (op->operands[1].regs[0] == X86R_ESP) {
1818  data[l++] = 0x24;
1819  }
1820  }
1821  }
1822  }
1823  return l;
1824 }
1825 
1826 static int oples(RzAsm *a, ut8 *data, const Opcode *op) {
1827  int l = 0;
1828  int offset = 0;
1829  int mod = 0;
1830 
1831  if (op->operands[1].type & OT_MEMORY) {
1832  data[l++] = 0xc4;
1833  if (op->operands[1].type & OT_GPREG) {
1834  offset = op->operands[1].offset * op->operands[1].offset_sign;
1835  if (offset) {
1836  mod = 1;
1837  if (offset > 128 || offset < -128) {
1838  mod = 2;
1839  }
1840  }
1841  data[l++] = mod << 6 | op->operands[0].reg << 3 | op->operands[1].regs[0];
1842  if (mod) {
1843  data[l++] = offset;
1844  if (mod > 1) {
1845  data[l++] = offset >> 8;
1846  data[l++] = offset >> 16;
1847  data[l++] = offset >> 24;
1848  }
1849  }
1850  } else {
1851  offset = op->operands[1].offset * op->operands[1].offset_sign;
1852  data[l++] = 0x05;
1853  data[l++] = offset;
1854  data[l++] = offset >> 8;
1855  data[l++] = offset >> 16;
1856  data[l++] = offset >> 24;
1857  }
1858  }
1859  return l;
1860 }
1861 
1862 static int opmov(RzAsm *a, ut8 *data, const Opcode *op) {
1863  int l = 0;
1864  st64 offset = 0;
1865  int mod = 0;
1866  int base = 0;
1867  int rex = 0;
1868  ut64 immediate = 0;
1869  if (op->operands[1].type & OT_CONSTANT) {
1870  if (!op->operands[1].is_good_flag) {
1871  return -1;
1872  }
1873  if (op->operands[1].immediate == -1 && a->num && a->num->nc.errors > 0) {
1874  return -1;
1875  }
1876  immediate = op->operands[1].immediate * op->operands[1].sign;
1877  if (op->operands[0].type & OT_GPREG && !(op->operands[0].type & OT_MEMORY)) {
1878  if ((op->operands[0].type & OT_DWORD) &&
1879  immediate > UT32_MAX && immediate < 0xffffffff80000000ULL /* -0x80000000 */) {
1880  return -1;
1881  }
1882  bool imm32in64 = false;
1883  if (a->bits == 64 && (op->operands[0].type & OT_QWORD)) {
1884  if (op->operands[0].extended) {
1885  data[l++] = 0x49;
1886  } else {
1887  data[l++] = 0x48;
1888  }
1889  } else if (op->operands[0].extended) {
1890  data[l++] = 0x41;
1891  }
1892  if (op->operands[0].type & OT_WORD) {
1893  if (a->bits > 16) {
1894  data[l++] = 0x66;
1895  }
1896  }
1897  if (op->operands[0].type & OT_BYTE) {
1898  data[l++] = 0xb0 | op->operands[0].reg;
1899  data[l++] = immediate;
1900  } else {
1901  if (a->bits == 64 && (op->operands[0].type & OT_QWORD) &&
1902  (immediate <= ST32_MAX || immediate >= 0xffffffff80000000ULL /* -0x80000000 */)) {
1903  data[l++] = 0xc7;
1904  data[l++] = 0xc0 | op->operands[0].reg;
1905  imm32in64 = true;
1906  } else {
1907  data[l++] = 0xb8 | op->operands[0].reg;
1908  }
1909  data[l++] = immediate;
1910  data[l++] = immediate >> 8;
1911  if (!(op->operands[0].type & OT_WORD)) {
1912  data[l++] = immediate >> 16;
1913  data[l++] = immediate >> 24;
1914  }
1915  if (a->bits == 64 &&
1916  (((op->operands[0].type & OT_QWORD) && !imm32in64) ||
1917  (immediate > UT32_MAX && immediate < 0xffffffff80000000ULL /* -0x80000000 */))) {
1918  data[l++] = immediate >> 32;
1919  data[l++] = immediate >> 40;
1920  data[l++] = immediate >> 48;
1921  data[l++] = immediate >> 56;
1922  }
1923  }
1924  } else if (op->operands[0].type & OT_MEMORY) {
1925  if (!op->operands[0].explicit_size) {
1926  if (op->operands[0].type & OT_GPREG) {
1927  ((Opcode *)op)->operands[0].dest_size = op->operands[0].reg_size;
1928  } else {
1929  return -1;
1930  }
1931  }
1932 
1933  int dest_bits = 8 * ((op->operands[0].dest_size & ALL_SIZE) >> OPSIZE_SHIFT);
1934  int reg_bits = 8 * ((op->operands[0].reg_size & ALL_SIZE) >> OPSIZE_SHIFT);
1935  int offset = op->operands[0].offset * op->operands[0].offset_sign;
1936 
1937  // addr_size_override prefix
1938  bool use_aso = false;
1939  if (reg_bits < a->bits) {
1940  use_aso = true;
1941  }
1942 
1943  // op_size_override prefix
1944  bool use_oso = false;
1945  if (dest_bits == 16) {
1946  use_oso = true;
1947  }
1948 
1949  bool rip_rel = op->operands[0].regs[0] == X86R_RIP;
1950 
1951  // rex prefix
1952  int rex = 1 << 6;
1953  bool use_rex = false;
1954  if (dest_bits == 64) { // W field
1955  use_rex = true;
1956  rex |= 1 << 3;
1957  }
1958  if (op->operands[0].extended) { // B field
1959  use_rex = true;
1960  rex |= 1;
1961  }
1962 
1963  // opcode selection
1964  int opcode;
1965  if (dest_bits == 8) {
1966  opcode = 0xc6;
1967  } else {
1968  opcode = 0xc7;
1969  }
1970 
1971  // modrm and SIB selection
1972  int modrm = 0;
1973  int mod;
1974  int reg = 0;
1975  int rm;
1976  bool use_sib = false;
1977  int sib;
1978  // mod
1979  if (offset == 0) {
1980  mod = 0;
1981  } else if (offset < 128 && offset > -129) {
1982  mod = 1;
1983  } else {
1984  mod = 2;
1985  }
1986 
1987  if (reg_bits == 16) {
1988  if (op->operands[0].regs[0] == X86R_BX && op->operands[0].regs[1] == X86R_SI) {
1989  rm = B0000;
1990  } else if (op->operands[0].regs[0] == X86R_BX && op->operands[0].regs[1] == X86R_DI) {
1991  rm = B0001;
1992  } else if (op->operands[0].regs[0] == X86R_BP && op->operands[0].regs[1] == X86R_SI) {
1993  rm = B0010;
1994  } else if (op->operands[0].regs[0] == X86R_BP && op->operands[0].regs[1] == X86R_DI) {
1995  rm = B0011;
1996  } else if (op->operands[0].regs[0] == X86R_SI && op->operands[0].regs[1] == -1) {
1997  rm = B0100;
1998  } else if (op->operands[0].regs[0] == X86R_DI && op->operands[0].regs[1] == -1) {
1999  rm = B0101;
2000  } else if (op->operands[0].regs[0] == X86R_BX && op->operands[0].regs[1] == -1) {
2001  rm = B0111;
2002  } else {
2003  // TODO allow for displacement only when parser is reworked
2004  return -1;
2005  }
2006  modrm = (mod << 6) | (reg << 3) | rm;
2007  } else {
2008  // rm
2009  if (op->operands[0].extended) {
2010  rm = op->operands[0].reg;
2011  } else {
2012  rm = op->operands[0].regs[0];
2013  }
2014  //[epb] alone is illegal, so we need to fake a [ebp+0]
2015  if (rm == 5 && mod == 0) {
2016  mod = 1;
2017  }
2018 
2019  // sib
2020  int index = op->operands[0].regs[1];
2021  int scale = getsib(op->operands[0].scale[1]);
2022  if (index != -1) {
2023  use_sib = true;
2024  sib = (scale << 6) | (index << 3) | rm;
2025  } else if (rm == 4) {
2026  use_sib = true;
2027  sib = 0x24;
2028  }
2029  if (use_sib) {
2030  rm = B0100;
2031  }
2032  if (rip_rel) {
2033  modrm = (B0000 << 6) | (reg << 3) | B0101;
2034  sib = (scale << 6) | (B0100 << 3) | B0101;
2035  } else {
2036  modrm = (mod << 6) | (reg << 3) | rm;
2037  }
2038  }
2039 
2040  // build the final result
2041  if (use_aso) {
2042  data[l++] = 0x67;
2043  }
2044  if (use_oso) {
2045  data[l++] = 0x66;
2046  }
2047  if (use_rex) {
2048  data[l++] = rex;
2049  }
2050  data[l++] = opcode;
2051  data[l++] = modrm;
2052  if (use_sib) {
2053  data[l++] = sib;
2054  }
2055  // offset
2056  if (mod == 1) {
2057  data[l++] = offset;
2058  } else if (reg_bits == 16 && mod == 2) {
2059  data[l++] = offset;
2060  data[l++] = offset >> 8;
2061  } else if (mod == 2 || rip_rel) {
2062  data[l++] = offset;
2063  data[l++] = offset >> 8;
2064  data[l++] = offset >> 16;
2065  data[l++] = offset >> 24;
2066  }
2067  // immediate
2068  int byte;
2069  for (byte = 0; byte < dest_bits && byte < 32; byte += 8) {
2070  data[l++] = (immediate >> byte);
2071  }
2072  }
2073  } else if (op->operands[1].type & OT_REGALL &&
2074  !(op->operands[1].type & OT_MEMORY)) {
2075  if (op->operands[0].type & OT_CONSTANT) {
2076  return -1;
2077  }
2078  if (op->operands[0].type & OT_REGTYPE & OT_SEGMENTREG &&
2079  op->operands[1].type & OT_REGTYPE & OT_SEGMENTREG) {
2080  return -1;
2081  }
2082  if (is_debug_or_control(op->operands[0]) &&
2083  !(op->operands[1].type & OT_REGTYPE & OT_GPREG)) {
2084  return -1;
2085  }
2086  if (is_debug_or_control(op->operands[1]) &&
2087  !(op->operands[0].type & OT_REGTYPE & OT_GPREG)) {
2088  return -1;
2089  }
2090  // Check reg sizes match
2091  if (op->operands[0].type & OT_REGTYPE && op->operands[1].type & OT_REGTYPE) {
2092  if (!((op->operands[0].type & ALL_SIZE) &
2093  (op->operands[1].type & ALL_SIZE))) {
2094  return -1;
2095  }
2096  }
2097 
2098  if (a->bits == 64) {
2099  if (op->operands[0].extended) {
2100  rex = 1;
2101  }
2102  if (op->operands[1].extended) {
2103  rex += 4;
2104  }
2105  if (op->operands[1].type & OT_QWORD) {
2106  if (!(op->operands[0].type & OT_QWORD)) {
2107  data[l++] = 0x67;
2108  data[l++] = 0x48;
2109  }
2110  }
2111  if (op->operands[1].type & OT_QWORD &&
2112  op->operands[0].type & OT_QWORD) {
2113  data[l++] = 0x48 | rex;
2114  }
2115  if (op->operands[1].type & OT_DWORD &&
2116  op->operands[0].type & OT_DWORD) {
2117  data[l++] = 0x40 | rex;
2118  }
2119  } else if (op->operands[0].extended && op->operands[1].extended) {
2120  data[l++] = 0x45;
2121  }
2122  offset = op->operands[0].offset * op->operands[0].offset_sign;
2123  if (op->operands[1].type & OT_REGTYPE & OT_SEGMENTREG) {
2124  data[l++] = 0x8c;
2125  } else if (is_debug_or_control(op->operands[0])) {
2126  data[l++] = 0x0f;
2127  if (op->operands[0].type & OT_REGTYPE & OT_DEBUGREG) {
2128  data[l++] = 0x23;
2129  } else {
2130  data[l++] = 0x22;
2131  }
2132  } else if (is_debug_or_control(op->operands[1])) {
2133  data[l++] = 0x0f;
2134  if (op->operands[1].type & OT_REGTYPE & OT_DEBUGREG) {
2135  data[l++] = 0x21;
2136  } else {
2137  data[l++] = 0x20;
2138  }
2139  } else {
2140  if (op->operands[0].type & OT_WORD) {
2141  data[l++] = 0x66;
2142  }
2143  data[l++] = (op->operands[0].type & OT_BYTE) ? 0x88 : 0x89;
2144  }
2145 
2146  if (op->operands[0].scale[0] > 1) {
2147  data[l++] = op->operands[1].reg << 3 | 4;
2148  data[l++] = getsib(op->operands[0].scale[0]) << 6 |
2149  op->operands[0].regs[0] << 3 | 5;
2150 
2151  data[l++] = offset;
2152  data[l++] = offset >> 8;
2153  data[l++] = offset >> 16;
2154  data[l++] = offset >> 24;
2155 
2156  return l;
2157  }
2158 
2159  if (!(op->operands[0].type & OT_MEMORY)) {
2160  if (op->operands[0].reg == X86R_UNDEFINED ||
2161  op->operands[1].reg == X86R_UNDEFINED) {
2162  return -1;
2163  }
2164  mod = 0x3;
2165  data[l++] = (is_debug_or_control(op->operands[0]))
2166  ? mod << 6 | op->operands[0].reg << 3 | op->operands[1].reg
2167  : mod << 6 | op->operands[1].reg << 3 | op->operands[0].reg;
2168  } else if (op->operands[0].regs[0] == X86R_UNDEFINED) {
2169  data[l++] = op->operands[1].reg << 3 | 0x5;
2170  data[l++] = offset;
2171  data[l++] = offset >> 8;
2172  data[l++] = offset >> 16;
2173  data[l++] = offset >> 24;
2174  } else {
2175  if (op->operands[0].type & OT_MEMORY) {
2176  if (op->operands[0].regs[1] != X86R_UNDEFINED) {
2177  data[l++] = op->operands[1].reg << 3 | 0x4;
2178  data[l++] = op->operands[0].regs[1] << 3 | op->operands[0].regs[0];
2179  return l;
2180  }
2181  if (offset) {
2182  mod = (offset > 128 || offset < -129) ? 0x2 : 0x1;
2183  }
2184  if (op->operands[0].regs[0] == X86R_EBP) {
2185  mod = 0x2;
2186  }
2187  data[l++] = mod << 6 | op->operands[1].reg << 3 | op->operands[0].regs[0];
2188  if (op->operands[0].regs[0] == X86R_ESP) {
2189  data[l++] = 0x24;
2190  }
2191  if (offset) {
2192  data[l++] = offset;
2193  }
2194  if (mod == 2) {
2195  // warning C4293: '>>': shift count negative or too big, undefined behavior
2196  data[l++] = offset >> 8;
2197  data[l++] = offset >> 16;
2198  data[l++] = offset >> 24;
2199  }
2200  }
2201  }
2202  } else if (op->operands[1].type & OT_MEMORY) {
2203  if (op->operands[0].type & OT_MEMORY) {
2204  return -1;
2205  }
2206  offset = op->operands[1].offset * op->operands[1].offset_sign;
2207  if (op->operands[0].reg == X86R_EAX && op->operands[1].regs[0] == X86R_UNDEFINED) {
2208  if (op->operands[0].type & OT_QWORD) {
2209  data[l++] = 0x48;
2210  } else if (op->operands[0].type & OT_WORD && a->bits != 16) {
2211  data[l++] = 0x66;
2212  }
2213  if (op->operands[0].type & OT_BYTE) {
2214  data[l++] = 0xa0;
2215  } else {
2216  data[l++] = 0xa1;
2217  }
2218  data[l++] = offset;
2219  data[l++] = offset >> 8;
2220  if (a->bits >= 32) {
2221  data[l++] = offset >> 16;
2222  data[l++] = offset >> 24;
2223  if (a->bits == 64) {
2224  data[l++] = offset >> 32;
2225  data[l++] = offset >> 40;
2226  data[l++] = offset >> 48;
2227  data[l++] = offset >> 56;
2228  }
2229  }
2230  return l;
2231  }
2232  if (op->operands[0].type & OT_BYTE && a->bits == 64 && op->operands[1].regs[0]) {
2233  if (op->operands[1].regs[0] >= X86R_R8 &&
2234  op->operands[0].reg < 4) {
2235  data[l++] = 0x41;
2236  data[l++] = 0x8a;
2237  data[l++] = op->operands[0].reg << 3 | (op->operands[1].regs[0] - 8);
2238  return l;
2239  }
2240  return -1;
2241  }
2242 
2243  if (op->operands[1].type & OT_REGTYPE & OT_SEGMENTREG) {
2244  if (op->operands[1].scale[0] == 0) {
2245  return -1;
2246  }
2247  data[l++] = SEG_REG_PREFIXES[op->operands[1].regs[0] % 6];
2248  data[l++] = 0x8b;
2249  data[l++] = (((ut32)op->operands[0].reg) << 3) | 0x5;
2250  data[l++] = offset;
2251  data[l++] = offset >> 8;
2252  data[l++] = offset >> 16;
2253  data[l++] = offset >> 24;
2254  return l;
2255  }
2256 
2257  if (a->bits == 64) {
2258  if (op->operands[0].type & OT_QWORD) {
2259  if (!(op->operands[1].type & OT_QWORD)) {
2260  if (op->operands[1].regs[0] != -1) {
2261  data[l++] = 0x67;
2262  }
2263  data[l++] = 0x48;
2264  }
2265  } else if (op->operands[1].type & OT_DWORD) {
2266  data[l++] = 0x44;
2267  } else if (!(op->operands[1].type & OT_QWORD)) {
2268  data[l++] = 0x67;
2269  }
2270  if (op->operands[1].type & OT_QWORD &&
2271  op->operands[0].type & OT_QWORD) {
2272  data[l++] = 0x48;
2273  }
2274  }
2275 
2276  if (op->operands[0].type & OT_WORD) {
2277  data[l++] = 0x66;
2278  data[l++] = op->operands[1].type & OT_BYTE ? 0x8a : 0x8b;
2279  } else {
2280  data[l++] = (op->operands[1].type & OT_BYTE ||
2281  op->operands[0].type & OT_BYTE)
2282  ? 0x8a
2283  : 0x8b;
2284  }
2285 
2286  if (op->operands[1].regs[0] == X86R_UNDEFINED) {
2287  if (a->bits == 64) {
2288  data[l++] = op->operands[0].reg << 3 | 0x4;
2289  data[l++] = 0x25;
2290  } else {
2291  data[l++] = op->operands[0].reg << 3 | 0x5;
2292  }
2293  data[l++] = offset;
2294  data[l++] = offset >> 8;
2295  data[l++] = offset >> 16;
2296  data[l++] = offset >> 24;
2297  } else {
2298  if (op->operands[1].scale[0] > 1) {
2299  data[l++] = op->operands[0].reg << 3 | 4;
2300 
2301  if (op->operands[1].scale[0] >= 2) {
2302  base = 5;
2303  }
2304  if (base) {
2305  data[l++] = getsib(op->operands[1].scale[0]) << 6 | op->operands[1].regs[0] << 3 | base;
2306  } else {
2307  data[l++] = getsib(op->operands[1].scale[0]) << 3 | op->operands[1].regs[0];
2308  }
2309  if (offset || base) {
2310  data[l++] = offset;
2311  data[l++] = offset >> 8;
2312  data[l++] = offset >> 16;
2313  data[l++] = offset >> 24;
2314  }
2315  return l;
2316  }
2317  if (op->operands[1].regs[1] != X86R_UNDEFINED) {
2318  data[l++] = op->operands[0].reg << 3 | 0x4;
2319  data[l++] = op->operands[1].regs[1] << 3 | op->operands[1].regs[0];
2320  return l;
2321  }
2322 
2323  if (offset || op->operands[1].regs[0] == X86R_EBP) {
2324  mod = 0x2;
2325  if (op->operands[1].offset > 127) {
2326  mod = 0x4;
2327  }
2328  }
2329  if (a->bits == 64 && offset && op->operands[0].type & OT_QWORD) {
2330  if (op->operands[1].regs[0] == X86R_RIP) {
2331  data[l++] = 0x5;
2332  } else {
2333  const ut8 pfx = (op->operands[1].offset > 127) ? 0x80 : 0x40;
2334  data[l++] = pfx | op->operands[0].reg << 3 | op->operands[1].regs[0];
2335  }
2336  if (op->operands[1].offset > 127) {
2337  mod = 0x1;
2338  }
2339  } else {
2340  if (op->operands[1].regs[0] == X86R_EIP && (op->operands[0].type & OT_DWORD)) {
2341  data[l++] = 0x0d;
2342  } else if (op->operands[1].regs[0] == X86R_RIP && (op->operands[0].type & OT_QWORD)) {
2343  data[l++] = 0x05;
2344  } else {
2345  data[l++] = mod << 5 | op->operands[0].reg << 3 | op->operands[1].regs[0];
2346  }
2347  }
2348  if (op->operands[1].regs[0] == X86R_ESP) {
2349  data[l++] = 0x24;
2350  }
2351  if (mod >= 0x2) {
2352  data[l++] = offset;
2353  if (op->operands[1].offset > 128 || op->operands[1].regs[0] == X86R_EIP) {
2354  data[l++] = offset >> 8;
2355  data[l++] = offset >> 16;
2356  data[l++] = offset >> 24;
2357  }
2358  } else if (a->bits == 64 && (offset || op->operands[1].regs[0] == X86R_RIP)) {
2359  data[l++] = offset;
2360  if (op->operands[1].offset > 127 || op->operands[1].regs[0] == X86R_RIP) {
2361  data[l++] = offset >> 8;
2362  data[l++] = offset >> 16;
2363  data[l++] = offset >> 24;
2364  }
2365  }
2366  }
2367  }
2368  return l;
2369 }
2370 
2371 // Only for MOV r64, imm64
2372 static int opmovabs(RzAsm *a, ut8 *data, const Opcode *op) {
2373  if (!(a->bits == 64 && (op->operands[0].type & OT_GPREG) && !(op->operands[0].type & OT_MEMORY) &&
2374  (op->operands[0].type & OT_QWORD) && (op->operands[1].type & OT_CONSTANT))) {
2375  return -1;
2376  }
2377  int l = 0;
2378  int byte_shift;
2379  ut64 immediate;
2380  if (op->operands[0].extended) {
2381  data[l++] = 0x49;
2382  } else {
2383  data[l++] = 0x48;
2384  }
2385  data[l++] = 0xb8 | op->operands[0].reg;
2386  immediate = op->operands[1].immediate * op->operands[1].sign;
2387  for (byte_shift = 0; byte_shift < 8; byte_shift++) {
2388  data[l++] = immediate >> (byte_shift * 8);
2389  }
2390  return l;
2391 }
2392 
2393 static int opmul(RzAsm *a, ut8 *data, const Opcode *op) {
2395  int l = 0;
2396 
2397  if (op->operands[0].type & OT_QWORD) {
2398  data[l++] = 0x48;
2399  }
2400  switch (op->operands_count) {
2401  case 1:
2402  if (op->operands[0].type & OT_WORD) {
2403  data[l++] = 0x66;
2404  }
2405  if (op->operands[0].type & OT_BYTE) {
2406  data[l++] = 0xf6;
2407  } else {
2408  data[l++] = 0xf7;
2409  }
2410  if (op->operands[0].type & OT_MEMORY) {
2411  data[l++] = 0x20 | op->operands[0].regs[0];
2412  } else {
2413  data[l++] = 0xe0 | op->operands[0].reg;
2414  }
2415  break;
2416  default:
2417  return -1;
2418  }
2419  return l;
2420 }
2421 
2422 static int oppop(RzAsm *a, ut8 *data, const Opcode *op) {
2424  int l = 0;
2425  int offset = 0;
2426  int mod = 0;
2427  if (op->operands[0].type & OT_GPREG) {
2428  if (op->operands[0].type & OT_MEMORY) {
2429  return -1;
2430  }
2431  if (op->operands[0].type & OT_REGTYPE & OT_SEGMENTREG) {
2432  ut8 base;
2433  if (op->operands[0].reg & X86R_FS) {
2434  data[l++] = 0x0f;
2435  base = 0x81;
2436  } else {
2437  base = 0x7;
2438  }
2439  data[l++] = base + (8 * op->operands[0].reg);
2440  } else {
2441  if (op->operands[0].extended && a->bits == 64) {
2442  data[l++] = 0x41;
2443  }
2444  ut8 base = 0x58;
2445  data[l++] = base + op->operands[0].reg;
2446  }
2447  } else if (op->operands[0].type & OT_MEMORY) {
2448  data[l++] = 0x8f;
2449  offset = op->operands[0].offset * op->operands[0].offset_sign;
2450  if (offset != 0 || op->operands[0].regs[0] == X86R_EBP) {
2451  mod = 1;
2452  if (offset >= 128 || offset < -128) {
2453  mod = 2;
2454  }
2455  data[l++] = mod << 6 | op->operands[0].regs[0];
2456  if (op->operands[0].regs[0] == X86R_ESP) {
2457  data[l++] = 0x24;
2458  }
2459  data[l++] = offset;
2460  if (mod == 2) {
2461  data[l++] = offset >> 8;
2462  data[l++] = offset >> 16;
2463  data[l++] = offset >> 24;
2464  }
2465  } else {
2466  data[l++] = op->operands[0].regs[0];
2467  if (op->operands[0].regs[0] == X86R_ESP) {
2468  data[l++] = 0x24;
2469  }
2470  }
2471  }
2472  return l;
2473 }
2474 
2475 static int oppush(RzAsm *a, ut8 *data, const Opcode *op) {
2477  int l = 0;
2478  int mod = 0;
2479  st32 immediate = 0;
2480  ;
2481  st32 offset = 0;
2482  if (op->operands[0].type & OT_GPREG &&
2483  !(op->operands[0].type & OT_MEMORY)) {
2484  if (op->operands[0].type & OT_REGTYPE & OT_SEGMENTREG) {
2485  ut8 base;
2486  if (op->operands[0].reg & X86R_FS) {
2487  data[l++] = 0x0f;
2488  base = 0x80;
2489  } else {
2490  base = 0x6;
2491  }
2492  data[l++] = base + (8 * op->operands[0].reg);
2493  } else {
2494  if (op->operands[0].extended && a->bits == 64) {
2495  data[l++] = 0x41;
2496  }
2497  ut8 base = 0x50;
2498  if (op->operands[0].reg == X86R_RIP) {
2499  RZ_LOG_ERROR("assembler: x86.nz: %s: invalid register (rip)\n", op->mnemonic);
2500  return -1;
2501  }
2502  data[l++] = base + op->operands[0].reg;
2503  }
2504  } else if (op->operands[0].type & OT_MEMORY) {
2505  data[l++] = 0xff;
2506  offset = op->operands[0].offset * op->operands[0].offset_sign;
2507  if (offset != 0 || op->operands[0].regs[0] == X86R_EBP) {
2508  mod = 1;
2509  if (offset >= 128 || offset < -128) {
2510  mod = 2;
2511  }
2512  data[l++] = mod << 6 | 6 << 3 | op->operands[0].regs[0];
2513  if (op->operands[0].regs[0] == X86R_ESP) {
2514  data[l++] = 0x24;
2515  }
2516  data[l++] = offset;
2517  if (mod == 2) {
2518  data[l++] = offset >> 8;
2519  data[l++] = offset >> 16;
2520  data[l++] = offset >> 24;
2521  }
2522  } else {
2523  mod = 3;
2524  data[l++] = mod << 4 | op->operands[0].regs[0];
2525  if (op->operands[0].regs[0] == X86R_ESP) {
2526  data[l++] = 0x24;
2527  }
2528  }
2529  } else {
2530  immediate = op->operands[0].immediate * op->operands[0].sign;
2531  if (immediate >= 128 || immediate < -128) {
2532  data[l++] = 0x68;
2533  data[l++] = immediate;
2534  data[l++] = immediate >> 8;
2535  data[l++] = immediate >> 16;
2536  data[l++] = immediate >> 24;
2537  } else {
2538  data[l++] = 0x6a;
2539  data[l++] = immediate;
2540  }
2541  }
2542  return l;
2543 }
2544 
2545 static int opout(RzAsm *a, ut8 *data, const Opcode *op) {
2547  int l = 0;
2548  st32 immediate = 0;
2549  if (op->operands[0].reg == X86R_DX) {
2550  if (op->operands[1].reg == X86R_AL && op->operands[1].type & OT_BYTE) {
2551  data[l++] = 0xee;
2552  return l;
2553  }
2554  if (op->operands[1].reg == X86R_AX && op->operands[1].type & OT_WORD) {
2555  data[l++] = 0x66;
2556  data[l++] = 0xef;
2557  return l;
2558  }
2559  if (op->operands[1].reg == X86R_EAX && op->operands[1].type & OT_DWORD) {
2560  data[l++] = 0xef;
2561  return l;
2562  }
2563  } else if (op->operands[0].type & OT_CONSTANT) {
2564  immediate = op->operands[0].immediate * op->operands[0].sign;
2565  if (immediate > 255 || immediate < -128) {
2566  return -1;
2567  }
2568  if (op->operands[1].reg == X86R_AL && op->operands[1].type & OT_BYTE) {
2569  data[l++] = 0xe6;
2570  } else if (op->operands[1].reg == X86R_AX && op->operands[1].type & OT_WORD) {
2571  data[l++] = 0x66;
2572  data[l++] = 0xe7;
2573  } else if (op->operands[1].reg == X86R_EAX && op->operands[1].type & OT_DWORD) {
2574  data[l++] = 0xe7;
2575  } else {
2576  return -1;
2577  }
2578  data[l++] = immediate;
2579  } else {
2580  return -1;
2581  }
2582  return l;
2583 }
2584 
2585 static int oploop(RzAsm *a, ut8 *data, const Opcode *op) {
2587  int l = 0;
2588  data[l++] = 0xe2;
2589  st8 delta = op->operands[0].immediate - a->pc - 2;
2590  data[l++] = (ut8)delta;
2591  return l;
2592 }
2593 
2594 static int opret(RzAsm *a, ut8 *data, const Opcode *op) {
2595  int l = 0;
2596  int immediate = 0;
2597  if (a->bits == 16) {
2598  data[l++] = 0xc3;
2599  return l;
2600  }
2601  if (op->operands[0].type == OT_UNKNOWN) {
2602  data[l++] = 0xc3;
2603  } else if (op->operands[0].type & (OT_CONSTANT | OT_WORD)) {
2604  data[l++] = 0xc2;
2605  immediate = op->operands[0].immediate * op->operands[0].sign;
2606  data[l++] = immediate;
2607  data[l++] = immediate << 8;
2608  }
2609  return l;
2610 }
2611 
2612 static int opretf(RzAsm *a, ut8 *data, const Opcode *op) {
2613  int l = 0;
2614  st32 immediate = 0;
2615  if (op->operands[0].type & OT_CONSTANT) {
2616  immediate = op->operands[0].immediate * op->operands[0].sign;
2617  data[l++] = 0xca;
2618  data[l++] = immediate;
2619  data[l++] = immediate >> 8;
2620  } else if (op->operands[0].type == OT_UNKNOWN) {
2621  data[l++] = 0xcb;
2622  }
2623  return l;
2624 }
2625 
2626 static int opstos(RzAsm *a, ut8 *data, const Opcode *op) {
2628  int l = 0;
2629  if (!strcmp(op->mnemonic, "stosw")) {
2630  data[l++] = 0x66;
2631  }
2632  if (!strcmp(op->mnemonic, "stosb")) {
2633  data[l++] = 0xaa;
2634  } else if (!strcmp(op->mnemonic, "stosw")) {
2635  data[l++] = 0xab;
2636  } else if (!strcmp(op->mnemonic, "stosd")) {
2637  data[l++] = 0xab;
2638  }
2639  return l;
2640 }
2641 
2642 static int opset(RzAsm *a, ut8 *data, const Opcode *op) {
2643  if (!(op->operands[0].type & (OT_GPREG | OT_BYTE))) {
2644  return -1;
2645  }
2646  int l = 0;
2647  int mod = 0;
2648  int reg = op->operands[0].regs[0];
2649 
2650  data[l++] = 0x0f;
2651  if (!strcmp(op->mnemonic, "seto")) {
2652  data[l++] = 0x90;
2653  } else if (!strcmp(op->mnemonic, "setno")) {
2654  data[l++] = 0x91;
2655  } else if (!strcmp(op->mnemonic, "setb") ||
2656  !strcmp(op->mnemonic, "setnae") ||
2657  !strcmp(op->mnemonic, "setc")) {
2658  data[l++] = 0x92;
2659  } else if (!strcmp(op->mnemonic, "setnb") ||
2660  !strcmp(op->mnemonic, "setae") ||
2661  !strcmp(op->mnemonic, "setnc")) {
2662  data[l++] = 0x93;
2663  } else if (!strcmp(op->mnemonic, "setz") ||
2664  !strcmp(op->mnemonic, "sete")) {
2665  data[l++] = 0x94;
2666  } else if (!strcmp(op->mnemonic, "setnz") ||
2667  !strcmp(op->mnemonic, "setne")) {
2668  data[l++] = 0x95;
2669  } else if (!strcmp(op->mnemonic, "setbe") ||
2670  !strcmp(op->mnemonic, "setna")) {
2671  data[l++] = 0x96;
2672  } else if (!strcmp(op->mnemonic, "setnbe") ||
2673  !strcmp(op->mnemonic, "seta")) {
2674  data[l++] = 0x97;
2675  } else if (!strcmp(op->mnemonic, "sets")) {
2676  data[l++] = 0x98;
2677  } else if (!strcmp(op->mnemonic, "setns")) {
2678  data[l++] = 0x99;
2679  } else if (!strcmp(op->mnemonic, "setp") ||
2680  !strcmp(op->mnemonic, "setpe")) {
2681  data[l++] = 0x9a;
2682  } else if (!strcmp(op->mnemonic, "setnp") ||
2683  !strcmp(op->mnemonic, "setpo")) {
2684  data[l++] = 0x9b;
2685  } else if (!strcmp(op->mnemonic, "setl") ||
2686  !strcmp(op->mnemonic, "setnge")) {
2687  data[l++] = 0x9c;
2688  } else if (!strcmp(op->mnemonic, "setnl") ||
2689  !strcmp(op->mnemonic, "setge")) {
2690  data[l++] = 0x9d;
2691  } else if (!strcmp(op->mnemonic, "setle") ||
2692  !strcmp(op->mnemonic, "setng")) {
2693  data[l++] = 0x9e;
2694  } else if (!strcmp(op->mnemonic, "setnle") ||
2695  !strcmp(op->mnemonic, "setg")) {
2696  data[l++] = 0x9f;
2697  } else {
2698  return -1;
2699  }
2700  if (!(op->operands[0].type & OT_MEMORY)) {
2701  mod = 3;
2702  reg = op->operands[0].reg;
2703  }
2704  data[l++] = mod << 6 | reg;
2705  return l;
2706 }
2707 
2708 static int optest(RzAsm *a, ut8 *data, const Opcode *op) {
2710  int l = 0;
2711  if (!op->operands[0].type || !op->operands[1].type) {
2712  RZ_LOG_ERROR("assembler: x86.nz: %s: invalid operands\n", op->mnemonic);
2713  return -1;
2714  }
2715  if (a->bits == 64) {
2716  if (op->operands[0].type & OT_MEMORY &&
2717  op->operands[0].reg_size & OT_DWORD) {
2718  data[l++] = 0x67;
2719  }
2720  if (op->operands[0].type & OT_QWORD) {
2721  if (op->operands[0].extended &&
2722  op->operands[1].extended) {
2723  data[l++] = 0x4d;
2724  } else {
2725  data[l++] = 0x48;
2726  }
2727  }
2728  }
2729 
2730  if (op->operands[1].type & OT_CONSTANT) {
2731  if (op->operands[0].type & OT_BYTE) {
2732  data[l++] = 0xf6;
2733  } else {
2734  if (op->operands[0].type & OT_WORD && a->bits != 16) {
2735  data[l++] = 0x66;
2736  }
2737  data[l++] = 0xf7;
2738  }
2739  if (op->operands[0].type & OT_MEMORY) {
2740  data[l++] = 0x00 | op->operands[0].reg;
2741  } else {
2742  data[l++] = 0xc0 | op->operands[0].reg;
2743  }
2744  data[l++] = op->operands[1].immediate >> 0;
2745  if (op->operands[0].type & OT_BYTE) {
2746  return l;
2747  }
2748  data[l++] = op->operands[1].immediate >> 8;
2749  if (op->operands[0].type & OT_WORD) {
2750  return l;
2751  }
2752  data[l++] = op->operands[1].immediate >> 16;
2753  data[l++] = op->operands[1].immediate >> 24;
2754  return l;
2755  }
2756  if (op->operands[0].type & OT_BYTE ||
2757  op->operands[1].type & OT_BYTE) {
2758  data[l++] = 0x84;
2759  } else {
2760  data[l++] = 0x85;
2761  }
2762  if (op->operands[0].type & OT_MEMORY) {
2763  data[l++] = 0x00 | op->operands[1].reg << 3 | op->operands[0].regs[0];
2764  } else {
2765  if (op->operands[1].type & OT_MEMORY) {
2766  data[l++] = 0x00 | op->operands[0].reg << 3 | op->operands[1].regs[0];
2767  } else {
2768  data[l++] = 0xc0 | op->operands[1].reg << 3 | op->operands[0].reg;
2769  }
2770  }
2771  return l;
2772 }
2773 
2774 static int opxchg(RzAsm *a, ut8 *data, const Opcode *op) {
2776  int l = 0;
2777  int mod_byte = 0;
2778  int reg = 0;
2779  int rm = 0;
2780  st32 offset = 0;
2781 
2782  if (op->operands[0].type & OT_MEMORY || op->operands[1].type & OT_MEMORY) {
2783  data[l++] = 0x87;
2784  if (op->operands[0].type & OT_MEMORY) {
2785  rm = op->operands[0].regs[0];
2786  offset = op->operands[0].offset * op->operands[0].offset_sign;
2787  reg = op->operands[1].reg;
2788  } else if (op->operands[1].type & OT_MEMORY) {
2789  rm = op->operands[1].regs[0];
2790  offset = op->operands[1].offset * op->operands[1].offset_sign;
2791  reg = op->operands[0].reg;
2792  }
2793  if (offset) {
2794  mod_byte = 1;
2796  mod_byte = 2;
2797  }
2798  }
2799  } else {
2800  if (!((op->operands[0].type & ALL_SIZE) &
2801  (op->operands[1].type & ALL_SIZE))) { // unmatched operand sizes
2802  return -1;
2803  }
2804  if (op->operands[0].reg == X86R_EAX &&
2805  !op->operands[0].extended &&
2806  !(op->operands[0].type & OT_BYTE) &&
2807  op->operands[1].type & OT_GPREG) {
2808  if (op->operands[0].type & OT_WORD) {
2809  data[l++] = 0x66;
2810  } else if (op->operands[0].type & OT_DWORD &&
2811  op->operands[1].extended) {
2812  data[l++] = 0x41;
2813  } else if (op->operands[0].type & OT_QWORD) {
2814  if (op->operands[1].extended) {
2815  data[l++] = 0x49;
2816  } else {
2817  data[l++] = 0x48;
2818  }
2819  }
2820  data[l++] = 0x90 + op->operands[1].reg;
2821  return l;
2822  } else if (op->operands[1].reg == X86R_EAX &&
2823  !op->operands[1].extended &&
2824  !(op->operands[1].type & OT_BYTE) &&
2825  op->operands[0].type & OT_GPREG) {
2826  if (op->operands[1].type & OT_WORD) {
2827  data[l++] = 0x66;
2828  } else if (op->operands[1].type & OT_DWORD &&
2829  op->operands[0].extended) {
2830  data[l++] = 0x41;
2831  } else if (op->operands[1].type & OT_QWORD) {
2832  if (op->operands[0].extended) {
2833  data[l++] = 0x49;
2834  } else {
2835  data[l++] = 0x48;
2836  }
2837  }
2838  data[l++] = 0x90 + op->operands[0].reg;
2839  return l;
2840  } else if (op->operands[0].type & OT_GPREG &&
2841  op->operands[1].type & OT_GPREG) {
2842  if (op->operands[0].type & OT_WORD) {
2843  data[l++] = 0x66;
2844  }
2845  ut8 rex = 0x40 | op->operands[0].extended | op->operands[1].extended << 2 | !!(op->operands[0].type & OT_QWORD) << 3;
2846  if (rex != 0x40) {
2847  data[l++] = rex;
2848  }
2849  if (op->operands[0].type & OT_BYTE) {
2850  data[l++] = 0x86;
2851  } else {
2852  data[l++] = 0x87;
2853  }
2854  mod_byte = 3;
2855  reg = op->operands[1].reg;
2856  rm = op->operands[0].reg;
2857  }
2858  }
2859  data[l++] = mod_byte << 6 | reg << 3 | rm;
2860  if (mod_byte > 0 && mod_byte < 3) {
2861  data[l++] = offset;
2862  if (mod_byte == 2) {
2863  data[l++] = offset >> 8;
2864  data[l++] = offset >> 16;
2865  data[l++] = offset >> 24;
2866  }
2867  }
2868  return l;
2869 }
2870 
2871 static int opcdqe(RzAsm *a, ut8 *data, const Opcode *op) {
2873  int l = 0;
2874  if (a->bits == 64) {
2875  data[l++] = 0x48;
2876  }
2877  data[l++] = 0x98;
2878  return l;
2879 }
2880 
2881 static int opfcmov(RzAsm *a, ut8 *data, const Opcode *op) {
2882  int l = 0;
2883  char *fcmov = op->mnemonic + strlen("fcmov");
2884  switch (op->operands_count) {
2885  case 2:
2886  if (op->operands[0].type & OT_FPUREG & ~OT_REGALL && op->operands[0].reg == 0 &&
2887  op->operands[1].type & OT_FPUREG & ~OT_REGALL) {
2888  if (!strcmp(fcmov, "b")) {
2889  data[l++] = 0xda;
2890  data[l++] = 0xc0 | op->operands[1].reg;
2891  } else if (!strcmp(fcmov, "e")) {
2892  data[l++] = 0xda;
2893  data[l++] = 0xc8 | op->operands[1].reg;
2894  } else if (!strcmp(fcmov, "be")) {
2895  data[l++] = 0xda;
2896  data[l++] = 0xd0 | op->operands[1].reg;
2897  } else if (!strcmp(fcmov, "u")) {
2898  data[l++] = 0xda;
2899  data[l++] = 0xd8 | op->operands[1].reg;
2900  } else if (!strcmp(fcmov, "nb")) {
2901  data[l++] = 0xdb;
2902  data[l++] = 0xc0 | op->operands[1].reg;
2903  } else if (!strcmp(fcmov, "ne")) {
2904  data[l++] = 0xdb;
2905  data[l++] = 0xc8 | op->operands[1].reg;
2906  } else if (!strcmp(fcmov, "nbe")) {
2907  data[l++] = 0xdb;
2908  data[l++] = 0xd0 | op->operands[1].reg;
2909  } else if (!strcmp(fcmov, "nu")) {
2910  data[l++] = 0xdb;
2911  data[l++] = 0xd8 | op->operands[1].reg;
2912  } else {
2913  return -1;
2914  }
2915  } else {
2916  return -1;
2917  }
2918  break;
2919  default:
2920  return -1;
2921  }
2922  return l;
2923 }
2924 
2925 static int opffree(RzAsm *a, ut8 *data, const Opcode *op) {
2926  int l = 0;
2927  switch (op->operands_count) {
2928  case 1:
2929  if (op->operands[0].type & OT_FPUREG & ~OT_REGALL) {
2930  data[l++] = 0xdd;
2931  data[l++] = 0xc0 | op->operands[0].reg;
2932  } else {
2933  return -1;
2934  }
2935  break;
2936  default:
2937  return -1;
2938  }
2939  return l;
2940 }
2941 
2942 static int opfrstor(RzAsm *a, ut8 *data, const Opcode *op) {
2943  int l = 0;
2944  switch (op->operands_count) {
2945  case 1:
2946  if (op->operands[0].type & OT_MEMORY) {
2947  data[l++] = 0xdd;
2948  data[l++] = 0x20 | op->operands[0].regs[0];
2949  } else {
2950  return -1;
2951  }
2952  break;
2953  default:
2954  return -1;
2955  }
2956  return l;
2957 }
2958 
2959 static int opfxch(RzAsm *a, ut8 *data, const Opcode *op) {
2960  int l = 0;
2961  switch (op->operands_count) {
2962  case 0:
2963  data[l++] = 0xd9;
2964  data[l++] = 0xc9;
2965  break;
2966  case 1:
2967  if (op->operands[0].type & OT_FPUREG & ~OT_REGALL) {
2968  data[l++] = 0xd9;
2969  data[l++] = 0xc8 | op->operands[0].reg;
2970  } else {
2971  return -1;
2972  }
2973  break;
2974  default:
2975  return -1;
2976  }
2977  return l;
2978 }
2979 
2980 static int opfucom(RzAsm *a, ut8 *data, const Opcode *op) {
2981  int l = 0;
2982  switch (op->operands_count) {
2983  case 1:
2984  if (op->operands[0].type & OT_FPUREG & ~OT_REGALL) {
2985  data[l++] = 0xdd;
2986  data[l++] = 0xe0 | op->operands[0].reg;
2987  } else {
2988  return -1;
2989  }
2990  break;
2991  case 0:
2992  data[l++] = 0xdd;
2993  data[l++] = 0xe1;
2994  break;
2995  default:
2996  return -1;
2997  }
2998  return l;
2999 }
3000 
3001 static int opfucomp(RzAsm *a, ut8 *data, const Opcode *op) {
3002  int l = 0;
3003  switch (op->operands_count) {
3004  case 1:
3005  if (op->operands[0].type & OT_FPUREG & ~OT_REGALL) {
3006  data[l++] = 0xdd;
3007  data[l++] = 0xe8 | op->operands[0].reg;
3008  } else {
3009  return -1;
3010  }
3011  break;
3012  case 0:
3013  data[l++] = 0xdd;
3014  data[l++] = 0xe9;
3015  break;
3016  default:
3017  return -1;
3018  }
3019  return l;
3020 }
3021 
3022 static int opfaddp(RzAsm *a, ut8 *data, const Opcode *op) {
3023  int l = 0;
3024  switch (op->operands_count) {
3025  case 2:
3026  if (op->operands[0].type & OT_FPUREG & ~OT_REGALL &&
3027  op->operands[1].type & OT_FPUREG & ~OT_REGALL && op->operands[1].reg == 0) {
3028  data[l++] = 0xde;
3029  data[l++] = 0xc0 | op->operands[0].reg;
3030  } else {
3031  return -1;
3032  }
3033  break;
3034  case 0:
3035  data[l++] = 0xde;
3036  data[l++] = 0xc1;
3037  break;
3038  default:
3039  return -1;
3040  }
3041  return l;
3042 }
3043 
3044 static int opfiadd(RzAsm *a, ut8 *data, const Opcode *op) {
3045  int l = 0;
3046  switch (op->operands_count) {
3047  case 1:
3048  if (op->operands[0].type & OT_MEMORY) {
3049  if (op->operands[0].type & OT_WORD) {
3050  data[l++] = 0xde;
3051  data[l++] = 0x00 | op->operands[0].regs[0];
3052  } else if (op->operands[0].type & OT_DWORD) {
3053  data[l++] = 0xda;
3054  data[l++] = 0x00 | op->operands[0].regs[0];
3055  } else {
3056  return -1;
3057  }
3058  } else {
3059  return -1;
3060  }
3061  break;
3062  default:
3063  return -1;
3064  }
3065  return l;
3066 }
3067 
3068 static int opfadd(RzAsm *a, ut8 *data, const Opcode *op) {
3069  int l = 0;
3070  switch (op->operands_count) {
3071  case 1:
3072  if (op->operands[0].type & OT_MEMORY) {
3073  if (op->operands[0].type & OT_QWORD) {
3074  data[l++] = 0xdc;
3075  data[l++] = 0x00 | op->operands[0].regs[0];
3076  } else if (op->operands[0].type & OT_DWORD) {
3077  data[l++] = 0xd8;
3078  data[l++] = 0x00 | op->operands[0].regs[0];
3079  } else {
3080  return -1;
3081  }
3082  } else {
3083  return -1;
3084  }
3085  break;
3086  case 2:
3087  if (op->operands[0].type & OT_FPUREG & ~OT_REGALL && op->operands[0].reg == 0 &&
3088  op->operands[1].type & OT_FPUREG & ~OT_REGALL) {
3089  data[l++] = 0xd8;
3090  data[l++] = 0xc0 | op->operands[1].reg;
3091  } else if (op->operands[0].type & OT_FPUREG & ~OT_REGALL &&
3092  op->operands[1].type & OT_FPUREG & ~OT_REGALL && op->operands[1].reg == 0) {
3093  data[l++] = 0xdc;
3094  data[l++] = 0xc0 | op->operands[0].reg;
3095  } else {
3096  return -1;
3097  }
3098  break;
3099  default:
3100  return -1;
3101  }
3102  return l;
3103 }
3104 
3105 static int opficom(RzAsm *a, ut8 *data, const Opcode *op) {
3106  int l = 0;
3107  switch (op->operands_count) {
3108  case 1:
3109  if (op->operands[0].type & OT_MEMORY) {
3110  if (op->operands[0].type & OT_WORD) {
3111  data[l++] = 0xde;
3112  data[l++] = 0x10 | op->operands[0].regs[0];
3113  } else if (op->operands[0].type & OT_DWORD) {
3114  data[l++] = 0xda;
3115  data[l++] = 0x10 | op->operands[0].regs[0];
3116  } else {
3117  return -1;
3118  }
3119  } else {
3120  return -1;
3121  }
3122  break;
3123  default:
3124  return -1;
3125  }
3126  return l;
3127 }
3128 
3129 static int opficomp(RzAsm *a, ut8 *data, const Opcode *op) {
3130  int l = 0;
3131  switch (op->operands_count) {
3132  case 1:
3133  if (op->operands[0].type & OT_MEMORY) {
3134  if (op->operands[0].type & OT_WORD) {
3135  data[l++] = 0xde;
3136  data[l++] = 0x18 | op->operands[0].regs[0];
3137  } else if (op->operands[0].type & OT_DWORD) {
3138  data[l++] = 0xda;
3139  data[l++] = 0x18 | op->operands[0].regs[0];
3140  } else {
3141  return -1;
3142  }
3143  } else {
3144  return -1;
3145  }
3146  break;
3147  default:
3148  return -1;
3149  }
3150  return l;
3151 }
3152 
3153 static int opfild(RzAsm *a, ut8 *data, const Opcode *op) {
3154  int l = 0;
3155  switch (op->operands_count) {
3156  case 1:
3157  if (op->operands[0].type & OT_MEMORY) {
3158  if (op->operands[0].type & OT_WORD) {
3159  data[l++] = 0xdf;
3160  data[l++] = 0x00 | op->operands[0].regs[0];
3161  } else if (op->operands[0].type & OT_DWORD) {
3162  data[l++] = 0xdb;
3163  data[l++] = 0x00 | op->operands[0].regs[0];
3164  } else if (op->operands[0].type & OT_QWORD) {
3165  data[l++] = 0xdf;
3166  data[l++] = 0x28 | op->operands[0].regs[0];
3167  } else {
3168  return -1;
3169  }
3170  } else {
3171  return -1;
3172  }
3173  break;
3174  default:
3175  return -1;
3176  }
3177  return l;
3178 }
3179 
3180 static int opfldcw(RzAsm *a, ut8 *data, const Opcode *op) {
3181  int l = 0;
3182  switch (op->operands_count) {
3183  case 1:
3184  if (op->operands[0].type & OT_MEMORY &&
3185  op->operands[0].type & OT_WORD) {
3186  data[l++] = 0xd9;
3187  data[l++] = 0x28 | op->operands[0].regs[0];
3188  } else {
3189  return -1;
3190  }
3191  break;
3192  default:
3193  return -1;
3194  }
3195  return l;
3196 }
3197 
3198 static int opfldenv(RzAsm *a, ut8 *data, const Opcode *op) {
3199  int l = 0;
3200  switch (op->operands_count) {
3201  case 1:
3202  if (op->operands[0].type & OT_MEMORY) {
3203  data[l++] = 0xd9;
3204  data[l++] = 0x20 | op->operands[0].regs[0];
3205  } else {
3206  return -1;
3207  }
3208  break;
3209  default:
3210  return -1;
3211  }
3212  return l;
3213 }
3214 
3215 static int opfbld(RzAsm *a, ut8 *data, const Opcode *op) {
3216  int l = 0;
3217  switch (op->operands_count) {
3218  case 1:
3219  if (op->operands[0].type & OT_MEMORY &&
3220  op->operands[0].type & OT_TBYTE) {
3221  data[l++] = 0xdf;
3222  data[l++] = 0x20 | op->operands[0].regs[0];
3223  } else {
3224  return -1;
3225  }
3226  break;
3227  default:
3228  return -1;
3229  }
3230  return l;
3231 }
3232 
3233 static int opfbstp(RzAsm *a, ut8 *data, const Opcode *op) {
3234  int l = 0;
3235  switch (op->operands_count) {
3236  case 1:
3237  if (op->operands[0].type & OT_MEMORY &&
3238  op->operands[0].type & OT_TBYTE) {
3239  data[l++] = 0xdf;
3240  data[l++] = 0x30 | op->operands[0].regs[0];
3241  } else {
3242  return -1;
3243  }
3244  break;
3245  default:
3246  return -1;
3247  }
3248  return l;
3249 }
3250 
3251 static int opfxrstor(RzAsm *a, ut8 *data, const Opcode *op) {
3252  int l = 0;
3253  switch (op->operands_count) {
3254  case 1:
3255  if (op->operands[0].type & OT_MEMORY) {
3256  data[l++] = 0x0f;
3257  data[l++] = 0xae;
3258  data[l++] = 0x08 | op->operands[0].regs[0];
3259  } else {
3260  return -1;
3261  }
3262  break;
3263  default:
3264  return -1;
3265  }
3266  return l;
3267 }
3268 
3269 static int opfxsave(RzAsm *a, ut8 *data, const Opcode *op) {
3270  int l = 0;
3271  switch (op->operands_count) {
3272  case 1:
3273  if (op->operands[0].type & OT_MEMORY) {
3274  data[l++] = 0x0f;
3275  data[l++] = 0xae;
3276  data[l++] = 0x00 | op->operands[0].regs[0];
3277  } else {
3278  return -1;
3279  }
3280  break;
3281  default:
3282  return -1;
3283  }
3284  return l;
3285 }
3286 
3287 static int opfist(RzAsm *a, ut8 *data, const Opcode *op) {
3288  int l = 0;
3289  switch (op->operands_count) {
3290  case 1:
3291  if (op->operands[0].type & OT_MEMORY) {
3292  if (op->operands[0].type & OT_WORD) {
3293  data[l++] = 0xdf;
3294  data[l++] = 0x10 | op->operands[0].regs[0];
3295  } else if (op->operands[0].type & OT_DWORD) {
3296  data[l++] = 0xdb;
3297  data[l++] = 0x10 | op->operands[0].regs[0];
3298  } else {
3299  return -1;
3300  }
3301  } else {
3302  return -1;
3303  }
3304  break;
3305  default:
3306  return -1;
3307  }
3308  return l;
3309 }
3310 
3311 static int opfistp(RzAsm *a, ut8 *data, const Opcode *op) {
3312  int l = 0;
3313  switch (op->operands_count) {
3314  case 1:
3315  if (op->operands[0].type & OT_MEMORY) {
3316  if (op->operands[0].type & OT_WORD) {
3317  data[l++] = 0xdf;
3318  data[l++] = 0x18 | op->operands[0].regs[0];
3319  } else if (op->operands[0].type & OT_DWORD) {
3320  data[l++] = 0xdb;
3321  data[l++] = 0x18 | op->operands[0].regs[0];
3322  } else if (op->operands[0].type & OT_QWORD) {
3323  data[l++] = 0xdf;
3324  data[l++] = 0x38 | op->operands[0].regs[0];
3325  } else {
3326  return -1;
3327  }
3328  } else {
3329  return -1;
3330  }
3331  break;
3332  default:
3333  return -1;
3334  }
3335  return l;
3336 }
3337 
3338 static int opfisttp(RzAsm *a, ut8 *data, const Opcode *op) {
3339  int l = 0;
3340  switch (op->operands_count) {
3341  case 1:
3342  if (op->operands[0].type & OT_MEMORY) {
3343  if (op->operands[0].type & OT_WORD) {
3344  data[l++] = 0xdf;
3345  data[l++] = 0x08 | op->operands[0].regs[0];
3346  } else if (op->operands[0].type & OT_DWORD) {
3347  data[l++] = 0xdb;
3348  data[l++] = 0x08 | op->operands[0].regs[0];
3349  } else if (op->operands[0].type & OT_QWORD) {
3350  data[l++] = 0xdd;
3351  data[l++] = 0x08 | op->operands[0].regs[0];
3352  } else {
3353  return -1;
3354  }
3355  } else {
3356  return -1;
3357  }
3358  break;
3359  default:
3360  return -1;
3361  }
3362  return l;
3363 }
3364 
3365 static int opfstenv(RzAsm *a, ut8 *data, const Opcode *op) {
3366  int l = 0;
3367  switch (op->operands_count) {
3368  case 1:
3369  if (op->operands[0].type & OT_MEMORY) {
3370  data[l++] = 0x9b;
3371  data[l++] = 0xd9;
3372  data[l++] = 0x30 | op->operands[0].regs[0];
3373  } else {
3374  return -1;
3375  }
3376  break;
3377  default:
3378  return -1;
3379  }
3380  return l;
3381 }
3382 
3383 static int opfnstenv(RzAsm *a, ut8 *data, const Opcode *op) {
3384  int l = 0;
3385  switch (op->operands_count) {
3386  case 1:
3387  if (op->operands[0].type & OT_MEMORY) {
3388  data[l++] = 0xd9;
3389  data[l++] = 0x30 | op->operands[0].regs[0];
3390  } else {
3391  return -1;
3392  }
3393  break;
3394  default:
3395  return -1;
3396  }
3397  return l;
3398 }
3399 
3400 static int opfdiv(RzAsm *a, ut8 *data, const Opcode *op) {
3401  int l = 0;
3402  switch (op->operands_count) {
3403  case 1:
3404  if (op->operands[0].type & OT_MEMORY) {
3405  if (op->operands[0].type & OT_DWORD) {
3406  data[l++] = 0xd8;
3407  data[l++] = 0x30 | op->operands[0].regs[0];
3408  } else if (op->operands[0].type & OT_QWORD) {
3409  data[l++] = 0xdc;
3410  data[l++] = 0x30 | op->operands[0].regs[0];
3411  } else {
3412  return -1;
3413  }
3414  } else {
3415  return -1;
3416  }
3417  break;
3418  case 2:
3419  if (op->operands[0].type & OT_FPUREG & ~OT_REGALL && op->operands[0].reg == 0 &&
3420  op->operands[1].type & OT_FPUREG & ~OT_REGALL) {
3421  data[l++] = 0xd8;
3422  data[l++] = 0xf0 | op->operands[1].reg;
3423  } else if (op->operands[0].type & OT_FPUREG & ~OT_REGALL &&
3424  op->operands[1].type & OT_FPUREG & ~OT_REGALL && op->operands[1].reg == 0) {
3425  data[l++] = 0xdc;
3426  data[l++] = 0xf8 | op->operands[0].reg;
3427  } else {
3428  return -1;
3429  }
3430  break;
3431  default:
3432  return -1;
3433  }
3434  return l;
3435 }
3436 
3437 static int opfdivp(RzAsm *a, ut8 *data, const Opcode *op) {
3438  int l = 0;
3439  switch (op->operands_count) {
3440  case 0:
3441  data[l++] = 0xde;
3442  data[l++] = 0xf9;
3443  break;
3444  case 2:
3445  if (op->operands[0].type & OT_FPUREG & ~OT_REGALL &&
3446  op->operands[1].type & OT_FPUREG & ~OT_REGALL && op->operands[1].reg == 0) {
3447  data[l++] = 0xde;
3448  data[l++] = 0xf8 | op->operands[0].reg;
3449  } else {
3450  return -1;
3451  }
3452  break;
3453  default:
3454  return -1;
3455  }
3456  return l;
3457 }
3458 
3459 static int opfidiv(RzAsm *a, ut8 *data, const Opcode *op) {
3460  int l = 0;
3461  switch (op->operands_count) {
3462  case 1:
3463  if (op->operands[0].type & OT_MEMORY) {
3464  if (op->operands[0].type & OT_DWORD) {
3465  data[l++] = 0xda;
3466  data[l++] = 0x30 | op->operands[0].regs[0];
3467  } else if (op->operands[0].type & OT_WORD) {
3468  data[l++] = 0xde;
3469  data[l++] = 0x30 | op->operands[0].regs[0];
3470  } else {
3471  return -1;
3472  }
3473  } else {
3474  return -1;
3475  }
3476  break;
3477  default:
3478  return -1;
3479  }
3480  return l;
3481 }
3482 
3483 static int opfdivr(RzAsm *a, ut8 *data, const Opcode *op) {
3484  int l = 0;
3485  switch (op->operands_count) {
3486  case 1:
3487  if (op->operands[0].type & OT_MEMORY) {
3488  if (op->operands[0].type & OT_DWORD) {
3489  data[l++] = 0xd8;
3490  data[l++] = 0x38 | op->operands[0].regs[0];
3491  } else if (op->operands[0].type & OT_QWORD) {
3492  data[l++] = 0xdc;
3493  data[l++] = 0x38 | op->operands[0].regs[0];
3494  } else {
3495  return -1;
3496  }
3497  } else {
3498  return -1;
3499  }
3500  break;
3501  case 2:
3502  if (op->operands[0].type & OT_FPUREG & ~OT_REGALL && op->operands[0].reg == 0 &&
3503  op->operands[1].type & OT_FPUREG & ~OT_REGALL) {
3504  data[l++] = 0xd8;
3505  data[l++] = 0xf8 | op->operands[1].reg;
3506  } else if (op->operands[0].type & OT_FPUREG & ~OT_REGALL &&
3507  op->operands[1].type & OT_FPUREG & ~OT_REGALL && op->operands[1].reg == 0) {
3508  data[l++] = 0xdc;
3509  data[l++] = 0xf0 | op->operands[0].reg;
3510  } else {
3511  return -1;
3512  }
3513  break;
3514  default:
3515  return -1;
3516  }
3517  return l;
3518 }
3519 
3520 static int opfdivrp(RzAsm *a, ut8 *data, const Opcode *op) {
3521  int l = 0;
3522  switch (op->operands_count) {
3523  case 0:
3524  data[l++] = 0xde;
3525  data[l++] = 0xf1;
3526  break;
3527  case 2:
3528  if (op->operands[0].type & OT_FPUREG & ~OT_REGALL &&
3529  op->operands[1].type & OT_FPUREG & ~OT_REGALL && op->operands[1].reg == 0) {
3530  data[l++] = 0xde;
3531  data[l++] = 0xf0 | op->operands[0].reg;
3532  } else {
3533  return -1;
3534  }
3535  break;
3536  default:
3537  return -1;
3538  }
3539  return l;
3540 }
3541 
3542 static int opfidivr(RzAsm *a, ut8 *data, const Opcode *op) {
3543  int l = 0;
3544  switch (op->operands_count) {
3545  case 1:
3546  if (op->operands[0].type & OT_MEMORY) {
3547  if (op->operands[0].type & OT_DWORD) {
3548  data[l++] = 0xda;
3549  data[l++] = 0x38 | op->operands[0].regs[0];
3550  } else if (op->operands[0].type & OT_WORD) {
3551  data[l++] = 0xde;
3552  data[l++] = 0x38 | op->operands[0].regs[0];
3553  } else {
3554  return -1;
3555  }
3556  } else {
3557  return -1;
3558  }
3559  break;
3560  default:
3561  return -1;
3562  }
3563  return l;
3564 }
3565 
3566 static int opfmul(RzAsm *a, ut8 *data, const Opcode *op) {
3567  int l = 0;
3568  switch (op->operands_count) {
3569  case 1:
3570  if (op->operands[0].type & OT_MEMORY) {
3571  if (op->operands[0].type & OT_DWORD) {
3572  data[l++] = 0xd8;
3573  data[l++] = 0x08 | op->operands[0].regs[0];
3574  } else if (op->operands[0].type & OT_QWORD) {
3575  data[l++] = 0xdc;
3576  data[l++] = 0x08 | op->operands[0].regs[0];
3577  } else {
3578  return -1;
3579  }
3580  } else {
3581  return -1;
3582  }
3583  break;
3584  case 2:
3585  if (op->operands[0].type & OT_FPUREG & ~OT_REGALL && op->operands[0].reg == 0 &&
3586  op->operands[1].type & OT_FPUREG & ~OT_REGALL) {
3587  data[l++] = 0xd8;
3588  data[l++] = 0xc8 | op->operands[1].reg;
3589  } else if (op->operands[0].type & OT_FPUREG & ~OT_REGALL &&
3590  op->operands[1].type & OT_FPUREG & ~OT_REGALL && op->operands[1].reg == 0) {
3591  data[l++] = 0xdc;
3592  data[l++] = 0xc8 | op->operands[0].reg;
3593  } else {
3594  return -1;
3595  }
3596  break;
3597  default:
3598  return -1;
3599  }
3600  return l;
3601 }
3602 
3603 static int opfmulp(RzAsm *a, ut8 *data, const Opcode *op) {
3604  int l = 0;
3605  switch (op->operands_count) {
3606  case 0:
3607  data[l++] = 0xde;
3608  data[l++] = 0xc9;
3609  break;
3610  case 2:
3611  if (op->operands[0].type & OT_FPUREG & ~OT_REGALL &&
3612  op->operands[1].type & OT_FPUREG & ~OT_REGALL && op->operands[1].reg == 0) {
3613  data[l++] = 0xde;
3614  data[l++] = 0xc8 | op->operands[0].reg;
3615  } else {
3616  return -1;
3617  }
3618  break;
3619  default:
3620  return -1;
3621  }
3622  return l;
3623 }
3624 
3625 static int opfimul(RzAsm *a, ut8 *data, const Opcode *op) {
3626  int l = 0;
3627  switch (op->operands_count) {
3628  case 1:
3629  if (op->operands[0].type & OT_MEMORY) {
3630  if (op->operands[0].type & OT_DWORD) {
3631  data[l++] = 0xda;
3632  data[l++] = 0x08 | op->operands[0].regs[0];
3633  } else if (op->operands[0].type & OT_WORD) {
3634  data[l++] = 0xde;
3635  data[l++] = 0x08 | op->operands[0].regs[0];
3636  } else {
3637  return -1;
3638  }
3639  } else {
3640  return -1;
3641  }
3642  break;
3643  default:
3644  return -1;
3645  }
3646  return l;
3647 }
3648 
3649 static int opfsub(RzAsm *a, ut8 *data, const Opcode *op) {
3650  int l = 0;
3651  switch (op->operands_count) {
3652  case 1:
3653  if (op->operands[0].type & OT_MEMORY) {
3654  if (op->operands[0].type & OT_DWORD) {
3655  data[l++] = 0xd8;
3656  data[l++] = 0x20 | op->operands[0].regs[0];
3657  } else if (op->operands[0].type & OT_QWORD) {
3658  data[l++] = 0xdc;
3659  data[l++] = 0x20 | op->operands[0].regs[0];
3660  } else {
3661  return -1;
3662  }
3663  } else {
3664  return -1;
3665  }
3666  break;
3667  case 2:
3668  if (op->operands[0].type & OT_FPUREG & ~OT_REGALL && op->operands[0].reg == 0 &&
3669  op->operands[1].type & OT_FPUREG & ~OT_REGALL) {
3670  data[l++] = 0xd8;
3671  data[l++] = 0xe0 | op->operands[1].reg;
3672  } else if (op->operands[0].type & OT_FPUREG & ~OT_REGALL &&
3673  op->operands[1].type & OT_FPUREG & ~OT_REGALL && op->operands[1].reg == 0) {
3674  data[l++] = 0xdc;
3675  data[l++] = 0xe8 | op->operands[0].reg;
3676  } else {
3677  return -1;
3678  }
3679  break;
3680  default:
3681  return -1;
3682  }
3683  return l;
3684 }
3685 
3686 static int opfsubp(RzAsm *a, ut8 *data, const Opcode *op) {
3687  int l = 0;
3688  switch (op->operands_count) {
3689  case 0:
3690  data[l++] = 0xde;
3691  data[l++] = 0xe9;
3692  break;
3693  case 2:
3694  if (op->operands[0].type & OT_FPUREG & ~OT_REGALL &&
3695  op->operands[1].type & OT_FPUREG & ~OT_REGALL && op->operands[1].reg == 0) {
3696  data[l++] = 0xde;
3697  data[l++] = 0xe8 | op->operands[0].reg;
3698  } else {
3699  return -1;
3700  }
3701  break;
3702  default:
3703  return -1;
3704  }
3705  return l;
3706 }
3707 
3708 static int opfisub(RzAsm *a, ut8 *data, const Opcode *op) {
3709  int l = 0;
3710  switch (op->operands_count) {
3711  case 1:
3712  if (op->operands[0].type & OT_MEMORY) {
3713  if (op->operands[0].type & OT_DWORD) {
3714  data[l++] = 0xda;
3715  data[l++] = 0x20 | op->operands[0].regs[0];
3716  } else if (op->operands[0].type & OT_WORD) {
3717  data[l++] = 0xde;
3718  data[l++] = 0x20 | op->operands[0].regs[0];
3719  } else {
3720  return -1;
3721  }
3722  } else {
3723  return -1;
3724  }
3725  break;
3726  default:
3727  return -1;
3728  }
3729  return l;
3730 }
3731 
3732 static int opfsubr(RzAsm *a, ut8 *data, const Opcode *op) {
3733  int l = 0;
3734  switch (op->operands_count) {
3735  case 1:
3736  if (op->operands[0].type & OT_MEMORY) {
3737  if (op->operands[0].type & OT_DWORD) {
3738  data[l++] = 0xd8;
3739  data[l++] = 0x28 | op->operands[0].regs[0];
3740  } else if (op->operands[0].type & OT_QWORD) {
3741  data[l++] = 0xdc;
3742  data[l++] = 0x28 | op->operands[0].regs[0];
3743  } else {
3744  return -1;
3745  }
3746  } else {
3747  return -1;
3748  }
3749  break;
3750  case 2:
3751  if (op->operands[0].type & OT_FPUREG & ~OT_REGALL && op->operands[0].reg == 0 &&
3752  op->operands[1].type & OT_FPUREG & ~OT_REGALL) {
3753  data[l++] = 0xd8;
3754  data[l++] = 0xe8 | op->operands[1].reg;
3755  } else if (op->operands[0].type & OT_FPUREG & ~OT_REGALL &&
3756  op->operands[1].type & OT_FPUREG & ~OT_REGALL && op->operands[1].reg == 0) {
3757  data[l++] = 0xdc;
3758  data[l++] = 0xe0 | op->operands[0].reg;
3759  } else {
3760  return -1;
3761  }
3762  break;
3763  default:
3764  return -1;
3765  }
3766  return l;
3767 }
3768 
3769 static int opfsubrp(RzAsm *a, ut8 *data, const Opcode *op) {
3770  int l = 0;
3771  switch (op->operands_count) {
3772  case 0:
3773  data[l++] = 0xde;
3774  data[l++] = 0xe1;
3775  break;
3776  case 2:
3777  if (op->operands[0].type & OT_FPUREG & ~OT_REGALL &&
3778  op->operands[1].type & OT_FPUREG & ~OT_REGALL && op->operands[1].reg == 0) {
3779  data[l++] = 0xde;
3780  data[l++] = 0xe0 | op->operands[0].reg;
3781  } else {
3782  return -1;
3783  }
3784  break;
3785  default:
3786  return -1;
3787  }
3788  return l;
3789 }
3790 
3791 static int opfisubr(RzAsm *a, ut8 *data, const Opcode *op) {
3792  int l = 0;
3793  switch (op->operands_count) {
3794  case 1:
3795  if (op->operands[0].type & OT_MEMORY) {
3796  if (op->operands[0].type & OT_DWORD) {
3797  data[l++] = 0xda;
3798  data[l++] = 0x28 | op->operands[0].regs[0];
3799  } else if (op->operands[0].type & OT_WORD) {
3800  data[l++] = 0xde;
3801  data[l++] = 0x28 | op->operands[0].regs[0];
3802  } else {
3803  return -1;
3804  }
3805  } else {
3806  return -1;
3807  }
3808  break;
3809  default:
3810  return -1;
3811  }
3812  return l;
3813 }
3814 
3815 static int opfnstcw(RzAsm *a, ut8 *data, const Opcode *op) {
3816  int l = 0;
3817  switch (op->operands_count) {
3818  case 1:
3819  if (op->operands[0].type & OT_MEMORY &&
3820  op->operands[0].type & OT_WORD) {
3821  data[l++] = 0xd9;
3822  data[l++] = 0x38 | op->operands[0].regs[0];
3823  } else {
3824  return -1;
3825  }
3826  break;
3827  default:
3828  return -1;
3829  }
3830  return l;
3831 }
3832 
3833 static int opfstcw(RzAsm *a, ut8 *data, const Opcode *op) {
3834  int l = 0;
3835  switch (op->operands_count) {
3836  case 1:
3837  if (op->operands[0].type & OT_MEMORY &&
3838  op->operands[0].type & OT_WORD) {
3839  data[l++] = 0x9b;
3840  data[l++] = 0xd9;
3841  data[l++] = 0x38 | op->operands[0].regs[0];
3842  } else {
3843  return -1;
3844  }
3845  break;
3846  default:
3847  return -1;
3848  }
3849  return l;
3850 }
3851 
3852 static int opfnstsw(RzAsm *a, ut8 *data, const Opcode *op) {
3853  int l = 0;
3854  switch (op->operands_count) {
3855  case 1:
3856  if (op->operands[0].type & OT_MEMORY &&
3857  op->operands[0].type & OT_WORD) {
3858  data[l++] = 0xdd;
3859  data[l++] = 0x38 | op->operands[0].regs[0];
3860  } else if (op->operands[0].type & OT_GPREG &&
3861  op->operands[0].type & OT_WORD &&
3862  op->operands[0].reg == X86R_AX) {
3863  data[l++] = 0xdf;
3864  data[l++] = 0xe0;
3865  } else {
3866  return -1;
3867  }
3868  break;
3869  default:
3870  return -1;
3871  }
3872  return l;
3873 }
3874 
3875 static int opfstsw(RzAsm *a, ut8 *data, const Opcode *op) {
3876  int l = 0;
3877  switch (op->operands_count) {
3878  case 1:
3879  if (op->operands[0].type & OT_MEMORY &&
3880  op->operands[0].type & OT_WORD) {
3881  data[l++] = 0x9b;
3882  data[l++] = 0xdd;
3883  data[l++] = 0x38 | op->operands[0].regs[0];
3884  } else if (op->operands[0].type & OT_GPREG &&
3885  op->operands[0].type & OT_WORD &&
3886  op->operands[0].reg == X86R_AX) {
3887  data[l++] = 0x9b;
3888  data[l++] = 0xdf;
3889  data[l++] = 0xe0;
3890  } else {
3891  return -1;
3892  }
3893  break;
3894  default:
3895  return -1;
3896  }
3897  return l;
3898 }
3899 
3900 static int opfnsave(RzAsm *a, ut8 *data, const Opcode *op) {
3901  int l = 0;
3902  switch (op->operands_count) {
3903  case 1:
3904  if (op->operands[0].type & OT_MEMORY &&
3905  op->operands[0].type & OT_DWORD) {
3906  data[l++] = 0xdd;
3907  data[l++] = 0x30 | op->operands[0].regs[0];
3908  } else {
3909  return -1;
3910  }
3911  break;
3912  default:
3913  return -1;
3914  }
3915  return l;
3916 }
3917 
3918 static int opfsave(RzAsm *a, ut8 *data, const Opcode *op) {
3919  int l = 0;
3920  switch (op->operands_count) {
3921  case 1:
3922  if (op->operands[0].type & OT_MEMORY &&
3923  op->operands[0].type & OT_DWORD) {
3924  data[l++] = 0x9b;
3925  data[l++] = 0xdd;
3926  data[l++] = 0x30 | op->operands[0].regs[0];
3927  } else {
3928  return -1;
3929  }
3930  break;
3931  default:
3932  return -1;
3933  }
3934  return l;
3935 }
3936 
3937 static int oplldt(RzAsm *a, ut8 *data, const Opcode *op) {
3938  int l = 0;
3939  switch (op->operands_count) {
3940  case 1:
3941  if (op->operands[0].type & OT_WORD) {
3942  data[l++] = 0x0f;
3943  data[l++] = 0x00;
3944  if (op->operands[0].type & OT_MEMORY) {
3945  data[l++] = 0x10 | op->operands[0].regs[0];
3946  } else {
3947  data[l++] = 0xd0 | op->operands[0].reg;
3948  }
3949  } else {
3950  return -1;
3951  }
3952  break;
3953  default:
3954  return -1;
3955  }
3956  return l;
3957 }
3958 
3959 static int oplmsw(RzAsm *a, ut8 *data, const Opcode *op) {
3960  int l = 0;
3961  switch (op->operands_count) {
3962  case 1:
3963  if (op->operands[0].type & OT_WORD) {
3964  data[l++] = 0x0f;
3965  data[l++] = 0x01;
3966  if (op->operands[0].type & OT_MEMORY) {
3967  data[l++] = 0x30 | op->operands[0].regs[0];
3968  } else {
3969  data[l++] = 0xf0 | op->operands[0].reg;
3970  }
3971  } else {
3972  return -1;
3973  }
3974  break;
3975  default:
3976  return -1;
3977  }
3978  return l;
3979 }
3980 
3981 static int oplgdt(RzAsm *a, ut8 *data, const Opcode *op) {
3982  int l = 0;
3983  switch (op->operands_count) {
3984  case 1:
3985  if (op->operands[0].type & OT_MEMORY) {
3986  data[l++] = 0x0f;
3987  data[l++] = 0x01;
3988  data[l++] = 0x10 | op->operands[0].regs[0];
3989  } else {
3990  return -1;
3991  }
3992  break;
3993  default:
3994  return -1;
3995  }
3996  return l;
3997 }
3998 
3999 static int oplidt(RzAsm *a, ut8 *data, const Opcode *op) {
4000  int l = 0;
4001  switch (op->operands_count) {
4002  case 1:
4003  if (op->operands[0].type & OT_MEMORY) {
4004  data[l++] = 0x0f;
4005  data[l++] = 0x01;
4006  data[l++] = 0x18 | op->operands[0].regs[0];
4007  } else {
4008  return -1;
4009  }
4010  break;
4011  default:
4012  return -1;
4013  }
4014  return l;
4015 }
4016 
4017 static int opsgdt(RzAsm *a, ut8 *data, const Opcode *op) {
4018  int l = 0;
4019  switch (op->operands_count) {
4020  case 1:
4021  if (op->operands[0].type & OT_MEMORY) {
4022  data[l++] = 0x0f;
4023  data[l++] = 0x01;
4024  data[l++] = 0x00 | op->operands[0].regs[0];
4025  } else {
4026  return -1;
4027  }
4028  break;
4029  default:
4030  return -1;
4031  }
4032  return l;
4033 }
4034 
4035 static int opstmxcsr(RzAsm *a, ut8 *data, const Opcode *op) {
4036  int l = 0;
4037  switch (op->operands_count) {
4038  case 1:
4039  if (op->operands[0].type & OT_MEMORY &&
4040  op->operands[0].type & OT_DWORD) {
4041  data[l++] = 0x0f;
4042  data[l++] = 0xae;
4043  data[l++] = 0x18 | op->operands[0].regs[0];
4044  } else {
4045  return -1;
4046  }
4047  break;
4048  default:
4049  return -1;
4050  }
4051  return l;
4052 }
4053 
4054 static int opstr(RzAsm *a, ut8 *data, const Opcode *op) {
4055  int l = 0;
4056  switch (op->operands_count) {
4057  case 1:
4058  if (op->operands[0].type & OT_MEMORY &&
4059  op->operands[0].type & OT_WORD) {
4060  data[l++] = 0x0f;
4061  data[l++] = 0x00;
4062  data[l++] = 0x08 | op->operands[0].regs[0];
4063  } else if (op->operands[0].type & OT_GPREG &&
4064  op->operands[0].type & OT_DWORD) {
4065  data[l++] = 0x0f;
4066  data[l++] = 0x00;
4067  data[l++] = 0xc8 | op->operands[0].reg;
4068  } else {
4069  return -1;
4070  }
4071  break;
4072  default:
4073  return -1;
4074  }
4075  return l;
4076 }
4077 
4078 static int opsidt(RzAsm *a, ut8 *data, const Opcode *op) {
4079  int l = 0;
4080  switch (op->operands_count) {
4081  case 1:
4082  if (op->operands[0].type & OT_MEMORY) {
4083  data[l++] = 0x0f;
4084  data[l++] = 0x01;
4085  data[l++] = 0x08 | op->operands[0].regs[0];
4086  } else {
4087  return -1;
4088  }
4089  break;
4090  default:
4091  return -1;
4092  }
4093  return l;
4094 }
4095 
4096 static int opsldt(RzAsm *a, ut8 *data, const Opcode *op) {
4097  int l = 0;
4098  switch (op->operands_count) {
4099  case 1:
4100  if (a->bits == 64) {
4101  data[l++] = 0x48;
4102  }
4103  data[l++] = 0x0f;
4104  data[l++] = 0x00;
4105  if (op->operands[0].type & OT_MEMORY) {
4106  data[l++] = 0x00 | op->operands[0].regs[0];
4107  } else {
4108  data[l++] = 0xc0 | op->operands[0].reg;
4109  }
4110  break;
4111  default:
4112  return -1;
4113  }
4114  return l;
4115 }
4116 
4117 static int opsmsw(RzAsm *a, ut8 *data, const Opcode *op) {
4118  int l = 0;
4119  switch (op->operands_count) {
4120  case 1:
4121  if (a->bits == 64) {
4122  data[l++] = 0x48;
4123  }
4124  data[l++] = 0x0f;
4125  data[l++] = 0x01;
4126  if (op->operands[0].type & OT_MEMORY) {
4127  data[l++] = 0x20 | op->operands[0].regs[0];
4128  } else {
4129  data[l++] = 0xe0 | op->operands[0].reg;
4130  }
4131  break;
4132  default:
4133  return -1;
4134  }
4135  return l;
4136 }
4137 
4138 static int opverr(RzAsm *a, ut8 *data, const Opcode *op) {
4139  int l = 0;
4140  switch (op->operands_count) {
4141  case 1:
4142  if (op->operands[0].type & OT_WORD) {
4143  data[l++] = 0x0f;
4144  data[l++] = 0x00;
4145  if (op->operands[0].type & OT_MEMORY) {
4146  data[l++] = 0x20 | op->operands[0].regs[0];
4147  } else {
4148  data[l++] = 0xe0 | op->operands[0].reg;
4149  }
4150  } else {
4151  return -1;
4152  }
4153  break;
4154  default:
4155  return -1;
4156  }
4157  return l;
4158 }
4159 
4160 static int opverw(RzAsm *a, ut8 *data, const Opcode *op) {
4161  int l = 0;
4162  switch (op->operands_count) {
4163  case 1:
4164  if (op->operands[0].type & OT_WORD) {
4165  data[l++] = 0x0f;
4166  data[l++] = 0x00;
4167  if (op->operands[0].type & OT_MEMORY) {
4168  data[l++] = 0x28 | op->operands[0].regs[0];
4169  } else {
4170  data[l++] = 0xe8 | op->operands[0].reg;
4171  }
4172  } else {
4173  return -1;
4174  }
4175  break;
4176  default:
4177  return -1;
4178  }
4179  return l;
4180 }
4181 
4182 static int opvmclear(RzAsm *a, ut8 *data, const Opcode *op) {
4183  int l = 0;
4184  switch (op->operands_count) {
4185  case 1:
4186  if (op->operands[0].type & OT_MEMORY &&
4187  op->operands[0].type & OT_QWORD) {
4188  data[l++] = 0x66;
4189  data[l++] = 0x0f;
4190  data[l++] = 0xc7;
4191  data[l++] = 0x30 | op->operands[0].regs[0];
4192  } else {
4193  return -1;
4194  }
4195  break;
4196  default:
4197  return -1;
4198  }
4199  return l;
4200 }
4201 
4202 static int opvmon(RzAsm *a, ut8 *data, const Opcode *op) {
4203  int l = 0;
4204  switch (op->operands_count) {
4205  case 1:
4206  if (op->operands[0].type & OT_MEMORY &&
4207  op->operands[0].type & OT_QWORD) {
4208  data[l++] = 0xf3;
4209  data[l++] = 0x0f;
4210  data[l++] = 0xc7;
4211  data[l++] = 0x30 | op->operands[0].regs[0];
4212  } else {
4213  return -1;
4214  }
4215  break;
4216  default:
4217  return -1;
4218  }
4219  return l;
4220 }
4221 
4222 static int opvmptrld(RzAsm *a, ut8 *data, const Opcode *op) {
4223  int l = 0;
4224  switch (op->operands_count) {
4225  case 1:
4226  if (op->operands[0].type & OT_MEMORY &&
4227  op->operands[0].type & OT_QWORD) {
4228  data[l++] = 0x0f;
4229  data[l++] = 0xc7;
4230  data[l++] = 0x30 | op->operands[0].regs[0];
4231  } else {
4232  return -1;
4233  }
4234  break;
4235  default:
4236  return -1;
4237  }
4238  return l;
4239 }
4240 
4241 static int opvmptrst(RzAsm *a, ut8 *data, const Opcode *op) {
4242  int l = 0;
4243  switch (op->operands_count) {
4244  case 1:
4245  if (op->operands[0].type & OT_MEMORY &&
4246  op->operands[0].type & OT_QWORD) {
4247  data[l++] = 0x0f;
4248  data[l++] = 0xc7;
4249  data[l++] = 0x38 | op->operands[0].regs[0];
4250  } else {
4251  return -1;
4252  }
4253  break;
4254  default:
4255  return -1;
4256  }
4257  return l;
4258 }
4259 
4260 typedef struct lookup_t {
4261  char mnemonic[12];
4263  int (*opdo)(RzAsm *, ut8 *, const Opcode *);
4265  int size;
4267 
4269  { "aaa", 0, NULL, 0x37, 1 },
4270  { "aad", 0, NULL, 0xd50a, 2 },
4271  { "aam", 0, opaam, 0 },
4272  { "aas", 0, NULL, 0x3f, 1 },
4273  { "adc", 0, &opadc, 0 },
4274  { "add", 0, &opadd, 0 },
4275  { "adx", 0, NULL, 0xd4, 1 },
4276  { "amx", 0, NULL, 0xd5, 1 },
4277  { "and", 0, &opand, 0 },
4278  { "bsf", 0, &opbs, 0 },
4279  { "bsr", 0, &opbs, 0 },
4280  { "bswap", 0, &opbswap, 0 },
4281  { "call", 0, &opcall, 0 },
4282  { "cbw", 0, NULL, 0x6698, 2 },
4283  { "cdq", 0, NULL, 0x99, 1 },
4284  { "cdqe", 0, &opcdqe, 0 },
4285  { "cwde", 0, &opcdqe, 0 },
4286  { "clc", 0, NULL, 0xf8, 1 },
4287  { "cld", 0, NULL, 0xfc, 1 },
4288  { "clflush", 0, &opclflush, 0 },
4289  { "clgi", 0, NULL, 0x0f01dd, 3 },
4290  { "cli", 0, NULL, 0xfa, 1 },
4291  { "clts", 0, NULL, 0x0f06, 2 },
4292  { "cmc", 0, NULL, 0xf5, 1 },
4293  { "cmovo", 0, &opcmov, 0 },
4294  { "cmovno", 0, &opcmov, 0 },
4295  { "cmovb", 0, &opcmov, 0 },
4296  { "cmovc", 0, &opcmov, 0 },
4297  { "cmovnae", 0, &opcmov, 0 },
4298  { "cmovae", 0, &opcmov, 0 },
4299  { "cmovnb", 0, &opcmov, 0 },
4300  { "cmovnc", 0, &opcmov, 0 },
4301  { "cmove", 0, &opcmov, 0 },
4302  { "cmovz", 0, &opcmov, 0 },
4303  { "cmovne", 0, &opcmov, 0 },
4304  { "cmovnz", 0, &opcmov, 0 },
4305  { "cmovbe", 0, &opcmov, 0 },
4306  { "cmovna", 0, &opcmov, 0 },
4307  { "cmova", 0, &opcmov, 0 },
4308  { "cmovnbe", 0, &opcmov, 0 },
4309  { "cmovne", 0, &opcmov, 0 },
4310  { "cmovnz", 0, &opcmov, 0 },
4311  { "cmovs", 0, &opcmov, 0 },
4312  { "cmovns", 0, &opcmov, 0 },
4313  { "cmovp", 0, &opcmov, 0 },
4314  { "cmovpe", 0, &opcmov, 0 },
4315  { "cmovnp", 0, &opcmov, 0 },
4316  { "cmovpo", 0, &opcmov, 0 },
4317  { "cmovl", 0, &opcmov, 0 },
4318  { "cmovnge", 0, &opcmov, 0 },
4319  { "cmovge", 0, &opcmov, 0 },
4320  { "cmovnl", 0, &opcmov, 0 },
4321  { "cmovle", 0, &opcmov, 0 },
4322  { "cmovng", 0, &opcmov, 0 },
4323  { "cmovg", 0, &opcmov, 0 },
4324  { "cmovnle", 0, &opcmov, 0 },
4325  { "cmp", 0, &opcmp, 0 },
4326  { "cmpsb", 0, NULL, 0xa6, 1 },
4327  { "cmpsd", 0, NULL, 0xa7, 1 },
4328  { "cmpsw", 0, NULL, 0x66a7, 2 },
4329  { "cpuid", 0, NULL, 0x0fa2, 2 },
4330  { "cwd", 0, NULL, 0x6699, 2 },
4331  { "cwde", 0, NULL, 0x98, 1 },
4332  { "daa", 0, NULL, 0x27, 1 },
4333  { "das", 0, NULL, 0x2f, 1 },
4334  { "dec", 0, &opdec, 0 },
4335  { "div", 0, &opdiv, 0 },
4336  { "emms", 0, NULL, 0x0f77, 2 },
4337  { "endbr32", 0, endbr32, 0 },
4338  { "endbr64", 0, endbr64, 0 },
4339  { "f2xm1", 0, NULL, 0xd9f0, 2 },
4340  { "fabs", 0, NULL, 0xd9e1, 2 },
4341  { "fadd", 0, &opfadd, 0 },
4342  { "faddp", 0, &opfaddp, 0 },
4343  { "fbld", 0, &opfbld, 0 },
4344  { "fbstp", 0, &opfbstp, 0 },
4345  { "fchs", 0, NULL, 0xd9e0, 2 },
4346  { "fclex", 0, NULL, 0x9bdbe2, 3 },
4347  { "fcmovb", 0, &opfcmov, 0 },
4348  { "fcmove", 0, &opfcmov, 0 },
4349  { "fcmovbe", 0, &opfcmov, 0 },
4350  { "fcmovu", 0, &opfcmov, 0 },
4351  { "fcmovnb", 0, &opfcmov, 0 },
4352  { "fcmovne", 0, &opfcmov, 0 },
4353  { "fcmovnbe", 0, &opfcmov, 0 },
4354  { "fcmovnu", 0, &opfcmov, 0 },
4355  { "fcos", 0, NULL, 0xd9ff, 2 },
4356  { "fdecstp", 0, NULL, 0xd9f6, 2 },
4357  { "fdiv", 0, &opfdiv, 0 },
4358  { "fdivp", 0, &opfdivp, 0 },
4359  { "fdivr", 0, &opfdivr, 0 },
4360  { "fdivrp", 0, &opfdivrp, 0 },
4361  { "femms", 0, NULL, 0x0f0e, 2 },
4362  { "ffree", 0, &opffree, 0 },
4363  { "fiadd", 0, &opfiadd, 0 },
4364  { "ficom", 0, &opficom, 0 },
4365  { "ficomp", 0, &opficomp, 0 },
4366  { "fidiv", 0, &opfidiv, 0 },
4367  { "fidivr", 0, &opfidivr, 0 },
4368  { "fild", 0, &opfild, 0 },
4369  { "fimul", 0, &opfimul, 0 },
4370  { "fincstp", 0, NULL, 0xd9f7, 2 },
4371  { "finit", 0, NULL, 0x9bdbe3, 3 },
4372  { "fist", 0, &opfist, 0 },
4373  { "fistp", 0, &opfistp, 0 },
4374  { "fisttp", 0, &opfisttp, 0 },
4375  { "fisub", 0, &opfisub, 0 },
4376  { "fisubr", 0, &opfisubr, 0 },
4377  { "fld1", 0, NULL, 0xd9e8, 2 },
4378  { "fldcw", 0, &opfldcw, 0 },
4379  { "fldenv", 0, &opfldenv, 0 },
4380  { "fldl2t", 0, NULL, 0xd9e9, 2 },
4381  { "fldl2e", 0, NULL, 0xd9ea, 2 },
4382  { "fldlg2", 0, NULL, 0xd9ec, 2 },
4383  { "fldln2", 0, NULL, 0xd9ed, 2 },
4384  { "fldpi", 0, NULL, 0xd9eb, 2 },
4385  { "fldz", 0, NULL, 0xd9ee, 2 },
4386  { "fmul", 0, &opfmul, 0 },
4387  { "fmulp", 0, &opfmulp, 0 },
4388  { "fnclex", 0, NULL, 0xdbe2, 2 },
4389  { "fninit", 0, NULL, 0xdbe3, 2 },
4390  { "fnop", 0, NULL, 0xd9d0, 2 },
4391  { "fnsave", 0, &opfnsave, 0 },
4392  { "fnstcw", 0, &opfnstcw, 0 },
4393  { "fnstenv", 0, &opfnstenv, 0 },
4394  { "fnstsw", 0, &opfnstsw, 0 },
4395  { "fpatan", 0, NULL, 0xd9f3, 2 },
4396  { "fprem", 0, NULL, 0xd9f8, 2 },
4397  { "fprem1", 0, NULL, 0xd9f5, 2 },
4398  { "fptan", 0, NULL, 0xd9f2, 2 },
4399  { "frndint", 0, NULL, 0xd9fc, 2 },
4400  { "frstor", 0, &opfrstor, 0 },
4401  { "fsave", 0, &opfsave, 0 },
4402  { "fscale", 0, NULL, 0xd9fd, 2 },
4403  { "fsin", 0, NULL, 0xd9fe, 2 },
4404  { "fsincos", 0, NULL, 0xd9fb, 2 },
4405  { "fsqrt", 0, NULL, 0xd9fa, 2 },
4406  { "fstcw", 0, &opfstcw, 0 },
4407  { "fstenv", 0, &opfstenv, 0 },
4408  { "fstsw", 0, &opfstsw, 0 },
4409  { "fsub", 0, &opfsub, 0 },
4410  { "fsubp", 0, &opfsubp, 0 },
4411  { "fsubr", 0, &opfsubr, 0 },
4412  { "fsubrp", 0, &opfsubrp, 0 },
4413  { "ftst", 0, NULL, 0xd9e4, 2 },
4414  { "fucom", 0, &opfucom, 0 },
4415  { "fucomp", 0, &opfucomp, 0 },
4416  { "fucompp", 0, NULL, 0xdae9, 2 },
4417  { "fwait", 0, NULL, 0x9b, 1 },
4418  { "fxam", 0, NULL, 0xd9e5, 2 },
4419  { "fxch", 0, &opfxch, 0 },
4420  { "fxrstor", 0, &opfxrstor, 0 },
4421  { "fxsave", 0, &opfxsave, 0 },
4422  { "fxtract", 0, NULL, 0xd9f4, 2 },
4423  { "fyl2x", 0, NULL, 0xd9f1, 2 },
4424  { "fyl2xp1", 0, NULL, 0xd9f9, 2 },
4425  { "getsec", 0, NULL, 0x0f37, 2 },
4426  { "hlt", 0, NULL, 0xf4, 1 },
4427  { "idiv", 0, &opidiv, 0 },
4428  { "imul", 0, &opimul, 0 },
4429  { "in", 0, &opin, 0 },
4430  { "inc", 0, &opinc, 0 },
4431  { "ins", 0, NULL, 0x6d, 1 },
4432  { "insb", 0, NULL, 0x6c, 1 },
4433  { "insd", 0, NULL, 0x6d, 1 },
4434  { "insw", 0, NULL, 0x666d, 2 },
4435  { "int", 0, &opint, 0 },
4436  { "int1", 0, NULL, 0xf1, 1 },
4437  { "int3", 0, NULL, 0xcc, 1 },
4438  { "into", 0, NULL, 0xce, 1 },
4439  { "invd", 0, NULL, 0x0f08, 2 },
4440  { "iret", 0, NULL, 0x66cf, 2 },
4441  { "iretd", 0, NULL, 0xcf, 1 },
4442  { "ja", 0, &opjc, 0 },
4443  { "jae", 0, &opjc, 0 },
4444  { "jb", 0, &opjc, 0 },
4445  { "jbe", 0, &opjc, 0 },
4446  { "jc", 0, &opjc, 0 },
4447  { "je", 0, &opjc, 0 },
4448  { "jg", 0, &opjc, 0 },
4449  { "jge", 0, &opjc, 0 },
4450  { "jl", 0, &opjc, 0 },
4451  { "jle", 0, &opjc, 0 },
4452  { "jmp", 0, &opjc, 0 },
4453  { "jna", 0, &opjc, 0 },
4454  { "jnae", 0, &opjc, 0 },
4455  { "jnb", 0, &opjc, 0 },
4456  { "jnbe", 0, &opjc, 0 },
4457  { "jnc", 0, &opjc, 0 },
4458  { "jne", 0, &opjc, 0 },
4459  { "jng", 0, &opjc, 0 },
4460  { "jnge", 0, &opjc, 0 },
4461  { "jnl", 0, &opjc, 0 },
4462  { "jnle", 0, &opjc, 0 },
4463  { "jno", 0, &opjc, 0 },
4464  { "jnp", 0, &opjc, 0 },
4465  { "jns", 0, &opjc, 0 },
4466  { "jnz", 0, &opjc, 0 },
4467  { "jo", 0, &opjc, 0 },
4468  { "jp", 0, &opjc, 0 },
4469  { "jpe", 0, &opjc, 0 },
4470  { "jpo", 0, &opjc, 0 },
4471  { "js", 0, &opjc, 0 },
4472  { "jz", 0, &opjc, 0 },
4473  { "lahf", 0, NULL, 0x9f, 1 },
4474  { "lea", 0, &oplea, 0 },
4475  { "leave", 0, NULL, 0xc9, 1 },
4476  { "les", 0, &oples, 0 },
4477  { "lfence", 0, NULL, 0x0faee8, 3 },
4478  { "lgdt", 0, &oplgdt, 0 },
4479  { "lidt", 0, &oplidt, 0 },
4480  { "lldt", 0, &oplldt, 0 },
4481  { "lmsw", 0, &oplmsw, 0 },
4482  { "lodsb", 0, NULL, 0xac, 1 },
4483  { "lodsd", 0, NULL, 0xad, 1 },
4484  { "lodsw", 0, NULL, 0x66ad, 2 },
4485  { "loop", 0, &oploop, 0 },
4486  { "mfence", 0, NULL, 0x0faef0, 3 },
4487  { "monitor", 0, NULL, 0x0f01c8, 3 },
4488  { "mov", 0, &opmov, 0 },
4489  { "movsb", 0, NULL, 0xa4, 1 },
4490  { "movsd", 0, NULL, 0xa5, 1 },
4491  { "movsw", 0, NULL, 0x66a5, 2 },
4492  { "movzx", 0, &opmovx, 0 },
4493  { "movsx", 0, &opmovx, 0 },
4494  { "movabs", 0, &opmovabs, 0 },
4495  { "mul", 0, &opmul, 0 },
4496  { "mwait", 0, NULL, 0x0f01c9, 3 },
4497  { "neg", 0, &opneg, 0 },
4498  { "nop", 0, NULL, 0x90, 1 },
4499  { "not", 0, &opnot, 0 },
4500  { "or", 0, &opor, 0 },
4501  { "out", 0, &opout, 0 },
4502  { "outsb", 0, NULL, 0x6e, 1 },
4503  { "outs", 0, NULL, 0x6f, 1 },
4504  { "outsd", 0, NULL, 0x6f, 1 },
4505  { "outsw", 0, NULL, 0x666f, 2 },
4506  { "pop", 0, &oppop, 0 },
4507  { "popa", 1, NULL, 0x61, 1 },
4508  { "popad", 1, NULL, 0x61, 1 },
4509  { "popal", 1, NULL, 0x61, 1 },
4510  { "popaw", 1, NULL, 0x6661, 2 },
4511  { "popfd", 1, NULL, 0x9d, 1 },
4512  { "prefetch", 0, NULL, 0x0f0d, 2 },
4513  { "push", 0, &oppush, 0 },
4514  { "pusha", 1, NULL, 0x60, 1 },
4515  { "pushad", 1, NULL, 0x60, 1 },
4516  { "pushal", 1, NULL, 0x60, 1 },
4517  { "pushfd", 0, NULL, 0x9c, 1 },
4518  { "rcl", 0, &process_group_2, 0 },
4519  { "rcr", 0, &process_group_2, 0 },
4520  { "rep", 0, &oprep, 0 },
4521  { "repe", 0, &oprep, 0 },
4522  { "repne", 0, &oprep, 0 },
4523  { "repz", 0, &oprep, 0 },
4524  { "repnz", 0, &oprep, 0 },
4525  { "rdmsr", 0, NULL, 0x0f32, 2 },
4526  { "rdpmc", 0, NULL, 0x0f33, 2 },
4527  { "rdtsc", 0, NULL, 0x0f31, 2 },
4528  { "rdtscp", 0, NULL, 0x0f01f9, 3 },
4529  { "ret", 0, &opret, 0 },
4530  { "retf", 0, &opretf, 0 },
4531  { "retw", 0, NULL, 0x66c3, 2 },
4532  { "rol", 0, &process_group_2, 0 },
4533  { "ror", 0, &process_group_2, 0 },
4534  { "rsm", 0, NULL, 0x0faa, 2 },
4535  { "sahf", 0, NULL, 0x9e, 1 },
4536  { "sal", 0, &process_group_2, 0 },
4537  { "salc", 0, NULL, 0xd6, 1 },
4538  { "sar", 0, &process_group_2, 0 },
4539  { "sbb", 0, &opsbb, 0 },
4540  { "scasb", 0, NULL, 0xae, 1 },
4541  { "scasd", 0, NULL, 0xaf, 1 },
4542  { "scasw", 0, NULL, 0x66af, 2 },
4543  { "seto", 0, &opset, 0 },
4544  { "setno", 0, &opset, 0 },
4545  { "setb", 0, &opset, 0 },
4546  { "setnae", 0, &opset, 0 },
4547  { "setc", 0, &opset, 0 },
4548  { "setnb", 0, &opset, 0 },
4549  { "setae", 0, &opset, 0 },
4550  { "setnc", 0, &opset, 0 },
4551  { "setz", 0, &opset, 0 },
4552  { "sete", 0, &opset, 0 },
4553  { "setnz", 0, &opset, 0 },
4554  { "setne", 0, &opset, 0 },
4555  { "setbe", 0, &opset, 0 },
4556  { "setna", 0, &opset, 0 },
4557  { "setnbe", 0, &opset, 0 },
4558  { "seta", 0, &opset, 0 },
4559  { "sets", 0, &opset, 0 },
4560  { "setns", 0, &opset, 0 },
4561  { "setp", 0, &opset, 0 },
4562  { "setpe", 0, &opset, 0 },
4563  { "setnp", 0, &opset, 0 },
4564  { "setpo", 0, &opset, 0 },
4565  { "setl", 0, &opset, 0 },
4566  { "setnge", 0, &opset, 0 },
4567  { "setnl", 0, &opset, 0 },
4568  { "setge", 0, &opset, 0 },
4569  { "setle", 0, &opset, 0 },
4570  { "setng", 0, &opset, 0 },
4571  { "setnle", 0, &opset, 0 },
4572  { "setg", 0, &opset, 0 },
4573  { "sfence", 0, NULL, 0x0faef8, 3 },
4574  { "sgdt", 0, &opsgdt, 0 },
4575  { "shl", 0, &process_group_2, 0 },
4576  { "shr", 0, &process_group_2, 0 },
4577  { "sidt", 0, &opsidt, 0 },
4578  { "sldt", 0, &opsldt, 0 },
4579  { "smsw", 0, &opsmsw, 0 },
4580  { "stc", 0, NULL, 0xf9, 1 },
4581  { "std", 0, NULL, 0xfd, 1 },
4582  { "stgi", 0, NULL, 0x0f01dc, 3 },
4583  { "sti", 0, NULL, 0xfb, 1 },
4584  { "stmxcsr", 0, &opstmxcsr, 0 },
4585  { "stosb", 0, &opstos, 0 },
4586  { "stosd", 0, &opstos, 0 },
4587  { "stosw", 0, &opstos, 0 },
4588  { "str", 0, &opstr, 0 },
4589  { "sub", 0, &opsub, 0 },
4590  { "swapgs", 0, NULL, 0x0f1ff8, 3 },
4591  { "syscall", 0, NULL, 0x0f05, 2 },
4592  { "sysenter", 0, NULL, 0x0f34, 2 },
4593  { "sysexit", 0, NULL, 0x0f35, 2 },
4594  { "sysret", 0, NULL, 0x0f07, 2 },
4595  { "ud2", 0, NULL, 0x0f0b, 2 },
4596  { "verr", 0, &opverr, 0 },
4597  { "verw", 0, &opverw, 0 },
4598  { "vmcall", 0, NULL, 0x0f01c1, 3 },
4599  { "vmclear", 0, &opvmclear, 0 },
4600  { "vmlaunch", 0, NULL, 0x0f01c2, 3 },
4601  { "vmload", 0, NULL, 0x0f01da, 3 },
4602  { "vmmcall", 0, NULL, 0x0f01d9, 3 },
4603  { "vmptrld", 0, &opvmptrld, 0 },
4604  { "vmptrst", 0, &opvmptrst, 0 },
4605  { "vmresume", 0, NULL, 0x0f01c3, 3 },
4606  { "vmrun", 0, NULL, 0x0f01d8, 3 },
4607  { "vmsave", 0, NULL, 0x0f01db, 3 },
4608  { "vmxoff", 0, NULL, 0x0f01c4, 3 },
4609  { "vmxon", 0, &opvmon, 0 },
4610  { "vzeroall", 0, NULL, 0xc5fc77, 3 },
4611  { "vzeroupper", 0, NULL, 0xc5f877, 3 },
4612  { "wait", 0, NULL, 0x9b, 1 },
4613  { "wbinvd", 0, NULL, 0x0f09, 2 },
4614  { "wrmsr", 0, NULL, 0x0f30, 2 },
4615  { "xadd", 0, &opxadd, 0 },
4616  { "xchg", 0, &opxchg, 0 },
4617  { "xgetbv", 0, NULL, 0x0f01d0, 3 },
4618  { "xlatb", 0, NULL, 0xd7, 1 },
4619  { "xor", 0, &opxor, 0 },
4620  { "xsetbv", 0, NULL, 0x0f01d1, 3 },
4621  { "test", 0, &optest, 0 },
4622  { "null", 0, NULL, 0, 0 }
4623 };
4624 
4625 static x86newTokenType getToken(const char *str, size_t *begin, size_t *end) {
4626  if (*begin > strlen(str)) {
4627  return TT_EOF;
4628  }
4629  // Skip whitespace
4630  while (begin && str[*begin] && isspace((ut8)str[*begin])) {
4631  ++(*begin);
4632  }
4633 
4634  if (!str[*begin]) { // null byte
4635  *end = *begin;
4636  return TT_EOF;
4637  }
4638  if (isalpha((ut8)str[*begin])) { // word token
4639  *end = *begin;
4640  while (end && str[*end] && isalnum((ut8)str[*end])) {
4641  ++(*end);
4642  }
4643  return TT_WORD;
4644  }
4645  if (isdigit((ut8)str[*begin])) { // number token
4646  *end = *begin;
4647  while (end && isalnum((ut8)str[*end])) { // accept alphanumeric characters, because hex.
4648  ++(*end);
4649  }
4650  return TT_NUMBER;
4651  } else { // special character: [, ], +, *, ...
4652  *end = *begin + 1;
4653  return TT_SPECIAL;
4654  }
4655 }
4656 
4657 static bool is_xmm_register(const char *token) {
4658  // check xmm0..xmm15
4659  if (!rz_str_ncasecmp("xmm", token, 3)) {
4660  int n = atoi(token + 3);
4661  return (n >= 0 && n <= 15);
4662  }
4663  return false;
4664 }
4665 
4666 static bool is_mm_register(const char *token) {
4667  if (!rz_str_ncasecmp("mm", token, 2)) {
4668  const bool parn = token[2] == '(';
4669  if (parn) {
4670  token++;
4671  }
4672  if (isdigit(token[2]) && !isdigit(token[3])) {
4673  int n = token[2];
4674  if (n >= '0' && n <= '7') {
4675  if (parn) {
4676  if (token[3] != ')') {
4677  return false;
4678  }
4679  }
4680  return true;
4681  }
4682  }
4683  }
4684  return false;
4685 }
4686 
4687 static bool is_st_register(const char *token) {
4688  if (!rz_str_ncasecmp("st", token, 2)) {
4689  const bool parn = token[2] == '(';
4690  if (parn) {
4691  token++;
4692  }
4693  if (isdigit(token[2]) && !isdigit(token[3])) {
4694  int n = token[2];
4695  if (n >= '0' && n <= '7') {
4696  if (parn) {
4697  if (token[3] != ')') {
4698  return false;
4699  }
4700  }
4701  return true;
4702  }
4703  }
4704  }
4705  return false;
4706 }
4707 
4711 static Register parseReg(RzAsm *a, const char *str, size_t *pos, ut32 *type) {
4712  int i;
4713  // Must be the same order as in enum register_t
4714  const char *regs[] = { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "eip", NULL };
4715  const char *regsext[] = { "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d", NULL };
4716  const char *regs8[] = { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", NULL };
4717  const char *regs16[] = { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", NULL };
4718  const char *regs64[] = { "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "rip", NULL };
4719  const char *regs64ext[] = { "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", NULL };
4720  const char *sregs[] = { "es", "cs", "ss", "ds", "fs", "gs", NULL };
4721  const char *cregs[] = { "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", NULL };
4722  const char *dregs[] = { "dr0", "dr1", "dr2", "dr3", "dr4", "dr5", "dr6", "dr7", NULL };
4723 
4724  // Get token (especially the length)
4725  size_t nextpos, length;
4726  const char *token;
4727  getToken(str, pos, &nextpos);
4728  token = str + *pos;
4729  length = nextpos - *pos;
4730  *pos = nextpos;
4731 
4732  // General purpose registers
4733  if (length == 3 && token[0] == 'e') {
4734  for (i = 0; regs[i]; i++) {
4735  if (!rz_str_ncasecmp(regs[i], token, length)) {
4736  *type = (OT_GPREG & OT_REG(i)) | OT_DWORD;
4737  return i;
4738  }
4739  }
4740  }
4741  // Control registers
4742  if (length == 3 && token[0] == 'c') {
4743  for (i = 0; cregs[i]; i++) {
4744  if (!rz_str_ncasecmp(cregs[i], token, length)) {
4745  *type = (OT_CONTROLREG & OT_REG(i)) | OT_DWORD;
4746  return i;
4747  }
4748  }
4749  }
4750  // Debug registers
4751  if (length == 3 && token[0] == 'd') {
4752  for (i = 0; cregs[i]; i++) {
4753  if (!rz_str_ncasecmp(dregs[i], token, length)) {
4754  *type = (OT_DEBUGREG & OT_REG(i)) | OT_DWORD;
4755  return i;
4756  }
4757  }
4758  }
4759  if (length == 2) {
4760  if (token[1] == 'l' || token[1] == 'h') {
4761  for (i = 0; regs8[i]; i++) {
4762  if (!rz_str_ncasecmp(regs8[i], token, length)) {
4763  *type = (OT_GPREG & OT_REG(i)) | OT_BYTE;
4764  return i;
4765  }
4766  }
4767  }
4768  for (i = 0; regs16[i]; i++) {
4769  if (!rz_str_ncasecmp(regs16[i], token, length)) {
4770  *type = (OT_GPREG & OT_REG(i)) | OT_WORD;
4771  return i;
4772  }
4773  }
4774  // This isn't working properly yet
4775  for (i = 0; sregs[i]; i++) {
4776  if (!rz_str_ncasecmp(sregs[i], token, length)) {
4777  *type = (OT_SEGMENTREG & OT_REG(i)) | OT_WORD;
4778  return i;
4779  }
4780  }
4781  }
4782  if (token[0] == 'r') {
4783  for (i = 0; regs64[i]; i++) {
4784  if (!rz_str_ncasecmp(regs64[i], token, length)) {
4785  *type = (OT_GPREG & OT_REG(i)) | OT_QWORD;
4786  a->bits = 64;
4787  return i;
4788  }
4789  }
4790  for (i = 0; regs64ext[i]; i++) {
4791  if (!rz_str_ncasecmp(regs64ext[i], token, length)) {
4792  *type = (OT_GPREG & OT_REG(i)) | OT_QWORD;
4793  a->bits = 64;
4794  return i + 9;
4795  }
4796  }
4797  for (i = 0; regsext[i]; i++) {
4798  if (!rz_str_ncasecmp(regsext[i], token, length)) {
4799  *type = (OT_GPREG & OT_REG(i)) | OT_DWORD;
4800  if (a->bits < 32) {
4801  a->bits = 32;
4802  }
4803  return i + 9;
4804  }
4805  }
4806  }
4807  // Extended registers
4808  if (is_st_register(token)) {
4809  *type = (OT_FPUREG & ~OT_REGALL);
4810  *pos = 2;
4811  }
4812  if (is_mm_register(token)) {
4813  *type = (OT_MMXREG & ~OT_REGALL);
4814  *pos = 2;
4815  }
4816  if (is_xmm_register(token)) {
4817  *type = (OT_XMMREG & ~OT_REGALL);
4818  *pos = 3;
4819  }
4820  // Now read number, possibly with parentheses
4821  if (*type & (OT_FPUREG | OT_MMXREG | OT_XMMREG) & ~OT_REGALL) {
4823  // pass by '(',if there is one
4824  if (getToken(token, pos, &nextpos) == TT_SPECIAL && token[*pos] == '(') {
4825  *pos = nextpos;
4826  }
4827  // read number
4828  // const int maxreg = (a->bits == 64) ? 15 : 7;
4829  if (getToken(token, pos, &nextpos) != TT_NUMBER) {
4830  RZ_LOG_ERROR("assembler: x86.nz: expected register number but found '%s'\n", str + *pos);
4831  return X86R_UNDEFINED;
4832  }
4833  reg = getnum(a, token + *pos);
4834  // st and mm go up to 7, xmm up to 15
4835  if ((reg > 15) || ((*type & (OT_FPUREG | OT_MMXREG) & ~OT_REGALL) && reg > 7)) {
4836  RZ_LOG_ERROR("assembler: x86.nz: register index is too large\n");
4837  return X86R_UNDEFINED;
4838  }
4839  *pos = nextpos;
4840 
4841  // pass by ')'
4842  if (getToken(token, pos, &nextpos) == TT_SPECIAL && token[*pos] == ')') {
4843  *pos = nextpos;
4844  }
4845  *type |= (OT_REG(reg) & ~OT_REGTYPE);
4846  return reg;
4847  }
4848  return X86R_UNDEFINED;
4849 }
4850 
4851 static void parse_segment_offset(RzAsm *a, const char *str, size_t *pos,
4852  Operand *op, int reg_index) {
4853  int nextpos = *pos;
4854  char *c = strchr(str + nextpos, ':');
4855  if (c) {
4856  nextpos++; // Skip the ':'
4857  c = strchr(str + nextpos, '[');
4858  if (c) {
4859  nextpos++;
4860  } // Skip the '['
4861 
4862  // Assign registers to match behaviour of OT_MEMORY type
4863  op->regs[reg_index] = op->reg;
4864  op->type |= OT_MEMORY;
4865  op->offset_sign = 1;
4866  char *p = strchr(str + nextpos, '-');
4867  if (p) {
4868  op->offset_sign = -1;
4869  nextpos++;
4870  }
4871  op->scale[reg_index] = getnum(a, str + nextpos);
4872  op->offset = op->scale[reg_index];
4873  }
4874 }
4875 // Parse operand
4876 static int parseOperand(RzAsm *a, const char *str, Operand *op, bool isrepop) {
4877  size_t pos, nextpos = 0;
4879  int size_token = 1;
4880  bool explicit_size = false;
4881  int reg_index = 0;
4882  // Reset type
4883  op->type = 0;
4884  // Consume tokens denoting the operand size
4885  while (size_token) {
4886  pos = nextpos;
4887  last_type = getToken(str, &pos, &nextpos);
4888 
4889  // Token may indicate size: then skip
4890  if (!rz_str_ncasecmp(str + pos, "ptr", 3)) {
4891  continue;
4892  } else if (!rz_str_ncasecmp(str + pos, "byte", 4)) {
4893  op->type |= OT_MEMORY | OT_BYTE;
4894  op->dest_size = OT_BYTE;
4895  explicit_size = true;
4896  } else if (!rz_str_ncasecmp(str + pos, "word", 4)) {
4897  op->type |= OT_MEMORY | OT_WORD;
4898  op->dest_size = OT_WORD;
4899  explicit_size = true;
4900  } else if (!rz_str_ncasecmp(str + pos, "dword", 5)) {
4901  op->type |= OT_MEMORY | OT_DWORD;
4902  op->dest_size = OT_DWORD;
4903  explicit_size = true;
4904  } else if (!rz_str_ncasecmp(str + pos, "qword", 5)) {
4905  op->type |= OT_MEMORY | OT_QWORD;
4906  op->dest_size = OT_QWORD;
4907  explicit_size = true;
4908  } else if (!rz_str_ncasecmp(str + pos, "oword", 5)) {
4909  op->type |= OT_MEMORY | OT_OWORD;
4910  op->dest_size = OT_OWORD;
4911  explicit_size = true;
4912  } else if (!rz_str_ncasecmp(str + pos, "tbyte", 5)) {
4913  op->type |= OT_MEMORY | OT_TBYTE;
4914  op->dest_size = OT_TBYTE;
4915  explicit_size = true;
4916  } else { // the current token doesn't denote a size
4917  size_token = 0;
4918  }
4919  }
4920 
4921  // Next token: register, immediate, or '['
4922  if (str[pos] == '[') {
4923  // Don't care about size, if none is given.
4924  if (!op->type) {
4925  op->type = OT_MEMORY;
4926  }
4927  // At the moment, we only accept plain linear combinations:
4928  // part := address | [factor *] register
4929  // address := part {+ part}*
4930  op->offset = op->scale[0] = op->scale[1] = 0;
4931 
4932  ut64 temp = 1;
4934  bool first_reg = true;
4935  while (str[pos] != ']') {
4936  if (pos > nextpos) {
4937  // RZ_LOG_ERROR("assembler: x86.nz: failed to parse instruction\n");
4938  break;
4939  }
4940  pos = nextpos;
4941  if (!str[pos]) {
4942  break;
4943  }
4944  last_type = getToken(str, &pos, &nextpos);
4945 
4946  if (last_type == TT_SPECIAL) {
4947  if (str[pos] == '+' || str[pos] == '-' || str[pos] == ']') {
4948  if (reg != X86R_UNDEFINED) {
4949  if (reg_index < 2) {
4950  op->regs[reg_index] = reg;
4951  op->scale[reg_index] = temp;
4952  }
4953  ++reg_index;
4954  } else {
4955  op->offset += temp;
4956  if (reg_index < 2) {
4957  op->regs[reg_index] = X86R_UNDEFINED;
4958  }
4959  }
4960  temp = 1;
4961  reg = X86R_UNDEFINED;
4962  } else if (str[pos] == '*') {
4963  // go to ], + or - to get scale
4964 
4965  // Something to do here?
4966  // Seems we are just ignoring '*' or assuming it implicitly.
4967  }
4968  } else if (last_type == TT_WORD) {
4969  ut32 reg_type = 0;
4970 
4971  // We can't multiply registers
4972  if (reg != X86R_UNDEFINED) {
4973  op->type = 0; // Make the result invalid
4974  }
4975 
4976  // Reset nextpos: parseReg wants to parse from the beginning
4977  nextpos = pos;
4978  reg = parseReg(a, str, &nextpos, &reg_type);
4979 
4980  if (first_reg) {
4981  op->extended = false;
4982  if (reg > 8) {
4983  op->extended = true;
4984  op->reg = reg - 9;
4985  } else {
4986  op->reg = reg;
4987  }
4988  first_reg = false;
4989  } else if (reg > 8) {
4990  op->reg = reg - 9;
4991  }
4992  if (reg_type & OT_REGTYPE & OT_SEGMENTREG) {
4993  op->reg = reg;
4994  op->type = reg_type;
4995  parse_segment_offset(a, str, &nextpos, op, reg_index);
4996  return nextpos;
4997  }
4998 
4999  // Still going to need to know the size if not specified
5000  if (!explicit_size) {
5001  op->type |= reg_type;
5002  }
5003  op->reg_size = reg_type;
5004  op->explicit_size = explicit_size;
5005 
5006  // Addressing only via general purpose registers
5007  if (!(reg_type & OT_GPREG)) {
5008  op->type = 0; // Make the result invalid
5009  }
5010  } else {
5011  char *p = strchr(str, '+');
5012  op->offset_sign = 1;
5013  if (!p) {
5014  p = strchr(str, '-');
5015  if (p) {
5016  op->offset_sign = -1;
5017  }
5018  }
5019  // with SIB notation, we need to consider the right sign
5020  char *plus = strchr(str, '+');
5021  char *minus = strchr(str, '-');
5022  char *closeB = strchr(str, ']');
5023  if (plus && minus && plus < closeB && minus < closeB) {
5024  op->offset_sign = -1;
5025  }
5026  // If there's a scale, we don't want to parse out the
5027  // scale with the offset (scale + offset) otherwise the scale
5028  // will be the sum of the two. This splits the numbers
5029  char *tmp;
5030  tmp = malloc(strlen(str + pos) + 1);
5031  strcpy(tmp, str + pos);
5032  strtok(tmp, "+-");
5033  st64 read = getnum(a, tmp);
5034  free(tmp);
5035  temp *= read;
5036  }
5037  }
5038  } else if (last_type == TT_WORD) { // register
5039  nextpos = pos;
5040 
5041  if (isrepop) {
5042  op->is_good_flag = false;
5043  strncpy(op->rep_op, str, MAX_REPOP_LENGTH - 1);
5044  op->rep_op[MAX_REPOP_LENGTH - 1] = '\0';
5045  return nextpos;
5046  }
5047 
5048  op->reg = parseReg(a, str, &nextpos, &op->type);
5049 
5050  op->extended = false;
5051  if (op->reg > 8) {
5052  op->extended = true;
5053  op->reg -= 9;
5054  }
5055  if (op->type & OT_REGTYPE & OT_SEGMENTREG) {
5056  parse_segment_offset(a, str, &nextpos, op, reg_index);
5057  return nextpos;
5058  }
5059  if (op->reg == X86R_UNDEFINED) {
5060  op->is_good_flag = false;
5061  if (a->num && a->num->value == 0) {
5062  return nextpos;
5063  }
5064  op->type = OT_CONSTANT;
5065  RzCore *core = a->num ? (RzCore *)(a->num->userptr) : NULL;
5066  if (core && rz_flag_get(core->flags, str)) {
5067  op->is_good_flag = true;
5068  }
5069 
5070  char *p = strchr(str, '-');
5071  if (p) {
5072  op->sign = -1;
5073  str = ++p;
5074  }
5075  op->immediate = getnum(a, str);
5076  } else if (op->reg < X86R_UNDEFINED) {
5077  strncpy(op->rep_op, str, MAX_REPOP_LENGTH - 1);
5078  op->rep_op[MAX_REPOP_LENGTH - 1] = '\0';
5079  }
5080  } else { // immediate
5081  // We don't know the size, so let's just set no size flag.
5082  op->type = OT_CONSTANT;
5083  op->sign = 1;
5084  char *p = strchr(str, '-');
5085  if (p) {
5086  op->sign = -1;
5087  str = ++p;
5088  }
5089  op->immediate = getnum(a, str);
5090  }
5091 
5092  return nextpos;
5093 }
5094 
5095 static int parseOpcode(RzAsm *a, const char *op, Opcode *out) {
5096  out->has_bnd = false;
5097  bool isrepop = false;
5098  if (!strncmp(op, "bnd ", 4)) {
5099  out->has_bnd = true;
5100  op += 4;
5101  }
5102  char *args = strchr(op, ' ');
5103  out->mnemonic = args ? rz_str_ndup(op, args - op) : strdup(op);
5104  out->operands[0].type = out->operands[1].type = 0;
5105  out->operands[0].extended = out->operands[1].extended = false;
5106  out->operands[0].reg = out->operands[0].regs[0] = out->operands[0].regs[1] = X86R_UNDEFINED;
5107  out->operands[1].reg = out->operands[1].regs[0] = out->operands[1].regs[1] = X86R_UNDEFINED;
5108  out->operands[0].immediate = out->operands[1].immediate = 0;
5109  out->operands[0].sign = out->operands[1].sign = 1;
5110  out->operands[0].is_good_flag = out->operands[1].is_good_flag = true;
5111  out->is_short = false;
5112  out->operands_count = 0;
5113  if (args) {
5114  args++;
5115  } else {
5116  return 1;
5117  }
5118  if (!rz_str_ncasecmp(args, "short", 5)) {
5119  out->is_short = true;
5120  args += 5;
5121  }
5122  if (!strncmp(out->mnemonic, "rep", 3)) {
5123  isrepop = true;
5124  }
5125  parseOperand(a, args, &(out->operands[0]), isrepop);
5126  out->operands_count = 1;
5127  while (out->operands_count < MAX_OPERANDS) {
5128  args = strchr(args, ',');
5129  if (!args) {
5130  break;
5131  }
5132  args++;
5133  parseOperand(a, args, &(out->operands[out->operands_count]), isrepop);
5134  out->operands_count++;
5135  }
5136  return 0;
5137 }
5138 
5139 static ut64 getnum(RzAsm *a, const char *s) {
5140  if (!s) {
5141  return 0;
5142  }
5143  if (*s == '$') {
5144  s++;
5145  }
5146  return rz_num_math(a->num, s);
5147 }
5148 
5149 static int oprep(RzAsm *a, ut8 *data, const Opcode *op) {
5150  int l = 0;
5151  LookupTable *lt_ptr;
5152  int retval;
5153  if (!strcmp(op->mnemonic, "rep") ||
5154  !strcmp(op->mnemonic, "repe") ||
5155  !strcmp(op->mnemonic, "repz")) {
5156  data[l++] = 0xf3;
5157  } else if (!strcmp(op->mnemonic, "repne") ||
5158  !strcmp(op->mnemonic, "repnz")) {
5159  data[l++] = 0xf2;
5160  }
5161  Opcode instr = { 0 };
5162  parseOpcode(a, op->operands[0].rep_op, &instr);
5163 
5164  for (lt_ptr = oplookup; strcmp(lt_ptr->mnemonic, "null"); lt_ptr++) {
5165  if (!rz_str_casecmp(instr.mnemonic, lt_ptr->mnemonic)) {
5166  if (lt_ptr->opcode > 0) {
5167  if (lt_ptr->only_x32 && a->bits == 64) {
5168  free(instr.mnemonic);
5169  return -1;
5170  }
5171  ut64 opcode = lt_ptr->opcode;
5172  int i = lt_ptr->size - 1;
5173  for (; i >= 0; i--) {
5174  data[i + l] = opcode & 0xff;
5175  opcode >>= 8;
5176  }
5177  free(instr.mnemonic);
5178  return l + lt_ptr->size;
5179  } else {
5180  if (lt_ptr->opdo) {
5181  data += l;
5182  if (instr.has_bnd) {
5183  data[l] = 0xf2;
5184  data++;
5185  }
5186  retval = lt_ptr->opdo(a, data, &instr);
5187  // if op supports bnd then the first byte will
5188  // be 0xf2.
5189  if (instr.has_bnd) {
5190  retval++;
5191  }
5192  return l + retval;
5193  }
5194  break;
5195  }
5196  }
5197  }
5198  free(instr.mnemonic);
5199  return -1;
5200 }
5201 
5202 static int assemble(RzAsm *a, RzAsmOp *ao, const char *str) {
5203  ut8 __data[32] = { 0 };
5204  ut8 *data = __data;
5205  char op[128];
5206  LookupTable *lt_ptr;
5207  int retval = -1;
5208  Opcode instr = { 0 };
5209 
5210  strncpy(op, str, sizeof(op) - 1);
5211  op[sizeof(op) - 1] = '\0';
5212  parseOpcode(a, op, &instr);
5213  for (lt_ptr = oplookup; strcmp(lt_ptr->mnemonic, "null"); lt_ptr++) {
5214  if (!rz_str_casecmp(instr.mnemonic, lt_ptr->mnemonic)) {
5215  if (lt_ptr->opcode > 0) {
5216  if (!lt_ptr->only_x32 || a->bits != 64) {
5217  ut64 opcode = lt_ptr->opcode;
5218  int i = lt_ptr->size - 1;
5219  for (; i >= 0; i--) {
5220  data[i] = opcode & 0xff;
5221  opcode >>= 8;
5222  }
5223  retval = lt_ptr->size;
5224  }
5225  } else {
5226  if (lt_ptr->opdo) {
5227  if (instr.has_bnd) {
5228  data[0] = 0xf2;
5229  data++;
5230  }
5231  retval = lt_ptr->opdo(a, data, &instr);
5232  // if op supports bnd then the first byte will
5233  // be 0xf2.
5234  if (instr.has_bnd) {
5235  retval++;
5236  }
5237  }
5238  }
5239  break;
5240  }
5241  }
5242  if (retval > 0) {
5243  rz_asm_op_set_buf(ao, __data, retval);
5244  }
5245  free(instr.mnemonic);
5246  return retval;
5247 }
5248 
5250  .name = "x86.nz",
5251  .desc = "x86 handmade assembler",
5252  .license = "LGPL3",
5253  .arch = "x86",
5254  .bits = 16 | 32 | 64,
5255  .endian = RZ_SYS_ENDIAN_LITTLE,
5256  .assemble = &assemble
5257 };
5258 
5259 #ifndef RZ_PLUGIN_INCORE
5261  .type = RZ_LIB_TYPE_ASM,
5262  .data = &rz_asm_plugin_x86_nz,
5263  .version = RZ_VERSION
5264 };
5265 #endif
ut8 op
Definition: 6502dis.c:13
static enum map_type last_type
Definition: aarch64-dis.c:45
static char * regs[]
Definition: analysis_sh.c:203
RZ_API void rz_asm_op_set_buf(RzAsmOp *op, const ut8 *buf, int len)
Definition: aop.c:83
lzma_index ** i
Definition: index.h:629
static ut32 reg_bits(arm_reg reg)
Definition: arm_il32.c:82
static int opmovabs(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:2372
#define is_valid_registers(op)
Definition: asm_x86_nz.c:79
static int opvmon(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:4202
const ut8 SEG_REG_PREFIXES[]
Definition: asm_x86_nz.c:83
static int opout(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:2545
static ut64 getnum(RzAsm *a, const char *s)
Definition: asm_x86_nz.c:5139
static int oplea(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:1761
static x86newTokenType getToken(const char *str, size_t *begin, size_t *end)
Definition: asm_x86_nz.c:4625
static int opretf(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:2612
static int opfiadd(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3044
static int opfsubr(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3732
static int opfucom(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:2980
enum tokentype_t x86newTokenType
static int opverr(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:4138
static int opfxsave(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3269
#define OT_GPREG
Definition: asm_x86_nz.c:33
tokentype_t
Definition: asm_x86_nz.c:85
@ TT_WORD
Definition: asm_x86_nz.c:87
@ TT_NUMBER
Definition: asm_x86_nz.c:88
@ TT_SPECIAL
Definition: asm_x86_nz.c:89
@ TT_EOF
Definition: asm_x86_nz.c:86
static int opor(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:626
static int opfldenv(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3198
static int opmov(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:1862
static int opfrstor(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:2942
static int process_16bit_group_1(RzAsm *a, ut8 *data, const Opcode *op, int op1)
Definition: asm_x86_nz.c:221
static int opin(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:1400
static int process_group_1(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:246
static int oplidt(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3999
static int opfcmov(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:2881
static int opfisubr(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3791
register_t
Definition: asm_x86_nz.c:92
@ X86R_R15
Definition: asm_x86_nz.c:135
@ X86R_BH
Definition: asm_x86_nz.c:118
@ X86R_R11
Definition: asm_x86_nz.c:131
@ X86R_RSI
Definition: asm_x86_nz.c:125
@ X86R_EDI
Definition: asm_x86_nz.c:101
@ X86R_R13
Definition: asm_x86_nz.c:133
@ X86R_CR7
Definition: asm_x86_nz.c:149
@ X86R_DH
Definition: asm_x86_nz.c:117
@ X86R_EIP
Definition: asm_x86_nz.c:102
@ X86R_ESI
Definition: asm_x86_nz.c:100
@ X86R_DR6
Definition: asm_x86_nz.c:156
@ X86R_CR3
Definition: asm_x86_nz.c:145
@ X86R_RSP
Definition: asm_x86_nz.c:123
@ X86R_FS
Definition: asm_x86_nz.c:140
@ X86R_SS
Definition: asm_x86_nz.c:137
@ X86R_CX
Definition: asm_x86_nz.c:104
@ X86R_CR0
Definition: asm_x86_nz.c:142
@ X86R_RDI
Definition: asm_x86_nz.c:126
@ X86R_CR4
Definition: asm_x86_nz.c:146
@ X86R_AL
Definition: asm_x86_nz.c:111
@ X86R_RCX
Definition: asm_x86_nz.c:120
@ X86R_RDX
Definition: asm_x86_nz.c:121
@ X86R_CR1
Definition: asm_x86_nz.c:143
@ X86R_EBX
Definition: asm_x86_nz.c:97
@ X86R_R10
Definition: asm_x86_nz.c:130
@ X86R_EBP
Definition: asm_x86_nz.c:99
@ X86R_DR7
Definition: asm_x86_nz.c:157
@ X86R_R14
Definition: asm_x86_nz.c:134
@ X86R_DR1
Definition: asm_x86_nz.c:151
@ X86R_CR6
Definition: asm_x86_nz.c:148
@ X86R_DR3
Definition: asm_x86_nz.c:153
@ X86R_SP
Definition: asm_x86_nz.c:107
@ X86R_RIP
Definition: asm_x86_nz.c:127
@ X86R_BX
Definition: asm_x86_nz.c:106
@ X86R_BP
Definition: asm_x86_nz.c:108
@ X86R_AH
Definition: asm_x86_nz.c:115
@ X86R_BL
Definition: asm_x86_nz.c:114
@ X86R_DS
Definition: asm_x86_nz.c:138
@ X86R_EAX
Definition: asm_x86_nz.c:94
@ X86R_R12
Definition: asm_x86_nz.c:132
@ X86R_CR2
Definition: asm_x86_nz.c:144
@ X86R_CL
Definition: asm_x86_nz.c:112
@ X86R_CR5
Definition: asm_x86_nz.c:147
@ X86R_RBX
Definition: asm_x86_nz.c:122
@ X86R_UNDEFINED
Definition: asm_x86_nz.c:93
@ X86R_GS
Definition: asm_x86_nz.c:141
@ X86R_ESP
Definition: asm_x86_nz.c:98
@ X86R_DR0
Definition: asm_x86_nz.c:150
@ X86R_DX
Definition: asm_x86_nz.c:105
@ X86R_ECX
Definition: asm_x86_nz.c:95
@ X86R_CS
Definition: asm_x86_nz.c:136
@ X86R_SI
Definition: asm_x86_nz.c:109
@ X86R_DI
Definition: asm_x86_nz.c:110
@ X86R_CH
Definition: asm_x86_nz.c:116
@ X86R_R8
Definition: asm_x86_nz.c:128
@ X86R_ES
Definition: asm_x86_nz.c:139
@ X86R_EDX
Definition: asm_x86_nz.c:96
@ X86R_RBP
Definition: asm_x86_nz.c:124
@ X86R_AX
Definition: asm_x86_nz.c:103
@ X86R_DL
Definition: asm_x86_nz.c:113
@ X86R_DR2
Definition: asm_x86_nz.c:152
@ X86R_R9
Definition: asm_x86_nz.c:129
@ X86R_RAX
Definition: asm_x86_nz.c:119
@ X86R_DR4
Definition: asm_x86_nz.c:154
@ X86R_DR5
Definition: asm_x86_nz.c:155
static int opfnstsw(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3852
RzAsmPlugin rz_asm_plugin_x86_nz
Definition: asm_x86_nz.c:5249
static int opfmulp(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3603
static int opdec(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:1055
static int opret(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:2594
static int opfstsw(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3875
static int opxor(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:664
static int opand(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:587
#define OT_REG(num)
Definition: asm_x86_nz.c:46
static int opfmul(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3566
static int opsbb(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:752
#define OT_FPUREG
Definition: asm_x86_nz.c:35
static int opfimul(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3625
static int opsmsw(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:4117
static int opfucomp(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3001
static int opfnstcw(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3815
static int opfdivp(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3437
static int parseOperand(RzAsm *a, const char *str, Operand *op, bool isrepop)
Definition: asm_x86_nz.c:4876
static int opsub(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:613
static int opxadd(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:639
#define OT_OWORD
Definition: asm_x86_nz.c:53
static int endbr32(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:714
static int opfxrstor(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3251
struct operand_t Operand
#define OT_REGALL
Definition: asm_x86_nz.c:28
static int opfnsave(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3900
#define OT_DEBUGREG
Definition: asm_x86_nz.c:39
static int opficom(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3105
LookupTable oplookup[]
Definition: asm_x86_nz.c:4268
static Register parseReg(RzAsm *a, const char *str, size_t *pos, ut32 *type)
Definition: asm_x86_nz.c:4711
static int opverw(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:4160
static int opficomp(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3129
static int opneg(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:687
static int opfldcw(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3180
static int opfdivrp(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3520
static int opmovx(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:1015
static int opvmclear(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:4182
#define OT_REGTYPE
Definition: asm_x86_nz.c:43
static int opadd(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:574
#define OT_SEGMENTREG
Definition: asm_x86_nz.c:34
static int is_al_reg(const Operand *op)
Definition: asm_x86_nz.c:209
static int endbr64(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:709
static bool is_st_register(const char *token)
Definition: asm_x86_nz.c:4687
static int assemble(RzAsm *a, RzAsmOp *ao, const char *str)
Definition: asm_x86_nz.c:5202
#define OT_WORD
Definition: asm_x86_nz.c:50
static int oprep(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:5149
static int opfistp(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3311
static int opbswap(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:806
#define OT_XMMREG
Definition: asm_x86_nz.c:37
#define MAX_REPOP_LENGTH
Definition: asm_x86_nz.c:77
#define OT_DWORD
Definition: asm_x86_nz.c:51
#define OT_QWORD
Definition: asm_x86_nz.c:52
static int opfsubrp(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3769
#define OT_MMXREG
Definition: asm_x86_nz.c:36
RZ_API RzLibStruct rizin_plugin
Definition: asm_x86_nz.c:5260
static int opfild(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3153
static int opsidt(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:4078
#define OT_BYTE
Definition: asm_x86_nz.c:49
#define OT_MEMORY
Definition: asm_x86_nz.c:31
static int opfsub(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3649
#define OT_CONSTANT
Definition: asm_x86_nz.c:32
static int oplgdt(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3981
static int opxchg(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:2774
static int opnot(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:719
enum register_t Register
static void parse_segment_offset(RzAsm *a, const char *str, size_t *pos, Operand *op, int reg_index)
Definition: asm_x86_nz.c:4851
static int opinc(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:1472
static int oppush(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:2475
static int opfxch(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:2959
static int opfsave(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3918
static bool is_xmm_register(const char *token)
Definition: asm_x86_nz.c:4657
static int oples(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:1826
static int opsgdt(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:4017
static int oppop(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:2422
static int oploop(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:2585
struct lookup_t LookupTable
static int opfisub(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3708
static int opfbstp(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3233
struct Opcode_t Opcode
static int opidiv(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:1202
static int opffree(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:2925
static int opaam(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:1042
static int opjc(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:1630
#define MAX_OPERANDS
Definition: asm_x86_nz.c:76
static int opvmptrld(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:4222
static int opint(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:1618
static int opclflush(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:1442
static int opfist(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3287
static int process_group_2(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:340
#define OPSIZE_SHIFT
Definition: asm_x86_nz.c:19
static int opmul(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:2393
static bool is_mm_register(const char *token)
Definition: asm_x86_nz.c:4666
static int opfidivr(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3542
static int opstmxcsr(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:4035
static int opcall(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:835
static bool is_debug_or_control(Operand op)
Definition: asm_x86_nz.c:198
static int opsldt(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:4096
static int opimul(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:1260
static int opcmp(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:600
static int opadc(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:561
static int opfidiv(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3459
static int opfdiv(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3400
static int opvmptrst(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:4241
static int opfnstenv(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3383
#define OT_UNKNOWN
Definition: asm_x86_nz.c:48
static int process_1byte_op(RzAsm *a, ut8 *data, const Opcode *op, int op1)
Definition: asm_x86_nz.c:414
static int opstr(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:4054
#define ALL_SIZE
Definition: asm_x86_nz.c:56
static int opbs(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:765
static int opset(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:2642
static int parseOpcode(RzAsm *a, const char *op, Opcode *out)
Definition: asm_x86_nz.c:5095
static int opfstcw(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3833
#define OT_TBYTE
Definition: asm_x86_nz.c:54
#define OT_CONTROLREG
Definition: asm_x86_nz.c:38
static int opfsubp(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3686
static int opcdqe(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:2871
static int opfbld(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3215
static int oplmsw(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3959
static int opcmov(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:886
static int opfisttp(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3338
static int opfstenv(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3365
static int oplldt(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3937
static int opstos(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:2626
static ut8 getsib(const ut8 sib)
Definition: asm_x86_nz.c:202
static int optest(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:2708
static int opfaddp(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3022
static int opdiv(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:1231
static int opfdivr(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3483
static int opfadd(RzAsm *a, ut8 *data, const Opcode *op)
Definition: asm_x86_nz.c:3068
int bits(struct state *s, int need)
Definition: blast.c:72
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
#define RZ_API
#define NULL
Definition: cris-opc.c:27
int mod(int a, int b)
Definition: crypto_rot.c:8
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void length
Definition: sflib.h:133
#define ut8
Definition: dcpu16.h:8
uint32_t ut32
RZ_API RzFlagItem * rz_flag_get(RzFlag *f, const char *name)
Definition: flag.c:310
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void uLong size
Definition: ioapi.h:138
voidpf uLong offset
Definition: ioapi.h:144
#define reg(n)
uint8_t ut8
Definition: lh5801.h:11
void * p
Definition: libc.cpp:67
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
void * malloc(size_t size)
Definition: malloc.c:123
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
int args
Definition: mipsasm.c:18
int n
Definition: mipsasm.c:19
int type
Definition: mipsasm.c:17
static RzSocket * s
Definition: rtr.c:28
@ RZ_LIB_TYPE_ASM
Definition: rz_lib.h:72
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RZ_API ut64 rz_num_math(RzNum *num, const char *str)
Definition: unum.c:456
RZ_API int rz_str_casecmp(const char *dst, const char *orig)
Definition: str.c:121
RZ_API char * rz_str_ndup(RZ_NULLABLE const char *ptr, int len)
Create new copy of string ptr limited to size len.
Definition: str.c:1006
RZ_API int rz_str_ncasecmp(const char *dst, const char *orig, size_t n)
Definition: str.c:129
#define RZ_SYS_ENDIAN_LITTLE
Definition: rz_types.h:526
#define B0010
#define st8
Definition: rz_types_base.h:16
#define B0111
#define ST8_MIN
#define st64
Definition: rz_types_base.h:10
#define UT32_MAX
Definition: rz_types_base.h:99
#define B0100
#define ST32_MAX
Definition: rz_types_base.h:97
#define B0011
#define B0001
#define B0000
#define B0101
#define st32
Definition: rz_types_base.h:12
#define ST8_MAX
#define RZ_VERSION
Definition: rz_version.h:8
#define isspace(c)
Definition: safe-ctype.h:141
#define isalpha(c)
Definition: safe-ctype.h:125
#define isdigit(c)
Definition: safe-ctype.h:131
#define isalnum(c)
Definition: safe-ctype.h:127
static int
Definition: sfsocketcall.h:114
#define c(i)
Definition: sha256.c:43
#define a(i)
Definition: sha256.c:41
ut8 opcode[3]
Definition: armass64.c:81
bool has_bnd
Definition: asm_x86_nz.c:195
size_t op_len
Definition: armass64.c:80
int operands_count
Definition: armass64.c:83
char * mnemonic
Definition: armass64.c:78
bool is_short
Definition: asm_x86_nz.c:191
int(* opdo)(RzAsm *, ut8 *, const Opcode *)
Definition: asm_x86_nz.c:4263
char mnemonic[12]
Definition: asm_x86_nz.c:4261
ut64 opcode
Definition: asm_x86_nz.c:4264
int only_x32
Definition: asm_x86_nz.c:4262
st8 offset_sign
Definition: asm_x86_nz.c:170
ut32 dest_size
Definition: asm_x86_nz.c:183
int scale[2]
Definition: asm_x86_nz.c:172
Register reg
Definition: asm_x86_nz.c:164
ut64 immediate
Definition: armass64.c:60
ut64 offset
Definition: asm_x86_nz.c:169
bool is_good_flag
Definition: asm_x86_nz.c:176
char rep_op[MAX_REPOP_LENGTH]
Definition: asm_x86_nz.c:179
bool extended
Definition: asm_x86_nz.c:165
ut32 type
Definition: asm_x86_nz.c:161
ut32 reg_size
Definition: asm_x86_nz.c:184
bool explicit_size
Definition: asm_x86_nz.c:182
Register regs[2]
Definition: asm_x86_nz.c:171
const char * name
Definition: rz_asm.h:130
const char * version
Definition: rz_asm.h:133
RzFlag * flags
Definition: rz_core.h:330
int pos
Definition: main.c:11
Definition: dis.c:32
static st64 delta
Definition: vmenus.c:2425
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
mnemonic
Definition: z80asm.h:48
int read(izstream &zs, T *x, Items items)
Definition: zstream.h:115