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 * \170 - encodes the literal byte 0. (Some compilers don't take
48 * kindly to a zero byte in the _middle_ of a compile time
49 * string constant, so I had to put this hack in.)
50 * \171 - placement of DREX suffix in the absence of an EA
51 * \172\ab - the register number from operand a in bits 7..4, with
52 * the 4-bit immediate from operand b in bits 0..3.
53 * \173\xab - the register number from operand a in bits 7..4, with
54 * the value b in bits 0..3.
55 * \2ab - a ModRM, calculated on EA in operand a, with the spare
56 * field equal to digit b.
57 * \250..\253 - same as \150..\153, except warn if the 64-bit operand
58 * is not equal to the truncated and sign-extended 32-bit
59 * operand; used for 32-bit immediates in 64-bit mode.
60 * \260..\263 - this instruction uses VEX rather than REX, with the
61 * V field taken from operand 0..3.
62 * \270 - this instruction uses VEX rather than REX, with the
63 * V field set to 1111b.
65 * VEX prefixes are followed by the sequence:
66 * \1mm\1wp where mm is the M field; and wp is:
70 * ww = 2 for W used as REX.W
72 * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
73 * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
74 * \312 - (disassembler only) marker on LOOP, LOOPxx instructions.
75 * \313 - indicates fixed 64-bit address size, 0x67 invalid.
76 * \314 - (disassembler only) invalid with REX.B
77 * \315 - (disassembler only) invalid with REX.X
78 * \316 - (disassembler only) invalid with REX.R
79 * \317 - (disassembler only) invalid with REX.W
80 * \320 - indicates fixed 16-bit operand size, i.e. optional 0x66.
81 * \321 - indicates fixed 32-bit operand size, i.e. optional 0x66.
82 * \322 - indicates that this instruction is only valid when the
83 * operand size is the default (instruction to disassembler,
84 * generates no code in the assembler)
85 * \323 - indicates fixed 64-bit operand size, REX on extensions only.
86 * \324 - indicates 64-bit operand size requiring REX prefix.
87 * \330 - a literal byte follows in the code stream, to be added
88 * to the condition code value of the instruction.
89 * \331 - instruction not valid with REP prefix. Hint for
90 * disassembler only; for SSE instructions.
91 * \332 - REP prefix (0xF2 byte) used as opcode extension.
92 * \333 - REP prefix (0xF3 byte) used as opcode extension.
93 * \334 - LOCK prefix used instead of REX.R
94 * \335 - disassemble a rep (0xF3 byte) prefix as repe not rep.
95 * \340 - reserve <operand 0> bytes of uninitialized storage.
96 * Operand 0 had better be a segmentless constant.
97 * \364 - operand-size prefix (0x66) not permitted
98 * \365 - address-size prefix (0x67) not permitted
99 * \366 - operand-size prefix (0x66) used as opcode extension
100 * \367 - address-size prefix (0x67) used as opcode extension
101 * \370,\371,\372 - match only if operand 0 meets byte jump criteria.
102 * 370 is used for Jcc, 371 is used for JMP.
103 * \373 - assemble 0x03 if bits==16, 0x05 if bits==32;
104 * used for conditional jump over longer jump
107 #include "compiler.h"
111 #include <inttypes.h>
115 #include "assemble.h"
118 #include "regflags.c"
122 int sib_present; /* is a SIB byte necessary? */
123 int bytes; /* # of bytes of offset needed */
124 int size; /* lazy - this is sib+bytes+1 */
125 uint8_t modrm, sib, rex, rip; /* the bytes themselves */
128 static uint32_t cpu; /* cpu level received from nasm.c */
129 static efunc errfunc;
130 static struct ofmt *outfmt;
131 static ListGen *list;
133 static int64_t calcsize(int32_t, int64_t, int, insn *, const uint8_t *);
134 static void gencode(int32_t, int64_t, int, insn *, const uint8_t *, int64_t);
135 static int matches(const struct itemplate *, insn *, int bits);
136 static int32_t regflag(const operand *);
137 static int32_t regval(const operand *);
138 static int rexflags(int, int32_t, int);
139 static int op_rexflags(const operand *, int);
140 static ea *process_ea(operand *, ea *, int, int, int, int32_t, int);
141 static void add_asp(insn *, int);
143 static int has_prefix(insn * ins, enum prefix_pos pos, enum prefixes prefix)
145 return ins->prefixes[pos] == prefix;
148 static void assert_no_prefix(insn * ins, enum prefix_pos pos)
150 if (ins->prefixes[pos])
151 errfunc(ERR_NONFATAL, "invalid %s prefix",
152 prefix_name(ins->prefixes[pos]));
155 static const char *size_name(int size)
175 static void warn_overflow(int size, int64_t data)
178 int64_t lim = ((int64_t)1 << (size*8))-1;
180 if (data < ~lim || data > lim)
181 errfunc(ERR_WARNING | ERR_WARN_NOV,
182 "%s data exceeds bounds", size_name(size));
186 * This routine wrappers the real output format's output routine,
187 * in order to pass a copy of the data off to the listing file
188 * generator at the same time.
190 static void out(int64_t offset, int32_t segto, const void *data,
191 enum out_type type, uint64_t size,
192 int32_t segment, int32_t wrt)
194 static int32_t lineno = 0; /* static!!! */
195 static char *lnfname = NULL;
198 if (type == OUT_ADDRESS && segment == NO_SEG && wrt == NO_SEG) {
200 * This is a non-relocated address, and we're going to
201 * convert it into RAWDATA format.
206 errfunc(ERR_PANIC, "OUT_ADDRESS with size > 8");
210 WRITEADDR(q, *(int64_t *)data, size);
215 list->output(offset, data, type, size);
218 * this call to src_get determines when we call the
219 * debug-format-specific "linenum" function
220 * it updates lineno and lnfname to the current values
221 * returning 0 if "same as last time", -2 if lnfname
222 * changed, and the amount by which lineno changed,
223 * if it did. thus, these variables must be static
226 if (src_get(&lineno, &lnfname)) {
227 outfmt->current_dfmt->linenum(lnfname, lineno, segto);
230 outfmt->output(segto, data, type, size, segment, wrt);
233 static int jmp_match(int32_t segment, int64_t offset, int bits,
234 insn * ins, const uint8_t *code)
239 if (c != 0370 && c != 0371)
241 if (ins->oprs[0].opflags & OPFLAG_FORWARD) {
242 if ((optimizing < 0 || (ins->oprs[0].type & STRICT))
246 return (pass0 == 0); /* match a forward reference */
248 isize = calcsize(segment, offset, bits, ins, code);
249 if (ins->oprs[0].segment != segment)
251 isize = ins->oprs[0].offset - offset - isize; /* isize is now the delta */
252 if (isize >= -128L && isize <= 127L)
253 return 1; /* it is byte size */
258 int64_t assemble(int32_t segment, int64_t offset, int bits, uint32_t cp,
259 insn * instruction, struct ofmt *output, efunc error,
262 const struct itemplate *temp;
267 int64_t start = offset;
268 int64_t wsize = 0; /* size for DB etc. */
270 errfunc = error; /* to pass to other functions */
272 outfmt = output; /* likewise */
273 list = listgen; /* and again */
275 switch (instruction->opcode) {
302 int32_t t = instruction->times;
305 "instruction->times < 0 (%ld) in assemble()", t);
307 while (t--) { /* repeat TIMES times */
308 for (e = instruction->eops; e; e = e->next) {
309 if (e->type == EOT_DB_NUMBER) {
311 if (e->segment != NO_SEG)
312 errfunc(ERR_NONFATAL,
313 "one-byte relocation attempted");
315 uint8_t out_byte = e->offset;
316 out(offset, segment, &out_byte,
317 OUT_RAWDATA, 1, NO_SEG, NO_SEG);
319 } else if (wsize > 8) {
320 errfunc(ERR_NONFATAL, "integer supplied to a DT or DO"
323 out(offset, segment, &e->offset,
324 OUT_ADDRESS, wsize, e->segment, e->wrt);
326 } else if (e->type == EOT_DB_STRING) {
329 out(offset, segment, e->stringval,
330 OUT_RAWDATA, e->stringlen, NO_SEG, NO_SEG);
331 align = e->stringlen % wsize;
334 align = wsize - align;
336 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
337 OUT_RAWDATA, align, NO_SEG, NO_SEG);
339 offset += e->stringlen + align;
342 if (t > 0 && t == instruction->times - 1) {
344 * Dummy call to list->output to give the offset to the
347 list->output(offset, NULL, OUT_RAWDATA, 0);
348 list->uplevel(LIST_TIMES);
351 if (instruction->times > 1)
352 list->downlevel(LIST_TIMES);
353 return offset - start;
356 if (instruction->opcode == I_INCBIN) {
357 static char fname[FILENAME_MAX];
360 char *prefix = "", *combine;
361 char **pPrevPath = NULL;
363 len = FILENAME_MAX - 1;
364 if (len > instruction->eops->stringlen)
365 len = instruction->eops->stringlen;
366 strncpy(fname, instruction->eops->stringval, len);
369 while (1) { /* added by alexfru: 'incbin' uses include paths */
370 combine = nasm_malloc(strlen(prefix) + len + 1);
371 strcpy(combine, prefix);
372 strcat(combine, fname);
374 if ((fp = fopen(combine, "rb")) != NULL) {
380 pPrevPath = pp_get_include_path_ptr(pPrevPath);
381 if (pPrevPath == NULL)
387 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
389 else if (fseek(fp, 0L, SEEK_END) < 0)
390 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
393 static char buf[2048];
394 int32_t t = instruction->times;
398 if (instruction->eops->next) {
399 base = instruction->eops->next->offset;
401 if (instruction->eops->next->next &&
402 len > instruction->eops->next->next->offset)
403 len = instruction->eops->next->next->offset;
406 * Dummy call to list->output to give the offset to the
409 list->output(offset, NULL, OUT_RAWDATA, 0);
410 list->uplevel(LIST_INCBIN);
414 fseek(fp, base, SEEK_SET);
418 fread(buf, 1, (l > (int32_t) sizeof(buf) ? (int32_t) sizeof(buf) : l),
422 * This shouldn't happen unless the file
423 * actually changes while we are reading
427 "`incbin': unexpected EOF while"
428 " reading file `%s'", fname);
429 t = 0; /* Try to exit cleanly */
432 out(offset, segment, buf, OUT_RAWDATA, m,
437 list->downlevel(LIST_INCBIN);
438 if (instruction->times > 1) {
440 * Dummy call to list->output to give the offset to the
443 list->output(offset, NULL, OUT_RAWDATA, 0);
444 list->uplevel(LIST_TIMES);
445 list->downlevel(LIST_TIMES);
448 return instruction->times * len;
450 return 0; /* if we're here, there's an error */
453 /* Check to see if we need an address-size prefix */
454 add_asp(instruction, bits);
458 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++){
459 int m = matches(temp, instruction, bits);
462 m += jmp_match(segment, offset, bits, instruction, temp->code);
464 if (m == 100) { /* matches! */
465 const uint8_t *codes = temp->code;
466 int64_t insn_size = calcsize(segment, offset, bits,
468 itimes = instruction->times;
469 if (insn_size < 0) /* shouldn't be, on pass two */
470 error(ERR_PANIC, "errors made it through from pass one");
473 for (j = 0; j < MAXPREFIX; j++) {
475 switch (instruction->prefixes[j]) {
491 "cs segment base generated, but will be ignored in 64-bit mode");
498 "ds segment base generated, but will be ignored in 64-bit mode");
505 "es segment base generated, but will be ignored in 64-bit mode");
518 "ss segment base generated, but will be ignored in 64-bit mode");
525 "segr6 and segr7 cannot be used as prefixes");
530 "16-bit addressing is not supported "
532 } else if (bits != 16)
542 "64-bit addressing is only supported "
566 error(ERR_PANIC, "invalid instruction prefix");
569 out(offset, segment, &c, OUT_RAWDATA, 1,
574 insn_end = offset + insn_size;
575 gencode(segment, offset, bits, instruction, codes,
578 if (itimes > 0 && itimes == instruction->times - 1) {
580 * Dummy call to list->output to give the offset to the
583 list->output(offset, NULL, OUT_RAWDATA, 0);
584 list->uplevel(LIST_TIMES);
587 if (instruction->times > 1)
588 list->downlevel(LIST_TIMES);
589 return offset - start;
590 } else if (m > 0 && m > size_prob) {
596 if (temp->opcode == -1) { /* didn't match any instruction */
599 error(ERR_NONFATAL, "operation size not specified");
602 error(ERR_NONFATAL, "mismatch in operand sizes");
605 error(ERR_NONFATAL, "no instruction for this cpu level");
608 error(ERR_NONFATAL, "instruction not supported in 64-bit mode");
612 "invalid combination of opcode and operands");
619 int64_t insn_size(int32_t segment, int64_t offset, int bits, uint32_t cp,
620 insn * instruction, efunc error)
622 const struct itemplate *temp;
624 errfunc = error; /* to pass to other functions */
627 if (instruction->opcode == -1)
630 if (instruction->opcode == I_DB || instruction->opcode == I_DW ||
631 instruction->opcode == I_DD || instruction->opcode == I_DQ ||
632 instruction->opcode == I_DT || instruction->opcode == I_DO) {
634 int32_t isize, osize, wsize = 0; /* placate gcc */
637 switch (instruction->opcode) {
660 for (e = instruction->eops; e; e = e->next) {
664 if (e->type == EOT_DB_NUMBER)
666 else if (e->type == EOT_DB_STRING)
667 osize = e->stringlen;
669 align = (-osize) % wsize;
672 isize += osize + align;
674 return isize * instruction->times;
677 if (instruction->opcode == I_INCBIN) {
678 char fname[FILENAME_MAX];
681 char *prefix = "", *combine;
682 char **pPrevPath = NULL;
684 len = FILENAME_MAX - 1;
685 if (len > instruction->eops->stringlen)
686 len = instruction->eops->stringlen;
687 strncpy(fname, instruction->eops->stringval, len);
690 /* added by alexfru: 'incbin' uses include paths */
692 combine = nasm_malloc(strlen(prefix) + len + 1);
693 strcpy(combine, prefix);
694 strcat(combine, fname);
696 if ((fp = fopen(combine, "rb")) != NULL) {
702 pPrevPath = pp_get_include_path_ptr(pPrevPath);
703 if (pPrevPath == NULL)
709 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
711 else if (fseek(fp, 0L, SEEK_END) < 0)
712 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
717 if (instruction->eops->next) {
718 len -= instruction->eops->next->offset;
719 if (instruction->eops->next->next &&
720 len > instruction->eops->next->next->offset) {
721 len = instruction->eops->next->next->offset;
724 return instruction->times * len;
726 return 0; /* if we're here, there's an error */
729 /* Check to see if we need an address-size prefix */
730 add_asp(instruction, bits);
732 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++) {
733 int m = matches(temp, instruction, bits);
735 m += jmp_match(segment, offset, bits, instruction, temp->code);
738 /* we've matched an instruction. */
740 const uint8_t *codes = temp->code;
743 isize = calcsize(segment, offset, bits, instruction, codes);
746 for (j = 0; j < MAXPREFIX; j++) {
747 switch (instruction->prefixes[j]) {
773 return isize * instruction->times;
776 return -1; /* didn't match any instruction */
779 static bool possible_sbyte(insn * ins, int op)
781 return !(ins->forw_ref && ins->oprs[op].opflags) &&
783 !(ins->oprs[op].type & STRICT) &&
784 ins->oprs[op].wrt == NO_SEG && ins->oprs[op].segment == NO_SEG;
787 /* check that opn[op] is a signed byte of size 16 or 32 */
788 static bool is_sbyte16(insn * ins, int op)
792 if (!possible_sbyte(ins, op))
795 v = ins->oprs[op].offset;
796 return v >= -128 && v <= 127;
799 static bool is_sbyte32(insn * ins, int op)
803 if (!possible_sbyte(ins, op))
806 v = ins->oprs[op].offset;
807 return v >= -128 && v <= 127;
810 /* check that opn[op] is a signed byte of size 32; warn if this is not
811 the original value when extended to 64 bits */
812 static bool is_sbyte64(insn * ins, int op)
817 /* dead in the water on forward reference or External */
818 if (!possible_sbyte(ins, op))
821 v64 = ins->oprs[op].offset;
824 warn_overflow(32, v64);
826 return v32 >= -128 && v32 <= 127;
828 static int64_t calcsize(int32_t segment, int64_t offset, int bits,
829 insn * ins, const uint8_t *codes)
836 ins->rex = 0; /* Ensure REX is reset */
838 if (ins->prefixes[PPS_OSIZE] == P_O64)
841 (void)segment; /* Don't warn that this parameter is unused */
842 (void)offset; /* Don't warn that this parameter is unused */
846 opx = &ins->oprs[c & 3];
851 codes += c, length += c;
864 op_rexflags(opx, REX_B|REX_H|REX_P|REX_W);
895 if (opx->type & (BITS16 | BITS32 | BITS64))
896 length += (opx->type & BITS16) ? 2 : 4;
898 length += (bits == 16) ? 2 : 4;
910 length += ins->addr_size >> 3;
922 length += 8; /* MOV reg64/imm */
934 if (opx->type & (BITS16 | BITS32 | BITS64))
935 length += (opx->type & BITS16) ? 2 : 4;
937 length += (bits == 16) ? 2 : 4;
955 length += is_sbyte16(ins, c & 3) ? 1 : 2;
968 length += is_sbyte32(ins, c & 3) ? 1 : 4;
983 ins->drexdst = regval(opx);
990 ins->rex |= REX_D|REX_OC;
991 ins->drexdst = regval(opx);
1007 length += is_sbyte64(ins, c & 3) ? 1 : 4;
1015 ins->drexdst = regval(opx);
1016 ins->vex_m = *codes++;
1017 ins->vex_wlp = *codes++;
1023 ins->vex_m = *codes++;
1024 ins->vex_wlp = *codes++;
1034 length += (bits != 16) && !has_prefix(ins, PPS_ASIZE, P_A16);
1037 length += (bits != 32) && !has_prefix(ins, PPS_ASIZE, P_A32);
1042 if (bits != 64 || has_prefix(ins, PPS_ASIZE, P_A16) ||
1043 has_prefix(ins, PPS_ASIZE, P_A32))
1052 length += (bits != 16);
1055 length += (bits == 16);
1080 if (ins->oprs[0].segment != NO_SEG)
1081 errfunc(ERR_NONFATAL, "attempt to reserve non-constant"
1082 " quantity of BSS space");
1084 length += ins->oprs[0].offset;
1100 default: /* can't do it by 'case' statements */
1101 if (c >= 0100 && c <= 0277) { /* it's an EA */
1105 ea_data.rex = 0; /* Ensure ea.REX is initially 0 */
1108 /* pick rfield from operand b */
1109 rflags = regflag(&ins->oprs[c & 7]);
1110 rfield = regvals[ins->oprs[c & 7].basereg];
1117 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
1118 ins->addr_size, rfield, rflags, ins->forw_ref)) {
1119 errfunc(ERR_NONFATAL, "invalid effective address");
1122 ins->rex |= ea_data.rex;
1123 length += ea_data.size;
1126 errfunc(ERR_PANIC, "internal instruction table corrupt"
1127 ": instruction code 0x%02X given", c);
1132 ins->rex &= rex_mask;
1134 if (ins->rex & REX_V) {
1135 int bad32 = REX_R|REX_W|REX_X|REX_B;
1137 if (ins->rex & REX_H) {
1138 errfunc(ERR_NONFATAL, "cannot use high register in vex instruction");
1141 switch (ins->vex_wlp & 030) {
1154 if (bits != 64 && ((ins->rex & bad32) || ins->drexdst > 7)) {
1155 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
1158 if (ins->vex_m != 1 || (ins->rex & (REX_W|REX_R|REX_B)))
1162 } else if (ins->rex & REX_D) {
1163 if (ins->rex & REX_H) {
1164 errfunc(ERR_NONFATAL, "cannot use high register in drex instruction");
1167 if (bits != 64 && ((ins->rex & (REX_R|REX_W|REX_X|REX_B)) ||
1168 ins->drexdst > 7)) {
1169 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
1173 } else if (ins->rex & REX_REAL) {
1174 if (ins->rex & REX_H) {
1175 errfunc(ERR_NONFATAL, "cannot use high register in rex instruction");
1177 } else if (bits == 64) {
1179 } else if ((ins->rex & REX_L) &&
1180 !(ins->rex & (REX_P|REX_W|REX_X|REX_B)) &&
1183 assert_no_prefix(ins, PPS_LREP);
1186 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
1194 #define EMIT_REX() \
1195 if (!(ins->rex & (REX_D|REX_V)) && (ins->rex & REX_REAL) && (bits == 64)) { \
1196 ins->rex = (ins->rex & REX_REAL)|REX_P; \
1197 out(offset, segment, &ins->rex, OUT_RAWDATA, 1, NO_SEG, NO_SEG); \
1202 static void gencode(int32_t segment, int64_t offset, int bits,
1203 insn * ins, const uint8_t *codes, int64_t insn_end)
1205 static char condval[] = { /* conditional opcodes */
1206 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
1207 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
1208 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
1214 struct operand *opx;
1218 opx = &ins->oprs[c & 3];
1224 out(offset, segment, codes, OUT_RAWDATA, c, NO_SEG, NO_SEG);
1231 switch (ins->oprs[0].basereg) {
1233 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0);
1236 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0);
1239 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0);
1242 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0);
1246 "bizarre 8086 segment register received");
1248 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1254 switch (ins->oprs[0].basereg) {
1256 bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0);
1259 bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0);
1263 "bizarre 386 segment register received");
1265 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1274 bytes[0] = *codes++ + ((regval(opx)) & 7);
1275 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1283 /* XXX: warns for legitimate optimizer actions */
1284 if (opx->offset < -128 || opx->offset > 127) {
1285 errfunc(ERR_WARNING | ERR_WARN_NOV,
1286 "signed byte value exceeds bounds");
1289 if (opx->segment != NO_SEG) {
1291 out(offset, segment, &data, OUT_ADDRESS, 1,
1292 opx->segment, opx->wrt);
1294 bytes[0] = opx->offset;
1295 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
1305 if (opx->offset < -256 || opx->offset > 255) {
1306 errfunc(ERR_WARNING | ERR_WARN_NOV,
1307 "byte value exceeds bounds");
1309 if (opx->segment != NO_SEG) {
1311 out(offset, segment, &data, OUT_ADDRESS, 1,
1312 opx->segment, opx->wrt);
1314 bytes[0] = opx->offset;
1315 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
1325 if (opx->offset < 0 || opx->offset > 255)
1326 errfunc(ERR_WARNING | ERR_WARN_NOV,
1327 "unsigned byte value exceeds bounds");
1328 if (opx->segment != NO_SEG) {
1330 out(offset, segment, &data, OUT_ADDRESS, 1,
1331 opx->segment, opx->wrt);
1333 bytes[0] = opx->offset;
1334 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
1345 if (opx->segment == NO_SEG && opx->wrt == NO_SEG)
1346 warn_overflow(2, data);
1347 out(offset, segment, &data, OUT_ADDRESS, 2,
1348 opx->segment, opx->wrt);
1356 if (opx->type & (BITS16 | BITS32))
1357 size = (opx->type & BITS16) ? 2 : 4;
1359 size = (bits == 16) ? 2 : 4;
1361 if (opx->segment == NO_SEG && opx->wrt == NO_SEG)
1362 warn_overflow(size, data);
1363 out(offset, segment, &data, OUT_ADDRESS, size,
1364 opx->segment, opx->wrt);
1373 if (opx->segment == NO_SEG && opx->wrt == NO_SEG)
1374 warn_overflow(4, data);
1375 out(offset, segment, &data, OUT_ADDRESS, 4,
1376 opx->segment, opx->wrt);
1385 size = ins->addr_size >> 3;
1386 if (opx->segment == NO_SEG &&
1388 warn_overflow(size, data);
1389 out(offset, segment, &data, OUT_ADDRESS, size,
1390 opx->segment, opx->wrt);
1398 if (opx->segment != segment)
1399 errfunc(ERR_NONFATAL,
1400 "short relative jump outside segment");
1401 data = opx->offset - insn_end;
1402 if (data > 127 || data < -128)
1403 errfunc(ERR_NONFATAL, "short jump is out of range");
1405 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1413 data = (int64_t)opx->offset;
1414 out(offset, segment, &data, OUT_ADDRESS, 8,
1415 opx->segment, opx->wrt);
1423 if (opx->segment != segment) {
1425 out(offset, segment, &data,
1426 OUT_REL2ADR, insn_end - offset,
1427 opx->segment, opx->wrt);
1429 data = opx->offset - insn_end;
1430 out(offset, segment, &data,
1431 OUT_ADDRESS, 2, NO_SEG, NO_SEG);
1440 if (opx->type & (BITS16 | BITS32 | BITS64))
1441 size = (opx->type & BITS16) ? 2 : 4;
1443 size = (bits == 16) ? 2 : 4;
1444 if (opx->segment != segment) {
1446 out(offset, segment, &data,
1447 size == 2 ? OUT_REL2ADR : OUT_REL4ADR,
1448 insn_end - offset, opx->segment, opx->wrt);
1450 data = opx->offset - insn_end;
1451 out(offset, segment, &data,
1452 OUT_ADDRESS, size, NO_SEG, NO_SEG);
1461 if (opx->segment != segment) {
1463 out(offset, segment, &data,
1464 OUT_REL4ADR, insn_end - offset,
1465 opx->segment, opx->wrt);
1467 data = opx->offset - insn_end;
1468 out(offset, segment, &data,
1469 OUT_ADDRESS, 4, NO_SEG, NO_SEG);
1478 if (opx->segment == NO_SEG)
1479 errfunc(ERR_NONFATAL, "value referenced by FAR is not"
1482 out(offset, segment, &data, OUT_ADDRESS, 2,
1483 outfmt->segbase(1 + opx->segment),
1493 if (is_sbyte16(ins, c & 3)) {
1495 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
1499 if (opx->segment == NO_SEG &&
1501 warn_overflow(2, data);
1502 out(offset, segment, &data, OUT_ADDRESS, 2,
1503 opx->segment, opx->wrt);
1513 bytes[0] = *codes++;
1514 if (is_sbyte16(ins, c & 3))
1515 bytes[0] |= 2; /* s-bit */
1516 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1525 if (is_sbyte32(ins, c & 3)) {
1527 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
1531 out(offset, segment, &data, OUT_ADDRESS, 4,
1532 opx->segment, opx->wrt);
1542 bytes[0] = *codes++;
1543 if (is_sbyte32(ins, c & 3))
1544 bytes[0] |= 2; /* s-bit */
1545 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1562 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1568 (ins->drexdst << 4) |
1569 (ins->rex & REX_OC ? 0x08 : 0) |
1570 (ins->rex & (REX_R|REX_X|REX_B));
1572 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1578 opx = &ins->oprs[c >> 3];
1579 bytes[0] = regvals[opx->basereg] << 4;
1580 opx = &ins->oprs[c & 7];
1581 if (opx->segment != NO_SEG || opx->wrt != NO_SEG) {
1582 errfunc(ERR_NONFATAL,
1583 "non-absolute expression not permitted as argument %d",
1586 if (opx->offset & ~15) {
1587 errfunc(ERR_WARNING | ERR_WARN_NOV,
1588 "four-bit argument exceeds bounds");
1590 bytes[0] |= opx->offset & 15;
1592 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1598 opx = &ins->oprs[c >> 4];
1599 bytes[0] = regvals[opx->basereg] << 4;
1601 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1610 /* is_sbyte32() is right here, we have already warned */
1611 if (is_sbyte32(ins, c & 3)) {
1613 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
1617 out(offset, segment, &data, OUT_ADDRESS, 4,
1618 opx->segment, opx->wrt);
1629 if (ins->vex_m != 1 || (ins->rex & (REX_W|REX_X|REX_B))) {
1631 bytes[1] = ins->vex_m | ((~ins->rex & 7) << 5);
1632 bytes[2] = ((ins->rex & REX_W) << (7-3)) |
1633 ((~ins->drexdst & 15)<< 3) | (ins->vex_wlp & 07);
1634 out(offset, segment, &bytes, OUT_RAWDATA, 3, NO_SEG, NO_SEG);
1638 bytes[1] = ((~ins->rex & REX_R) << (7-2)) |
1639 ((~ins->drexdst & 15) << 3) | (ins->vex_wlp & 07);
1640 out(offset, segment, &bytes, OUT_RAWDATA, 2, NO_SEG, NO_SEG);
1652 if (bits == 32 && !has_prefix(ins, PPS_ASIZE, P_A16)) {
1654 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1661 if (bits != 32 && !has_prefix(ins, PPS_ASIZE, P_A32)) {
1663 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1685 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1694 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1709 *bytes = *codes++ ^ condval[ins->condition];
1710 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1719 *bytes = c - 0332 + 0xF2;
1720 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1725 if (ins->rex & REX_R) {
1727 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1730 ins->rex &= ~(REX_L|REX_R);
1737 if (ins->oprs[0].segment != NO_SEG)
1738 errfunc(ERR_PANIC, "non-constant BSS size in pass two");
1740 int64_t size = ins->oprs[0].offset;
1742 out(offset, segment, NULL,
1743 OUT_RESERVE, size, NO_SEG, NO_SEG);
1754 *bytes = c - 0366 + 0x66;
1755 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1765 *bytes = bits == 16 ? 3 : 5;
1766 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1770 default: /* can't do it by 'case' statements */
1771 if (c >= 0100 && c <= 0277) { /* it's an EA */
1779 /* pick rfield from operand b */
1780 rflags = regflag(&ins->oprs[c & 7]);
1781 rfield = regvals[ins->oprs[c & 7].basereg];
1783 /* rfield is constant */
1789 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
1790 ins->addr_size, rfield, rflags, ins->forw_ref)) {
1791 errfunc(ERR_NONFATAL, "invalid effective address");
1796 *p++ = ea_data.modrm;
1797 if (ea_data.sib_present)
1800 /* DREX suffixes come between the SIB and the displacement */
1801 if (ins->rex & REX_D) {
1803 (ins->drexdst << 4) |
1804 (ins->rex & REX_OC ? 0x08 : 0) |
1805 (ins->rex & (REX_R|REX_X|REX_B));
1810 out(offset, segment, bytes, OUT_RAWDATA, s, NO_SEG, NO_SEG);
1812 switch (ea_data.bytes) {
1816 if (ins->oprs[(c >> 3) & 7].segment != NO_SEG) {
1817 data = ins->oprs[(c >> 3) & 7].offset;
1818 out(offset, segment, &data, OUT_ADDRESS, 1,
1819 ins->oprs[(c >> 3) & 7].segment,
1820 ins->oprs[(c >> 3) & 7].wrt);
1822 *bytes = ins->oprs[(c >> 3) & 7].offset;
1823 out(offset, segment, bytes, OUT_RAWDATA, 1,
1831 data = ins->oprs[(c >> 3) & 7].offset;
1832 warn_overflow(ea_data.bytes, data);
1833 out(offset, segment, &data,
1834 ea_data.rip ? OUT_REL4ADR : OUT_ADDRESS,
1836 ins->oprs[(c >> 3) & 7].segment,
1837 ins->oprs[(c >> 3) & 7].wrt);
1843 errfunc(ERR_PANIC, "internal instruction table corrupt"
1844 ": instruction code 0x%02X given", c);
1850 static int32_t regflag(const operand * o)
1852 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1853 errfunc(ERR_PANIC, "invalid operand passed to regflag()");
1855 return reg_flags[o->basereg];
1858 static int32_t regval(const operand * o)
1860 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1861 errfunc(ERR_PANIC, "invalid operand passed to regval()");
1863 return regvals[o->basereg];
1866 static int op_rexflags(const operand * o, int mask)
1871 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1872 errfunc(ERR_PANIC, "invalid operand passed to op_rexflags()");
1875 flags = reg_flags[o->basereg];
1876 val = regvals[o->basereg];
1878 return rexflags(val, flags, mask);
1881 static int rexflags(int val, int32_t flags, int mask)
1886 rex |= REX_B|REX_X|REX_R;
1889 if (!(REG_HIGH & ~flags)) /* AH, CH, DH, BH */
1891 else if (!(REG8 & ~flags) && val >= 4) /* SPL, BPL, SIL, DIL */
1897 static int matches(const struct itemplate *itemp, insn * instruction, int bits)
1899 int i, size[MAX_OPERANDS], asize, oprs, ret;
1906 if (itemp->opcode != instruction->opcode)
1910 * Count the operands
1912 if (itemp->operands != instruction->operands)
1916 * Check that no spurious colons or TOs are present
1918 for (i = 0; i < itemp->operands; i++)
1919 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON | TO))
1923 * Process size flags
1925 if (itemp->flags & IF_ARMASK) {
1926 memset(size, 0, sizeof size);
1928 i = ((itemp->flags & IF_ARMASK) >> IF_ARSHFT) - 1;
1930 switch (itemp->flags & IF_SMASK) {
1964 switch (itemp->flags & IF_SMASK) {
1996 for (i = 0; i < MAX_OPERANDS; i++)
2001 * Check that the operand flags all match up
2003 for (i = 0; i < itemp->operands; i++) {
2004 int32_t type = instruction->oprs[i].type;
2005 if (!(type & SIZE_MASK))
2008 if (itemp->opd[i] & SAME_AS) {
2009 int j = itemp->opd[i] & ~SAME_AS;
2010 if (type != instruction->oprs[j].type ||
2011 instruction->oprs[i].basereg != instruction->oprs[j].basereg)
2013 } else if (itemp->opd[i] & ~type ||
2014 ((itemp->opd[i] & SIZE_MASK) &&
2015 ((itemp->opd[i] ^ type) & SIZE_MASK))) {
2016 if ((itemp->opd[i] & ~type & ~SIZE_MASK) ||
2025 * Check operand sizes
2027 if (itemp->flags & (IF_SM | IF_SM2)) {
2028 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
2030 for (i = 0; i < oprs; i++) {
2031 if ((asize = itemp->opd[i] & SIZE_MASK) != 0) {
2033 for (j = 0; j < oprs; j++)
2039 oprs = itemp->operands;
2042 for (i = 0; i < itemp->operands; i++) {
2043 if (!(itemp->opd[i] & SIZE_MASK) &&
2044 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
2049 * Check template is okay at the set cpu level
2051 if (((itemp->flags & IF_PLEVEL) > cpu))
2055 * Check if instruction is available in long mode
2057 if ((itemp->flags & IF_NOLONG) && (bits == 64))
2061 * Check if special handling needed for Jumps
2063 if ((uint8_t)(itemp->code[0]) >= 0370)
2069 static ea *process_ea(operand * input, ea * output, int bits,
2070 int addrbits, int rfield, int32_t rflags, int forw_ref)
2072 output->rip = false;
2074 /* REX flags for the rfield operand */
2075 output->rex |= rexflags(rfield, rflags, REX_R|REX_P|REX_W|REX_H);
2077 if (!(REGISTER & ~input->type)) { /* register direct */
2081 if (input->basereg < EXPR_REG_START /* Verify as Register */
2082 || input->basereg >= REG_ENUM_LIMIT)
2085 i = regvals[input->basereg];
2088 return NULL; /* Invalid EA register */
2090 output->rex |= op_rexflags(input, REX_B|REX_P|REX_W|REX_H);
2092 output->sib_present = false; /* no SIB necessary */
2093 output->bytes = 0; /* no offset necessary either */
2094 output->modrm = 0xC0 | ((rfield & 7) << 3) | (i & 7);
2095 } else { /* it's a memory reference */
2096 if (input->basereg == -1
2097 && (input->indexreg == -1 || input->scale == 0)) {
2098 /* it's a pure offset */
2099 if (bits == 64 && (~input->type & IP_REL)) {
2100 int scale, index, base;
2101 output->sib_present = true;
2105 output->sib = (scale << 6) | (index << 3) | base;
2107 output->modrm = 4 | ((rfield & 7) << 3);
2108 output->rip = false;
2110 output->sib_present = false;
2111 output->bytes = (addrbits != 16 ? 4 : 2);
2112 output->modrm = (addrbits != 16 ? 5 : 6) | ((rfield & 7) << 3);
2113 output->rip = bits == 64;
2115 } else { /* it's an indirection */
2116 int i = input->indexreg, b = input->basereg, s = input->scale;
2117 int32_t o = input->offset, seg = input->segment;
2118 int hb = input->hintbase, ht = input->hinttype;
2121 int32_t ix, bx; /* register flags */
2124 i = -1; /* make this easy, at least */
2126 if (i >= EXPR_REG_START && i < REG_ENUM_LIMIT) {
2134 if (b >= EXPR_REG_START && b < REG_ENUM_LIMIT) {
2142 /* check for a 32/64-bit memory reference... */
2143 if ((ix|bx) & (BITS32|BITS64)) {
2144 /* it must be a 32/64-bit memory reference. Firstly we have
2145 * to check that all registers involved are type E/Rxx. */
2146 int32_t sok = BITS32|BITS64;
2149 if (!(REG64 & ~ix) || !(REG32 & ~ix))
2157 return NULL; /* Invalid register */
2158 if (~sok & bx & SIZE_MASK)
2159 return NULL; /* Invalid size */
2163 /* While we're here, ensure the user didn't specify
2165 if (input->disp_size == 16 || input->disp_size == 64)
2168 if (addrbits == 16 ||
2169 (addrbits == 32 && !(sok & BITS32)) ||
2170 (addrbits == 64 && !(sok & BITS64)))
2173 /* now reorganize base/index */
2174 if (s == 1 && bt != it && bt != -1 && it != -1 &&
2175 ((hb == b && ht == EAH_NOTBASE)
2176 || (hb == i && ht == EAH_MAKEBASE))) {
2177 /* swap if hints say so */
2178 t = bt, bt = it, it = t;
2179 t = bx, bx = ix, ix = t;
2181 if (bt == it) /* convert EAX+2*EAX to 3*EAX */
2182 bt = -1, bx = 0, s++;
2183 if (bt == -1 && s == 1 && !(hb == it && ht == EAH_NOTBASE)) {
2184 /* make single reg base, unless hint */
2185 bt = it, bx = ix, it = -1, ix = 0;
2187 if (((s == 2 && it != REG_NUM_ESP
2188 && !(input->eaflags & EAF_TIMESTWO)) || s == 3
2189 || s == 5 || s == 9) && bt == -1)
2190 bt = it, bx = ix, s--; /* convert 3*EAX to EAX+2*EAX */
2191 if (it == -1 && (bt & 7) != REG_NUM_ESP
2192 && (input->eaflags & EAF_TIMESTWO))
2193 it = bt, ix = bx, bt = -1, bx = 0, s = 1;
2194 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
2195 if (s == 1 && it == REG_NUM_ESP) {
2196 /* swap ESP into base if scale is 1 */
2197 t = it, it = bt, bt = t;
2198 t = ix, ix = bx, bx = t;
2200 if (it == REG_NUM_ESP
2201 || (s != 1 && s != 2 && s != 4 && s != 8 && it != -1))
2202 return NULL; /* wrong, for various reasons */
2204 output->rex |= rexflags(it, ix, REX_X);
2205 output->rex |= rexflags(bt, bx, REX_B);
2207 if (it == -1 && (bt & 7) != REG_NUM_ESP) {
2216 if (rm != REG_NUM_EBP && o == 0 &&
2217 seg == NO_SEG && !forw_ref &&
2219 (EAF_BYTEOFFS | EAF_WORDOFFS)))
2221 else if (input->eaflags & EAF_BYTEOFFS ||
2222 (o >= -128 && o <= 127 && seg == NO_SEG
2224 && !(input->eaflags & EAF_WORDOFFS)))
2230 output->sib_present = false;
2231 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
2232 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
2235 int mod, scale, index, base;
2255 default: /* then what the smeg is it? */
2256 return NULL; /* panic */
2264 if (base != REG_NUM_EBP && o == 0 &&
2265 seg == NO_SEG && !forw_ref &&
2267 (EAF_BYTEOFFS | EAF_WORDOFFS)))
2269 else if (input->eaflags & EAF_BYTEOFFS ||
2270 (o >= -128 && o <= 127 && seg == NO_SEG
2272 && !(input->eaflags & EAF_WORDOFFS)))
2278 output->sib_present = true;
2279 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
2280 output->modrm = (mod << 6) | ((rfield & 7) << 3) | 4;
2281 output->sib = (scale << 6) | (index << 3) | base;
2283 } else { /* it's 16-bit */
2286 /* check for 64-bit long mode */
2290 /* check all registers are BX, BP, SI or DI */
2291 if ((b != -1 && b != R_BP && b != R_BX && b != R_SI
2292 && b != R_DI) || (i != -1 && i != R_BP && i != R_BX
2293 && i != R_SI && i != R_DI))
2296 /* ensure the user didn't specify DWORD/QWORD */
2297 if (input->disp_size == 32 || input->disp_size == 64)
2300 if (s != 1 && i != -1)
2301 return NULL; /* no can do, in 16-bit EA */
2302 if (b == -1 && i != -1) {
2307 if ((b == R_SI || b == R_DI) && i != -1) {
2312 /* have BX/BP as base, SI/DI index */
2314 return NULL; /* shouldn't ever happen, in theory */
2315 if (i != -1 && b != -1 &&
2316 (i == R_BP || i == R_BX || b == R_SI || b == R_DI))
2317 return NULL; /* invalid combinations */
2318 if (b == -1) /* pure offset: handled above */
2319 return NULL; /* so if it gets to here, panic! */
2323 switch (i * 256 + b) {
2324 case R_SI * 256 + R_BX:
2327 case R_DI * 256 + R_BX:
2330 case R_SI * 256 + R_BP:
2333 case R_DI * 256 + R_BP:
2351 if (rm == -1) /* can't happen, in theory */
2352 return NULL; /* so panic if it does */
2354 if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
2355 !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
2357 else if (input->eaflags & EAF_BYTEOFFS ||
2358 (o >= -128 && o <= 127 && seg == NO_SEG
2360 && !(input->eaflags & EAF_WORDOFFS)))
2365 output->sib_present = false; /* no SIB - it's 16-bit */
2366 output->bytes = mod; /* bytes of offset needed */
2367 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
2372 output->size = 1 + output->sib_present + output->bytes;
2376 static void add_asp(insn *ins, int addrbits)
2381 valid = (addrbits == 64) ? 64|32 : 32|16;
2383 switch (ins->prefixes[PPS_ASIZE]) {
2394 valid &= (addrbits == 32) ? 16 : 32;
2400 for (j = 0; j < ins->operands; j++) {
2401 if (!(MEMORY & ~ins->oprs[j].type)) {
2404 /* Verify as Register */
2405 if (ins->oprs[j].indexreg < EXPR_REG_START
2406 || ins->oprs[j].indexreg >= REG_ENUM_LIMIT)
2409 i = reg_flags[ins->oprs[j].indexreg];
2411 /* Verify as Register */
2412 if (ins->oprs[j].basereg < EXPR_REG_START
2413 || ins->oprs[j].basereg >= REG_ENUM_LIMIT)
2416 b = reg_flags[ins->oprs[j].basereg];
2418 if (ins->oprs[j].scale == 0)
2422 int ds = ins->oprs[j].disp_size;
2423 if ((addrbits != 64 && ds > 8) ||
2424 (addrbits == 64 && ds == 16))
2444 if (valid & addrbits) {
2445 ins->addr_size = addrbits;
2446 } else if (valid & ((addrbits == 32) ? 16 : 32)) {
2447 /* Add an address size prefix */
2448 enum prefixes pref = (addrbits == 32) ? P_A16 : P_A32;
2449 ins->prefixes[PPS_ASIZE] = pref;
2450 ins->addr_size = (addrbits == 32) ? 16 : 32;
2453 errfunc(ERR_NONFATAL, "impossible combination of address sizes");
2454 ins->addr_size = addrbits; /* Error recovery */
2457 defdisp = ins->addr_size == 16 ? 16 : 32;
2459 for (j = 0; j < ins->operands; j++) {
2460 if (!(MEM_OFFS & ~ins->oprs[j].type) &&
2461 (ins->oprs[j].disp_size ? ins->oprs[j].disp_size : defdisp)
2462 != ins->addr_size) {
2463 /* mem_offs sizes must match the address size; if not,
2464 strip the MEM_OFFS bit and match only EA instructions */
2465 ins->oprs[j].type &= ~(MEM_OFFS & ~MEMORY);