blob: 575103abfefcba7f95a62c1623b61a3db33e65cc [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.
Keith Kanios48af1772007-08-17 07:37:52 +000073 * \366 - operand-size override prefix (0x66); to ensure proper
74 REX prefix placement.
H. Peter Anvin788e6c12002-04-30 21:02:01 +000075 * \370,\371,\372 - match only if operand 0 meets byte jump criteria.
76 * 370 is used for Jcc, 371 is used for JMP.
H. Peter Anvinaf535c12002-04-30 20:59:21 +000077 * \373 - assemble 0x03 if bits==16, 0x05 if bits==32;
78 * used for conditional jump over longer jump
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000079 */
80
81#include <stdio.h>
82#include <string.h>
Keith Kaniosb7a89542007-04-12 02:40:54 +000083#include <inttypes.h>
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000084
85#include "nasm.h"
H. Peter Anvin6768eb72002-04-30 20:52:26 +000086#include "nasmlib.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000087#include "assemble.h"
88#include "insns.h"
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +000089#include "preproc.h"
H. Peter Anvin3df97a72007-05-30 03:25:21 +000090#include "regflags.c"
Keith Kaniosb7a89542007-04-12 02:40:54 +000091#include "regvals.c"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000092
93extern struct itemplate *nasm_instructions[];
94
95typedef 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);
Keith Kaniosb7a89542007-04-12 02:40:54 +0000109static int matches(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 Anvinea6e34d2002-04-30 20:51:32 +0000218 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 Anvineba20a72002-04-30 20:53:55 +0000249 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000250
H. Peter Anvineba20a72002-04-30 20:53:55 +0000251 if (wsize) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000252 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000253 int32_t t = instruction->times;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000254 if (t < 0)
255 errfunc(ERR_PANIC,
256 "instruction->times < 0 (%ld) in assemble()", t);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000257
H. Peter Anvine2c80182005-01-15 22:15:51 +0000258 while (t--) { /* repeat TIMES times */
259 for (e = instruction->eops; e; e = e->next) {
260 if (e->type == EOT_DB_NUMBER) {
261 if (wsize == 1) {
262 if (e->segment != NO_SEG)
263 errfunc(ERR_NONFATAL,
264 "one-byte relocation attempted");
265 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000266 uint8_t out_byte = e->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000267 out(offset, segment, &out_byte,
268 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
269 }
Keith Kanios61ff53c2007-04-14 18:54:52 +0000270 } else if (wsize > 8) {
271 errfunc(ERR_NONFATAL, "integer supplied to a DT"
272 " instruction");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000273 } else
274 out(offset, segment, &e->offset,
275 OUT_ADDRESS + wsize, e->segment, e->wrt);
276 offset += wsize;
277 } else if (e->type == EOT_DB_STRING) {
278 int align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000279
H. Peter Anvine2c80182005-01-15 22:15:51 +0000280 out(offset, segment, e->stringval,
281 OUT_RAWDATA + e->stringlen, NO_SEG, NO_SEG);
282 align = e->stringlen % wsize;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000283
H. Peter Anvine2c80182005-01-15 22:15:51 +0000284 if (align) {
285 align = wsize - align;
286 out(offset, segment, "\0\0\0\0\0\0\0\0",
287 OUT_RAWDATA + align, NO_SEG, NO_SEG);
288 }
289 offset += e->stringlen + align;
290 }
291 }
292 if (t > 0 && t == instruction->times - 1) {
293 /*
294 * Dummy call to list->output to give the offset to the
295 * listing module.
296 */
297 list->output(offset, NULL, OUT_RAWDATA);
298 list->uplevel(LIST_TIMES);
299 }
300 }
301 if (instruction->times > 1)
302 list->downlevel(LIST_TIMES);
303 return offset - start;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000304 }
305
H. Peter Anvine2c80182005-01-15 22:15:51 +0000306 if (instruction->opcode == I_INCBIN) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000307 static char fname[FILENAME_MAX];
H. Peter Anvine2c80182005-01-15 22:15:51 +0000308 FILE *fp;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000309 int32_t len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000310 char *prefix = "", *combine;
311 char **pPrevPath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000312
H. Peter Anvine2c80182005-01-15 22:15:51 +0000313 len = FILENAME_MAX - 1;
314 if (len > instruction->eops->stringlen)
315 len = instruction->eops->stringlen;
316 strncpy(fname, instruction->eops->stringval, len);
317 fname[len] = '\0';
H. Peter Anvineba20a72002-04-30 20:53:55 +0000318
Keith Kaniosb7a89542007-04-12 02:40:54 +0000319 while (1) { /* added by alexfru: 'incbin' uses include paths */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000320 combine = nasm_malloc(strlen(prefix) + len + 1);
321 strcpy(combine, prefix);
322 strcat(combine, fname);
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000323
H. Peter Anvine2c80182005-01-15 22:15:51 +0000324 if ((fp = fopen(combine, "rb")) != NULL) {
325 nasm_free(combine);
326 break;
327 }
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000328
H. Peter Anvine2c80182005-01-15 22:15:51 +0000329 nasm_free(combine);
330 pPrevPath = pp_get_include_path_ptr(pPrevPath);
331 if (pPrevPath == NULL)
332 break;
333 prefix = *pPrevPath;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000334 }
335
336 if (fp == NULL)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000337 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
338 fname);
339 else if (fseek(fp, 0L, SEEK_END) < 0)
340 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
341 fname);
342 else {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000343 static char buf[2048];
Keith Kaniosb7a89542007-04-12 02:40:54 +0000344 int32_t t = instruction->times;
345 int32_t base = 0;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000346
H. Peter Anvine2c80182005-01-15 22:15:51 +0000347 len = ftell(fp);
348 if (instruction->eops->next) {
349 base = instruction->eops->next->offset;
350 len -= base;
351 if (instruction->eops->next->next &&
352 len > instruction->eops->next->next->offset)
353 len = instruction->eops->next->next->offset;
354 }
355 /*
356 * Dummy call to list->output to give the offset to the
357 * listing module.
358 */
359 list->output(offset, NULL, OUT_RAWDATA);
360 list->uplevel(LIST_INCBIN);
361 while (t--) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000362 int32_t l;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000363
H. Peter Anvine2c80182005-01-15 22:15:51 +0000364 fseek(fp, base, SEEK_SET);
365 l = len;
366 while (l > 0) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000367 int32_t m =
H. Peter Anvine2c80182005-01-15 22:15:51 +0000368 fread(buf, 1, (l > sizeof(buf) ? sizeof(buf) : l),
369 fp);
370 if (!m) {
371 /*
372 * This shouldn't happen unless the file
373 * actually changes while we are reading
374 * it.
375 */
376 error(ERR_NONFATAL,
377 "`incbin': unexpected EOF while"
378 " reading file `%s'", fname);
379 t = 0; /* Try to exit cleanly */
380 break;
381 }
382 out(offset, segment, buf, OUT_RAWDATA + m,
383 NO_SEG, NO_SEG);
384 l -= m;
385 }
386 }
387 list->downlevel(LIST_INCBIN);
388 if (instruction->times > 1) {
389 /*
390 * Dummy call to list->output to give the offset to the
391 * listing module.
392 */
393 list->output(offset, NULL, OUT_RAWDATA);
394 list->uplevel(LIST_TIMES);
395 list->downlevel(LIST_TIMES);
396 }
397 fclose(fp);
398 return instruction->times * len;
399 }
400 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000401 }
402
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000403 size_prob = FALSE;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000404
405 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++){
406 int m = matches(temp, instruction, bits);
407
H. Peter Anvine2c80182005-01-15 22:15:51 +0000408 if (m == 99)
409 m += jmp_match(segment, offset, bits, instruction, temp->code);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000410
H. Peter Anvine2c80182005-01-15 22:15:51 +0000411 if (m == 100) { /* matches! */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000412 const char *codes = temp->code;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000413 int32_t insn_size = calcsize(segment, offset, bits,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000414 instruction, codes);
415 itimes = instruction->times;
416 if (insn_size < 0) /* shouldn't be, on pass two */
417 error(ERR_PANIC, "errors made it through from pass one");
418 else
419 while (itimes--) {
420 for (j = 0; j < instruction->nprefix; j++) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000421 uint8_t c = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000422 switch (instruction->prefixes[j]) {
423 case P_LOCK:
424 c = 0xF0;
425 break;
426 case P_REPNE:
427 case P_REPNZ:
428 c = 0xF2;
429 break;
430 case P_REPE:
431 case P_REPZ:
432 case P_REP:
433 c = 0xF3;
434 break;
435 case R_CS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000436 if (bits == 64) {
437 error(ERR_WARNING,
438 "cs segment base ignored in 64-bit mode");
439 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000440 c = 0x2E;
441 break;
442 case R_DS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000443 if (bits == 64) {
444 error(ERR_WARNING,
445 "ds segment base ignored in 64-bit mode");
446 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000447 c = 0x3E;
448 break;
449 case R_ES:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000450 if (bits == 64) {
451 error(ERR_WARNING,
452 "es segment base ignored in 64-bit mode");
453 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000454 c = 0x26;
455 break;
456 case R_FS:
457 c = 0x64;
458 break;
459 case R_GS:
460 c = 0x65;
461 break;
462 case R_SS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000463 if (bits == 64) {
464 error(ERR_WARNING,
465 "ss segment base ignored in 64-bit mode");
466 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000467 c = 0x36;
468 break;
469 case R_SEGR6:
470 case R_SEGR7:
471 error(ERR_NONFATAL,
472 "segr6 and segr7 cannot be used as prefixes");
473 break;
474 case P_A16:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000475 if (bits == 64) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000476 error(ERR_NONFATAL,
477 "16-bit addressing is not supported "
478 "in 64-bit mode");
Keith Kaniosb7a89542007-04-12 02:40:54 +0000479 break;
480 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000481 if (bits != 16)
482 c = 0x67;
483 break;
484 case P_A32:
485 if (bits != 32)
486 c = 0x67;
487 break;
488 case P_O16:
489 if (bits != 16)
490 c = 0x66;
491 break;
492 case P_O32:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000493 if (bits == 16)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000494 c = 0x66;
495 break;
496 default:
497 error(ERR_PANIC, "invalid instruction prefix");
498 }
499 if (c != 0) {
500 out(offset, segment, &c, OUT_RAWDATA + 1,
501 NO_SEG, NO_SEG);
502 offset++;
503 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000504 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000505 insn_end = offset + insn_size;
506 gencode(segment, offset, bits, instruction, codes,
507 insn_end);
508 offset += insn_size;
509 if (itimes > 0 && itimes == instruction->times - 1) {
510 /*
511 * Dummy call to list->output to give the offset to the
512 * listing module.
513 */
514 list->output(offset, NULL, OUT_RAWDATA);
515 list->uplevel(LIST_TIMES);
516 }
517 }
518 if (instruction->times > 1)
519 list->downlevel(LIST_TIMES);
520 return offset - start;
521 } else if (m > 0 && m > size_prob) {
522 size_prob = m;
523 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000524// temp++;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000525 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000526
H. Peter Anvine2c80182005-01-15 22:15:51 +0000527 if (temp->opcode == -1) { /* didn't match any instruction */
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000528 switch (size_prob) {
529 case 1:
530 error(ERR_NONFATAL, "operation size not specified");
531 break;
532 case 2:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000533 error(ERR_NONFATAL, "mismatch in operand sizes");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000534 break;
535 case 3:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000536 error(ERR_NONFATAL, "no instruction for this cpu level");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000537 break;
538 case 4:
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000539 error(ERR_NONFATAL, "instruction not supported in 64-bit mode");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000540 break;
541 default:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000542 error(ERR_NONFATAL,
543 "invalid combination of opcode and operands");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000544 break;
545 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000546 }
547 return 0;
548}
549
Keith Kaniosb7a89542007-04-12 02:40:54 +0000550int32_t insn_size(int32_t segment, int32_t offset, int bits, uint32_t cp,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000551 insn * instruction, efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000552{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000553 struct itemplate *temp;
554
H. Peter Anvine2c80182005-01-15 22:15:51 +0000555 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000556 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000557
558 if (instruction->opcode == -1)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000559 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000560
561 if (instruction->opcode == I_DB ||
H. Peter Anvine2c80182005-01-15 22:15:51 +0000562 instruction->opcode == I_DW ||
563 instruction->opcode == I_DD ||
564 instruction->opcode == I_DQ || instruction->opcode == I_DT) {
565 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000566 int32_t isize, osize, wsize = 0; /* placate gcc */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000567
H. Peter Anvine2c80182005-01-15 22:15:51 +0000568 isize = 0;
569 switch (instruction->opcode) {
570 case I_DB:
571 wsize = 1;
572 break;
573 case I_DW:
574 wsize = 2;
575 break;
576 case I_DD:
577 wsize = 4;
578 break;
579 case I_DQ:
580 wsize = 8;
581 break;
582 case I_DT:
583 wsize = 10;
584 break;
585 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000586
H. Peter Anvine2c80182005-01-15 22:15:51 +0000587 for (e = instruction->eops; e; e = e->next) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000588 int32_t align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000589
H. Peter Anvine2c80182005-01-15 22:15:51 +0000590 osize = 0;
591 if (e->type == EOT_DB_NUMBER)
592 osize = 1;
593 else if (e->type == EOT_DB_STRING)
594 osize = e->stringlen;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000595
H. Peter Anvine2c80182005-01-15 22:15:51 +0000596 align = (-osize) % wsize;
597 if (align < 0)
598 align += wsize;
599 isize += osize + align;
600 }
601 return isize * instruction->times;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000602 }
603
H. Peter Anvine2c80182005-01-15 22:15:51 +0000604 if (instruction->opcode == I_INCBIN) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000605 char fname[FILENAME_MAX];
H. Peter Anvine2c80182005-01-15 22:15:51 +0000606 FILE *fp;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000607 int32_t len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000608 char *prefix = "", *combine;
609 char **pPrevPath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000610
H. Peter Anvine2c80182005-01-15 22:15:51 +0000611 len = FILENAME_MAX - 1;
612 if (len > instruction->eops->stringlen)
613 len = instruction->eops->stringlen;
614 strncpy(fname, instruction->eops->stringval, len);
615 fname[len] = '\0';
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000616
H. Peter Anvine2c80182005-01-15 22:15:51 +0000617 while (1) { /* added by alexfru: 'incbin' uses include paths */
618 combine = nasm_malloc(strlen(prefix) + len + 1);
619 strcpy(combine, prefix);
620 strcat(combine, fname);
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000621
H. Peter Anvine2c80182005-01-15 22:15:51 +0000622 if ((fp = fopen(combine, "rb")) != NULL) {
623 nasm_free(combine);
624 break;
625 }
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000626
H. Peter Anvine2c80182005-01-15 22:15:51 +0000627 nasm_free(combine);
628 pPrevPath = pp_get_include_path_ptr(pPrevPath);
629 if (pPrevPath == NULL)
630 break;
631 prefix = *pPrevPath;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000632 }
633
634 if (fp == NULL)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000635 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
636 fname);
637 else if (fseek(fp, 0L, SEEK_END) < 0)
638 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
639 fname);
640 else {
641 len = ftell(fp);
642 fclose(fp);
643 if (instruction->eops->next) {
644 len -= instruction->eops->next->offset;
645 if (instruction->eops->next->next &&
646 len > instruction->eops->next->next->offset) {
647 len = instruction->eops->next->next->offset;
648 }
649 }
650 return instruction->times * len;
651 }
652 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000653 }
654
Keith Kaniosb7a89542007-04-12 02:40:54 +0000655 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++) {
656 int m = matches(temp, instruction, bits);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000657 if (m == 99)
658 m += jmp_match(segment, offset, bits, instruction, temp->code);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000659
H. Peter Anvine2c80182005-01-15 22:15:51 +0000660 if (m == 100) {
661 /* we've matched an instruction. */
Keith Kaniosb7a89542007-04-12 02:40:54 +0000662 int32_t isize;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000663 const char *codes = temp->code;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000664 int j;
665
666 isize = calcsize(segment, offset, bits, instruction, codes);
667 if (isize < 0)
668 return -1;
669 for (j = 0; j < instruction->nprefix; j++) {
670 if ((instruction->prefixes[j] != P_A16 &&
671 instruction->prefixes[j] != P_O16 && bits == 16) ||
672 (instruction->prefixes[j] != P_A32 &&
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000673 instruction->prefixes[j] != P_O32 && bits >= 32)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000674 isize++;
675 }
676 }
677 return isize * instruction->times;
678 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000679 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000680 return -1; /* didn't match any instruction */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000681}
682
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000683/* check that opn[op] is a signed byte of size 16 or 32,
684 and return the signed value*/
H. Peter Anvine2c80182005-01-15 22:15:51 +0000685static int is_sbyte(insn * ins, int op, int size)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000686{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000687 int32_t v;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000688 int ret;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000689
690 ret = !(ins->forw_ref && ins->oprs[op].opflags) && /* dead in the water on forward reference or External */
691 optimizing >= 0 &&
692 !(ins->oprs[op].type & STRICT) &&
693 ins->oprs[op].wrt == NO_SEG && ins->oprs[op].segment == NO_SEG;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000694
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000695 v = ins->oprs[op].offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000696 if (size == 16)
Keith Kaniosb7a89542007-04-12 02:40:54 +0000697 v = (int16_t)v; /* sign extend if 16 bits */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000698
699 return ret && v >= -128L && v <= 127L;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000700}
701
Keith Kaniosb7a89542007-04-12 02:40:54 +0000702static int32_t calcsize(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000703 insn * ins, const char *codes)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000704{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000705 int32_t length = 0;
706 uint8_t c;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000707 int rex_mask = ~0;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000708 ins->rex = 0; /* Ensure REX is reset */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000709
H. Peter Anvine2c80182005-01-15 22:15:51 +0000710 (void)segment; /* Don't warn that this parameter is unused */
711 (void)offset; /* Don't warn that this parameter is unused */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000712
H. Peter Anvine2c80182005-01-15 22:15:51 +0000713 while (*codes)
714 switch (c = *codes++) {
715 case 01:
716 case 02:
717 case 03:
718 codes += c, length += c;
719 break;
720 case 04:
721 case 05:
722 case 06:
723 case 07:
724 length++;
725 break;
726 case 010:
727 case 011:
728 case 012:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000729 ins->rex |=
730 op_rexflags(&ins->oprs[c - 010], REX_B|REX_H|REX_P|REX_W);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000731 codes++, length++;
732 break;
733 case 017:
734 length++;
735 break;
736 case 014:
737 case 015:
738 case 016:
739 length++;
740 break;
741 case 020:
742 case 021:
743 case 022:
744 length++;
745 break;
746 case 024:
747 case 025:
748 case 026:
749 length++;
750 break;
751 case 030:
752 case 031:
753 case 032:
754 length += 2;
755 break;
756 case 034:
757 case 035:
758 case 036:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000759 if (ins->oprs[c - 034].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000760 length += (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
761 else
762 length += (bits == 16) ? 2 : 4;
763 break;
764 case 037:
765 length += 2;
766 break;
767 case 040:
768 case 041:
769 case 042:
770 length += 4;
771 break;
772 case 044:
773 case 045:
774 case 046:
775 length += ((ins->oprs[c - 044].addr_size ?
Keith Kaniosb7a89542007-04-12 02:40:54 +0000776 ins->oprs[c - 044].addr_size : bits) >> 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000777 break;
778 case 050:
779 case 051:
780 case 052:
781 length++;
782 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000783 case 054:
784 case 055:
785 case 056:
786 length += 8; /* MOV reg64/imm */
787 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000788 case 060:
789 case 061:
790 case 062:
791 length += 2;
792 break;
793 case 064:
794 case 065:
795 case 066:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000796 if (ins->oprs[c - 064].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000797 length += (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
798 else
799 length += (bits == 16) ? 2 : 4;
800 break;
801 case 070:
802 case 071:
803 case 072:
804 length += 4;
805 break;
806 case 0130:
807 case 0131:
808 case 0132:
809 length += is_sbyte(ins, c - 0130, 16) ? 1 : 2;
810 break;
811 case 0133:
812 case 0134:
813 case 0135:
814 codes += 2;
815 length++;
816 break;
817 case 0140:
818 case 0141:
819 case 0142:
820 length += is_sbyte(ins, c - 0140, 32) ? 1 : 4;
821 break;
822 case 0143:
823 case 0144:
824 case 0145:
825 codes += 2;
826 length++;
827 break;
828 case 0300:
829 case 0301:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000830 case 0302:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000831 length += chsize(&ins->oprs[c - 0300], bits);
832 break;
833 case 0310:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000834 length += (bits != 16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000835 break;
836 case 0311:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000837 length += (bits != 32);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000838 break;
839 case 0312:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000840 break;
841 case 0313:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000842 break;
843 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000844 length += (bits != 16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000845 break;
846 case 0321:
847 length += (bits == 16);
848 break;
849 case 0322:
850 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000851 case 0323:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000852 rex_mask &= ~REX_W;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000853 break;
854 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000855 ins->rex |= REX_W;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000856 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000857 case 0330:
858 codes++, length++;
859 break;
860 case 0331:
861 case 0332:
862 break;
863 case 0333:
864 length++;
865 break;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000866 case 0334:
867 assert_no_prefix(ins, P_LOCK);
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000868 ins->rex |= REX_L;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000869 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000870 case 0340:
871 case 0341:
872 case 0342:
873 if (ins->oprs[0].segment != NO_SEG)
874 errfunc(ERR_NONFATAL, "attempt to reserve non-constant"
875 " quantity of BSS space");
876 else
877 length += ins->oprs[0].offset << (c - 0340);
878 break;
Keith Kanios48af1772007-08-17 07:37:52 +0000879 case 0366:
880 length++;
881 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000882 case 0370:
883 case 0371:
884 case 0372:
885 break;
886 case 0373:
887 length++;
888 break;
889 default: /* can't do it by 'case' statements */
890 if (c >= 0100 && c <= 0277) { /* it's an EA */
891 ea ea_data;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000892 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000893 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000894 ea_data.rex = 0; /* Ensure ea.REX is initially 0 */
895
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000896 if (c <= 0177) {
897 /* pick rfield from operand b */
898 rflags = regflag(&ins->oprs[c & 7]);
899 rfield = regvals[ins->oprs[c & 7].basereg];
900 } else {
901 rflags = 0;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000902 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000903 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000904
H. Peter Anvine2c80182005-01-15 22:15:51 +0000905 if (!process_ea
Keith Kaniosb7a89542007-04-12 02:40:54 +0000906 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000907 rfield, rflags, ins->forw_ref)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000908 errfunc(ERR_NONFATAL, "invalid effective address");
909 return -1;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000910 } else {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000911 ins->rex |= ea_data.rex;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000912 length += ea_data.size;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000913 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000914 } else
915 errfunc(ERR_PANIC, "internal instruction table corrupt"
916 ": instruction code 0x%02X given", c);
917 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000918
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000919 ins->rex &= rex_mask;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000920 if (ins->rex & REX_REAL) {
921 if (ins->rex & REX_H) {
922 errfunc(ERR_NONFATAL, "cannot use high register in rex instruction");
923 return -1;
924 } else if (bits == 64 ||
925 ((ins->rex & REX_L) &&
926 !(ins->rex & (REX_P|REX_W|REX_X|REX_B)) &&
927 cpu >= IF_X86_64)) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000928 length++;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000929 } else {
930 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
931 return -1;
932 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000933 }
934
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000935 return length;
936}
Keith Kaniosb7a89542007-04-12 02:40:54 +0000937
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000938#define EMIT_REX() \
939 if((ins->rex & REX_REAL) && (bits == 64)) { \
940 ins->rex = (ins->rex & REX_REAL)|REX_P; \
941 out(offset, segment, &ins->rex, OUT_RAWDATA+1, NO_SEG, NO_SEG); \
942 ins->rex = 0; \
943 offset += 1; \
944 }
945
Keith Kaniosb7a89542007-04-12 02:40:54 +0000946static void gencode(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000947 insn * ins, const char *codes, int32_t insn_end)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000948{
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000949 static char condval[] = { /* conditional opcodes */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000950 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
951 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
952 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000953 };
Keith Kaniosb7a89542007-04-12 02:40:54 +0000954 uint8_t c;
955 uint8_t bytes[4];
956 int32_t size;
957 int64_t data;
958
H. Peter Anvineba20a72002-04-30 20:53:55 +0000959 while (*codes)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000960 switch (c = *codes++) {
961 case 01:
962 case 02:
963 case 03:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000964 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +0000965 out(offset, segment, codes, OUT_RAWDATA + c, NO_SEG, NO_SEG);
966 codes += c;
967 offset += c;
968 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000969
H. Peter Anvine2c80182005-01-15 22:15:51 +0000970 case 04:
971 case 06:
972 switch (ins->oprs[0].basereg) {
973 case R_CS:
974 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0);
975 break;
976 case R_DS:
977 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0);
978 break;
979 case R_ES:
980 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0);
981 break;
982 case R_SS:
983 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0);
984 break;
985 default:
986 errfunc(ERR_PANIC,
987 "bizarre 8086 segment register received");
988 }
989 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
990 offset++;
991 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000992
H. Peter Anvine2c80182005-01-15 22:15:51 +0000993 case 05:
994 case 07:
995 switch (ins->oprs[0].basereg) {
996 case R_FS:
997 bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0);
998 break;
999 case R_GS:
1000 bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0);
1001 break;
1002 default:
1003 errfunc(ERR_PANIC,
1004 "bizarre 386 segment register received");
1005 }
1006 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1007 offset++;
1008 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001009
H. Peter Anvine2c80182005-01-15 22:15:51 +00001010 case 010:
1011 case 011:
1012 case 012:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001013 EMIT_REX();
Keith Kaniosb7a89542007-04-12 02:40:54 +00001014 bytes[0] = *codes++ + ((regval(&ins->oprs[c - 010])) & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001015 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1016 offset += 1;
1017 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001018
H. Peter Anvine2c80182005-01-15 22:15:51 +00001019 case 017:
1020 bytes[0] = 0;
1021 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1022 offset += 1;
1023 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001024
H. Peter Anvine2c80182005-01-15 22:15:51 +00001025 case 014:
1026 case 015:
1027 case 016:
1028 if (ins->oprs[c - 014].offset < -128
1029 || ins->oprs[c - 014].offset > 127) {
1030 errfunc(ERR_WARNING, "signed byte value exceeds bounds");
1031 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001032
H. Peter Anvine2c80182005-01-15 22:15:51 +00001033 if (ins->oprs[c - 014].segment != NO_SEG) {
1034 data = ins->oprs[c - 014].offset;
1035 out(offset, segment, &data, OUT_ADDRESS + 1,
1036 ins->oprs[c - 014].segment, ins->oprs[c - 014].wrt);
1037 } else {
1038 bytes[0] = ins->oprs[c - 014].offset;
1039 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1040 NO_SEG);
1041 }
1042 offset += 1;
1043 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001044
H. Peter Anvine2c80182005-01-15 22:15:51 +00001045 case 020:
1046 case 021:
1047 case 022:
1048 if (ins->oprs[c - 020].offset < -256
1049 || ins->oprs[c - 020].offset > 255) {
1050 errfunc(ERR_WARNING, "byte value exceeds bounds");
1051 }
1052 if (ins->oprs[c - 020].segment != NO_SEG) {
1053 data = ins->oprs[c - 020].offset;
1054 out(offset, segment, &data, OUT_ADDRESS + 1,
1055 ins->oprs[c - 020].segment, ins->oprs[c - 020].wrt);
1056 } else {
1057 bytes[0] = ins->oprs[c - 020].offset;
1058 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1059 NO_SEG);
1060 }
1061 offset += 1;
1062 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001063
H. Peter Anvine2c80182005-01-15 22:15:51 +00001064 case 024:
1065 case 025:
1066 case 026:
1067 if (ins->oprs[c - 024].offset < 0
1068 || ins->oprs[c - 024].offset > 255)
1069 errfunc(ERR_WARNING, "unsigned byte value exceeds bounds");
1070 if (ins->oprs[c - 024].segment != NO_SEG) {
1071 data = ins->oprs[c - 024].offset;
1072 out(offset, segment, &data, OUT_ADDRESS + 1,
1073 ins->oprs[c - 024].segment, ins->oprs[c - 024].wrt);
1074 } else {
1075 bytes[0] = ins->oprs[c - 024].offset;
1076 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1077 NO_SEG);
1078 }
1079 offset += 1;
1080 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001081
H. Peter Anvine2c80182005-01-15 22:15:51 +00001082 case 030:
1083 case 031:
1084 case 032:
1085 if (ins->oprs[c - 030].segment == NO_SEG &&
1086 ins->oprs[c - 030].wrt == NO_SEG &&
1087 (ins->oprs[c - 030].offset < -65536L ||
1088 ins->oprs[c - 030].offset > 65535L)) {
1089 errfunc(ERR_WARNING, "word value exceeds bounds");
1090 }
1091 data = ins->oprs[c - 030].offset;
1092 out(offset, segment, &data, OUT_ADDRESS + 2,
1093 ins->oprs[c - 030].segment, ins->oprs[c - 030].wrt);
1094 offset += 2;
1095 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001096
H. Peter Anvine2c80182005-01-15 22:15:51 +00001097 case 034:
1098 case 035:
1099 case 036:
1100 if (ins->oprs[c - 034].type & (BITS16 | BITS32))
1101 size = (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
1102 else
1103 size = (bits == 16) ? 2 : 4;
1104 data = ins->oprs[c - 034].offset;
1105 if (size == 2 && (data < -65536L || data > 65535L))
1106 errfunc(ERR_WARNING, "word value exceeds bounds");
1107 out(offset, segment, &data, OUT_ADDRESS + size,
1108 ins->oprs[c - 034].segment, ins->oprs[c - 034].wrt);
1109 offset += size;
1110 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001111
H. Peter Anvine2c80182005-01-15 22:15:51 +00001112 case 037:
1113 if (ins->oprs[0].segment == NO_SEG)
1114 errfunc(ERR_NONFATAL, "value referenced by FAR is not"
1115 " relocatable");
1116 data = 0L;
1117 out(offset, segment, &data, OUT_ADDRESS + 2,
1118 outfmt->segbase(1 + ins->oprs[0].segment),
1119 ins->oprs[0].wrt);
1120 offset += 2;
1121 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001122
H. Peter Anvine2c80182005-01-15 22:15:51 +00001123 case 040:
1124 case 041:
1125 case 042:
1126 data = ins->oprs[c - 040].offset;
1127 out(offset, segment, &data, OUT_ADDRESS + 4,
1128 ins->oprs[c - 040].segment, ins->oprs[c - 040].wrt);
1129 offset += 4;
1130 break;
H. Peter Anvin3ba46772002-05-27 23:19:35 +00001131
H. Peter Anvine2c80182005-01-15 22:15:51 +00001132 case 044:
1133 case 045:
1134 case 046:
1135 data = ins->oprs[c - 044].offset;
1136 size = ((ins->oprs[c - 044].addr_size ?
Keith Kaniosb7a89542007-04-12 02:40:54 +00001137 ins->oprs[c - 044].addr_size : bits) >> 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001138 if (size == 2 && (data < -65536L || data > 65535L))
1139 errfunc(ERR_WARNING, "word value exceeds bounds");
1140 out(offset, segment, &data, OUT_ADDRESS + size,
1141 ins->oprs[c - 044].segment, ins->oprs[c - 044].wrt);
1142 offset += size;
1143 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001144
H. Peter Anvine2c80182005-01-15 22:15:51 +00001145 case 050:
1146 case 051:
1147 case 052:
1148 if (ins->oprs[c - 050].segment != segment)
1149 errfunc(ERR_NONFATAL,
1150 "short relative jump outside segment");
1151 data = ins->oprs[c - 050].offset - insn_end;
1152 if (data > 127 || data < -128)
1153 errfunc(ERR_NONFATAL, "short jump is out of range");
1154 bytes[0] = data;
1155 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1156 offset += 1;
1157 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001158
1159 case 054:
1160 case 055:
1161 case 056:
1162 data = (int64_t)ins->oprs[c - 054].offset;
1163 out(offset, segment, &data, OUT_ADDRESS + 8,
1164 ins->oprs[c - 054].segment, ins->oprs[c - 054].wrt);
1165 offset += 8;
1166 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001167
H. Peter Anvine2c80182005-01-15 22:15:51 +00001168 case 060:
1169 case 061:
1170 case 062:
1171 if (ins->oprs[c - 060].segment != segment) {
1172 data = ins->oprs[c - 060].offset;
1173 out(offset, segment, &data,
1174 OUT_REL2ADR + insn_end - offset,
1175 ins->oprs[c - 060].segment, ins->oprs[c - 060].wrt);
1176 } else {
1177 data = ins->oprs[c - 060].offset - insn_end;
1178 out(offset, segment, &data,
1179 OUT_ADDRESS + 2, NO_SEG, NO_SEG);
1180 }
1181 offset += 2;
1182 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001183
H. Peter Anvine2c80182005-01-15 22:15:51 +00001184 case 064:
1185 case 065:
1186 case 066:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001187 if (ins->oprs[c - 064].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001188 size = (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
1189 else
1190 size = (bits == 16) ? 2 : 4;
1191 if (ins->oprs[c - 064].segment != segment) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001192 int32_t reltype = (size == 2 ? OUT_REL2ADR : OUT_REL4ADR);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001193 data = ins->oprs[c - 064].offset;
1194 out(offset, segment, &data, reltype + insn_end - offset,
1195 ins->oprs[c - 064].segment, ins->oprs[c - 064].wrt);
1196 } else {
1197 data = ins->oprs[c - 064].offset - insn_end;
1198 out(offset, segment, &data,
1199 OUT_ADDRESS + size, NO_SEG, NO_SEG);
1200 }
1201 offset += size;
1202 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001203
H. Peter Anvine2c80182005-01-15 22:15:51 +00001204 case 070:
1205 case 071:
1206 case 072:
1207 if (ins->oprs[c - 070].segment != segment) {
1208 data = ins->oprs[c - 070].offset;
1209 out(offset, segment, &data,
1210 OUT_REL4ADR + insn_end - offset,
1211 ins->oprs[c - 070].segment, ins->oprs[c - 070].wrt);
1212 } else {
1213 data = ins->oprs[c - 070].offset - insn_end;
1214 out(offset, segment, &data,
1215 OUT_ADDRESS + 4, NO_SEG, NO_SEG);
1216 }
1217 offset += 4;
1218 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001219
H. Peter Anvine2c80182005-01-15 22:15:51 +00001220 case 0130:
1221 case 0131:
1222 case 0132:
1223 data = ins->oprs[c - 0130].offset;
1224 if (is_sbyte(ins, c - 0130, 16)) {
1225 bytes[0] = data;
1226 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1227 NO_SEG);
1228 offset++;
1229 } else {
1230 if (ins->oprs[c - 0130].segment == NO_SEG &&
1231 ins->oprs[c - 0130].wrt == NO_SEG &&
1232 (data < -65536L || data > 65535L)) {
1233 errfunc(ERR_WARNING, "word value exceeds bounds");
1234 }
1235 out(offset, segment, &data, OUT_ADDRESS + 2,
1236 ins->oprs[c - 0130].segment, ins->oprs[c - 0130].wrt);
1237 offset += 2;
1238 }
1239 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001240
H. Peter Anvine2c80182005-01-15 22:15:51 +00001241 case 0133:
1242 case 0134:
1243 case 0135:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001244 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001245 codes++;
1246 bytes[0] = *codes++;
1247 if (is_sbyte(ins, c - 0133, 16))
1248 bytes[0] |= 2; /* s-bit */
1249 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1250 offset++;
1251 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001252
H. Peter Anvine2c80182005-01-15 22:15:51 +00001253 case 0140:
1254 case 0141:
1255 case 0142:
1256 data = ins->oprs[c - 0140].offset;
1257 if (is_sbyte(ins, c - 0140, 32)) {
1258 bytes[0] = data;
1259 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1260 NO_SEG);
1261 offset++;
1262 } else {
1263 out(offset, segment, &data, OUT_ADDRESS + 4,
1264 ins->oprs[c - 0140].segment, ins->oprs[c - 0140].wrt);
1265 offset += 4;
1266 }
1267 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001268
H. Peter Anvine2c80182005-01-15 22:15:51 +00001269 case 0143:
1270 case 0144:
1271 case 0145:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001272 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001273 codes++;
1274 bytes[0] = *codes++;
1275 if (is_sbyte(ins, c - 0143, 32))
1276 bytes[0] |= 2; /* s-bit */
1277 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1278 offset++;
1279 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001280
H. Peter Anvine2c80182005-01-15 22:15:51 +00001281 case 0300:
1282 case 0301:
1283 case 0302:
1284 if (chsize(&ins->oprs[c - 0300], bits)) {
1285 *bytes = 0x67;
1286 out(offset, segment, bytes,
1287 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1288 offset += 1;
1289 } else
1290 offset += 0;
1291 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001292
H. Peter Anvine2c80182005-01-15 22:15:51 +00001293 case 0310:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001294 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001295 *bytes = 0x67;
1296 out(offset, segment, bytes,
1297 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1298 offset += 1;
1299 } else
1300 offset += 0;
1301 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001302
H. Peter Anvine2c80182005-01-15 22:15:51 +00001303 case 0311:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001304 if (bits != 32) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001305 *bytes = 0x67;
1306 out(offset, segment, bytes,
1307 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1308 offset += 1;
1309 } else
1310 offset += 0;
1311 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001312
H. Peter Anvine2c80182005-01-15 22:15:51 +00001313 case 0312:
1314 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001315
Keith Kaniosb7a89542007-04-12 02:40:54 +00001316 case 0313:
1317 ins->rex = 0;
1318 break;
1319
H. Peter Anvine2c80182005-01-15 22:15:51 +00001320 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001321 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001322 *bytes = 0x66;
1323 out(offset, segment, bytes,
1324 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1325 offset += 1;
1326 } else
1327 offset += 0;
1328 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001329
H. Peter Anvine2c80182005-01-15 22:15:51 +00001330 case 0321:
1331 if (bits == 16) {
1332 *bytes = 0x66;
1333 out(offset, segment, bytes,
1334 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1335 offset += 1;
1336 } else
1337 offset += 0;
1338 break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001339
H. Peter Anvine2c80182005-01-15 22:15:51 +00001340 case 0322:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001341 case 0323:
1342 break;
1343
1344 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001345 ins->rex |= REX_W;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001346 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001347
H. Peter Anvine2c80182005-01-15 22:15:51 +00001348 case 0330:
1349 *bytes = *codes++ ^ condval[ins->condition];
1350 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1351 offset += 1;
1352 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001353
H. Peter Anvine2c80182005-01-15 22:15:51 +00001354 case 0331:
1355 case 0332:
1356 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001357
H. Peter Anvine2c80182005-01-15 22:15:51 +00001358 case 0333:
1359 *bytes = 0xF3;
1360 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1361 offset += 1;
1362 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001363
Keith Kanios48af1772007-08-17 07:37:52 +00001364 case 0334:
1365 if (ins->rex & REX_R) {
1366 *bytes = 0xF0;
1367 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1368 offset += 1;
1369 }
1370 ins->rex &= ~(REX_L|REX_R);
1371 break;
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001372
H. Peter Anvine2c80182005-01-15 22:15:51 +00001373 case 0340:
1374 case 0341:
1375 case 0342:
1376 if (ins->oprs[0].segment != NO_SEG)
1377 errfunc(ERR_PANIC, "non-constant BSS size in pass two");
1378 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001379 int32_t size = ins->oprs[0].offset << (c - 0340);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001380 if (size > 0)
1381 out(offset, segment, NULL,
1382 OUT_RESERVE + size, NO_SEG, NO_SEG);
1383 offset += size;
1384 }
1385 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001386
Keith Kanios48af1772007-08-17 07:37:52 +00001387 case 0366:
1388 *bytes = 0x66;
1389 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1390 offset += 1;
1391 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001392 case 0370:
1393 case 0371:
1394 case 0372:
1395 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001396
H. Peter Anvine2c80182005-01-15 22:15:51 +00001397 case 0373:
1398 *bytes = bits == 16 ? 3 : 5;
1399 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1400 offset += 1;
1401 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001402
H. Peter Anvine2c80182005-01-15 22:15:51 +00001403 default: /* can't do it by 'case' statements */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001404 if (c >= 0100 && c <= 0277) { /* it's an EA */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001405 ea ea_data;
1406 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001407 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001408 uint8_t *p;
1409 int32_t s;
1410
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001411 if (c <= 0177) {
1412 /* pick rfield from operand b */
1413 rflags = regflag(&ins->oprs[c & 7]);
1414 rfield = regvals[ins->oprs[c & 7].basereg];
1415 } else {
1416 /* rfield is constant */
1417 rflags = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001418 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001419 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001420
1421 if (!process_ea
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001422 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
1423 rfield, rflags, ins->forw_ref)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001424 errfunc(ERR_NONFATAL, "invalid effective address");
1425 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001426
H. Peter Anvine2c80182005-01-15 22:15:51 +00001427 p = bytes;
1428 *p++ = ea_data.modrm;
1429 if (ea_data.sib_present)
1430 *p++ = ea_data.sib;
1431
1432 s = p - bytes;
1433 out(offset, segment, bytes, OUT_RAWDATA + s,
1434 NO_SEG, NO_SEG);
1435
1436 switch (ea_data.bytes) {
1437 case 0:
1438 break;
1439 case 1:
1440 if (ins->oprs[(c >> 3) & 7].segment != NO_SEG) {
1441 data = ins->oprs[(c >> 3) & 7].offset;
1442 out(offset, segment, &data, OUT_ADDRESS + 1,
1443 ins->oprs[(c >> 3) & 7].segment,
1444 ins->oprs[(c >> 3) & 7].wrt);
1445 } else {
1446 *bytes = ins->oprs[(c >> 3) & 7].offset;
1447 out(offset, segment, bytes, OUT_RAWDATA + 1,
1448 NO_SEG, NO_SEG);
1449 }
1450 s++;
1451 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001452 case 8:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001453 case 2:
1454 case 4:
1455 data = ins->oprs[(c >> 3) & 7].offset;
Keith Kaniose83b3182007-04-16 14:31:54 +00001456 if (ea_data.rip && (ins->oprs[(c >> 3) & 7].segment == 0xFFFFFFFF))
1457 ea_data.rip = 0; /* Make distinction between Symbols and Immediates */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001458 out(offset, segment, &data, /* RIP = Relative, not Absolute */
1459 (ea_data.rip ? OUT_REL4ADR : OUT_ADDRESS) + ea_data.bytes,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001460 ins->oprs[(c >> 3) & 7].segment,
1461 ins->oprs[(c >> 3) & 7].wrt);
1462 s += ea_data.bytes;
1463 break;
1464 }
1465 offset += s;
1466 } else
1467 errfunc(ERR_PANIC, "internal instruction table corrupt"
1468 ": instruction code 0x%02X given", c);
1469 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001470}
1471
H. Peter Anvin0ec60e62007-07-07 01:59:52 +00001472static int32_t regflag(const operand * o)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001473{
1474 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1475 errfunc(ERR_PANIC, "invalid operand passed to regflag()");
1476 }
1477 return reg_flags[o->basereg];
1478}
1479
H. Peter Anvin5b0e3ec2007-07-07 02:01:08 +00001480static int32_t regval(const operand * o)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001481{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001482 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1483 errfunc(ERR_PANIC, "invalid operand passed to regval()");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001484 }
H. Peter Anvin232badb2002-06-06 02:41:20 +00001485 return regvals[o->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001486}
1487
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001488static int op_rexflags(const operand * o, int mask)
1489{
1490 int32_t flags;
1491 int val;
1492
1493 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1494 errfunc(ERR_PANIC, "invalid operand passed to op_rexflags()");
1495 }
1496
1497 flags = reg_flags[o->basereg];
1498 val = regvals[o->basereg];
1499
1500 return rexflags(val, flags, mask);
1501}
1502
1503static int rexflags(int val, int32_t flags, int mask)
1504{
1505 int rex = 0;
1506
1507 if (val >= 8)
1508 rex |= REX_B|REX_X|REX_R;
1509 if (flags & BITS64)
1510 rex |= REX_W;
1511 if (!(REG_HIGH & ~flags)) /* AH, CH, DH, BH */
1512 rex |= REX_H;
1513 else if (!(REG8 & ~flags) && val >= 4) /* SPL, BPL, SIL, DIL */
1514 rex |= REX_P;
1515
1516 return rex & mask;
1517}
1518
Keith Kaniosb7a89542007-04-12 02:40:54 +00001519static int matches(struct itemplate *itemp, insn * instruction, int bits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001520{
H. Peter Anvin34539fb2007-05-30 04:27:58 +00001521 int i, size[3], asize, oprs, ret;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001522
1523 ret = 100;
1524
1525 /*
1526 * Check the opcode
1527 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001528 if (itemp->opcode != instruction->opcode)
1529 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001530
1531 /*
1532 * Count the operands
1533 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001534 if (itemp->operands != instruction->operands)
1535 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001536
1537 /*
1538 * Check that no spurious colons or TOs are present
1539 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001540 for (i = 0; i < itemp->operands; i++)
1541 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON | TO))
1542 return 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001543
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001544 /*
1545 * Check that the operand flags all match up
1546 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001547 for (i = 0; i < itemp->operands; i++)
1548 if (itemp->opd[i] & ~instruction->oprs[i].type ||
1549 ((itemp->opd[i] & SIZE_MASK) &&
1550 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK))) {
H. Peter Anvin5a640e12007-05-29 23:57:12 +00001551 if ((itemp->opd[i] & ~instruction->oprs[i].type & ~SIZE_MASK) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001552 (instruction->oprs[i].type & SIZE_MASK))
1553 return 0;
1554 else
H. Peter Anvine2c80182005-01-15 22:15:51 +00001555 return 1;
1556 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001557
1558 /*
1559 * Check operand sizes
1560 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001561 if (itemp->flags & IF_ARMASK) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001562 size[0] = size[1] = size[2] = 0;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001563
H. Peter Anvine2c80182005-01-15 22:15:51 +00001564 switch (itemp->flags & IF_ARMASK) {
1565 case IF_AR0:
1566 i = 0;
1567 break;
1568 case IF_AR1:
1569 i = 1;
1570 break;
1571 case IF_AR2:
1572 i = 2;
1573 break;
1574 default:
1575 break; /* Shouldn't happen */
1576 }
1577 if (itemp->flags & IF_SB) {
1578 size[i] = BITS8;
1579 } else if (itemp->flags & IF_SW) {
1580 size[i] = BITS16;
1581 } else if (itemp->flags & IF_SD) {
1582 size[i] = BITS32;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001583 } else if (itemp->flags & IF_SQ) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001584 size[i] = BITS64;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001585 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001586 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001587 asize = 0;
1588 if (itemp->flags & IF_SB) {
1589 asize = BITS8;
1590 oprs = itemp->operands;
1591 } else if (itemp->flags & IF_SW) {
1592 asize = BITS16;
1593 oprs = itemp->operands;
1594 } else if (itemp->flags & IF_SD) {
1595 asize = BITS32;
1596 oprs = itemp->operands;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001597 } else if (itemp->flags & IF_SQ) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001598 asize = BITS64;
1599 oprs = itemp->operands;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001600 }
1601 size[0] = size[1] = size[2] = asize;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001602 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001603
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001604 if (itemp->flags & (IF_SM | IF_SM2)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001605 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
1606 asize = 0;
1607 for (i = 0; i < oprs; i++) {
1608 if ((asize = itemp->opd[i] & SIZE_MASK) != 0) {
1609 int j;
1610 for (j = 0; j < oprs; j++)
1611 size[j] = asize;
1612 break;
1613 }
1614 }
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001615 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001616 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001617 }
1618
Keith Kaniosb7a89542007-04-12 02:40:54 +00001619 for (i = 0; i < itemp->operands; i++) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001620 if (!(itemp->opd[i] & SIZE_MASK) &&
1621 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001622 return 2;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001623 }
1624
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001625 /*
1626 * Check template is okay at the set cpu level
1627 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001628 if (((itemp->flags & IF_PLEVEL) > cpu))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001629 return 3;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001630
1631 /*
1632 * Check if instruction is available in long mode
1633 */
1634 if ((itemp->flags & IF_NOLONG) && (bits == 64))
1635 return 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001636
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001637 /*
1638 * Check if special handling needed for Jumps
1639 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001640 if ((uint8_t)(itemp->code[0]) >= 0370)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001641 return 99;
1642
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001643 return ret;
1644}
1645
H. Peter Anvine2c80182005-01-15 22:15:51 +00001646static ea *process_ea(operand * input, ea * output, int addrbits,
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001647 int rfield, int32_t rflags, int forw_ref)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001648{
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001649 output->rip = FALSE;
1650
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001651 /* REX flags for the rfield operand */
1652 output->rex |= rexflags(rfield, rflags, REX_R|REX_P|REX_W|REX_H);
1653
Keith Kaniosb7a89542007-04-12 02:40:54 +00001654 if (!(REGISTER & ~input->type)) { /* register direct */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001655 int i;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001656 int32_t f;
1657
1658 if (input->basereg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001659 || input->basereg >= REG_ENUM_LIMIT)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001660 return NULL;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001661 f = regflag(input);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001662 i = regvals[input->basereg];
Keith Kaniosb7a89542007-04-12 02:40:54 +00001663
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001664 if (REG_EA & ~f)
1665 return NULL; /* Invalid EA register */
1666
1667 output->rex |= op_rexflags(input, REX_B|REX_P|REX_W|REX_H);
1668
Keith Kaniosb7a89542007-04-12 02:40:54 +00001669 output->sib_present = FALSE; /* no SIB necessary */
1670 output->bytes = 0; /* no offset necessary either */
1671 output->modrm = 0xC0 | ((rfield & 7) << 3) | (i & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001672 } else { /* it's a memory reference */
1673 if (input->basereg == -1
1674 && (input->indexreg == -1 || input->scale == 0)) {
1675 /* it's a pure offset */
1676 if (input->addr_size)
1677 addrbits = input->addr_size;
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001678
1679 if (globalbits == 64 && (~input->type & IP_REL)) {
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00001680 int scale, index, base;
1681 output->sib_present = TRUE;
1682 scale = 0;
1683 index = 4;
1684 base = 5;
1685 output->sib = (scale << 6) | (index << 3) | base;
1686 output->bytes = 4;
1687 output->modrm = 4 | ((rfield & 7) << 3);
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001688 output->rip = FALSE;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00001689 } else {
1690 output->sib_present = FALSE;
1691 output->bytes = (addrbits != 16 ? 4 : 2);
1692 output->modrm = (addrbits != 16 ? 5 : 6) | ((rfield & 7) << 3);
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001693 output->rip = globalbits == 64;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00001694 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001695 } else { /* it's an indirection */
1696 int i = input->indexreg, b = input->basereg, s = input->scale;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001697 int32_t o = input->offset, seg = input->segment;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001698 int hb = input->hintbase, ht = input->hinttype;
1699 int t;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001700 int it, bt;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001701 int32_t ix, bx; /* register flags */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001702
H. Peter Anvine2c80182005-01-15 22:15:51 +00001703 if (s == 0)
1704 i = -1; /* make this easy, at least */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001705
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001706 if (i >= EXPR_REG_START && i < REG_ENUM_LIMIT) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001707 it = regvals[i];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001708 ix = reg_flags[i];
1709 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001710 it = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001711 ix = 0;
1712 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001713
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001714 if (b != -1 && b >= EXPR_REG_START && b < REG_ENUM_LIMIT) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001715 bt = regvals[b];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001716 bx = reg_flags[b];
1717 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001718 bt = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001719 bx = 0;
1720 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001721
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001722 /* check for a 32/64-bit memory reference... */
1723 if ((ix|bx) & (BITS32|BITS64)) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001724 /* it must be a 32/64-bit memory reference. Firstly we have
1725 * to check that all registers involved are type E/Rxx. */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001726 int32_t sok = BITS32|BITS64;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001727
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001728 if (it != -1) {
1729 if (!(REG64 & ~ix) || !(REG32 & ~ix))
1730 sok &= ix;
1731 else
1732 return NULL;
1733 }
1734
1735 if (bt != -1) {
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001736 if (REG_GPR & ~bx)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001737 return NULL; /* Invalid register */
H. Peter Anvina57e8d42007-05-30 03:44:02 +00001738 if (~sok & bx & SIZE_MASK)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001739 return NULL; /* Invalid size */
1740 sok &= ~bx;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001741 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001742
H. Peter Anvine2c80182005-01-15 22:15:51 +00001743 /* While we're here, ensure the user didn't specify WORD. */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001744 if (input->addr_size == 16 ||
1745 (input->addr_size == 32 && !(sok & BITS32)) ||
1746 (input->addr_size == 64 && !(sok & BITS64)))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001747 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001748
Keith Kaniosb7a89542007-04-12 02:40:54 +00001749 /* now reorganize base/index */
1750 if (s == 1 && bt != it && bt != -1 && it != -1 &&
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001751 ((hb == b && ht == EAH_NOTBASE)
1752 || (hb == i && ht == EAH_MAKEBASE))) {
1753 /* swap if hints say so */
1754 t = bt, bt = it, it = t;
1755 t = bx, bx = ix, ix = t;
1756 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001757 if (bt == it) /* convert EAX+2*EAX to 3*EAX */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001758 bt = -1, bx = 0, s++;
1759 if (bt == -1 && s == 1 && !(hb == it && ht == EAH_NOTBASE)) {
1760 /* make single reg base, unless hint */
1761 bt = it, bx = ix, it = -1, ix = 0;
1762 }
Keith Kanios48af1772007-08-17 07:37:52 +00001763 if (((s == 2 && t != REG_NUM_ESP
H. Peter Anvine2c80182005-01-15 22:15:51 +00001764 && !(input->eaflags & EAF_TIMESTWO)) || s == 3
Keith Kaniosb7a89542007-04-12 02:40:54 +00001765 || s == 5 || s == 9) && bt == -1)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001766 bt = it, bx = ix, s--; /* convert 3*EAX to EAX+2*EAX */
Keith Kanios48af1772007-08-17 07:37:52 +00001767 if (it == -1 && (bt & 7) != REG_NUM_ESP
H. Peter Anvine2c80182005-01-15 22:15:51 +00001768 && (input->eaflags & EAF_TIMESTWO))
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001769 it = bt, ix = bx, bt = -1, bx = 0, s = 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001770 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
Keith Kanios48af1772007-08-17 07:37:52 +00001771 if (s == 1 && it == REG_NUM_ESP) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001772 /* swap ESP into base if scale is 1 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001773 t = it, it = bt, bt = t;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001774 t = ix, ix = bx, bx = t;
1775 }
Keith Kanios48af1772007-08-17 07:37:52 +00001776 if (it == REG_NUM_ESP
Keith Kaniosb7a89542007-04-12 02:40:54 +00001777 || (s != 1 && s != 2 && s != 4 && s != 8 && it != -1))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001778 return NULL; /* wrong, for various reasons */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001779
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001780 output->rex |= rexflags(it, ix, REX_X);
1781 output->rex |= rexflags(bt, bx, REX_B);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001782
Keith Kanios48af1772007-08-17 07:37:52 +00001783 if (it == -1 && (bt & 7) != REG_NUM_ESP) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001784 /* no SIB needed */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001785 int mod, rm;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001786
1787 if (bt == -1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001788 rm = 5;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001789 mod = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001790 } else {
1791 rm = (bt & 7);
Keith Kanios48af1772007-08-17 07:37:52 +00001792 if (rm != REG_NUM_EBP && o == 0 &&
Keith Kaniosb7a89542007-04-12 02:40:54 +00001793 seg == NO_SEG && !forw_ref &&
1794 !(input->eaflags &
1795 (EAF_BYTEOFFS | EAF_WORDOFFS)))
1796 mod = 0;
1797 else if (input->eaflags & EAF_BYTEOFFS ||
1798 (o >= -128 && o <= 127 && seg == NO_SEG
1799 && !forw_ref
1800 && !(input->eaflags & EAF_WORDOFFS)))
1801 mod = 1;
1802 else
1803 mod = 2;
1804 }
H. Peter Anvinea838272002-04-30 20:51:53 +00001805
H. Peter Anvine2c80182005-01-15 22:15:51 +00001806 output->sib_present = FALSE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001807 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
1808 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001809 } else {
1810 /* we need a SIB */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001811 int mod, scale, index, base;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001812
1813 if (it == -1)
1814 index = 4, s = 1;
1815 else
1816 index = (it & 7);
1817
H. Peter Anvine2c80182005-01-15 22:15:51 +00001818 switch (s) {
1819 case 1:
1820 scale = 0;
1821 break;
1822 case 2:
1823 scale = 1;
1824 break;
1825 case 4:
1826 scale = 2;
1827 break;
1828 case 8:
1829 scale = 3;
1830 break;
1831 default: /* then what the smeg is it? */
1832 return NULL; /* panic */
1833 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001834
1835 if (bt == -1) {
1836 base = 5;
1837 mod = 0;
1838 } else {
1839 base = (bt & 7);
Keith Kanios48af1772007-08-17 07:37:52 +00001840 if (base != REG_NUM_EBP && o == 0 &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00001841 seg == NO_SEG && !forw_ref &&
1842 !(input->eaflags &
Keith Kaniosb7a89542007-04-12 02:40:54 +00001843 (EAF_BYTEOFFS | EAF_WORDOFFS)))
1844 mod = 0;
1845 else if (input->eaflags & EAF_BYTEOFFS ||
1846 (o >= -128 && o <= 127 && seg == NO_SEG
1847 && !forw_ref
1848 && !(input->eaflags & EAF_WORDOFFS)))
1849 mod = 1;
1850 else
1851 mod = 2;
1852 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001853
H. Peter Anvine2c80182005-01-15 22:15:51 +00001854 output->sib_present = TRUE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001855 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
1856 output->modrm = (mod << 6) | ((rfield & 7) << 3) | 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001857 output->sib = (scale << 6) | (index << 3) | base;
1858 }
1859 } else { /* it's 16-bit */
1860 int mod, rm;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001861
1862 /* check for 64-bit long mode */
1863 if (addrbits == 64)
1864 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001865
H. Peter Anvine2c80182005-01-15 22:15:51 +00001866 /* check all registers are BX, BP, SI or DI */
1867 if ((b != -1 && b != R_BP && b != R_BX && b != R_SI
1868 && b != R_DI) || (i != -1 && i != R_BP && i != R_BX
1869 && i != R_SI && i != R_DI))
1870 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001871
Keith Kaniosb7a89542007-04-12 02:40:54 +00001872 /* ensure the user didn't specify DWORD/QWORD */
1873 if (input->addr_size == 32 || input->addr_size == 64)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001874 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001875
H. Peter Anvine2c80182005-01-15 22:15:51 +00001876 if (s != 1 && i != -1)
1877 return NULL; /* no can do, in 16-bit EA */
1878 if (b == -1 && i != -1) {
1879 int tmp = b;
1880 b = i;
1881 i = tmp;
1882 } /* swap */
1883 if ((b == R_SI || b == R_DI) && i != -1) {
1884 int tmp = b;
1885 b = i;
1886 i = tmp;
1887 }
1888 /* have BX/BP as base, SI/DI index */
1889 if (b == i)
1890 return NULL; /* shouldn't ever happen, in theory */
1891 if (i != -1 && b != -1 &&
1892 (i == R_BP || i == R_BX || b == R_SI || b == R_DI))
1893 return NULL; /* invalid combinations */
1894 if (b == -1) /* pure offset: handled above */
1895 return NULL; /* so if it gets to here, panic! */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001896
H. Peter Anvine2c80182005-01-15 22:15:51 +00001897 rm = -1;
1898 if (i != -1)
1899 switch (i * 256 + b) {
1900 case R_SI * 256 + R_BX:
1901 rm = 0;
1902 break;
1903 case R_DI * 256 + R_BX:
1904 rm = 1;
1905 break;
1906 case R_SI * 256 + R_BP:
1907 rm = 2;
1908 break;
1909 case R_DI * 256 + R_BP:
1910 rm = 3;
1911 break;
1912 } else
1913 switch (b) {
1914 case R_SI:
1915 rm = 4;
1916 break;
1917 case R_DI:
1918 rm = 5;
1919 break;
1920 case R_BP:
1921 rm = 6;
1922 break;
1923 case R_BX:
1924 rm = 7;
1925 break;
1926 }
1927 if (rm == -1) /* can't happen, in theory */
1928 return NULL; /* so panic if it does */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001929
H. Peter Anvine2c80182005-01-15 22:15:51 +00001930 if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
1931 !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
1932 mod = 0;
1933 else if (input->eaflags & EAF_BYTEOFFS ||
1934 (o >= -128 && o <= 127 && seg == NO_SEG
1935 && !forw_ref
1936 && !(input->eaflags & EAF_WORDOFFS)))
1937 mod = 1;
1938 else
1939 mod = 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001940
H. Peter Anvine2c80182005-01-15 22:15:51 +00001941 output->sib_present = FALSE; /* no SIB - it's 16-bit */
1942 output->bytes = mod; /* bytes of offset needed */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001943 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001944 }
1945 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001946 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001947
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001948 output->size = 1 + output->sib_present + output->bytes;
1949 return output;
1950}
1951
H. Peter Anvine2c80182005-01-15 22:15:51 +00001952static int chsize(operand * input, int addrbits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001953{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001954 if (!(MEMORY & ~input->type)) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001955 int32_t i, b;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001956
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001957 if (input->indexreg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001958 || input->indexreg >= REG_ENUM_LIMIT)
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00001959 i = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001960 else
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001961 i = reg_flags[input->indexreg];
Keith Kaniosb7a89542007-04-12 02:40:54 +00001962
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001963 if (input->basereg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001964 || input->basereg >= REG_ENUM_LIMIT)
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00001965 b = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001966 else
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001967 b = reg_flags[input->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001968
H. Peter Anvine2c80182005-01-15 22:15:51 +00001969 if (input->scale == 0)
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00001970 i = 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001971
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00001972 if (!i && !b) /* pure offset */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001973 return (input->addr_size != 0 && input->addr_size != addrbits);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001974
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001975 if (!(REG32 & ~i) || !(REG32 & ~b))
Keith Kaniosb7a89542007-04-12 02:40:54 +00001976 return (addrbits != 32);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001977 else
1978 return (addrbits == 32);
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001979 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001980 return 0;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001981 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001982}