1 /* assemble.c code generation for the Netwide Assembler
3 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
4 * Julian Hall. All rights reserved. The software is
5 * redistributable under the license given in the file "LICENSE"
6 * distributed in the NASM archive.
8 * the actual codes (C syntax, i.e. octal):
9 * \0 - terminates the code. (Unless it's a literal of course.)
10 * \1, \2, \3 - that many literal bytes follow in the code stream
11 * \4, \6 - the POP/PUSH (respectively) codes for CS, DS, ES, SS
12 * (POP is never used for CS) depending on operand 0
13 * \5, \7 - the second byte of POP/PUSH codes for FS, GS, depending
15 * \10..\13 - a literal byte follows in the code stream, to be added
16 * to the register value of operand 0..3
17 * \14..\17 - a signed byte immediate operand, from operand 0..3
18 * \20..\23 - a byte immediate operand, from operand 0..3
19 * \24..\27 - an unsigned byte immediate operand, from operand 0..3
20 * \30..\33 - a word immediate operand, from operand 0..3
21 * \34..\37 - select between \3[0-3] and \4[0-3] depending on 16/32 bit
22 * assembly mode or the operand-size override on the operand
23 * \40..\43 - a long immediate operand, from operand 0..3
24 * \44..\47 - select between \3[0-3], \4[0-3] and \5[4-7]
25 * depending on the address size of the instruction.
26 * \50..\53 - a byte relative operand, from operand 0..3
27 * \54..\57 - a qword immediate operand, from operand 0..3
28 * \60..\63 - a word relative operand, from operand 0..3
29 * \64..\67 - select between \6[0-3] and \7[0-3] depending on 16/32 bit
30 * assembly mode or the operand-size override on the operand
31 * \70..\73 - a long relative operand, from operand 0..3
32 * \74..\77 - a word constant, from the _segment_ part of operand 0..3
33 * \1ab - a ModRM, calculated on EA in operand a, with the spare
34 * field the register value of operand b.
35 * \140..\143 - an immediate word or signed byte for operand 0..3
36 * \144..\147 - or 2 (s-field) into opcode byte if operand 0..3
37 * is a signed byte rather than a word. Opcode byte follows.
38 * \150..\153 - an immediate dword or signed byte for operand 0..3
39 * \154..\157 - or 2 (s-field) into opcode byte if operand 0..3
40 * is a signed byte rather than a dword. Opcode byte follows.
41 * \160..\163 - this instruction uses DREX rather than REX, with the
42 * OC0 field set to 0, and the dest field taken from
44 * \164..\167 - this instruction uses DREX rather than REX, with the
45 * OC0 field set to 1, and the dest field taken from
47 * \171 - placement of DREX suffix in the absence of an EA
48 * \172\ab - the register number from operand a in bits 7..4, with
49 * the 4-bit immediate from operand b in bits 0..3.
50 * \173\xab - the register number from operand a in bits 7..4, with
51 * the value b in bits 0..3.
52 * \2ab - a ModRM, calculated on EA in operand a, with the spare
53 * field equal to digit b.
54 * \250..\253 - same as \150..\153, except warn if the 64-bit operand
55 * is not equal to the truncated and sign-extended 32-bit
56 * operand; used for 32-bit immediates in 64-bit mode.
57 * \260..\263 - this instruction uses VEX rather than REX, with the
58 * V field taken from operand 0..3.
59 * \270 - this instruction uses VEX rather than REX, with the
60 * V field set to 1111b.
62 * VEX prefixes are followed by the sequence:
63 * \mm\wlp where mm is the M field; and wlp is:
67 * ww = 2 for W used as REX.W
69 * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
70 * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
71 * \312 - (disassembler only) marker on LOOP, LOOPxx instructions.
72 * \313 - indicates fixed 64-bit address size, 0x67 invalid.
73 * \314 - (disassembler only) invalid with REX.B
74 * \315 - (disassembler only) invalid with REX.X
75 * \316 - (disassembler only) invalid with REX.R
76 * \317 - (disassembler only) invalid with REX.W
77 * \320 - indicates fixed 16-bit operand size, i.e. optional 0x66.
78 * \321 - indicates fixed 32-bit operand size, i.e. optional 0x66.
79 * \322 - indicates that this instruction is only valid when the
80 * operand size is the default (instruction to disassembler,
81 * generates no code in the assembler)
82 * \323 - indicates fixed 64-bit operand size, REX on extensions only.
83 * \324 - indicates 64-bit operand size requiring REX prefix.
84 * \330 - a literal byte follows in the code stream, to be added
85 * to the condition code value of the instruction.
86 * \331 - instruction not valid with REP prefix. Hint for
87 * disassembler only; for SSE instructions.
88 * \332 - REP prefix (0xF2 byte) used as opcode extension.
89 * \333 - REP prefix (0xF3 byte) used as opcode extension.
90 * \334 - LOCK prefix used instead of REX.R
91 * \335 - disassemble a rep (0xF3 byte) prefix as repe not rep.
92 * \340 - reserve <operand 0> bytes of uninitialized storage.
93 * Operand 0 had better be a segmentless constant.
94 * \364 - operand-size prefix (0x66) not permitted
95 * \365 - address-size prefix (0x67) not permitted
96 * \366 - operand-size prefix (0x66) used as opcode extension
97 * \367 - address-size prefix (0x67) used as opcode extension
98 * \370,\371,\372 - match only if operand 0 meets byte jump criteria.
99 * 370 is used for Jcc, 371 is used for JMP.
100 * \373 - assemble 0x03 if bits==16, 0x05 if bits==32;
101 * used for conditional jump over longer jump
104 #include "compiler.h"
108 #include <inttypes.h>
112 #include "assemble.h"
115 #include "regflags.c"
119 int sib_present; /* is a SIB byte necessary? */
120 int bytes; /* # of bytes of offset needed */
121 int size; /* lazy - this is sib+bytes+1 */
122 uint8_t modrm, sib, rex, rip; /* the bytes themselves */
125 static uint32_t cpu; /* cpu level received from nasm.c */
126 static efunc errfunc;
127 static struct ofmt *outfmt;
128 static ListGen *list;
130 static int64_t calcsize(int32_t, int64_t, int, insn *, const uint8_t *);
131 static void gencode(int32_t, int64_t, int, insn *, const uint8_t *, int64_t);
132 static int matches(const struct itemplate *, insn *, int bits);
133 static int32_t regflag(const operand *);
134 static int32_t regval(const operand *);
135 static int rexflags(int, int32_t, int);
136 static int op_rexflags(const operand *, int);
137 static ea *process_ea(operand *, ea *, int, int, int, int32_t, int);
138 static void add_asp(insn *, int);
140 static int has_prefix(insn * ins, enum prefix_pos pos, enum prefixes prefix)
142 return ins->prefixes[pos] == prefix;
145 static void assert_no_prefix(insn * ins, enum prefix_pos pos)
147 if (ins->prefixes[pos])
148 errfunc(ERR_NONFATAL, "invalid %s prefix",
149 prefix_name(ins->prefixes[pos]));
152 static const char *size_name(int size)
172 static void warn_overflow(int size, int64_t data)
175 int64_t lim = ((int64_t)1 << (size*8))-1;
177 if (data < ~lim || data > lim)
178 errfunc(ERR_WARNING | ERR_WARN_NOV,
179 "%s data exceeds bounds", size_name(size));
183 * This routine wrappers the real output format's output routine,
184 * in order to pass a copy of the data off to the listing file
185 * generator at the same time.
187 static void out(int64_t offset, int32_t segto, const void *data,
188 enum out_type type, uint64_t size,
189 int32_t segment, int32_t wrt)
191 static int32_t lineno = 0; /* static!!! */
192 static char *lnfname = NULL;
195 if (type == OUT_ADDRESS && segment == NO_SEG && wrt == NO_SEG) {
197 * This is a non-relocated address, and we're going to
198 * convert it into RAWDATA format.
203 errfunc(ERR_PANIC, "OUT_ADDRESS with size > 8");
207 WRITEADDR(q, *(int64_t *)data, size);
212 list->output(offset, data, type, size);
215 * this call to src_get determines when we call the
216 * debug-format-specific "linenum" function
217 * it updates lineno and lnfname to the current values
218 * returning 0 if "same as last time", -2 if lnfname
219 * changed, and the amount by which lineno changed,
220 * if it did. thus, these variables must be static
223 if (src_get(&lineno, &lnfname)) {
224 outfmt->current_dfmt->linenum(lnfname, lineno, segto);
227 outfmt->output(segto, data, type, size, segment, wrt);
230 static int jmp_match(int32_t segment, int64_t offset, int bits,
231 insn * ins, const uint8_t *code)
236 if (c != 0370 && c != 0371)
238 if (ins->oprs[0].opflags & OPFLAG_FORWARD) {
239 if ((optimizing < 0 || (ins->oprs[0].type & STRICT))
243 return (pass0 == 0); /* match a forward reference */
245 isize = calcsize(segment, offset, bits, ins, code);
246 if (ins->oprs[0].segment != segment)
248 isize = ins->oprs[0].offset - offset - isize; /* isize is now the delta */
249 if (isize >= -128L && isize <= 127L)
250 return 1; /* it is byte size */
255 int64_t assemble(int32_t segment, int64_t offset, int bits, uint32_t cp,
256 insn * instruction, struct ofmt *output, efunc error,
259 const struct itemplate *temp;
264 int64_t start = offset;
265 int64_t wsize = 0; /* size for DB etc. */
267 errfunc = error; /* to pass to other functions */
269 outfmt = output; /* likewise */
270 list = listgen; /* and again */
272 switch (instruction->opcode) {
299 int32_t t = instruction->times;
302 "instruction->times < 0 (%ld) in assemble()", t);
304 while (t--) { /* repeat TIMES times */
305 for (e = instruction->eops; e; e = e->next) {
306 if (e->type == EOT_DB_NUMBER) {
308 if (e->segment != NO_SEG)
309 errfunc(ERR_NONFATAL,
310 "one-byte relocation attempted");
312 uint8_t out_byte = e->offset;
313 out(offset, segment, &out_byte,
314 OUT_RAWDATA, 1, NO_SEG, NO_SEG);
316 } else if (wsize > 8) {
317 errfunc(ERR_NONFATAL, "integer supplied to a DT or DO"
320 out(offset, segment, &e->offset,
321 OUT_ADDRESS, wsize, e->segment, e->wrt);
323 } else if (e->type == EOT_DB_STRING) {
326 out(offset, segment, e->stringval,
327 OUT_RAWDATA, e->stringlen, NO_SEG, NO_SEG);
328 align = e->stringlen % wsize;
331 align = wsize - align;
333 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
334 OUT_RAWDATA, align, NO_SEG, NO_SEG);
336 offset += e->stringlen + align;
339 if (t > 0 && t == instruction->times - 1) {
341 * Dummy call to list->output to give the offset to the
344 list->output(offset, NULL, OUT_RAWDATA, 0);
345 list->uplevel(LIST_TIMES);
348 if (instruction->times > 1)
349 list->downlevel(LIST_TIMES);
350 return offset - start;
353 if (instruction->opcode == I_INCBIN) {
354 static char fname[FILENAME_MAX];
357 char *prefix = "", *combine;
358 char **pPrevPath = NULL;
360 len = FILENAME_MAX - 1;
361 if (len > instruction->eops->stringlen)
362 len = instruction->eops->stringlen;
363 strncpy(fname, instruction->eops->stringval, len);
366 while (1) { /* added by alexfru: 'incbin' uses include paths */
367 combine = nasm_malloc(strlen(prefix) + len + 1);
368 strcpy(combine, prefix);
369 strcat(combine, fname);
371 if ((fp = fopen(combine, "rb")) != NULL) {
377 pPrevPath = pp_get_include_path_ptr(pPrevPath);
378 if (pPrevPath == NULL)
384 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
386 else if (fseek(fp, 0L, SEEK_END) < 0)
387 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
390 static char buf[2048];
391 int32_t t = instruction->times;
395 if (instruction->eops->next) {
396 base = instruction->eops->next->offset;
398 if (instruction->eops->next->next &&
399 len > instruction->eops->next->next->offset)
400 len = instruction->eops->next->next->offset;
403 * Dummy call to list->output to give the offset to the
406 list->output(offset, NULL, OUT_RAWDATA, 0);
407 list->uplevel(LIST_INCBIN);
411 fseek(fp, base, SEEK_SET);
415 fread(buf, 1, (l > (int32_t) sizeof(buf) ? (int32_t) sizeof(buf) : l),
419 * This shouldn't happen unless the file
420 * actually changes while we are reading
424 "`incbin': unexpected EOF while"
425 " reading file `%s'", fname);
426 t = 0; /* Try to exit cleanly */
429 out(offset, segment, buf, OUT_RAWDATA, m,
434 list->downlevel(LIST_INCBIN);
435 if (instruction->times > 1) {
437 * Dummy call to list->output to give the offset to the
440 list->output(offset, NULL, OUT_RAWDATA, 0);
441 list->uplevel(LIST_TIMES);
442 list->downlevel(LIST_TIMES);
445 return instruction->times * len;
447 return 0; /* if we're here, there's an error */
450 /* Check to see if we need an address-size prefix */
451 add_asp(instruction, bits);
455 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++){
456 int m = matches(temp, instruction, bits);
459 m += jmp_match(segment, offset, bits, instruction, temp->code);
461 if (m == 100) { /* matches! */
462 const uint8_t *codes = temp->code;
463 int64_t insn_size = calcsize(segment, offset, bits,
465 itimes = instruction->times;
466 if (insn_size < 0) /* shouldn't be, on pass two */
467 error(ERR_PANIC, "errors made it through from pass one");
470 for (j = 0; j < MAXPREFIX; j++) {
472 switch (instruction->prefixes[j]) {
488 "cs segment base generated, but will be ignored in 64-bit mode");
495 "ds segment base generated, but will be ignored in 64-bit mode");
502 "es segment base generated, but will be ignored in 64-bit mode");
515 "ss segment base generated, but will be ignored in 64-bit mode");
522 "segr6 and segr7 cannot be used as prefixes");
527 "16-bit addressing is not supported "
529 } else if (bits != 16)
539 "64-bit addressing is only supported "
563 error(ERR_PANIC, "invalid instruction prefix");
566 out(offset, segment, &c, OUT_RAWDATA, 1,
571 insn_end = offset + insn_size;
572 gencode(segment, offset, bits, instruction, codes,
575 if (itimes > 0 && itimes == instruction->times - 1) {
577 * Dummy call to list->output to give the offset to the
580 list->output(offset, NULL, OUT_RAWDATA, 0);
581 list->uplevel(LIST_TIMES);
584 if (instruction->times > 1)
585 list->downlevel(LIST_TIMES);
586 return offset - start;
587 } else if (m > 0 && m > size_prob) {
593 if (temp->opcode == -1) { /* didn't match any instruction */
596 error(ERR_NONFATAL, "operation size not specified");
599 error(ERR_NONFATAL, "mismatch in operand sizes");
602 error(ERR_NONFATAL, "no instruction for this cpu level");
605 error(ERR_NONFATAL, "instruction not supported in 64-bit mode");
609 "invalid combination of opcode and operands");
616 int64_t insn_size(int32_t segment, int64_t offset, int bits, uint32_t cp,
617 insn * instruction, efunc error)
619 const struct itemplate *temp;
621 errfunc = error; /* to pass to other functions */
624 if (instruction->opcode == -1)
627 if (instruction->opcode == I_DB || instruction->opcode == I_DW ||
628 instruction->opcode == I_DD || instruction->opcode == I_DQ ||
629 instruction->opcode == I_DT || instruction->opcode == I_DO) {
631 int32_t isize, osize, wsize = 0; /* placate gcc */
634 switch (instruction->opcode) {
657 for (e = instruction->eops; e; e = e->next) {
661 if (e->type == EOT_DB_NUMBER)
663 else if (e->type == EOT_DB_STRING)
664 osize = e->stringlen;
666 align = (-osize) % wsize;
669 isize += osize + align;
671 return isize * instruction->times;
674 if (instruction->opcode == I_INCBIN) {
675 char fname[FILENAME_MAX];
678 char *prefix = "", *combine;
679 char **pPrevPath = NULL;
681 len = FILENAME_MAX - 1;
682 if (len > instruction->eops->stringlen)
683 len = instruction->eops->stringlen;
684 strncpy(fname, instruction->eops->stringval, len);
687 /* added by alexfru: 'incbin' uses include paths */
689 combine = nasm_malloc(strlen(prefix) + len + 1);
690 strcpy(combine, prefix);
691 strcat(combine, fname);
693 if ((fp = fopen(combine, "rb")) != NULL) {
699 pPrevPath = pp_get_include_path_ptr(pPrevPath);
700 if (pPrevPath == NULL)
706 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
708 else if (fseek(fp, 0L, SEEK_END) < 0)
709 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
714 if (instruction->eops->next) {
715 len -= instruction->eops->next->offset;
716 if (instruction->eops->next->next &&
717 len > instruction->eops->next->next->offset) {
718 len = instruction->eops->next->next->offset;
721 return instruction->times * len;
723 return 0; /* if we're here, there's an error */
726 /* Check to see if we need an address-size prefix */
727 add_asp(instruction, bits);
729 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++) {
730 int m = matches(temp, instruction, bits);
732 m += jmp_match(segment, offset, bits, instruction, temp->code);
735 /* we've matched an instruction. */
737 const uint8_t *codes = temp->code;
740 isize = calcsize(segment, offset, bits, instruction, codes);
743 for (j = 0; j < MAXPREFIX; j++) {
744 switch (instruction->prefixes[j]) {
770 return isize * instruction->times;
773 return -1; /* didn't match any instruction */
776 static bool possible_sbyte(insn * ins, int op)
778 return !(ins->forw_ref && ins->oprs[op].opflags) &&
780 !(ins->oprs[op].type & STRICT) &&
781 ins->oprs[op].wrt == NO_SEG && ins->oprs[op].segment == NO_SEG;
784 /* check that opn[op] is a signed byte of size 16 or 32 */
785 static bool is_sbyte16(insn * ins, int op)
789 if (!possible_sbyte(ins, op))
792 v = ins->oprs[op].offset;
793 return v >= -128 && v <= 127;
796 static bool is_sbyte32(insn * ins, int op)
800 if (!possible_sbyte(ins, op))
803 v = ins->oprs[op].offset;
804 return v >= -128 && v <= 127;
807 /* check that opn[op] is a signed byte of size 32; warn if this is not
808 the original value when extended to 64 bits */
809 static bool is_sbyte64(insn * ins, int op)
814 /* dead in the water on forward reference or External */
815 if (!possible_sbyte(ins, op))
818 v64 = ins->oprs[op].offset;
821 warn_overflow(32, v64);
823 return v32 >= -128 && v32 <= 127;
825 static int64_t calcsize(int32_t segment, int64_t offset, int bits,
826 insn * ins, const uint8_t *codes)
833 ins->rex = 0; /* Ensure REX is reset */
835 if (ins->prefixes[PPS_OSIZE] == P_O64)
838 (void)segment; /* Don't warn that this parameter is unused */
839 (void)offset; /* Don't warn that this parameter is unused */
843 opx = &ins->oprs[c & 3];
848 codes += c, length += c;
861 op_rexflags(opx, REX_B|REX_H|REX_P|REX_W);
892 if (opx->type & (BITS16 | BITS32 | BITS64))
893 length += (opx->type & BITS16) ? 2 : 4;
895 length += (bits == 16) ? 2 : 4;
907 length += ins->addr_size >> 3;
919 length += 8; /* MOV reg64/imm */
931 if (opx->type & (BITS16 | BITS32 | BITS64))
932 length += (opx->type & BITS16) ? 2 : 4;
934 length += (bits == 16) ? 2 : 4;
952 length += is_sbyte16(ins, c & 3) ? 1 : 2;
965 length += is_sbyte32(ins, c & 3) ? 1 : 4;
980 ins->drexdst = regval(opx);
987 ins->rex |= REX_D|REX_OC;
988 ins->drexdst = regval(opx);
1001 length += is_sbyte64(ins, c & 3) ? 1 : 4;
1009 ins->drexdst = regval(opx);
1010 ins->vex_m = *codes++;
1011 ins->vex_wlp = *codes++;
1017 ins->vex_m = *codes++;
1018 ins->vex_wlp = *codes++;
1028 length += (bits != 16) && !has_prefix(ins, PPS_ASIZE, P_A16);
1031 length += (bits != 32) && !has_prefix(ins, PPS_ASIZE, P_A32);
1036 if (bits != 64 || has_prefix(ins, PPS_ASIZE, P_A16) ||
1037 has_prefix(ins, PPS_ASIZE, P_A32))
1046 length += (bits != 16);
1049 length += (bits == 16);
1074 if (ins->oprs[0].segment != NO_SEG)
1075 errfunc(ERR_NONFATAL, "attempt to reserve non-constant"
1076 " quantity of BSS space");
1078 length += ins->oprs[0].offset;
1094 default: /* can't do it by 'case' statements */
1095 if (c >= 0100 && c <= 0277) { /* it's an EA */
1099 ea_data.rex = 0; /* Ensure ea.REX is initially 0 */
1102 /* pick rfield from operand b */
1103 rflags = regflag(&ins->oprs[c & 7]);
1104 rfield = regvals[ins->oprs[c & 7].basereg];
1111 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
1112 ins->addr_size, rfield, rflags, ins->forw_ref)) {
1113 errfunc(ERR_NONFATAL, "invalid effective address");
1116 ins->rex |= ea_data.rex;
1117 length += ea_data.size;
1120 errfunc(ERR_PANIC, "internal instruction table corrupt"
1121 ": instruction code 0x%02X given", c);
1126 ins->rex &= rex_mask;
1128 if (ins->rex & REX_V) {
1129 int bad32 = REX_R|REX_W|REX_X|REX_B;
1131 if (ins->rex & REX_H) {
1132 errfunc(ERR_NONFATAL, "cannot use high register in vex instruction");
1135 switch (ins->vex_wlp & 030) {
1148 if (bits != 64 && ((ins->rex & bad32) || ins->drexdst > 7)) {
1149 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
1152 if (ins->vex_m != 1 || (ins->rex & (REX_W|REX_R|REX_B)))
1156 } else if (ins->rex & REX_D) {
1157 if (ins->rex & REX_H) {
1158 errfunc(ERR_NONFATAL, "cannot use high register in drex instruction");
1161 if (bits != 64 && ((ins->rex & (REX_R|REX_W|REX_X|REX_B)) ||
1162 ins->drexdst > 7)) {
1163 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
1167 } else if (ins->rex & REX_REAL) {
1168 if (ins->rex & REX_H) {
1169 errfunc(ERR_NONFATAL, "cannot use high register in rex instruction");
1171 } else if (bits == 64) {
1173 } else if ((ins->rex & REX_L) &&
1174 !(ins->rex & (REX_P|REX_W|REX_X|REX_B)) &&
1177 assert_no_prefix(ins, PPS_LREP);
1180 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
1188 #define EMIT_REX() \
1189 if (!(ins->rex & (REX_D|REX_V)) && (ins->rex & REX_REAL) && (bits == 64)) { \
1190 ins->rex = (ins->rex & REX_REAL)|REX_P; \
1191 out(offset, segment, &ins->rex, OUT_RAWDATA, 1, NO_SEG, NO_SEG); \
1196 static void gencode(int32_t segment, int64_t offset, int bits,
1197 insn * ins, const uint8_t *codes, int64_t insn_end)
1199 static char condval[] = { /* conditional opcodes */
1200 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
1201 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
1202 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
1208 struct operand *opx;
1212 opx = &ins->oprs[c & 3];
1218 out(offset, segment, codes, OUT_RAWDATA, c, NO_SEG, NO_SEG);
1225 switch (ins->oprs[0].basereg) {
1227 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0);
1230 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0);
1233 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0);
1236 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0);
1240 "bizarre 8086 segment register received");
1242 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1248 switch (ins->oprs[0].basereg) {
1250 bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0);
1253 bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0);
1257 "bizarre 386 segment register received");
1259 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1268 bytes[0] = *codes++ + ((regval(opx)) & 7);
1269 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1277 /* XXX: warns for legitimate optimizer actions */
1278 if (opx->offset < -128 || opx->offset > 127) {
1279 errfunc(ERR_WARNING | ERR_WARN_NOV,
1280 "signed byte value exceeds bounds");
1283 if (opx->segment != NO_SEG) {
1285 out(offset, segment, &data, OUT_ADDRESS, 1,
1286 opx->segment, opx->wrt);
1288 bytes[0] = opx->offset;
1289 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
1299 if (opx->offset < -256 || opx->offset > 255) {
1300 errfunc(ERR_WARNING | ERR_WARN_NOV,
1301 "byte value exceeds bounds");
1303 if (opx->segment != NO_SEG) {
1305 out(offset, segment, &data, OUT_ADDRESS, 1,
1306 opx->segment, opx->wrt);
1308 bytes[0] = opx->offset;
1309 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
1319 if (opx->offset < 0 || opx->offset > 255)
1320 errfunc(ERR_WARNING | ERR_WARN_NOV,
1321 "unsigned byte value exceeds bounds");
1322 if (opx->segment != NO_SEG) {
1324 out(offset, segment, &data, OUT_ADDRESS, 1,
1325 opx->segment, opx->wrt);
1327 bytes[0] = opx->offset;
1328 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
1339 if (opx->segment == NO_SEG && opx->wrt == NO_SEG)
1340 warn_overflow(2, data);
1341 out(offset, segment, &data, OUT_ADDRESS, 2,
1342 opx->segment, opx->wrt);
1350 if (opx->type & (BITS16 | BITS32))
1351 size = (opx->type & BITS16) ? 2 : 4;
1353 size = (bits == 16) ? 2 : 4;
1355 if (opx->segment == NO_SEG && opx->wrt == NO_SEG)
1356 warn_overflow(size, data);
1357 out(offset, segment, &data, OUT_ADDRESS, size,
1358 opx->segment, opx->wrt);
1367 if (opx->segment == NO_SEG && opx->wrt == NO_SEG)
1368 warn_overflow(4, data);
1369 out(offset, segment, &data, OUT_ADDRESS, 4,
1370 opx->segment, opx->wrt);
1379 size = ins->addr_size >> 3;
1380 if (opx->segment == NO_SEG &&
1382 warn_overflow(size, data);
1383 out(offset, segment, &data, OUT_ADDRESS, size,
1384 opx->segment, opx->wrt);
1392 if (opx->segment != segment)
1393 errfunc(ERR_NONFATAL,
1394 "short relative jump outside segment");
1395 data = opx->offset - insn_end;
1396 if (data > 127 || data < -128)
1397 errfunc(ERR_NONFATAL, "short jump is out of range");
1399 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1407 data = (int64_t)opx->offset;
1408 out(offset, segment, &data, OUT_ADDRESS, 8,
1409 opx->segment, opx->wrt);
1417 if (opx->segment != segment) {
1419 out(offset, segment, &data,
1420 OUT_REL2ADR, insn_end - offset,
1421 opx->segment, opx->wrt);
1423 data = opx->offset - insn_end;
1424 out(offset, segment, &data,
1425 OUT_ADDRESS, 2, NO_SEG, NO_SEG);
1434 if (opx->type & (BITS16 | BITS32 | BITS64))
1435 size = (opx->type & BITS16) ? 2 : 4;
1437 size = (bits == 16) ? 2 : 4;
1438 if (opx->segment != segment) {
1440 out(offset, segment, &data,
1441 size == 2 ? OUT_REL2ADR : OUT_REL4ADR,
1442 insn_end - offset, opx->segment, opx->wrt);
1444 data = opx->offset - insn_end;
1445 out(offset, segment, &data,
1446 OUT_ADDRESS, size, NO_SEG, NO_SEG);
1455 if (opx->segment != segment) {
1457 out(offset, segment, &data,
1458 OUT_REL4ADR, insn_end - offset,
1459 opx->segment, opx->wrt);
1461 data = opx->offset - insn_end;
1462 out(offset, segment, &data,
1463 OUT_ADDRESS, 4, NO_SEG, NO_SEG);
1472 if (opx->segment == NO_SEG)
1473 errfunc(ERR_NONFATAL, "value referenced by FAR is not"
1476 out(offset, segment, &data, OUT_ADDRESS, 2,
1477 outfmt->segbase(1 + opx->segment),
1487 if (is_sbyte16(ins, c & 3)) {
1489 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
1493 if (opx->segment == NO_SEG &&
1495 warn_overflow(2, data);
1496 out(offset, segment, &data, OUT_ADDRESS, 2,
1497 opx->segment, opx->wrt);
1507 bytes[0] = *codes++;
1508 if (is_sbyte16(ins, c & 3))
1509 bytes[0] |= 2; /* s-bit */
1510 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1519 if (is_sbyte32(ins, c & 3)) {
1521 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
1525 out(offset, segment, &data, OUT_ADDRESS, 4,
1526 opx->segment, opx->wrt);
1536 bytes[0] = *codes++;
1537 if (is_sbyte32(ins, c & 3))
1538 bytes[0] |= 2; /* s-bit */
1539 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1555 (ins->drexdst << 4) |
1556 (ins->rex & REX_OC ? 0x08 : 0) |
1557 (ins->rex & (REX_R|REX_X|REX_B));
1559 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1565 opx = &ins->oprs[c >> 3];
1566 bytes[0] = regvals[opx->basereg] << 4;
1567 opx = &ins->oprs[c & 7];
1568 if (opx->segment != NO_SEG || opx->wrt != NO_SEG) {
1569 errfunc(ERR_NONFATAL,
1570 "non-absolute expression not permitted as argument %d",
1573 if (opx->offset & ~15) {
1574 errfunc(ERR_WARNING | ERR_WARN_NOV,
1575 "four-bit argument exceeds bounds");
1577 bytes[0] |= opx->offset & 15;
1579 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1585 opx = &ins->oprs[c >> 4];
1586 bytes[0] = regvals[opx->basereg] << 4;
1588 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1597 /* is_sbyte32() is right here, we have already warned */
1598 if (is_sbyte32(ins, c & 3)) {
1600 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
1604 out(offset, segment, &data, OUT_ADDRESS, 4,
1605 opx->segment, opx->wrt);
1616 if (ins->vex_m != 1 || (ins->rex & (REX_W|REX_X|REX_B))) {
1618 bytes[1] = ins->vex_m | ((~ins->rex & 7) << 5);
1619 bytes[2] = ((ins->rex & REX_W) << (7-3)) |
1620 ((~ins->drexdst & 15)<< 3) | (ins->vex_wlp & 07);
1621 out(offset, segment, &bytes, OUT_RAWDATA, 3, NO_SEG, NO_SEG);
1625 bytes[1] = ((~ins->rex & REX_R) << (7-2)) |
1626 ((~ins->drexdst & 15) << 3) | (ins->vex_wlp & 07);
1627 out(offset, segment, &bytes, OUT_RAWDATA, 2, NO_SEG, NO_SEG);
1639 if (bits == 32 && !has_prefix(ins, PPS_ASIZE, P_A16)) {
1641 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1648 if (bits != 32 && !has_prefix(ins, PPS_ASIZE, P_A32)) {
1650 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1672 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1681 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1696 *bytes = *codes++ ^ condval[ins->condition];
1697 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1706 *bytes = c - 0332 + 0xF2;
1707 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1712 if (ins->rex & REX_R) {
1714 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1717 ins->rex &= ~(REX_L|REX_R);
1724 if (ins->oprs[0].segment != NO_SEG)
1725 errfunc(ERR_PANIC, "non-constant BSS size in pass two");
1727 int64_t size = ins->oprs[0].offset;
1729 out(offset, segment, NULL,
1730 OUT_RESERVE, size, NO_SEG, NO_SEG);
1741 *bytes = c - 0366 + 0x66;
1742 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1752 *bytes = bits == 16 ? 3 : 5;
1753 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1757 default: /* can't do it by 'case' statements */
1758 if (c >= 0100 && c <= 0277) { /* it's an EA */
1766 /* pick rfield from operand b */
1767 rflags = regflag(&ins->oprs[c & 7]);
1768 rfield = regvals[ins->oprs[c & 7].basereg];
1770 /* rfield is constant */
1776 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
1777 ins->addr_size, rfield, rflags, ins->forw_ref)) {
1778 errfunc(ERR_NONFATAL, "invalid effective address");
1783 *p++ = ea_data.modrm;
1784 if (ea_data.sib_present)
1787 /* DREX suffixes come between the SIB and the displacement */
1788 if (ins->rex & REX_D) {
1790 (ins->drexdst << 4) |
1791 (ins->rex & REX_OC ? 0x08 : 0) |
1792 (ins->rex & (REX_R|REX_X|REX_B));
1797 out(offset, segment, bytes, OUT_RAWDATA, s, NO_SEG, NO_SEG);
1799 switch (ea_data.bytes) {
1803 if (ins->oprs[(c >> 3) & 7].segment != NO_SEG) {
1804 data = ins->oprs[(c >> 3) & 7].offset;
1805 out(offset, segment, &data, OUT_ADDRESS, 1,
1806 ins->oprs[(c >> 3) & 7].segment,
1807 ins->oprs[(c >> 3) & 7].wrt);
1809 *bytes = ins->oprs[(c >> 3) & 7].offset;
1810 out(offset, segment, bytes, OUT_RAWDATA, 1,
1818 data = ins->oprs[(c >> 3) & 7].offset;
1819 warn_overflow(ea_data.bytes, data);
1820 out(offset, segment, &data,
1821 ea_data.rip ? OUT_REL4ADR : OUT_ADDRESS,
1823 ins->oprs[(c >> 3) & 7].segment,
1824 ins->oprs[(c >> 3) & 7].wrt);
1830 errfunc(ERR_PANIC, "internal instruction table corrupt"
1831 ": instruction code 0x%02X given", c);
1837 static int32_t regflag(const operand * o)
1839 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1840 errfunc(ERR_PANIC, "invalid operand passed to regflag()");
1842 return reg_flags[o->basereg];
1845 static int32_t regval(const operand * o)
1847 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1848 errfunc(ERR_PANIC, "invalid operand passed to regval()");
1850 return regvals[o->basereg];
1853 static int op_rexflags(const operand * o, int mask)
1858 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1859 errfunc(ERR_PANIC, "invalid operand passed to op_rexflags()");
1862 flags = reg_flags[o->basereg];
1863 val = regvals[o->basereg];
1865 return rexflags(val, flags, mask);
1868 static int rexflags(int val, int32_t flags, int mask)
1873 rex |= REX_B|REX_X|REX_R;
1876 if (!(REG_HIGH & ~flags)) /* AH, CH, DH, BH */
1878 else if (!(REG8 & ~flags) && val >= 4) /* SPL, BPL, SIL, DIL */
1884 static int matches(const struct itemplate *itemp, insn * instruction, int bits)
1886 int i, size[MAX_OPERANDS], asize, oprs, ret;
1893 if (itemp->opcode != instruction->opcode)
1897 * Count the operands
1899 if (itemp->operands != instruction->operands)
1903 * Check that no spurious colons or TOs are present
1905 for (i = 0; i < itemp->operands; i++)
1906 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON | TO))
1910 * Process size flags
1912 if (itemp->flags & IF_ARMASK) {
1913 memset(size, 0, sizeof size);
1915 i = ((itemp->flags & IF_ARMASK) >> IF_ARSHFT) - 1;
1917 switch (itemp->flags & IF_SMASK) {
1951 switch (itemp->flags & IF_SMASK) {
1983 for (i = 0; i < MAX_OPERANDS; i++)
1988 * Check that the operand flags all match up
1990 for (i = 0; i < itemp->operands; i++) {
1991 int32_t type = instruction->oprs[i].type;
1992 if (!(type & SIZE_MASK))
1995 if (itemp->opd[i] & SAME_AS) {
1996 int j = itemp->opd[i] & ~SAME_AS;
1997 if (type != instruction->oprs[j].type ||
1998 instruction->oprs[i].basereg != instruction->oprs[j].basereg)
2000 } else if (itemp->opd[i] & ~type ||
2001 ((itemp->opd[i] & SIZE_MASK) &&
2002 ((itemp->opd[i] ^ type) & SIZE_MASK))) {
2003 if ((itemp->opd[i] & ~type & ~SIZE_MASK) ||
2012 * Check operand sizes
2014 if (itemp->flags & (IF_SM | IF_SM2)) {
2015 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
2017 for (i = 0; i < oprs; i++) {
2018 if ((asize = itemp->opd[i] & SIZE_MASK) != 0) {
2020 for (j = 0; j < oprs; j++)
2026 oprs = itemp->operands;
2029 for (i = 0; i < itemp->operands; i++) {
2030 if (!(itemp->opd[i] & SIZE_MASK) &&
2031 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
2036 * Check template is okay at the set cpu level
2038 if (((itemp->flags & IF_PLEVEL) > cpu))
2042 * Check if instruction is available in long mode
2044 if ((itemp->flags & IF_NOLONG) && (bits == 64))
2048 * Check if special handling needed for Jumps
2050 if ((uint8_t)(itemp->code[0]) >= 0370)
2056 static ea *process_ea(operand * input, ea * output, int bits,
2057 int addrbits, int rfield, int32_t rflags, int forw_ref)
2059 output->rip = false;
2061 /* REX flags for the rfield operand */
2062 output->rex |= rexflags(rfield, rflags, REX_R|REX_P|REX_W|REX_H);
2064 if (!(REGISTER & ~input->type)) { /* register direct */
2068 if (input->basereg < EXPR_REG_START /* Verify as Register */
2069 || input->basereg >= REG_ENUM_LIMIT)
2072 i = regvals[input->basereg];
2075 return NULL; /* Invalid EA register */
2077 output->rex |= op_rexflags(input, REX_B|REX_P|REX_W|REX_H);
2079 output->sib_present = false; /* no SIB necessary */
2080 output->bytes = 0; /* no offset necessary either */
2081 output->modrm = 0xC0 | ((rfield & 7) << 3) | (i & 7);
2082 } else { /* it's a memory reference */
2083 if (input->basereg == -1
2084 && (input->indexreg == -1 || input->scale == 0)) {
2085 /* it's a pure offset */
2086 if (bits == 64 && (~input->type & IP_REL)) {
2087 int scale, index, base;
2088 output->sib_present = true;
2092 output->sib = (scale << 6) | (index << 3) | base;
2094 output->modrm = 4 | ((rfield & 7) << 3);
2095 output->rip = false;
2097 output->sib_present = false;
2098 output->bytes = (addrbits != 16 ? 4 : 2);
2099 output->modrm = (addrbits != 16 ? 5 : 6) | ((rfield & 7) << 3);
2100 output->rip = bits == 64;
2102 } else { /* it's an indirection */
2103 int i = input->indexreg, b = input->basereg, s = input->scale;
2104 int32_t o = input->offset, seg = input->segment;
2105 int hb = input->hintbase, ht = input->hinttype;
2108 int32_t ix, bx; /* register flags */
2111 i = -1; /* make this easy, at least */
2113 if (i >= EXPR_REG_START && i < REG_ENUM_LIMIT) {
2121 if (b >= EXPR_REG_START && b < REG_ENUM_LIMIT) {
2129 /* check for a 32/64-bit memory reference... */
2130 if ((ix|bx) & (BITS32|BITS64)) {
2131 /* it must be a 32/64-bit memory reference. Firstly we have
2132 * to check that all registers involved are type E/Rxx. */
2133 int32_t sok = BITS32|BITS64;
2136 if (!(REG64 & ~ix) || !(REG32 & ~ix))
2144 return NULL; /* Invalid register */
2145 if (~sok & bx & SIZE_MASK)
2146 return NULL; /* Invalid size */
2150 /* While we're here, ensure the user didn't specify
2152 if (input->disp_size == 16 || input->disp_size == 64)
2155 if (addrbits == 16 ||
2156 (addrbits == 32 && !(sok & BITS32)) ||
2157 (addrbits == 64 && !(sok & BITS64)))
2160 /* now reorganize base/index */
2161 if (s == 1 && bt != it && bt != -1 && it != -1 &&
2162 ((hb == b && ht == EAH_NOTBASE)
2163 || (hb == i && ht == EAH_MAKEBASE))) {
2164 /* swap if hints say so */
2165 t = bt, bt = it, it = t;
2166 t = bx, bx = ix, ix = t;
2168 if (bt == it) /* convert EAX+2*EAX to 3*EAX */
2169 bt = -1, bx = 0, s++;
2170 if (bt == -1 && s == 1 && !(hb == it && ht == EAH_NOTBASE)) {
2171 /* make single reg base, unless hint */
2172 bt = it, bx = ix, it = -1, ix = 0;
2174 if (((s == 2 && it != REG_NUM_ESP
2175 && !(input->eaflags & EAF_TIMESTWO)) || s == 3
2176 || s == 5 || s == 9) && bt == -1)
2177 bt = it, bx = ix, s--; /* convert 3*EAX to EAX+2*EAX */
2178 if (it == -1 && (bt & 7) != REG_NUM_ESP
2179 && (input->eaflags & EAF_TIMESTWO))
2180 it = bt, ix = bx, bt = -1, bx = 0, s = 1;
2181 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
2182 if (s == 1 && it == REG_NUM_ESP) {
2183 /* swap ESP into base if scale is 1 */
2184 t = it, it = bt, bt = t;
2185 t = ix, ix = bx, bx = t;
2187 if (it == REG_NUM_ESP
2188 || (s != 1 && s != 2 && s != 4 && s != 8 && it != -1))
2189 return NULL; /* wrong, for various reasons */
2191 output->rex |= rexflags(it, ix, REX_X);
2192 output->rex |= rexflags(bt, bx, REX_B);
2194 if (it == -1 && (bt & 7) != REG_NUM_ESP) {
2203 if (rm != REG_NUM_EBP && o == 0 &&
2204 seg == NO_SEG && !forw_ref &&
2206 (EAF_BYTEOFFS | EAF_WORDOFFS)))
2208 else if (input->eaflags & EAF_BYTEOFFS ||
2209 (o >= -128 && o <= 127 && seg == NO_SEG
2211 && !(input->eaflags & EAF_WORDOFFS)))
2217 output->sib_present = false;
2218 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
2219 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
2222 int mod, scale, index, base;
2242 default: /* then what the smeg is it? */
2243 return NULL; /* panic */
2251 if (base != REG_NUM_EBP && o == 0 &&
2252 seg == NO_SEG && !forw_ref &&
2254 (EAF_BYTEOFFS | EAF_WORDOFFS)))
2256 else if (input->eaflags & EAF_BYTEOFFS ||
2257 (o >= -128 && o <= 127 && seg == NO_SEG
2259 && !(input->eaflags & EAF_WORDOFFS)))
2265 output->sib_present = true;
2266 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
2267 output->modrm = (mod << 6) | ((rfield & 7) << 3) | 4;
2268 output->sib = (scale << 6) | (index << 3) | base;
2270 } else { /* it's 16-bit */
2273 /* check for 64-bit long mode */
2277 /* check all registers are BX, BP, SI or DI */
2278 if ((b != -1 && b != R_BP && b != R_BX && b != R_SI
2279 && b != R_DI) || (i != -1 && i != R_BP && i != R_BX
2280 && i != R_SI && i != R_DI))
2283 /* ensure the user didn't specify DWORD/QWORD */
2284 if (input->disp_size == 32 || input->disp_size == 64)
2287 if (s != 1 && i != -1)
2288 return NULL; /* no can do, in 16-bit EA */
2289 if (b == -1 && i != -1) {
2294 if ((b == R_SI || b == R_DI) && i != -1) {
2299 /* have BX/BP as base, SI/DI index */
2301 return NULL; /* shouldn't ever happen, in theory */
2302 if (i != -1 && b != -1 &&
2303 (i == R_BP || i == R_BX || b == R_SI || b == R_DI))
2304 return NULL; /* invalid combinations */
2305 if (b == -1) /* pure offset: handled above */
2306 return NULL; /* so if it gets to here, panic! */
2310 switch (i * 256 + b) {
2311 case R_SI * 256 + R_BX:
2314 case R_DI * 256 + R_BX:
2317 case R_SI * 256 + R_BP:
2320 case R_DI * 256 + R_BP:
2338 if (rm == -1) /* can't happen, in theory */
2339 return NULL; /* so panic if it does */
2341 if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
2342 !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
2344 else if (input->eaflags & EAF_BYTEOFFS ||
2345 (o >= -128 && o <= 127 && seg == NO_SEG
2347 && !(input->eaflags & EAF_WORDOFFS)))
2352 output->sib_present = false; /* no SIB - it's 16-bit */
2353 output->bytes = mod; /* bytes of offset needed */
2354 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
2359 output->size = 1 + output->sib_present + output->bytes;
2363 static void add_asp(insn *ins, int addrbits)
2368 valid = (addrbits == 64) ? 64|32 : 32|16;
2370 switch (ins->prefixes[PPS_ASIZE]) {
2381 valid &= (addrbits == 32) ? 16 : 32;
2387 for (j = 0; j < ins->operands; j++) {
2388 if (!(MEMORY & ~ins->oprs[j].type)) {
2391 /* Verify as Register */
2392 if (ins->oprs[j].indexreg < EXPR_REG_START
2393 || ins->oprs[j].indexreg >= REG_ENUM_LIMIT)
2396 i = reg_flags[ins->oprs[j].indexreg];
2398 /* Verify as Register */
2399 if (ins->oprs[j].basereg < EXPR_REG_START
2400 || ins->oprs[j].basereg >= REG_ENUM_LIMIT)
2403 b = reg_flags[ins->oprs[j].basereg];
2405 if (ins->oprs[j].scale == 0)
2409 int ds = ins->oprs[j].disp_size;
2410 if ((addrbits != 64 && ds > 8) ||
2411 (addrbits == 64 && ds == 16))
2431 if (valid & addrbits) {
2432 ins->addr_size = addrbits;
2433 } else if (valid & ((addrbits == 32) ? 16 : 32)) {
2434 /* Add an address size prefix */
2435 enum prefixes pref = (addrbits == 32) ? P_A16 : P_A32;
2436 ins->prefixes[PPS_ASIZE] = pref;
2437 ins->addr_size = (addrbits == 32) ? 16 : 32;
2440 errfunc(ERR_NONFATAL, "impossible combination of address sizes");
2441 ins->addr_size = addrbits; /* Error recovery */
2444 defdisp = ins->addr_size == 16 ? 16 : 32;
2446 for (j = 0; j < ins->operands; j++) {
2447 if (!(MEM_OFFS & ~ins->oprs[j].type) &&
2448 (ins->oprs[j].disp_size ? ins->oprs[j].disp_size : defdisp)
2449 != ins->addr_size) {
2450 /* mem_offs sizes must match the address size; if not,
2451 strip the MEM_OFFS bit and match only EA instructions */
2452 ins->oprs[j].type &= ~(MEM_OFFS & ~MEMORY);