blob: 9288aab9f7152b3bcd747efa07634f7ab6d45f57 [file] [log] [blame]
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001/* assemble.c code generation for the Netwide Assembler
2 *
3 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
4 * Julian Hall. All rights reserved. The software is
5 * redistributable under the licence given in the file "Licence"
6 * distributed in the NASM archive.
7 *
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
14 * on operand 0
15 * \10, \11, \12 - a literal byte follows in the code stream, to be added
16 * to the register value of operand 0, 1 or 2
17 * \17 - encodes the literal byte 0. (Some compilers don't take
18 * kindly to a zero byte in the _middle_ of a compile time
19 * string constant, so I had to put this hack in.)
20 * \14, \15, \16 - a signed byte immediate operand, from operand 0, 1 or 2
21 * \20, \21, \22 - a byte immediate operand, from operand 0, 1 or 2
22 * \24, \25, \26 - an unsigned byte immediate operand, from operand 0, 1 or 2
23 * \30, \31, \32 - a word immediate operand, from operand 0, 1 or 2
24 * \34, \35, \36 - select between \3[012] and \4[012] depending on 16/32 bit
H. Peter Anvin3ba46772002-05-27 23:19:35 +000025 * assembly mode or the operand-size override on the operand
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000026 * \37 - a word constant, from the _segment_ part of operand 0
27 * \40, \41, \42 - a long immediate operand, from operand 0, 1 or 2
H. Peter Anvinb061d592007-04-16 02:02:06 +000028 * \44, \45, \46 - select between \3[012], \4[012] and \5[456]
29 * depending on assembly mode or the address-size override
30 * on the operand.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000031 * \50, \51, \52 - a byte relative operand, from operand 0, 1 or 2
Keith Kaniosb7a89542007-04-12 02:40:54 +000032 * \54, \55, \56 - a qword immediate operand, from operand 0, 1 or 2
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000033 * \60, \61, \62 - a word relative operand, from operand 0, 1 or 2
34 * \64, \65, \66 - select between \6[012] and \7[012] depending on 16/32 bit
H. Peter Anvin17799b42002-05-21 03:31:21 +000035 * assembly mode or the operand-size override on the operand
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000036 * \70, \71, \72 - a long relative operand, from operand 0, 1 or 2
37 * \1ab - a ModRM, calculated on EA in operand a, with the spare
38 * field the register value of operand b.
H. Peter Anvinaf535c12002-04-30 20:59:21 +000039 * \130,\131,\132 - an immediate word or signed byte for operand 0, 1, or 2
40 * \133,\134,\135 - or 2 (s-field) into next opcode byte if operand 0, 1, or 2
41 * is a signed byte rather than a word.
42 * \140,\141,\142 - an immediate dword or signed byte for operand 0, 1, or 2
43 * \143,\144,\145 - or 2 (s-field) into next opcode byte if operand 0, 1, or 2
44 * is a signed byte rather than a dword.
Keith Kaniosb7a89542007-04-12 02:40:54 +000045 * \150,\151,\152 - an immediate qword or signed byte for operand 0, 1, or 2
46 * \153,\154,\155 - or 2 (s-field) into next opcode byte if operand 0, 1, or 2
47 * is a signed byte rather than a qword.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000048 * \2ab - a ModRM, calculated on EA in operand a, with the spare
49 * field equal to digit b.
50 * \30x - might be an 0x67 byte, depending on the address size of
51 * the memory reference in operand x.
52 * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
53 * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
Keith Kanios48af1772007-08-17 07:37:52 +000054 * \312 - (disassembler only) marker on LOOP, LOOPxx instructions.
H. Peter Anvince2b3972007-05-30 22:21:11 +000055 * \313 - indicates fixed 64-bit address size, 0x67 invalid.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000056 * \320 - indicates fixed 16-bit operand size, i.e. optional 0x66.
57 * \321 - indicates fixed 32-bit operand size, i.e. optional 0x66.
58 * \322 - indicates that this instruction is only valid when the
59 * operand size is the default (instruction to disassembler,
60 * generates no code in the assembler)
H. Peter Anvince2b3972007-05-30 22:21:11 +000061 * \323 - indicates fixed 64-bit operand size, REX on extensions only.
Keith Kaniosb7a89542007-04-12 02:40:54 +000062 * \324 - indicates 64-bit operand size requiring REX prefix.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000063 * \330 - a literal byte follows in the code stream, to be added
64 * to the condition code value of the instruction.
Keith Kanios48af1772007-08-17 07:37:52 +000065 * \331 - instruction not valid with REP prefix. Hint for
H. Peter Anvinef7468f2002-04-30 20:57:59 +000066 * disassembler only; for SSE instructions.
Keith Kanios48af1772007-08-17 07:37:52 +000067 * \332 - disassemble a rep (0xF3 byte) prefix as repe not rep.
68 * \333 - REP prefix (0xF3 byte); for SSE instructions. Not encoded
69 * as a literal byte in order to aid the disassembler.
70 * \334 - LOCK prefix used instead of REX.R
Keith Kaniosb7a89542007-04-12 02:40:54 +000071 * \340 - reserve <operand 0> bytes of uninitialized storage.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000072 * Operand 0 had better be a segmentless constant.
H. Peter Anvin62cb6062007-09-11 22:44:03 +000073 * \364 - operand-size prefix (0x66) not permitted
74 * \365 - address-size prefix (0x67) not permitted
75 * \366 - operand-size prefix (0x66) used as opcode extension
76 * \367 - address-size prefix (0x67) used as opcode extension
H. Peter Anvin788e6c12002-04-30 21:02:01 +000077 * \370,\371,\372 - match only if operand 0 meets byte jump criteria.
78 * 370 is used for Jcc, 371 is used for JMP.
H. Peter Anvinaf535c12002-04-30 20:59:21 +000079 * \373 - assemble 0x03 if bits==16, 0x05 if bits==32;
80 * used for conditional jump over longer jump
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000081 */
82
83#include <stdio.h>
84#include <string.h>
Keith Kaniosb7a89542007-04-12 02:40:54 +000085#include <inttypes.h>
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000086
87#include "nasm.h"
H. Peter Anvin6768eb72002-04-30 20:52:26 +000088#include "nasmlib.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000089#include "assemble.h"
90#include "insns.h"
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +000091#include "preproc.h"
H. Peter Anvin3df97a72007-05-30 03:25:21 +000092#include "regflags.c"
Keith Kaniosb7a89542007-04-12 02:40:54 +000093#include "regvals.c"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000094
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000095typedef struct {
Keith Kaniosb7a89542007-04-12 02:40:54 +000096 int sib_present; /* is a SIB byte necessary? */
97 int bytes; /* # of bytes of offset needed */
98 int size; /* lazy - this is sib+bytes+1 */
99 uint8_t modrm, sib, rex, rip; /* the bytes themselves */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000100} ea;
101
Keith Kaniosb7a89542007-04-12 02:40:54 +0000102static uint32_t cpu; /* cpu level received from nasm.c */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000103static efunc errfunc;
104static struct ofmt *outfmt;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000105static ListGen *list;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000106
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000107static int32_t calcsize(int32_t, int32_t, int, insn *, const char *);
108static void gencode(int32_t, int32_t, int, insn *, const char *, int32_t);
H. Peter Anvin3360d792007-09-11 04:16:57 +0000109static int matches(const struct itemplate *, insn *, int bits);
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000110static int32_t regflag(const operand *);
111static int32_t regval(const operand *);
112static int rexflags(int, int32_t, int);
113static int op_rexflags(const operand *, int);
H. Peter Anvin5b0e3ec2007-07-07 02:01:08 +0000114static ea *process_ea(operand *, ea *, int, int, int32_t, int);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000115static int chsize(operand *, int);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000116
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000117static void assert_no_prefix(insn * ins, int prefix)
118{
119 int j;
120
121 for (j = 0; j < ins->nprefix; j++) {
122 if (ins->prefixes[j] == prefix) {
123 errfunc(ERR_NONFATAL, "invalid %s prefix", prefix_name(prefix));
124 break;
125 }
126 }
127}
128
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000129/*
130 * This routine wrappers the real output format's output routine,
131 * in order to pass a copy of the data off to the listing file
132 * generator at the same time.
133 */
Keith Kaniosb7a89542007-04-12 02:40:54 +0000134static void out(int32_t offset, int32_t segto, const void *data,
135 uint32_t type, int32_t segment, int32_t wrt)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000136{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000137 static int32_t lineno = 0; /* static!!! */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000138 static char *lnfname = NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000139
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000140 if ((type & OUT_TYPMASK) == OUT_ADDRESS) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000141 if (segment != NO_SEG || wrt != NO_SEG) {
142 /*
143 * This address is relocated. We must write it as
144 * OUT_ADDRESS, so there's no work to be done here.
145 */
146 list->output(offset, data, type);
147 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000148 uint8_t p[8], *q = p;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000149 /*
150 * This is a non-relocated address, and we're going to
151 * convert it into RAWDATA format.
152 */
153 if ((type & OUT_SIZMASK) == 4) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000154 WRITELONG(q, *(int32_t *)data);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000155 list->output(offset, p, OUT_RAWDATA + 4);
Keith Kaniosb7a89542007-04-12 02:40:54 +0000156 } else if ((type & OUT_SIZMASK) == 8) {
157 WRITEDLONG(q, *(int64_t *)data);
158 list->output(offset, p, OUT_RAWDATA + 8);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000159 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000160 WRITESHORT(q, *(int32_t *)data);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000161 list->output(offset, p, OUT_RAWDATA + 2);
162 }
163 }
164 } else if ((type & OUT_TYPMASK) == OUT_RAWDATA) {
165 list->output(offset, data, type);
166 } else if ((type & OUT_TYPMASK) == OUT_RESERVE) {
167 list->output(offset, NULL, type);
168 } else if ((type & OUT_TYPMASK) == OUT_REL2ADR ||
169 (type & OUT_TYPMASK) == OUT_REL4ADR) {
170 list->output(offset, data, type);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000171 }
172
Frank Kotlerabebb082003-09-06 04:45:37 +0000173 /*
174 * this call to src_get determines when we call the
175 * debug-format-specific "linenum" function
176 * it updates lineno and lnfname to the current values
177 * returning 0 if "same as last time", -2 if lnfname
178 * changed, and the amount by which lineno changed,
179 * if it did. thus, these variables must be static
180 */
181
H. Peter Anvine2c80182005-01-15 22:15:51 +0000182 if (src_get(&lineno, &lnfname)) {
183 outfmt->current_dfmt->linenum(lnfname, lineno, segto);
H. Peter Anvince616072002-04-30 21:02:23 +0000184 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000185
H. Peter Anvine2c80182005-01-15 22:15:51 +0000186 outfmt->output(segto, data, type, segment, wrt);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000187}
188
Keith Kaniosb7a89542007-04-12 02:40:54 +0000189static int jmp_match(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000190 insn * ins, const char *code)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000191{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000192 int32_t isize;
193 uint8_t c = code[0];
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000194
H. Peter Anvine2c80182005-01-15 22:15:51 +0000195 if (c != 0370 && c != 0371)
196 return 0;
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000197 if (ins->oprs[0].opflags & OPFLAG_FORWARD) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000198 if ((optimizing < 0 || (ins->oprs[0].type & STRICT))
199 && c == 0370)
200 return 1;
201 else
202 return (pass0 == 0); /* match a forward reference */
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000203 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000204 isize = calcsize(segment, offset, bits, ins, code);
205 if (ins->oprs[0].segment != segment)
206 return 0;
207 isize = ins->oprs[0].offset - offset - isize; /* isize is now the delta */
208 if (isize >= -128L && isize <= 127L)
209 return 1; /* it is byte size */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000210
211 return 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000212}
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000213
Keith Kaniosb7a89542007-04-12 02:40:54 +0000214int32_t assemble(int32_t segment, int32_t offset, int bits, uint32_t cp,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000215 insn * instruction, struct ofmt *output, efunc error,
216 ListGen * listgen)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000217{
H. Peter Anvin3360d792007-09-11 04:16:57 +0000218 const struct itemplate *temp;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000219 int j;
220 int size_prob;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000221 int32_t insn_end;
222 int32_t itimes;
223 int32_t start = offset;
224 int32_t wsize = 0; /* size for DB etc. */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000225
H. Peter Anvine2c80182005-01-15 22:15:51 +0000226 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000227 cpu = cp;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000228 outfmt = output; /* likewise */
229 list = listgen; /* and again */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000230
H. Peter Anvine2c80182005-01-15 22:15:51 +0000231 switch (instruction->opcode) {
232 case -1:
233 return 0;
234 case I_DB:
235 wsize = 1;
236 break;
237 case I_DW:
238 wsize = 2;
239 break;
240 case I_DD:
241 wsize = 4;
242 break;
243 case I_DQ:
244 wsize = 8;
245 break;
246 case I_DT:
247 wsize = 10;
248 break;
H. Peter Anvin16b0a332007-09-12 20:27:41 -0700249 default:
250 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000251 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000252
H. Peter Anvineba20a72002-04-30 20:53:55 +0000253 if (wsize) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000254 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000255 int32_t t = instruction->times;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000256 if (t < 0)
257 errfunc(ERR_PANIC,
258 "instruction->times < 0 (%ld) in assemble()", t);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000259
H. Peter Anvine2c80182005-01-15 22:15:51 +0000260 while (t--) { /* repeat TIMES times */
261 for (e = instruction->eops; e; e = e->next) {
262 if (e->type == EOT_DB_NUMBER) {
263 if (wsize == 1) {
264 if (e->segment != NO_SEG)
265 errfunc(ERR_NONFATAL,
266 "one-byte relocation attempted");
267 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000268 uint8_t out_byte = e->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000269 out(offset, segment, &out_byte,
270 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
271 }
Keith Kanios61ff53c2007-04-14 18:54:52 +0000272 } else if (wsize > 8) {
273 errfunc(ERR_NONFATAL, "integer supplied to a DT"
274 " instruction");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000275 } else
276 out(offset, segment, &e->offset,
277 OUT_ADDRESS + wsize, e->segment, e->wrt);
278 offset += wsize;
279 } else if (e->type == EOT_DB_STRING) {
280 int align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000281
H. Peter Anvine2c80182005-01-15 22:15:51 +0000282 out(offset, segment, e->stringval,
283 OUT_RAWDATA + e->stringlen, NO_SEG, NO_SEG);
284 align = e->stringlen % wsize;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000285
H. Peter Anvine2c80182005-01-15 22:15:51 +0000286 if (align) {
287 align = wsize - align;
288 out(offset, segment, "\0\0\0\0\0\0\0\0",
289 OUT_RAWDATA + align, NO_SEG, NO_SEG);
290 }
291 offset += e->stringlen + align;
292 }
293 }
294 if (t > 0 && t == instruction->times - 1) {
295 /*
296 * Dummy call to list->output to give the offset to the
297 * listing module.
298 */
299 list->output(offset, NULL, OUT_RAWDATA);
300 list->uplevel(LIST_TIMES);
301 }
302 }
303 if (instruction->times > 1)
304 list->downlevel(LIST_TIMES);
305 return offset - start;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000306 }
307
H. Peter Anvine2c80182005-01-15 22:15:51 +0000308 if (instruction->opcode == I_INCBIN) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000309 static char fname[FILENAME_MAX];
H. Peter Anvine2c80182005-01-15 22:15:51 +0000310 FILE *fp;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000311 int32_t len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000312 char *prefix = "", *combine;
313 char **pPrevPath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000314
H. Peter Anvine2c80182005-01-15 22:15:51 +0000315 len = FILENAME_MAX - 1;
316 if (len > instruction->eops->stringlen)
317 len = instruction->eops->stringlen;
318 strncpy(fname, instruction->eops->stringval, len);
319 fname[len] = '\0';
H. Peter Anvineba20a72002-04-30 20:53:55 +0000320
Keith Kaniosb7a89542007-04-12 02:40:54 +0000321 while (1) { /* added by alexfru: 'incbin' uses include paths */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000322 combine = nasm_malloc(strlen(prefix) + len + 1);
323 strcpy(combine, prefix);
324 strcat(combine, fname);
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000325
H. Peter Anvine2c80182005-01-15 22:15:51 +0000326 if ((fp = fopen(combine, "rb")) != NULL) {
327 nasm_free(combine);
328 break;
329 }
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000330
H. Peter Anvine2c80182005-01-15 22:15:51 +0000331 nasm_free(combine);
332 pPrevPath = pp_get_include_path_ptr(pPrevPath);
333 if (pPrevPath == NULL)
334 break;
335 prefix = *pPrevPath;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000336 }
337
338 if (fp == NULL)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000339 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
340 fname);
341 else if (fseek(fp, 0L, SEEK_END) < 0)
342 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
343 fname);
344 else {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000345 static char buf[2048];
Keith Kaniosb7a89542007-04-12 02:40:54 +0000346 int32_t t = instruction->times;
347 int32_t base = 0;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000348
H. Peter Anvine2c80182005-01-15 22:15:51 +0000349 len = ftell(fp);
350 if (instruction->eops->next) {
351 base = instruction->eops->next->offset;
352 len -= base;
353 if (instruction->eops->next->next &&
354 len > instruction->eops->next->next->offset)
355 len = instruction->eops->next->next->offset;
356 }
357 /*
358 * Dummy call to list->output to give the offset to the
359 * listing module.
360 */
361 list->output(offset, NULL, OUT_RAWDATA);
362 list->uplevel(LIST_INCBIN);
363 while (t--) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000364 int32_t l;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000365
H. Peter Anvine2c80182005-01-15 22:15:51 +0000366 fseek(fp, base, SEEK_SET);
367 l = len;
368 while (l > 0) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000369 int32_t m =
H. Peter Anvine2c80182005-01-15 22:15:51 +0000370 fread(buf, 1, (l > sizeof(buf) ? sizeof(buf) : l),
371 fp);
372 if (!m) {
373 /*
374 * This shouldn't happen unless the file
375 * actually changes while we are reading
376 * it.
377 */
378 error(ERR_NONFATAL,
379 "`incbin': unexpected EOF while"
380 " reading file `%s'", fname);
381 t = 0; /* Try to exit cleanly */
382 break;
383 }
384 out(offset, segment, buf, OUT_RAWDATA + m,
385 NO_SEG, NO_SEG);
386 l -= m;
387 }
388 }
389 list->downlevel(LIST_INCBIN);
390 if (instruction->times > 1) {
391 /*
392 * Dummy call to list->output to give the offset to the
393 * listing module.
394 */
395 list->output(offset, NULL, OUT_RAWDATA);
396 list->uplevel(LIST_TIMES);
397 list->downlevel(LIST_TIMES);
398 }
399 fclose(fp);
400 return instruction->times * len;
401 }
402 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000403 }
404
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000405 size_prob = FALSE;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000406
407 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++){
408 int m = matches(temp, instruction, bits);
409
H. Peter Anvine2c80182005-01-15 22:15:51 +0000410 if (m == 99)
411 m += jmp_match(segment, offset, bits, instruction, temp->code);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000412
H. Peter Anvine2c80182005-01-15 22:15:51 +0000413 if (m == 100) { /* matches! */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000414 const char *codes = temp->code;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000415 int32_t insn_size = calcsize(segment, offset, bits,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000416 instruction, codes);
417 itimes = instruction->times;
418 if (insn_size < 0) /* shouldn't be, on pass two */
419 error(ERR_PANIC, "errors made it through from pass one");
420 else
421 while (itimes--) {
422 for (j = 0; j < instruction->nprefix; j++) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000423 uint8_t c = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000424 switch (instruction->prefixes[j]) {
425 case P_LOCK:
426 c = 0xF0;
427 break;
428 case P_REPNE:
429 case P_REPNZ:
430 c = 0xF2;
431 break;
432 case P_REPE:
433 case P_REPZ:
434 case P_REP:
435 c = 0xF3;
436 break;
437 case R_CS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000438 if (bits == 64) {
439 error(ERR_WARNING,
440 "cs segment base ignored in 64-bit mode");
441 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000442 c = 0x2E;
443 break;
444 case R_DS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000445 if (bits == 64) {
446 error(ERR_WARNING,
447 "ds segment base ignored in 64-bit mode");
448 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000449 c = 0x3E;
450 break;
451 case R_ES:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000452 if (bits == 64) {
453 error(ERR_WARNING,
454 "es segment base ignored in 64-bit mode");
455 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000456 c = 0x26;
457 break;
458 case R_FS:
459 c = 0x64;
460 break;
461 case R_GS:
462 c = 0x65;
463 break;
464 case R_SS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000465 if (bits == 64) {
466 error(ERR_WARNING,
467 "ss segment base ignored in 64-bit mode");
468 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000469 c = 0x36;
470 break;
471 case R_SEGR6:
472 case R_SEGR7:
473 error(ERR_NONFATAL,
474 "segr6 and segr7 cannot be used as prefixes");
475 break;
476 case P_A16:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000477 if (bits == 64) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000478 error(ERR_NONFATAL,
479 "16-bit addressing is not supported "
480 "in 64-bit mode");
Keith Kaniosb7a89542007-04-12 02:40:54 +0000481 break;
482 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000483 if (bits != 16)
484 c = 0x67;
485 break;
486 case P_A32:
487 if (bits != 32)
488 c = 0x67;
489 break;
490 case P_O16:
491 if (bits != 16)
492 c = 0x66;
493 break;
494 case P_O32:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000495 if (bits == 16)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000496 c = 0x66;
497 break;
498 default:
499 error(ERR_PANIC, "invalid instruction prefix");
500 }
501 if (c != 0) {
502 out(offset, segment, &c, OUT_RAWDATA + 1,
503 NO_SEG, NO_SEG);
504 offset++;
505 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000506 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000507 insn_end = offset + insn_size;
508 gencode(segment, offset, bits, instruction, codes,
509 insn_end);
510 offset += insn_size;
511 if (itimes > 0 && itimes == instruction->times - 1) {
512 /*
513 * Dummy call to list->output to give the offset to the
514 * listing module.
515 */
516 list->output(offset, NULL, OUT_RAWDATA);
517 list->uplevel(LIST_TIMES);
518 }
519 }
520 if (instruction->times > 1)
521 list->downlevel(LIST_TIMES);
522 return offset - start;
523 } else if (m > 0 && m > size_prob) {
524 size_prob = m;
525 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000526// temp++;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000527 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000528
H. Peter Anvine2c80182005-01-15 22:15:51 +0000529 if (temp->opcode == -1) { /* didn't match any instruction */
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000530 switch (size_prob) {
531 case 1:
532 error(ERR_NONFATAL, "operation size not specified");
533 break;
534 case 2:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000535 error(ERR_NONFATAL, "mismatch in operand sizes");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000536 break;
537 case 3:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000538 error(ERR_NONFATAL, "no instruction for this cpu level");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000539 break;
540 case 4:
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000541 error(ERR_NONFATAL, "instruction not supported in 64-bit mode");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000542 break;
543 default:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000544 error(ERR_NONFATAL,
545 "invalid combination of opcode and operands");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000546 break;
547 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000548 }
549 return 0;
550}
551
Keith Kaniosb7a89542007-04-12 02:40:54 +0000552int32_t insn_size(int32_t segment, int32_t offset, int bits, uint32_t cp,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000553 insn * instruction, efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000554{
H. Peter Anvin3360d792007-09-11 04:16:57 +0000555 const struct itemplate *temp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000556
H. Peter Anvine2c80182005-01-15 22:15:51 +0000557 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000558 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000559
560 if (instruction->opcode == -1)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000561 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000562
563 if (instruction->opcode == I_DB ||
H. Peter Anvine2c80182005-01-15 22:15:51 +0000564 instruction->opcode == I_DW ||
565 instruction->opcode == I_DD ||
566 instruction->opcode == I_DQ || instruction->opcode == I_DT) {
567 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000568 int32_t isize, osize, wsize = 0; /* placate gcc */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000569
H. Peter Anvine2c80182005-01-15 22:15:51 +0000570 isize = 0;
571 switch (instruction->opcode) {
572 case I_DB:
573 wsize = 1;
574 break;
575 case I_DW:
576 wsize = 2;
577 break;
578 case I_DD:
579 wsize = 4;
580 break;
581 case I_DQ:
582 wsize = 8;
583 break;
584 case I_DT:
585 wsize = 10;
586 break;
H. Peter Anvin16b0a332007-09-12 20:27:41 -0700587 default:
588 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000589 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000590
H. Peter Anvine2c80182005-01-15 22:15:51 +0000591 for (e = instruction->eops; e; e = e->next) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000592 int32_t align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000593
H. Peter Anvine2c80182005-01-15 22:15:51 +0000594 osize = 0;
595 if (e->type == EOT_DB_NUMBER)
596 osize = 1;
597 else if (e->type == EOT_DB_STRING)
598 osize = e->stringlen;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000599
H. Peter Anvine2c80182005-01-15 22:15:51 +0000600 align = (-osize) % wsize;
601 if (align < 0)
602 align += wsize;
603 isize += osize + align;
604 }
605 return isize * instruction->times;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000606 }
607
H. Peter Anvine2c80182005-01-15 22:15:51 +0000608 if (instruction->opcode == I_INCBIN) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000609 char fname[FILENAME_MAX];
H. Peter Anvine2c80182005-01-15 22:15:51 +0000610 FILE *fp;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000611 int32_t len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000612 char *prefix = "", *combine;
613 char **pPrevPath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000614
H. Peter Anvine2c80182005-01-15 22:15:51 +0000615 len = FILENAME_MAX - 1;
616 if (len > instruction->eops->stringlen)
617 len = instruction->eops->stringlen;
618 strncpy(fname, instruction->eops->stringval, len);
619 fname[len] = '\0';
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000620
H. Peter Anvine2c80182005-01-15 22:15:51 +0000621 while (1) { /* added by alexfru: 'incbin' uses include paths */
622 combine = nasm_malloc(strlen(prefix) + len + 1);
623 strcpy(combine, prefix);
624 strcat(combine, fname);
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000625
H. Peter Anvine2c80182005-01-15 22:15:51 +0000626 if ((fp = fopen(combine, "rb")) != NULL) {
627 nasm_free(combine);
628 break;
629 }
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000630
H. Peter Anvine2c80182005-01-15 22:15:51 +0000631 nasm_free(combine);
632 pPrevPath = pp_get_include_path_ptr(pPrevPath);
633 if (pPrevPath == NULL)
634 break;
635 prefix = *pPrevPath;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000636 }
637
638 if (fp == NULL)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000639 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
640 fname);
641 else if (fseek(fp, 0L, SEEK_END) < 0)
642 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
643 fname);
644 else {
645 len = ftell(fp);
646 fclose(fp);
647 if (instruction->eops->next) {
648 len -= instruction->eops->next->offset;
649 if (instruction->eops->next->next &&
650 len > instruction->eops->next->next->offset) {
651 len = instruction->eops->next->next->offset;
652 }
653 }
654 return instruction->times * len;
655 }
656 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000657 }
658
Keith Kaniosb7a89542007-04-12 02:40:54 +0000659 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++) {
660 int m = matches(temp, instruction, bits);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000661 if (m == 99)
662 m += jmp_match(segment, offset, bits, instruction, temp->code);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000663
H. Peter Anvine2c80182005-01-15 22:15:51 +0000664 if (m == 100) {
665 /* we've matched an instruction. */
Keith Kaniosb7a89542007-04-12 02:40:54 +0000666 int32_t isize;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000667 const char *codes = temp->code;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000668 int j;
669
670 isize = calcsize(segment, offset, bits, instruction, codes);
671 if (isize < 0)
672 return -1;
673 for (j = 0; j < instruction->nprefix; j++) {
674 if ((instruction->prefixes[j] != P_A16 &&
675 instruction->prefixes[j] != P_O16 && bits == 16) ||
676 (instruction->prefixes[j] != P_A32 &&
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000677 instruction->prefixes[j] != P_O32 && bits >= 32)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000678 isize++;
679 }
680 }
681 return isize * instruction->times;
682 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000683 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000684 return -1; /* didn't match any instruction */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000685}
686
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000687/* check that opn[op] is a signed byte of size 16 or 32,
688 and return the signed value*/
H. Peter Anvine2c80182005-01-15 22:15:51 +0000689static int is_sbyte(insn * ins, int op, int size)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000690{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000691 int32_t v;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000692 int ret;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000693
694 ret = !(ins->forw_ref && ins->oprs[op].opflags) && /* dead in the water on forward reference or External */
695 optimizing >= 0 &&
696 !(ins->oprs[op].type & STRICT) &&
697 ins->oprs[op].wrt == NO_SEG && ins->oprs[op].segment == NO_SEG;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000698
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000699 v = ins->oprs[op].offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000700 if (size == 16)
Keith Kaniosb7a89542007-04-12 02:40:54 +0000701 v = (int16_t)v; /* sign extend if 16 bits */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000702
703 return ret && v >= -128L && v <= 127L;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000704}
705
Keith Kaniosb7a89542007-04-12 02:40:54 +0000706static int32_t calcsize(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000707 insn * ins, const char *codes)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000708{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000709 int32_t length = 0;
710 uint8_t c;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000711 int rex_mask = ~0;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000712 ins->rex = 0; /* Ensure REX is reset */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000713
H. Peter Anvine2c80182005-01-15 22:15:51 +0000714 (void)segment; /* Don't warn that this parameter is unused */
715 (void)offset; /* Don't warn that this parameter is unused */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000716
H. Peter Anvine2c80182005-01-15 22:15:51 +0000717 while (*codes)
718 switch (c = *codes++) {
719 case 01:
720 case 02:
721 case 03:
722 codes += c, length += c;
723 break;
724 case 04:
725 case 05:
726 case 06:
727 case 07:
728 length++;
729 break;
730 case 010:
731 case 011:
732 case 012:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000733 ins->rex |=
734 op_rexflags(&ins->oprs[c - 010], REX_B|REX_H|REX_P|REX_W);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000735 codes++, length++;
736 break;
737 case 017:
738 length++;
739 break;
740 case 014:
741 case 015:
742 case 016:
743 length++;
744 break;
745 case 020:
746 case 021:
747 case 022:
748 length++;
749 break;
750 case 024:
751 case 025:
752 case 026:
753 length++;
754 break;
755 case 030:
756 case 031:
757 case 032:
758 length += 2;
759 break;
760 case 034:
761 case 035:
762 case 036:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000763 if (ins->oprs[c - 034].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000764 length += (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
765 else
766 length += (bits == 16) ? 2 : 4;
767 break;
768 case 037:
769 length += 2;
770 break;
771 case 040:
772 case 041:
773 case 042:
774 length += 4;
775 break;
776 case 044:
777 case 045:
778 case 046:
779 length += ((ins->oprs[c - 044].addr_size ?
Keith Kaniosb7a89542007-04-12 02:40:54 +0000780 ins->oprs[c - 044].addr_size : bits) >> 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000781 break;
782 case 050:
783 case 051:
784 case 052:
785 length++;
786 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000787 case 054:
788 case 055:
789 case 056:
790 length += 8; /* MOV reg64/imm */
791 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000792 case 060:
793 case 061:
794 case 062:
795 length += 2;
796 break;
797 case 064:
798 case 065:
799 case 066:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000800 if (ins->oprs[c - 064].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000801 length += (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
802 else
803 length += (bits == 16) ? 2 : 4;
804 break;
805 case 070:
806 case 071:
807 case 072:
808 length += 4;
809 break;
810 case 0130:
811 case 0131:
812 case 0132:
813 length += is_sbyte(ins, c - 0130, 16) ? 1 : 2;
814 break;
815 case 0133:
816 case 0134:
817 case 0135:
818 codes += 2;
819 length++;
820 break;
821 case 0140:
822 case 0141:
823 case 0142:
824 length += is_sbyte(ins, c - 0140, 32) ? 1 : 4;
825 break;
826 case 0143:
827 case 0144:
828 case 0145:
829 codes += 2;
830 length++;
831 break;
832 case 0300:
833 case 0301:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000834 case 0302:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000835 length += chsize(&ins->oprs[c - 0300], bits);
836 break;
837 case 0310:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000838 length += (bits != 16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000839 break;
840 case 0311:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000841 length += (bits != 32);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000842 break;
843 case 0312:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000844 break;
845 case 0313:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000846 break;
847 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000848 length += (bits != 16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000849 break;
850 case 0321:
851 length += (bits == 16);
852 break;
853 case 0322:
854 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000855 case 0323:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000856 rex_mask &= ~REX_W;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000857 break;
858 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000859 ins->rex |= REX_W;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000860 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000861 case 0330:
862 codes++, length++;
863 break;
864 case 0331:
865 case 0332:
866 break;
867 case 0333:
868 length++;
869 break;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000870 case 0334:
871 assert_no_prefix(ins, P_LOCK);
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000872 ins->rex |= REX_L;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000873 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000874 case 0340:
875 case 0341:
876 case 0342:
877 if (ins->oprs[0].segment != NO_SEG)
878 errfunc(ERR_NONFATAL, "attempt to reserve non-constant"
879 " quantity of BSS space");
880 else
881 length += ins->oprs[0].offset << (c - 0340);
882 break;
H. Peter Anvin62cb6062007-09-11 22:44:03 +0000883 case 0364:
884 case 0365:
885 break;
Keith Kanios48af1772007-08-17 07:37:52 +0000886 case 0366:
H. Peter Anvin62cb6062007-09-11 22:44:03 +0000887 case 0367:
888 length++;
889 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000890 case 0370:
891 case 0371:
892 case 0372:
893 break;
894 case 0373:
895 length++;
896 break;
897 default: /* can't do it by 'case' statements */
898 if (c >= 0100 && c <= 0277) { /* it's an EA */
899 ea ea_data;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000900 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000901 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000902 ea_data.rex = 0; /* Ensure ea.REX is initially 0 */
903
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000904 if (c <= 0177) {
905 /* pick rfield from operand b */
906 rflags = regflag(&ins->oprs[c & 7]);
907 rfield = regvals[ins->oprs[c & 7].basereg];
908 } else {
909 rflags = 0;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000910 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000911 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000912
H. Peter Anvine2c80182005-01-15 22:15:51 +0000913 if (!process_ea
Keith Kaniosb7a89542007-04-12 02:40:54 +0000914 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000915 rfield, rflags, ins->forw_ref)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000916 errfunc(ERR_NONFATAL, "invalid effective address");
917 return -1;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000918 } else {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000919 ins->rex |= ea_data.rex;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000920 length += ea_data.size;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000921 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000922 } else
923 errfunc(ERR_PANIC, "internal instruction table corrupt"
924 ": instruction code 0x%02X given", c);
925 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000926
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000927 ins->rex &= rex_mask;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000928 if (ins->rex & REX_REAL) {
929 if (ins->rex & REX_H) {
930 errfunc(ERR_NONFATAL, "cannot use high register in rex instruction");
931 return -1;
932 } else if (bits == 64 ||
933 ((ins->rex & REX_L) &&
934 !(ins->rex & (REX_P|REX_W|REX_X|REX_B)) &&
935 cpu >= IF_X86_64)) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000936 length++;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000937 } else {
938 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
939 return -1;
940 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000941 }
942
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000943 return length;
944}
Keith Kaniosb7a89542007-04-12 02:40:54 +0000945
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000946#define EMIT_REX() \
947 if((ins->rex & REX_REAL) && (bits == 64)) { \
948 ins->rex = (ins->rex & REX_REAL)|REX_P; \
949 out(offset, segment, &ins->rex, OUT_RAWDATA+1, NO_SEG, NO_SEG); \
950 ins->rex = 0; \
951 offset += 1; \
952 }
953
Keith Kaniosb7a89542007-04-12 02:40:54 +0000954static void gencode(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000955 insn * ins, const char *codes, int32_t insn_end)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000956{
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000957 static char condval[] = { /* conditional opcodes */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000958 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
959 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
960 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000961 };
Keith Kaniosb7a89542007-04-12 02:40:54 +0000962 uint8_t c;
963 uint8_t bytes[4];
964 int32_t size;
965 int64_t data;
966
H. Peter Anvineba20a72002-04-30 20:53:55 +0000967 while (*codes)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000968 switch (c = *codes++) {
969 case 01:
970 case 02:
971 case 03:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000972 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +0000973 out(offset, segment, codes, OUT_RAWDATA + c, NO_SEG, NO_SEG);
974 codes += c;
975 offset += c;
976 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000977
H. Peter Anvine2c80182005-01-15 22:15:51 +0000978 case 04:
979 case 06:
980 switch (ins->oprs[0].basereg) {
981 case R_CS:
982 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0);
983 break;
984 case R_DS:
985 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0);
986 break;
987 case R_ES:
988 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0);
989 break;
990 case R_SS:
991 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0);
992 break;
993 default:
994 errfunc(ERR_PANIC,
995 "bizarre 8086 segment register received");
996 }
997 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
998 offset++;
999 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001000
H. Peter Anvine2c80182005-01-15 22:15:51 +00001001 case 05:
1002 case 07:
1003 switch (ins->oprs[0].basereg) {
1004 case R_FS:
1005 bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0);
1006 break;
1007 case R_GS:
1008 bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0);
1009 break;
1010 default:
1011 errfunc(ERR_PANIC,
1012 "bizarre 386 segment register received");
1013 }
1014 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1015 offset++;
1016 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001017
H. Peter Anvine2c80182005-01-15 22:15:51 +00001018 case 010:
1019 case 011:
1020 case 012:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001021 EMIT_REX();
Keith Kaniosb7a89542007-04-12 02:40:54 +00001022 bytes[0] = *codes++ + ((regval(&ins->oprs[c - 010])) & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001023 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1024 offset += 1;
1025 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001026
H. Peter Anvine2c80182005-01-15 22:15:51 +00001027 case 017:
1028 bytes[0] = 0;
1029 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1030 offset += 1;
1031 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001032
H. Peter Anvine2c80182005-01-15 22:15:51 +00001033 case 014:
1034 case 015:
1035 case 016:
1036 if (ins->oprs[c - 014].offset < -128
1037 || ins->oprs[c - 014].offset > 127) {
1038 errfunc(ERR_WARNING, "signed byte value exceeds bounds");
1039 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001040
H. Peter Anvine2c80182005-01-15 22:15:51 +00001041 if (ins->oprs[c - 014].segment != NO_SEG) {
1042 data = ins->oprs[c - 014].offset;
1043 out(offset, segment, &data, OUT_ADDRESS + 1,
1044 ins->oprs[c - 014].segment, ins->oprs[c - 014].wrt);
1045 } else {
1046 bytes[0] = ins->oprs[c - 014].offset;
1047 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1048 NO_SEG);
1049 }
1050 offset += 1;
1051 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001052
H. Peter Anvine2c80182005-01-15 22:15:51 +00001053 case 020:
1054 case 021:
1055 case 022:
1056 if (ins->oprs[c - 020].offset < -256
1057 || ins->oprs[c - 020].offset > 255) {
1058 errfunc(ERR_WARNING, "byte value exceeds bounds");
1059 }
1060 if (ins->oprs[c - 020].segment != NO_SEG) {
1061 data = ins->oprs[c - 020].offset;
1062 out(offset, segment, &data, OUT_ADDRESS + 1,
1063 ins->oprs[c - 020].segment, ins->oprs[c - 020].wrt);
1064 } else {
1065 bytes[0] = ins->oprs[c - 020].offset;
1066 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1067 NO_SEG);
1068 }
1069 offset += 1;
1070 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001071
H. Peter Anvine2c80182005-01-15 22:15:51 +00001072 case 024:
1073 case 025:
1074 case 026:
1075 if (ins->oprs[c - 024].offset < 0
1076 || ins->oprs[c - 024].offset > 255)
1077 errfunc(ERR_WARNING, "unsigned byte value exceeds bounds");
1078 if (ins->oprs[c - 024].segment != NO_SEG) {
1079 data = ins->oprs[c - 024].offset;
1080 out(offset, segment, &data, OUT_ADDRESS + 1,
1081 ins->oprs[c - 024].segment, ins->oprs[c - 024].wrt);
1082 } else {
1083 bytes[0] = ins->oprs[c - 024].offset;
1084 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1085 NO_SEG);
1086 }
1087 offset += 1;
1088 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001089
H. Peter Anvine2c80182005-01-15 22:15:51 +00001090 case 030:
1091 case 031:
1092 case 032:
1093 if (ins->oprs[c - 030].segment == NO_SEG &&
1094 ins->oprs[c - 030].wrt == NO_SEG &&
1095 (ins->oprs[c - 030].offset < -65536L ||
1096 ins->oprs[c - 030].offset > 65535L)) {
1097 errfunc(ERR_WARNING, "word value exceeds bounds");
1098 }
1099 data = ins->oprs[c - 030].offset;
1100 out(offset, segment, &data, OUT_ADDRESS + 2,
1101 ins->oprs[c - 030].segment, ins->oprs[c - 030].wrt);
1102 offset += 2;
1103 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001104
H. Peter Anvine2c80182005-01-15 22:15:51 +00001105 case 034:
1106 case 035:
1107 case 036:
1108 if (ins->oprs[c - 034].type & (BITS16 | BITS32))
1109 size = (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
1110 else
1111 size = (bits == 16) ? 2 : 4;
1112 data = ins->oprs[c - 034].offset;
1113 if (size == 2 && (data < -65536L || data > 65535L))
1114 errfunc(ERR_WARNING, "word value exceeds bounds");
1115 out(offset, segment, &data, OUT_ADDRESS + size,
1116 ins->oprs[c - 034].segment, ins->oprs[c - 034].wrt);
1117 offset += size;
1118 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001119
H. Peter Anvine2c80182005-01-15 22:15:51 +00001120 case 037:
1121 if (ins->oprs[0].segment == NO_SEG)
1122 errfunc(ERR_NONFATAL, "value referenced by FAR is not"
1123 " relocatable");
1124 data = 0L;
1125 out(offset, segment, &data, OUT_ADDRESS + 2,
1126 outfmt->segbase(1 + ins->oprs[0].segment),
1127 ins->oprs[0].wrt);
1128 offset += 2;
1129 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001130
H. Peter Anvine2c80182005-01-15 22:15:51 +00001131 case 040:
1132 case 041:
1133 case 042:
1134 data = ins->oprs[c - 040].offset;
1135 out(offset, segment, &data, OUT_ADDRESS + 4,
1136 ins->oprs[c - 040].segment, ins->oprs[c - 040].wrt);
1137 offset += 4;
1138 break;
H. Peter Anvin3ba46772002-05-27 23:19:35 +00001139
H. Peter Anvine2c80182005-01-15 22:15:51 +00001140 case 044:
1141 case 045:
1142 case 046:
1143 data = ins->oprs[c - 044].offset;
1144 size = ((ins->oprs[c - 044].addr_size ?
Keith Kaniosb7a89542007-04-12 02:40:54 +00001145 ins->oprs[c - 044].addr_size : bits) >> 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001146 if (size == 2 && (data < -65536L || data > 65535L))
1147 errfunc(ERR_WARNING, "word value exceeds bounds");
1148 out(offset, segment, &data, OUT_ADDRESS + size,
1149 ins->oprs[c - 044].segment, ins->oprs[c - 044].wrt);
1150 offset += size;
1151 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001152
H. Peter Anvine2c80182005-01-15 22:15:51 +00001153 case 050:
1154 case 051:
1155 case 052:
1156 if (ins->oprs[c - 050].segment != segment)
1157 errfunc(ERR_NONFATAL,
1158 "short relative jump outside segment");
1159 data = ins->oprs[c - 050].offset - insn_end;
1160 if (data > 127 || data < -128)
1161 errfunc(ERR_NONFATAL, "short jump is out of range");
1162 bytes[0] = data;
1163 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1164 offset += 1;
1165 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001166
1167 case 054:
1168 case 055:
1169 case 056:
1170 data = (int64_t)ins->oprs[c - 054].offset;
1171 out(offset, segment, &data, OUT_ADDRESS + 8,
1172 ins->oprs[c - 054].segment, ins->oprs[c - 054].wrt);
1173 offset += 8;
1174 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001175
H. Peter Anvine2c80182005-01-15 22:15:51 +00001176 case 060:
1177 case 061:
1178 case 062:
1179 if (ins->oprs[c - 060].segment != segment) {
1180 data = ins->oprs[c - 060].offset;
1181 out(offset, segment, &data,
1182 OUT_REL2ADR + insn_end - offset,
1183 ins->oprs[c - 060].segment, ins->oprs[c - 060].wrt);
1184 } else {
1185 data = ins->oprs[c - 060].offset - insn_end;
1186 out(offset, segment, &data,
1187 OUT_ADDRESS + 2, NO_SEG, NO_SEG);
1188 }
1189 offset += 2;
1190 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001191
H. Peter Anvine2c80182005-01-15 22:15:51 +00001192 case 064:
1193 case 065:
1194 case 066:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001195 if (ins->oprs[c - 064].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001196 size = (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
1197 else
1198 size = (bits == 16) ? 2 : 4;
1199 if (ins->oprs[c - 064].segment != segment) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001200 int32_t reltype = (size == 2 ? OUT_REL2ADR : OUT_REL4ADR);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001201 data = ins->oprs[c - 064].offset;
1202 out(offset, segment, &data, reltype + insn_end - offset,
1203 ins->oprs[c - 064].segment, ins->oprs[c - 064].wrt);
1204 } else {
1205 data = ins->oprs[c - 064].offset - insn_end;
1206 out(offset, segment, &data,
1207 OUT_ADDRESS + size, NO_SEG, NO_SEG);
1208 }
1209 offset += size;
1210 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001211
H. Peter Anvine2c80182005-01-15 22:15:51 +00001212 case 070:
1213 case 071:
1214 case 072:
1215 if (ins->oprs[c - 070].segment != segment) {
1216 data = ins->oprs[c - 070].offset;
1217 out(offset, segment, &data,
1218 OUT_REL4ADR + insn_end - offset,
1219 ins->oprs[c - 070].segment, ins->oprs[c - 070].wrt);
1220 } else {
1221 data = ins->oprs[c - 070].offset - insn_end;
1222 out(offset, segment, &data,
1223 OUT_ADDRESS + 4, NO_SEG, NO_SEG);
1224 }
1225 offset += 4;
1226 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001227
H. Peter Anvine2c80182005-01-15 22:15:51 +00001228 case 0130:
1229 case 0131:
1230 case 0132:
1231 data = ins->oprs[c - 0130].offset;
1232 if (is_sbyte(ins, c - 0130, 16)) {
1233 bytes[0] = data;
1234 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1235 NO_SEG);
1236 offset++;
1237 } else {
1238 if (ins->oprs[c - 0130].segment == NO_SEG &&
1239 ins->oprs[c - 0130].wrt == NO_SEG &&
1240 (data < -65536L || data > 65535L)) {
1241 errfunc(ERR_WARNING, "word value exceeds bounds");
1242 }
1243 out(offset, segment, &data, OUT_ADDRESS + 2,
1244 ins->oprs[c - 0130].segment, ins->oprs[c - 0130].wrt);
1245 offset += 2;
1246 }
1247 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001248
H. Peter Anvine2c80182005-01-15 22:15:51 +00001249 case 0133:
1250 case 0134:
1251 case 0135:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001252 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001253 codes++;
1254 bytes[0] = *codes++;
1255 if (is_sbyte(ins, c - 0133, 16))
1256 bytes[0] |= 2; /* s-bit */
1257 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1258 offset++;
1259 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001260
H. Peter Anvine2c80182005-01-15 22:15:51 +00001261 case 0140:
1262 case 0141:
1263 case 0142:
1264 data = ins->oprs[c - 0140].offset;
1265 if (is_sbyte(ins, c - 0140, 32)) {
1266 bytes[0] = data;
1267 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1268 NO_SEG);
1269 offset++;
1270 } else {
1271 out(offset, segment, &data, OUT_ADDRESS + 4,
1272 ins->oprs[c - 0140].segment, ins->oprs[c - 0140].wrt);
1273 offset += 4;
1274 }
1275 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001276
H. Peter Anvine2c80182005-01-15 22:15:51 +00001277 case 0143:
1278 case 0144:
1279 case 0145:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001280 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001281 codes++;
1282 bytes[0] = *codes++;
1283 if (is_sbyte(ins, c - 0143, 32))
1284 bytes[0] |= 2; /* s-bit */
1285 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1286 offset++;
1287 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001288
H. Peter Anvine2c80182005-01-15 22:15:51 +00001289 case 0300:
1290 case 0301:
1291 case 0302:
1292 if (chsize(&ins->oprs[c - 0300], bits)) {
1293 *bytes = 0x67;
1294 out(offset, segment, bytes,
1295 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1296 offset += 1;
1297 } else
1298 offset += 0;
1299 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001300
H. Peter Anvine2c80182005-01-15 22:15:51 +00001301 case 0310:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001302 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001303 *bytes = 0x67;
1304 out(offset, segment, bytes,
1305 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1306 offset += 1;
1307 } else
1308 offset += 0;
1309 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001310
H. Peter Anvine2c80182005-01-15 22:15:51 +00001311 case 0311:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001312 if (bits != 32) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001313 *bytes = 0x67;
1314 out(offset, segment, bytes,
1315 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1316 offset += 1;
1317 } else
1318 offset += 0;
1319 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001320
H. Peter Anvine2c80182005-01-15 22:15:51 +00001321 case 0312:
1322 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001323
Keith Kaniosb7a89542007-04-12 02:40:54 +00001324 case 0313:
1325 ins->rex = 0;
1326 break;
1327
H. Peter Anvine2c80182005-01-15 22:15:51 +00001328 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001329 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001330 *bytes = 0x66;
1331 out(offset, segment, bytes,
1332 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1333 offset += 1;
1334 } else
1335 offset += 0;
1336 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001337
H. Peter Anvine2c80182005-01-15 22:15:51 +00001338 case 0321:
1339 if (bits == 16) {
1340 *bytes = 0x66;
1341 out(offset, segment, bytes,
1342 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1343 offset += 1;
1344 } else
1345 offset += 0;
1346 break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001347
H. Peter Anvine2c80182005-01-15 22:15:51 +00001348 case 0322:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001349 case 0323:
1350 break;
1351
1352 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001353 ins->rex |= REX_W;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001354 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001355
H. Peter Anvine2c80182005-01-15 22:15:51 +00001356 case 0330:
1357 *bytes = *codes++ ^ condval[ins->condition];
1358 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1359 offset += 1;
1360 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001361
H. Peter Anvine2c80182005-01-15 22:15:51 +00001362 case 0331:
1363 case 0332:
1364 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001365
H. Peter Anvine2c80182005-01-15 22:15:51 +00001366 case 0333:
1367 *bytes = 0xF3;
1368 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1369 offset += 1;
1370 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001371
Keith Kanios48af1772007-08-17 07:37:52 +00001372 case 0334:
1373 if (ins->rex & REX_R) {
1374 *bytes = 0xF0;
1375 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1376 offset += 1;
1377 }
1378 ins->rex &= ~(REX_L|REX_R);
1379 break;
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001380
H. Peter Anvine2c80182005-01-15 22:15:51 +00001381 case 0340:
1382 case 0341:
1383 case 0342:
1384 if (ins->oprs[0].segment != NO_SEG)
1385 errfunc(ERR_PANIC, "non-constant BSS size in pass two");
1386 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001387 int32_t size = ins->oprs[0].offset << (c - 0340);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001388 if (size > 0)
1389 out(offset, segment, NULL,
1390 OUT_RESERVE + size, NO_SEG, NO_SEG);
1391 offset += size;
1392 }
1393 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001394
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001395 case 0364:
1396 case 0365:
1397 break;
1398
Keith Kanios48af1772007-08-17 07:37:52 +00001399 case 0366:
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001400 case 0367:
1401 *bytes = c - 0366 + 0x66;
Keith Kanios48af1772007-08-17 07:37:52 +00001402 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1403 offset += 1;
1404 break;
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001405
H. Peter Anvine2c80182005-01-15 22:15:51 +00001406 case 0370:
1407 case 0371:
1408 case 0372:
1409 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001410
H. Peter Anvine2c80182005-01-15 22:15:51 +00001411 case 0373:
1412 *bytes = bits == 16 ? 3 : 5;
1413 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1414 offset += 1;
1415 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001416
H. Peter Anvine2c80182005-01-15 22:15:51 +00001417 default: /* can't do it by 'case' statements */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001418 if (c >= 0100 && c <= 0277) { /* it's an EA */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001419 ea ea_data;
1420 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001421 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001422 uint8_t *p;
1423 int32_t s;
1424
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001425 if (c <= 0177) {
1426 /* pick rfield from operand b */
1427 rflags = regflag(&ins->oprs[c & 7]);
1428 rfield = regvals[ins->oprs[c & 7].basereg];
1429 } else {
1430 /* rfield is constant */
1431 rflags = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001432 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001433 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001434
1435 if (!process_ea
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001436 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
1437 rfield, rflags, ins->forw_ref)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001438 errfunc(ERR_NONFATAL, "invalid effective address");
1439 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001440
H. Peter Anvine2c80182005-01-15 22:15:51 +00001441 p = bytes;
1442 *p++ = ea_data.modrm;
1443 if (ea_data.sib_present)
1444 *p++ = ea_data.sib;
1445
1446 s = p - bytes;
1447 out(offset, segment, bytes, OUT_RAWDATA + s,
1448 NO_SEG, NO_SEG);
1449
1450 switch (ea_data.bytes) {
1451 case 0:
1452 break;
1453 case 1:
1454 if (ins->oprs[(c >> 3) & 7].segment != NO_SEG) {
1455 data = ins->oprs[(c >> 3) & 7].offset;
1456 out(offset, segment, &data, OUT_ADDRESS + 1,
1457 ins->oprs[(c >> 3) & 7].segment,
1458 ins->oprs[(c >> 3) & 7].wrt);
1459 } else {
1460 *bytes = ins->oprs[(c >> 3) & 7].offset;
1461 out(offset, segment, bytes, OUT_RAWDATA + 1,
1462 NO_SEG, NO_SEG);
1463 }
1464 s++;
1465 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001466 case 8:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001467 case 2:
1468 case 4:
1469 data = ins->oprs[(c >> 3) & 7].offset;
Keith Kaniose83b3182007-04-16 14:31:54 +00001470 if (ea_data.rip && (ins->oprs[(c >> 3) & 7].segment == 0xFFFFFFFF))
1471 ea_data.rip = 0; /* Make distinction between Symbols and Immediates */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001472 out(offset, segment, &data, /* RIP = Relative, not Absolute */
1473 (ea_data.rip ? OUT_REL4ADR : OUT_ADDRESS) + ea_data.bytes,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001474 ins->oprs[(c >> 3) & 7].segment,
1475 ins->oprs[(c >> 3) & 7].wrt);
1476 s += ea_data.bytes;
1477 break;
1478 }
1479 offset += s;
1480 } else
1481 errfunc(ERR_PANIC, "internal instruction table corrupt"
1482 ": instruction code 0x%02X given", c);
1483 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001484}
1485
H. Peter Anvin0ec60e62007-07-07 01:59:52 +00001486static int32_t regflag(const operand * o)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001487{
1488 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1489 errfunc(ERR_PANIC, "invalid operand passed to regflag()");
1490 }
1491 return reg_flags[o->basereg];
1492}
1493
H. Peter Anvin5b0e3ec2007-07-07 02:01:08 +00001494static int32_t regval(const operand * o)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001495{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001496 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1497 errfunc(ERR_PANIC, "invalid operand passed to regval()");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001498 }
H. Peter Anvin232badb2002-06-06 02:41:20 +00001499 return regvals[o->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001500}
1501
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001502static int op_rexflags(const operand * o, int mask)
1503{
1504 int32_t flags;
1505 int val;
1506
1507 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1508 errfunc(ERR_PANIC, "invalid operand passed to op_rexflags()");
1509 }
1510
1511 flags = reg_flags[o->basereg];
1512 val = regvals[o->basereg];
1513
1514 return rexflags(val, flags, mask);
1515}
1516
1517static int rexflags(int val, int32_t flags, int mask)
1518{
1519 int rex = 0;
1520
1521 if (val >= 8)
1522 rex |= REX_B|REX_X|REX_R;
1523 if (flags & BITS64)
1524 rex |= REX_W;
1525 if (!(REG_HIGH & ~flags)) /* AH, CH, DH, BH */
1526 rex |= REX_H;
1527 else if (!(REG8 & ~flags) && val >= 4) /* SPL, BPL, SIL, DIL */
1528 rex |= REX_P;
1529
1530 return rex & mask;
1531}
1532
H. Peter Anvin3360d792007-09-11 04:16:57 +00001533static int matches(const struct itemplate *itemp, insn * instruction, int bits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001534{
H. Peter Anvin34539fb2007-05-30 04:27:58 +00001535 int i, size[3], asize, oprs, ret;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001536
1537 ret = 100;
1538
1539 /*
1540 * Check the opcode
1541 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001542 if (itemp->opcode != instruction->opcode)
1543 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001544
1545 /*
1546 * Count the operands
1547 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001548 if (itemp->operands != instruction->operands)
1549 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001550
1551 /*
1552 * Check that no spurious colons or TOs are present
1553 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001554 for (i = 0; i < itemp->operands; i++)
1555 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON | TO))
1556 return 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001557
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001558 /*
1559 * Check that the operand flags all match up
1560 */
H. Peter Anvin16b0a332007-09-12 20:27:41 -07001561 for (i = 0; i < itemp->operands; i++) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001562 if (itemp->opd[i] & ~instruction->oprs[i].type ||
1563 ((itemp->opd[i] & SIZE_MASK) &&
1564 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK))) {
H. Peter Anvin5a640e12007-05-29 23:57:12 +00001565 if ((itemp->opd[i] & ~instruction->oprs[i].type & ~SIZE_MASK) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001566 (instruction->oprs[i].type & SIZE_MASK))
1567 return 0;
1568 else
H. Peter Anvine2c80182005-01-15 22:15:51 +00001569 return 1;
1570 }
H. Peter Anvin16b0a332007-09-12 20:27:41 -07001571 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001572
1573 /*
1574 * Check operand sizes
1575 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001576 if (itemp->flags & IF_ARMASK) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001577 size[0] = size[1] = size[2] = 0;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001578
H. Peter Anvine2c80182005-01-15 22:15:51 +00001579 switch (itemp->flags & IF_ARMASK) {
1580 case IF_AR0:
1581 i = 0;
1582 break;
1583 case IF_AR1:
1584 i = 1;
1585 break;
1586 case IF_AR2:
1587 i = 2;
1588 break;
1589 default:
1590 break; /* Shouldn't happen */
1591 }
1592 if (itemp->flags & IF_SB) {
1593 size[i] = BITS8;
1594 } else if (itemp->flags & IF_SW) {
1595 size[i] = BITS16;
1596 } else if (itemp->flags & IF_SD) {
1597 size[i] = BITS32;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001598 } else if (itemp->flags & IF_SQ) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001599 size[i] = BITS64;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001600 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001601 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001602 asize = 0;
1603 if (itemp->flags & IF_SB) {
1604 asize = BITS8;
1605 oprs = itemp->operands;
1606 } else if (itemp->flags & IF_SW) {
1607 asize = BITS16;
1608 oprs = itemp->operands;
1609 } else if (itemp->flags & IF_SD) {
1610 asize = BITS32;
1611 oprs = itemp->operands;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001612 } else if (itemp->flags & IF_SQ) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001613 asize = BITS64;
1614 oprs = itemp->operands;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001615 }
1616 size[0] = size[1] = size[2] = asize;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001617 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001618
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001619 if (itemp->flags & (IF_SM | IF_SM2)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001620 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
1621 asize = 0;
1622 for (i = 0; i < oprs; i++) {
1623 if ((asize = itemp->opd[i] & SIZE_MASK) != 0) {
1624 int j;
1625 for (j = 0; j < oprs; j++)
1626 size[j] = asize;
1627 break;
1628 }
1629 }
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001630 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001631 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001632 }
1633
Keith Kaniosb7a89542007-04-12 02:40:54 +00001634 for (i = 0; i < itemp->operands; i++) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001635 if (!(itemp->opd[i] & SIZE_MASK) &&
1636 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001637 return 2;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001638 }
1639
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001640 /*
1641 * Check template is okay at the set cpu level
1642 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001643 if (((itemp->flags & IF_PLEVEL) > cpu))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001644 return 3;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001645
1646 /*
1647 * Check if instruction is available in long mode
1648 */
1649 if ((itemp->flags & IF_NOLONG) && (bits == 64))
1650 return 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001651
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001652 /*
1653 * Check if special handling needed for Jumps
1654 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001655 if ((uint8_t)(itemp->code[0]) >= 0370)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001656 return 99;
1657
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001658 return ret;
1659}
1660
H. Peter Anvine2c80182005-01-15 22:15:51 +00001661static ea *process_ea(operand * input, ea * output, int addrbits,
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001662 int rfield, int32_t rflags, int forw_ref)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001663{
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001664 output->rip = FALSE;
1665
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001666 /* REX flags for the rfield operand */
1667 output->rex |= rexflags(rfield, rflags, REX_R|REX_P|REX_W|REX_H);
1668
Keith Kaniosb7a89542007-04-12 02:40:54 +00001669 if (!(REGISTER & ~input->type)) { /* register direct */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001670 int i;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001671 int32_t f;
1672
1673 if (input->basereg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001674 || input->basereg >= REG_ENUM_LIMIT)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001675 return NULL;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001676 f = regflag(input);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001677 i = regvals[input->basereg];
Keith Kaniosb7a89542007-04-12 02:40:54 +00001678
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001679 if (REG_EA & ~f)
1680 return NULL; /* Invalid EA register */
1681
1682 output->rex |= op_rexflags(input, REX_B|REX_P|REX_W|REX_H);
1683
Keith Kaniosb7a89542007-04-12 02:40:54 +00001684 output->sib_present = FALSE; /* no SIB necessary */
1685 output->bytes = 0; /* no offset necessary either */
1686 output->modrm = 0xC0 | ((rfield & 7) << 3) | (i & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001687 } else { /* it's a memory reference */
1688 if (input->basereg == -1
1689 && (input->indexreg == -1 || input->scale == 0)) {
1690 /* it's a pure offset */
1691 if (input->addr_size)
1692 addrbits = input->addr_size;
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001693
1694 if (globalbits == 64 && (~input->type & IP_REL)) {
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00001695 int scale, index, base;
1696 output->sib_present = TRUE;
1697 scale = 0;
1698 index = 4;
1699 base = 5;
1700 output->sib = (scale << 6) | (index << 3) | base;
1701 output->bytes = 4;
1702 output->modrm = 4 | ((rfield & 7) << 3);
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001703 output->rip = FALSE;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00001704 } else {
1705 output->sib_present = FALSE;
1706 output->bytes = (addrbits != 16 ? 4 : 2);
1707 output->modrm = (addrbits != 16 ? 5 : 6) | ((rfield & 7) << 3);
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001708 output->rip = globalbits == 64;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00001709 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001710 } else { /* it's an indirection */
1711 int i = input->indexreg, b = input->basereg, s = input->scale;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001712 int32_t o = input->offset, seg = input->segment;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001713 int hb = input->hintbase, ht = input->hinttype;
1714 int t;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001715 int it, bt;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001716 int32_t ix, bx; /* register flags */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001717
H. Peter Anvine2c80182005-01-15 22:15:51 +00001718 if (s == 0)
1719 i = -1; /* make this easy, at least */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001720
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001721 if (i >= EXPR_REG_START && i < REG_ENUM_LIMIT) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001722 it = regvals[i];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001723 ix = reg_flags[i];
1724 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001725 it = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001726 ix = 0;
1727 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001728
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001729 if (b != -1 && b >= EXPR_REG_START && b < REG_ENUM_LIMIT) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001730 bt = regvals[b];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001731 bx = reg_flags[b];
1732 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001733 bt = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001734 bx = 0;
1735 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001736
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001737 /* check for a 32/64-bit memory reference... */
1738 if ((ix|bx) & (BITS32|BITS64)) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001739 /* it must be a 32/64-bit memory reference. Firstly we have
1740 * to check that all registers involved are type E/Rxx. */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001741 int32_t sok = BITS32|BITS64;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001742
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001743 if (it != -1) {
1744 if (!(REG64 & ~ix) || !(REG32 & ~ix))
1745 sok &= ix;
1746 else
1747 return NULL;
1748 }
1749
1750 if (bt != -1) {
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001751 if (REG_GPR & ~bx)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001752 return NULL; /* Invalid register */
H. Peter Anvina57e8d42007-05-30 03:44:02 +00001753 if (~sok & bx & SIZE_MASK)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001754 return NULL; /* Invalid size */
1755 sok &= ~bx;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001756 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001757
H. Peter Anvine2c80182005-01-15 22:15:51 +00001758 /* While we're here, ensure the user didn't specify WORD. */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001759 if (input->addr_size == 16 ||
1760 (input->addr_size == 32 && !(sok & BITS32)) ||
1761 (input->addr_size == 64 && !(sok & BITS64)))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001762 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001763
Keith Kaniosb7a89542007-04-12 02:40:54 +00001764 /* now reorganize base/index */
1765 if (s == 1 && bt != it && bt != -1 && it != -1 &&
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001766 ((hb == b && ht == EAH_NOTBASE)
1767 || (hb == i && ht == EAH_MAKEBASE))) {
1768 /* swap if hints say so */
1769 t = bt, bt = it, it = t;
1770 t = bx, bx = ix, ix = t;
1771 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001772 if (bt == it) /* convert EAX+2*EAX to 3*EAX */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001773 bt = -1, bx = 0, s++;
1774 if (bt == -1 && s == 1 && !(hb == it && ht == EAH_NOTBASE)) {
1775 /* make single reg base, unless hint */
1776 bt = it, bx = ix, it = -1, ix = 0;
1777 }
H. Peter Anvinf5843c62007-09-10 18:59:26 +00001778 if (((s == 2 && it != REG_NUM_ESP
H. Peter Anvine2c80182005-01-15 22:15:51 +00001779 && !(input->eaflags & EAF_TIMESTWO)) || s == 3
Keith Kaniosb7a89542007-04-12 02:40:54 +00001780 || s == 5 || s == 9) && bt == -1)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001781 bt = it, bx = ix, s--; /* convert 3*EAX to EAX+2*EAX */
Keith Kanios48af1772007-08-17 07:37:52 +00001782 if (it == -1 && (bt & 7) != REG_NUM_ESP
H. Peter Anvine2c80182005-01-15 22:15:51 +00001783 && (input->eaflags & EAF_TIMESTWO))
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001784 it = bt, ix = bx, bt = -1, bx = 0, s = 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001785 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
Keith Kanios48af1772007-08-17 07:37:52 +00001786 if (s == 1 && it == REG_NUM_ESP) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001787 /* swap ESP into base if scale is 1 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001788 t = it, it = bt, bt = t;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001789 t = ix, ix = bx, bx = t;
1790 }
Keith Kanios48af1772007-08-17 07:37:52 +00001791 if (it == REG_NUM_ESP
Keith Kaniosb7a89542007-04-12 02:40:54 +00001792 || (s != 1 && s != 2 && s != 4 && s != 8 && it != -1))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001793 return NULL; /* wrong, for various reasons */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001794
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001795 output->rex |= rexflags(it, ix, REX_X);
1796 output->rex |= rexflags(bt, bx, REX_B);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001797
Keith Kanios48af1772007-08-17 07:37:52 +00001798 if (it == -1 && (bt & 7) != REG_NUM_ESP) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001799 /* no SIB needed */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001800 int mod, rm;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001801
1802 if (bt == -1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001803 rm = 5;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001804 mod = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001805 } else {
1806 rm = (bt & 7);
Keith Kanios48af1772007-08-17 07:37:52 +00001807 if (rm != REG_NUM_EBP && o == 0 &&
Keith Kaniosb7a89542007-04-12 02:40:54 +00001808 seg == NO_SEG && !forw_ref &&
1809 !(input->eaflags &
1810 (EAF_BYTEOFFS | EAF_WORDOFFS)))
1811 mod = 0;
1812 else if (input->eaflags & EAF_BYTEOFFS ||
1813 (o >= -128 && o <= 127 && seg == NO_SEG
1814 && !forw_ref
1815 && !(input->eaflags & EAF_WORDOFFS)))
1816 mod = 1;
1817 else
1818 mod = 2;
1819 }
H. Peter Anvinea838272002-04-30 20:51:53 +00001820
H. Peter Anvine2c80182005-01-15 22:15:51 +00001821 output->sib_present = FALSE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001822 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
1823 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001824 } else {
1825 /* we need a SIB */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001826 int mod, scale, index, base;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001827
1828 if (it == -1)
1829 index = 4, s = 1;
1830 else
1831 index = (it & 7);
1832
H. Peter Anvine2c80182005-01-15 22:15:51 +00001833 switch (s) {
1834 case 1:
1835 scale = 0;
1836 break;
1837 case 2:
1838 scale = 1;
1839 break;
1840 case 4:
1841 scale = 2;
1842 break;
1843 case 8:
1844 scale = 3;
1845 break;
1846 default: /* then what the smeg is it? */
1847 return NULL; /* panic */
1848 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001849
1850 if (bt == -1) {
1851 base = 5;
1852 mod = 0;
1853 } else {
1854 base = (bt & 7);
Keith Kanios48af1772007-08-17 07:37:52 +00001855 if (base != REG_NUM_EBP && o == 0 &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00001856 seg == NO_SEG && !forw_ref &&
1857 !(input->eaflags &
Keith Kaniosb7a89542007-04-12 02:40:54 +00001858 (EAF_BYTEOFFS | EAF_WORDOFFS)))
1859 mod = 0;
1860 else if (input->eaflags & EAF_BYTEOFFS ||
1861 (o >= -128 && o <= 127 && seg == NO_SEG
1862 && !forw_ref
1863 && !(input->eaflags & EAF_WORDOFFS)))
1864 mod = 1;
1865 else
1866 mod = 2;
1867 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001868
H. Peter Anvine2c80182005-01-15 22:15:51 +00001869 output->sib_present = TRUE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001870 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
1871 output->modrm = (mod << 6) | ((rfield & 7) << 3) | 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001872 output->sib = (scale << 6) | (index << 3) | base;
1873 }
1874 } else { /* it's 16-bit */
1875 int mod, rm;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001876
1877 /* check for 64-bit long mode */
1878 if (addrbits == 64)
1879 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001880
H. Peter Anvine2c80182005-01-15 22:15:51 +00001881 /* check all registers are BX, BP, SI or DI */
1882 if ((b != -1 && b != R_BP && b != R_BX && b != R_SI
1883 && b != R_DI) || (i != -1 && i != R_BP && i != R_BX
1884 && i != R_SI && i != R_DI))
1885 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001886
Keith Kaniosb7a89542007-04-12 02:40:54 +00001887 /* ensure the user didn't specify DWORD/QWORD */
1888 if (input->addr_size == 32 || input->addr_size == 64)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001889 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001890
H. Peter Anvine2c80182005-01-15 22:15:51 +00001891 if (s != 1 && i != -1)
1892 return NULL; /* no can do, in 16-bit EA */
1893 if (b == -1 && i != -1) {
1894 int tmp = b;
1895 b = i;
1896 i = tmp;
1897 } /* swap */
1898 if ((b == R_SI || b == R_DI) && i != -1) {
1899 int tmp = b;
1900 b = i;
1901 i = tmp;
1902 }
1903 /* have BX/BP as base, SI/DI index */
1904 if (b == i)
1905 return NULL; /* shouldn't ever happen, in theory */
1906 if (i != -1 && b != -1 &&
1907 (i == R_BP || i == R_BX || b == R_SI || b == R_DI))
1908 return NULL; /* invalid combinations */
1909 if (b == -1) /* pure offset: handled above */
1910 return NULL; /* so if it gets to here, panic! */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001911
H. Peter Anvine2c80182005-01-15 22:15:51 +00001912 rm = -1;
1913 if (i != -1)
1914 switch (i * 256 + b) {
1915 case R_SI * 256 + R_BX:
1916 rm = 0;
1917 break;
1918 case R_DI * 256 + R_BX:
1919 rm = 1;
1920 break;
1921 case R_SI * 256 + R_BP:
1922 rm = 2;
1923 break;
1924 case R_DI * 256 + R_BP:
1925 rm = 3;
1926 break;
1927 } else
1928 switch (b) {
1929 case R_SI:
1930 rm = 4;
1931 break;
1932 case R_DI:
1933 rm = 5;
1934 break;
1935 case R_BP:
1936 rm = 6;
1937 break;
1938 case R_BX:
1939 rm = 7;
1940 break;
1941 }
1942 if (rm == -1) /* can't happen, in theory */
1943 return NULL; /* so panic if it does */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001944
H. Peter Anvine2c80182005-01-15 22:15:51 +00001945 if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
1946 !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
1947 mod = 0;
1948 else if (input->eaflags & EAF_BYTEOFFS ||
1949 (o >= -128 && o <= 127 && seg == NO_SEG
1950 && !forw_ref
1951 && !(input->eaflags & EAF_WORDOFFS)))
1952 mod = 1;
1953 else
1954 mod = 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001955
H. Peter Anvine2c80182005-01-15 22:15:51 +00001956 output->sib_present = FALSE; /* no SIB - it's 16-bit */
1957 output->bytes = mod; /* bytes of offset needed */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001958 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001959 }
1960 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001961 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001962
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001963 output->size = 1 + output->sib_present + output->bytes;
1964 return output;
1965}
1966
H. Peter Anvine2c80182005-01-15 22:15:51 +00001967static int chsize(operand * input, int addrbits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001968{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001969 if (!(MEMORY & ~input->type)) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001970 int32_t i, b;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001971
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001972 if (input->indexreg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001973 || input->indexreg >= REG_ENUM_LIMIT)
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00001974 i = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001975 else
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001976 i = reg_flags[input->indexreg];
Keith Kaniosb7a89542007-04-12 02:40:54 +00001977
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001978 if (input->basereg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001979 || input->basereg >= REG_ENUM_LIMIT)
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00001980 b = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001981 else
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001982 b = reg_flags[input->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001983
H. Peter Anvine2c80182005-01-15 22:15:51 +00001984 if (input->scale == 0)
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00001985 i = 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001986
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00001987 if (!i && !b) /* pure offset */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001988 return (input->addr_size != 0 && input->addr_size != addrbits);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001989
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001990 if (!(REG32 & ~i) || !(REG32 & ~b))
Keith Kaniosb7a89542007-04-12 02:40:54 +00001991 return (addrbits != 32);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001992 else
1993 return (addrbits == 32);
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001994 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001995 return 0;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001996 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001997}