blob: 417bb2d8a6b2c8a76b27b65b38d1479395649ebe [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 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 Anvin3360d792007-09-11 04:16:57 +0000553 const struct itemplate *temp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000554
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;
H. Peter Anvin62cb6062007-09-11 22:44:03 +0000879 case 0364:
880 case 0365:
881 break;
Keith Kanios48af1772007-08-17 07:37:52 +0000882 case 0366:
H. Peter Anvin62cb6062007-09-11 22:44:03 +0000883 case 0367:
884 length++;
885 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000886 case 0370:
887 case 0371:
888 case 0372:
889 break;
890 case 0373:
891 length++;
892 break;
893 default: /* can't do it by 'case' statements */
894 if (c >= 0100 && c <= 0277) { /* it's an EA */
895 ea ea_data;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000896 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000897 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000898 ea_data.rex = 0; /* Ensure ea.REX is initially 0 */
899
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000900 if (c <= 0177) {
901 /* pick rfield from operand b */
902 rflags = regflag(&ins->oprs[c & 7]);
903 rfield = regvals[ins->oprs[c & 7].basereg];
904 } else {
905 rflags = 0;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000906 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000907 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000908
H. Peter Anvine2c80182005-01-15 22:15:51 +0000909 if (!process_ea
Keith Kaniosb7a89542007-04-12 02:40:54 +0000910 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000911 rfield, rflags, ins->forw_ref)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000912 errfunc(ERR_NONFATAL, "invalid effective address");
913 return -1;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000914 } else {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000915 ins->rex |= ea_data.rex;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000916 length += ea_data.size;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000917 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000918 } else
919 errfunc(ERR_PANIC, "internal instruction table corrupt"
920 ": instruction code 0x%02X given", c);
921 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000922
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000923 ins->rex &= rex_mask;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000924 if (ins->rex & REX_REAL) {
925 if (ins->rex & REX_H) {
926 errfunc(ERR_NONFATAL, "cannot use high register in rex instruction");
927 return -1;
928 } else if (bits == 64 ||
929 ((ins->rex & REX_L) &&
930 !(ins->rex & (REX_P|REX_W|REX_X|REX_B)) &&
931 cpu >= IF_X86_64)) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000932 length++;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000933 } else {
934 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
935 return -1;
936 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000937 }
938
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000939 return length;
940}
Keith Kaniosb7a89542007-04-12 02:40:54 +0000941
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000942#define EMIT_REX() \
943 if((ins->rex & REX_REAL) && (bits == 64)) { \
944 ins->rex = (ins->rex & REX_REAL)|REX_P; \
945 out(offset, segment, &ins->rex, OUT_RAWDATA+1, NO_SEG, NO_SEG); \
946 ins->rex = 0; \
947 offset += 1; \
948 }
949
Keith Kaniosb7a89542007-04-12 02:40:54 +0000950static void gencode(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000951 insn * ins, const char *codes, int32_t insn_end)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000952{
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000953 static char condval[] = { /* conditional opcodes */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000954 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
955 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
956 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000957 };
Keith Kaniosb7a89542007-04-12 02:40:54 +0000958 uint8_t c;
959 uint8_t bytes[4];
960 int32_t size;
961 int64_t data;
962
H. Peter Anvineba20a72002-04-30 20:53:55 +0000963 while (*codes)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000964 switch (c = *codes++) {
965 case 01:
966 case 02:
967 case 03:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000968 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +0000969 out(offset, segment, codes, OUT_RAWDATA + c, NO_SEG, NO_SEG);
970 codes += c;
971 offset += c;
972 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000973
H. Peter Anvine2c80182005-01-15 22:15:51 +0000974 case 04:
975 case 06:
976 switch (ins->oprs[0].basereg) {
977 case R_CS:
978 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0);
979 break;
980 case R_DS:
981 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0);
982 break;
983 case R_ES:
984 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0);
985 break;
986 case R_SS:
987 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0);
988 break;
989 default:
990 errfunc(ERR_PANIC,
991 "bizarre 8086 segment register received");
992 }
993 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
994 offset++;
995 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000996
H. Peter Anvine2c80182005-01-15 22:15:51 +0000997 case 05:
998 case 07:
999 switch (ins->oprs[0].basereg) {
1000 case R_FS:
1001 bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0);
1002 break;
1003 case R_GS:
1004 bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0);
1005 break;
1006 default:
1007 errfunc(ERR_PANIC,
1008 "bizarre 386 segment register received");
1009 }
1010 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1011 offset++;
1012 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001013
H. Peter Anvine2c80182005-01-15 22:15:51 +00001014 case 010:
1015 case 011:
1016 case 012:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001017 EMIT_REX();
Keith Kaniosb7a89542007-04-12 02:40:54 +00001018 bytes[0] = *codes++ + ((regval(&ins->oprs[c - 010])) & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001019 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1020 offset += 1;
1021 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001022
H. Peter Anvine2c80182005-01-15 22:15:51 +00001023 case 017:
1024 bytes[0] = 0;
1025 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1026 offset += 1;
1027 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001028
H. Peter Anvine2c80182005-01-15 22:15:51 +00001029 case 014:
1030 case 015:
1031 case 016:
1032 if (ins->oprs[c - 014].offset < -128
1033 || ins->oprs[c - 014].offset > 127) {
1034 errfunc(ERR_WARNING, "signed byte value exceeds bounds");
1035 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001036
H. Peter Anvine2c80182005-01-15 22:15:51 +00001037 if (ins->oprs[c - 014].segment != NO_SEG) {
1038 data = ins->oprs[c - 014].offset;
1039 out(offset, segment, &data, OUT_ADDRESS + 1,
1040 ins->oprs[c - 014].segment, ins->oprs[c - 014].wrt);
1041 } else {
1042 bytes[0] = ins->oprs[c - 014].offset;
1043 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1044 NO_SEG);
1045 }
1046 offset += 1;
1047 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001048
H. Peter Anvine2c80182005-01-15 22:15:51 +00001049 case 020:
1050 case 021:
1051 case 022:
1052 if (ins->oprs[c - 020].offset < -256
1053 || ins->oprs[c - 020].offset > 255) {
1054 errfunc(ERR_WARNING, "byte value exceeds bounds");
1055 }
1056 if (ins->oprs[c - 020].segment != NO_SEG) {
1057 data = ins->oprs[c - 020].offset;
1058 out(offset, segment, &data, OUT_ADDRESS + 1,
1059 ins->oprs[c - 020].segment, ins->oprs[c - 020].wrt);
1060 } else {
1061 bytes[0] = ins->oprs[c - 020].offset;
1062 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1063 NO_SEG);
1064 }
1065 offset += 1;
1066 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001067
H. Peter Anvine2c80182005-01-15 22:15:51 +00001068 case 024:
1069 case 025:
1070 case 026:
1071 if (ins->oprs[c - 024].offset < 0
1072 || ins->oprs[c - 024].offset > 255)
1073 errfunc(ERR_WARNING, "unsigned byte value exceeds bounds");
1074 if (ins->oprs[c - 024].segment != NO_SEG) {
1075 data = ins->oprs[c - 024].offset;
1076 out(offset, segment, &data, OUT_ADDRESS + 1,
1077 ins->oprs[c - 024].segment, ins->oprs[c - 024].wrt);
1078 } else {
1079 bytes[0] = ins->oprs[c - 024].offset;
1080 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1081 NO_SEG);
1082 }
1083 offset += 1;
1084 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001085
H. Peter Anvine2c80182005-01-15 22:15:51 +00001086 case 030:
1087 case 031:
1088 case 032:
1089 if (ins->oprs[c - 030].segment == NO_SEG &&
1090 ins->oprs[c - 030].wrt == NO_SEG &&
1091 (ins->oprs[c - 030].offset < -65536L ||
1092 ins->oprs[c - 030].offset > 65535L)) {
1093 errfunc(ERR_WARNING, "word value exceeds bounds");
1094 }
1095 data = ins->oprs[c - 030].offset;
1096 out(offset, segment, &data, OUT_ADDRESS + 2,
1097 ins->oprs[c - 030].segment, ins->oprs[c - 030].wrt);
1098 offset += 2;
1099 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001100
H. Peter Anvine2c80182005-01-15 22:15:51 +00001101 case 034:
1102 case 035:
1103 case 036:
1104 if (ins->oprs[c - 034].type & (BITS16 | BITS32))
1105 size = (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
1106 else
1107 size = (bits == 16) ? 2 : 4;
1108 data = ins->oprs[c - 034].offset;
1109 if (size == 2 && (data < -65536L || data > 65535L))
1110 errfunc(ERR_WARNING, "word value exceeds bounds");
1111 out(offset, segment, &data, OUT_ADDRESS + size,
1112 ins->oprs[c - 034].segment, ins->oprs[c - 034].wrt);
1113 offset += size;
1114 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001115
H. Peter Anvine2c80182005-01-15 22:15:51 +00001116 case 037:
1117 if (ins->oprs[0].segment == NO_SEG)
1118 errfunc(ERR_NONFATAL, "value referenced by FAR is not"
1119 " relocatable");
1120 data = 0L;
1121 out(offset, segment, &data, OUT_ADDRESS + 2,
1122 outfmt->segbase(1 + ins->oprs[0].segment),
1123 ins->oprs[0].wrt);
1124 offset += 2;
1125 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001126
H. Peter Anvine2c80182005-01-15 22:15:51 +00001127 case 040:
1128 case 041:
1129 case 042:
1130 data = ins->oprs[c - 040].offset;
1131 out(offset, segment, &data, OUT_ADDRESS + 4,
1132 ins->oprs[c - 040].segment, ins->oprs[c - 040].wrt);
1133 offset += 4;
1134 break;
H. Peter Anvin3ba46772002-05-27 23:19:35 +00001135
H. Peter Anvine2c80182005-01-15 22:15:51 +00001136 case 044:
1137 case 045:
1138 case 046:
1139 data = ins->oprs[c - 044].offset;
1140 size = ((ins->oprs[c - 044].addr_size ?
Keith Kaniosb7a89542007-04-12 02:40:54 +00001141 ins->oprs[c - 044].addr_size : bits) >> 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001142 if (size == 2 && (data < -65536L || data > 65535L))
1143 errfunc(ERR_WARNING, "word value exceeds bounds");
1144 out(offset, segment, &data, OUT_ADDRESS + size,
1145 ins->oprs[c - 044].segment, ins->oprs[c - 044].wrt);
1146 offset += size;
1147 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001148
H. Peter Anvine2c80182005-01-15 22:15:51 +00001149 case 050:
1150 case 051:
1151 case 052:
1152 if (ins->oprs[c - 050].segment != segment)
1153 errfunc(ERR_NONFATAL,
1154 "short relative jump outside segment");
1155 data = ins->oprs[c - 050].offset - insn_end;
1156 if (data > 127 || data < -128)
1157 errfunc(ERR_NONFATAL, "short jump is out of range");
1158 bytes[0] = data;
1159 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1160 offset += 1;
1161 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001162
1163 case 054:
1164 case 055:
1165 case 056:
1166 data = (int64_t)ins->oprs[c - 054].offset;
1167 out(offset, segment, &data, OUT_ADDRESS + 8,
1168 ins->oprs[c - 054].segment, ins->oprs[c - 054].wrt);
1169 offset += 8;
1170 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001171
H. Peter Anvine2c80182005-01-15 22:15:51 +00001172 case 060:
1173 case 061:
1174 case 062:
1175 if (ins->oprs[c - 060].segment != segment) {
1176 data = ins->oprs[c - 060].offset;
1177 out(offset, segment, &data,
1178 OUT_REL2ADR + insn_end - offset,
1179 ins->oprs[c - 060].segment, ins->oprs[c - 060].wrt);
1180 } else {
1181 data = ins->oprs[c - 060].offset - insn_end;
1182 out(offset, segment, &data,
1183 OUT_ADDRESS + 2, NO_SEG, NO_SEG);
1184 }
1185 offset += 2;
1186 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001187
H. Peter Anvine2c80182005-01-15 22:15:51 +00001188 case 064:
1189 case 065:
1190 case 066:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001191 if (ins->oprs[c - 064].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001192 size = (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
1193 else
1194 size = (bits == 16) ? 2 : 4;
1195 if (ins->oprs[c - 064].segment != segment) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001196 int32_t reltype = (size == 2 ? OUT_REL2ADR : OUT_REL4ADR);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001197 data = ins->oprs[c - 064].offset;
1198 out(offset, segment, &data, reltype + insn_end - offset,
1199 ins->oprs[c - 064].segment, ins->oprs[c - 064].wrt);
1200 } else {
1201 data = ins->oprs[c - 064].offset - insn_end;
1202 out(offset, segment, &data,
1203 OUT_ADDRESS + size, NO_SEG, NO_SEG);
1204 }
1205 offset += size;
1206 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001207
H. Peter Anvine2c80182005-01-15 22:15:51 +00001208 case 070:
1209 case 071:
1210 case 072:
1211 if (ins->oprs[c - 070].segment != segment) {
1212 data = ins->oprs[c - 070].offset;
1213 out(offset, segment, &data,
1214 OUT_REL4ADR + insn_end - offset,
1215 ins->oprs[c - 070].segment, ins->oprs[c - 070].wrt);
1216 } else {
1217 data = ins->oprs[c - 070].offset - insn_end;
1218 out(offset, segment, &data,
1219 OUT_ADDRESS + 4, NO_SEG, NO_SEG);
1220 }
1221 offset += 4;
1222 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001223
H. Peter Anvine2c80182005-01-15 22:15:51 +00001224 case 0130:
1225 case 0131:
1226 case 0132:
1227 data = ins->oprs[c - 0130].offset;
1228 if (is_sbyte(ins, c - 0130, 16)) {
1229 bytes[0] = data;
1230 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1231 NO_SEG);
1232 offset++;
1233 } else {
1234 if (ins->oprs[c - 0130].segment == NO_SEG &&
1235 ins->oprs[c - 0130].wrt == NO_SEG &&
1236 (data < -65536L || data > 65535L)) {
1237 errfunc(ERR_WARNING, "word value exceeds bounds");
1238 }
1239 out(offset, segment, &data, OUT_ADDRESS + 2,
1240 ins->oprs[c - 0130].segment, ins->oprs[c - 0130].wrt);
1241 offset += 2;
1242 }
1243 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001244
H. Peter Anvine2c80182005-01-15 22:15:51 +00001245 case 0133:
1246 case 0134:
1247 case 0135:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001248 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001249 codes++;
1250 bytes[0] = *codes++;
1251 if (is_sbyte(ins, c - 0133, 16))
1252 bytes[0] |= 2; /* s-bit */
1253 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1254 offset++;
1255 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001256
H. Peter Anvine2c80182005-01-15 22:15:51 +00001257 case 0140:
1258 case 0141:
1259 case 0142:
1260 data = ins->oprs[c - 0140].offset;
1261 if (is_sbyte(ins, c - 0140, 32)) {
1262 bytes[0] = data;
1263 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1264 NO_SEG);
1265 offset++;
1266 } else {
1267 out(offset, segment, &data, OUT_ADDRESS + 4,
1268 ins->oprs[c - 0140].segment, ins->oprs[c - 0140].wrt);
1269 offset += 4;
1270 }
1271 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001272
H. Peter Anvine2c80182005-01-15 22:15:51 +00001273 case 0143:
1274 case 0144:
1275 case 0145:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001276 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001277 codes++;
1278 bytes[0] = *codes++;
1279 if (is_sbyte(ins, c - 0143, 32))
1280 bytes[0] |= 2; /* s-bit */
1281 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1282 offset++;
1283 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001284
H. Peter Anvine2c80182005-01-15 22:15:51 +00001285 case 0300:
1286 case 0301:
1287 case 0302:
1288 if (chsize(&ins->oprs[c - 0300], bits)) {
1289 *bytes = 0x67;
1290 out(offset, segment, bytes,
1291 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1292 offset += 1;
1293 } else
1294 offset += 0;
1295 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001296
H. Peter Anvine2c80182005-01-15 22:15:51 +00001297 case 0310:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001298 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001299 *bytes = 0x67;
1300 out(offset, segment, bytes,
1301 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1302 offset += 1;
1303 } else
1304 offset += 0;
1305 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001306
H. Peter Anvine2c80182005-01-15 22:15:51 +00001307 case 0311:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001308 if (bits != 32) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001309 *bytes = 0x67;
1310 out(offset, segment, bytes,
1311 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1312 offset += 1;
1313 } else
1314 offset += 0;
1315 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001316
H. Peter Anvine2c80182005-01-15 22:15:51 +00001317 case 0312:
1318 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001319
Keith Kaniosb7a89542007-04-12 02:40:54 +00001320 case 0313:
1321 ins->rex = 0;
1322 break;
1323
H. Peter Anvine2c80182005-01-15 22:15:51 +00001324 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001325 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001326 *bytes = 0x66;
1327 out(offset, segment, bytes,
1328 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1329 offset += 1;
1330 } else
1331 offset += 0;
1332 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001333
H. Peter Anvine2c80182005-01-15 22:15:51 +00001334 case 0321:
1335 if (bits == 16) {
1336 *bytes = 0x66;
1337 out(offset, segment, bytes,
1338 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1339 offset += 1;
1340 } else
1341 offset += 0;
1342 break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001343
H. Peter Anvine2c80182005-01-15 22:15:51 +00001344 case 0322:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001345 case 0323:
1346 break;
1347
1348 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001349 ins->rex |= REX_W;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001350 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001351
H. Peter Anvine2c80182005-01-15 22:15:51 +00001352 case 0330:
1353 *bytes = *codes++ ^ condval[ins->condition];
1354 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1355 offset += 1;
1356 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001357
H. Peter Anvine2c80182005-01-15 22:15:51 +00001358 case 0331:
1359 case 0332:
1360 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001361
H. Peter Anvine2c80182005-01-15 22:15:51 +00001362 case 0333:
1363 *bytes = 0xF3;
1364 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1365 offset += 1;
1366 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001367
Keith Kanios48af1772007-08-17 07:37:52 +00001368 case 0334:
1369 if (ins->rex & REX_R) {
1370 *bytes = 0xF0;
1371 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1372 offset += 1;
1373 }
1374 ins->rex &= ~(REX_L|REX_R);
1375 break;
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001376
H. Peter Anvine2c80182005-01-15 22:15:51 +00001377 case 0340:
1378 case 0341:
1379 case 0342:
1380 if (ins->oprs[0].segment != NO_SEG)
1381 errfunc(ERR_PANIC, "non-constant BSS size in pass two");
1382 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001383 int32_t size = ins->oprs[0].offset << (c - 0340);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001384 if (size > 0)
1385 out(offset, segment, NULL,
1386 OUT_RESERVE + size, NO_SEG, NO_SEG);
1387 offset += size;
1388 }
1389 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001390
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001391 case 0364:
1392 case 0365:
1393 break;
1394
Keith Kanios48af1772007-08-17 07:37:52 +00001395 case 0366:
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001396 case 0367:
1397 *bytes = c - 0366 + 0x66;
Keith Kanios48af1772007-08-17 07:37:52 +00001398 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1399 offset += 1;
1400 break;
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001401
H. Peter Anvine2c80182005-01-15 22:15:51 +00001402 case 0370:
1403 case 0371:
1404 case 0372:
1405 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001406
H. Peter Anvine2c80182005-01-15 22:15:51 +00001407 case 0373:
1408 *bytes = bits == 16 ? 3 : 5;
1409 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1410 offset += 1;
1411 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001412
H. Peter Anvine2c80182005-01-15 22:15:51 +00001413 default: /* can't do it by 'case' statements */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001414 if (c >= 0100 && c <= 0277) { /* it's an EA */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001415 ea ea_data;
1416 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001417 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001418 uint8_t *p;
1419 int32_t s;
1420
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001421 if (c <= 0177) {
1422 /* pick rfield from operand b */
1423 rflags = regflag(&ins->oprs[c & 7]);
1424 rfield = regvals[ins->oprs[c & 7].basereg];
1425 } else {
1426 /* rfield is constant */
1427 rflags = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001428 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001429 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001430
1431 if (!process_ea
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001432 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
1433 rfield, rflags, ins->forw_ref)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001434 errfunc(ERR_NONFATAL, "invalid effective address");
1435 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001436
H. Peter Anvine2c80182005-01-15 22:15:51 +00001437 p = bytes;
1438 *p++ = ea_data.modrm;
1439 if (ea_data.sib_present)
1440 *p++ = ea_data.sib;
1441
1442 s = p - bytes;
1443 out(offset, segment, bytes, OUT_RAWDATA + s,
1444 NO_SEG, NO_SEG);
1445
1446 switch (ea_data.bytes) {
1447 case 0:
1448 break;
1449 case 1:
1450 if (ins->oprs[(c >> 3) & 7].segment != NO_SEG) {
1451 data = ins->oprs[(c >> 3) & 7].offset;
1452 out(offset, segment, &data, OUT_ADDRESS + 1,
1453 ins->oprs[(c >> 3) & 7].segment,
1454 ins->oprs[(c >> 3) & 7].wrt);
1455 } else {
1456 *bytes = ins->oprs[(c >> 3) & 7].offset;
1457 out(offset, segment, bytes, OUT_RAWDATA + 1,
1458 NO_SEG, NO_SEG);
1459 }
1460 s++;
1461 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001462 case 8:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001463 case 2:
1464 case 4:
1465 data = ins->oprs[(c >> 3) & 7].offset;
Keith Kaniose83b3182007-04-16 14:31:54 +00001466 if (ea_data.rip && (ins->oprs[(c >> 3) & 7].segment == 0xFFFFFFFF))
1467 ea_data.rip = 0; /* Make distinction between Symbols and Immediates */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001468 out(offset, segment, &data, /* RIP = Relative, not Absolute */
1469 (ea_data.rip ? OUT_REL4ADR : OUT_ADDRESS) + ea_data.bytes,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001470 ins->oprs[(c >> 3) & 7].segment,
1471 ins->oprs[(c >> 3) & 7].wrt);
1472 s += ea_data.bytes;
1473 break;
1474 }
1475 offset += s;
1476 } else
1477 errfunc(ERR_PANIC, "internal instruction table corrupt"
1478 ": instruction code 0x%02X given", c);
1479 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001480}
1481
H. Peter Anvin0ec60e62007-07-07 01:59:52 +00001482static int32_t regflag(const operand * o)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001483{
1484 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1485 errfunc(ERR_PANIC, "invalid operand passed to regflag()");
1486 }
1487 return reg_flags[o->basereg];
1488}
1489
H. Peter Anvin5b0e3ec2007-07-07 02:01:08 +00001490static int32_t regval(const operand * o)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001491{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001492 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1493 errfunc(ERR_PANIC, "invalid operand passed to regval()");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001494 }
H. Peter Anvin232badb2002-06-06 02:41:20 +00001495 return regvals[o->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001496}
1497
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001498static int op_rexflags(const operand * o, int mask)
1499{
1500 int32_t flags;
1501 int val;
1502
1503 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1504 errfunc(ERR_PANIC, "invalid operand passed to op_rexflags()");
1505 }
1506
1507 flags = reg_flags[o->basereg];
1508 val = regvals[o->basereg];
1509
1510 return rexflags(val, flags, mask);
1511}
1512
1513static int rexflags(int val, int32_t flags, int mask)
1514{
1515 int rex = 0;
1516
1517 if (val >= 8)
1518 rex |= REX_B|REX_X|REX_R;
1519 if (flags & BITS64)
1520 rex |= REX_W;
1521 if (!(REG_HIGH & ~flags)) /* AH, CH, DH, BH */
1522 rex |= REX_H;
1523 else if (!(REG8 & ~flags) && val >= 4) /* SPL, BPL, SIL, DIL */
1524 rex |= REX_P;
1525
1526 return rex & mask;
1527}
1528
H. Peter Anvin3360d792007-09-11 04:16:57 +00001529static int matches(const struct itemplate *itemp, insn * instruction, int bits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001530{
H. Peter Anvin34539fb2007-05-30 04:27:58 +00001531 int i, size[3], asize, oprs, ret;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001532
1533 ret = 100;
1534
1535 /*
1536 * Check the opcode
1537 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001538 if (itemp->opcode != instruction->opcode)
1539 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001540
1541 /*
1542 * Count the operands
1543 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001544 if (itemp->operands != instruction->operands)
1545 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001546
1547 /*
1548 * Check that no spurious colons or TOs are present
1549 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001550 for (i = 0; i < itemp->operands; i++)
1551 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON | TO))
1552 return 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001553
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001554 /*
1555 * Check that the operand flags all match up
1556 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001557 for (i = 0; i < itemp->operands; i++)
1558 if (itemp->opd[i] & ~instruction->oprs[i].type ||
1559 ((itemp->opd[i] & SIZE_MASK) &&
1560 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK))) {
H. Peter Anvin5a640e12007-05-29 23:57:12 +00001561 if ((itemp->opd[i] & ~instruction->oprs[i].type & ~SIZE_MASK) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001562 (instruction->oprs[i].type & SIZE_MASK))
1563 return 0;
1564 else
H. Peter Anvine2c80182005-01-15 22:15:51 +00001565 return 1;
1566 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001567
1568 /*
1569 * Check operand sizes
1570 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001571 if (itemp->flags & IF_ARMASK) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001572 size[0] = size[1] = size[2] = 0;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001573
H. Peter Anvine2c80182005-01-15 22:15:51 +00001574 switch (itemp->flags & IF_ARMASK) {
1575 case IF_AR0:
1576 i = 0;
1577 break;
1578 case IF_AR1:
1579 i = 1;
1580 break;
1581 case IF_AR2:
1582 i = 2;
1583 break;
1584 default:
1585 break; /* Shouldn't happen */
1586 }
1587 if (itemp->flags & IF_SB) {
1588 size[i] = BITS8;
1589 } else if (itemp->flags & IF_SW) {
1590 size[i] = BITS16;
1591 } else if (itemp->flags & IF_SD) {
1592 size[i] = BITS32;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001593 } else if (itemp->flags & IF_SQ) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001594 size[i] = BITS64;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001595 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001596 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001597 asize = 0;
1598 if (itemp->flags & IF_SB) {
1599 asize = BITS8;
1600 oprs = itemp->operands;
1601 } else if (itemp->flags & IF_SW) {
1602 asize = BITS16;
1603 oprs = itemp->operands;
1604 } else if (itemp->flags & IF_SD) {
1605 asize = BITS32;
1606 oprs = itemp->operands;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001607 } else if (itemp->flags & IF_SQ) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001608 asize = BITS64;
1609 oprs = itemp->operands;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001610 }
1611 size[0] = size[1] = size[2] = asize;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001612 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001613
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001614 if (itemp->flags & (IF_SM | IF_SM2)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001615 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
1616 asize = 0;
1617 for (i = 0; i < oprs; i++) {
1618 if ((asize = itemp->opd[i] & SIZE_MASK) != 0) {
1619 int j;
1620 for (j = 0; j < oprs; j++)
1621 size[j] = asize;
1622 break;
1623 }
1624 }
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001625 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001626 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001627 }
1628
Keith Kaniosb7a89542007-04-12 02:40:54 +00001629 for (i = 0; i < itemp->operands; i++) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001630 if (!(itemp->opd[i] & SIZE_MASK) &&
1631 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001632 return 2;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001633 }
1634
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001635 /*
1636 * Check template is okay at the set cpu level
1637 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001638 if (((itemp->flags & IF_PLEVEL) > cpu))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001639 return 3;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001640
1641 /*
1642 * Check if instruction is available in long mode
1643 */
1644 if ((itemp->flags & IF_NOLONG) && (bits == 64))
1645 return 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001646
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001647 /*
1648 * Check if special handling needed for Jumps
1649 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001650 if ((uint8_t)(itemp->code[0]) >= 0370)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001651 return 99;
1652
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001653 return ret;
1654}
1655
H. Peter Anvine2c80182005-01-15 22:15:51 +00001656static ea *process_ea(operand * input, ea * output, int addrbits,
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001657 int rfield, int32_t rflags, int forw_ref)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001658{
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001659 output->rip = FALSE;
1660
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001661 /* REX flags for the rfield operand */
1662 output->rex |= rexflags(rfield, rflags, REX_R|REX_P|REX_W|REX_H);
1663
Keith Kaniosb7a89542007-04-12 02:40:54 +00001664 if (!(REGISTER & ~input->type)) { /* register direct */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001665 int i;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001666 int32_t f;
1667
1668 if (input->basereg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001669 || input->basereg >= REG_ENUM_LIMIT)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001670 return NULL;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001671 f = regflag(input);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001672 i = regvals[input->basereg];
Keith Kaniosb7a89542007-04-12 02:40:54 +00001673
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001674 if (REG_EA & ~f)
1675 return NULL; /* Invalid EA register */
1676
1677 output->rex |= op_rexflags(input, REX_B|REX_P|REX_W|REX_H);
1678
Keith Kaniosb7a89542007-04-12 02:40:54 +00001679 output->sib_present = FALSE; /* no SIB necessary */
1680 output->bytes = 0; /* no offset necessary either */
1681 output->modrm = 0xC0 | ((rfield & 7) << 3) | (i & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001682 } else { /* it's a memory reference */
1683 if (input->basereg == -1
1684 && (input->indexreg == -1 || input->scale == 0)) {
1685 /* it's a pure offset */
1686 if (input->addr_size)
1687 addrbits = input->addr_size;
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001688
1689 if (globalbits == 64 && (~input->type & IP_REL)) {
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00001690 int scale, index, base;
1691 output->sib_present = TRUE;
1692 scale = 0;
1693 index = 4;
1694 base = 5;
1695 output->sib = (scale << 6) | (index << 3) | base;
1696 output->bytes = 4;
1697 output->modrm = 4 | ((rfield & 7) << 3);
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001698 output->rip = FALSE;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00001699 } else {
1700 output->sib_present = FALSE;
1701 output->bytes = (addrbits != 16 ? 4 : 2);
1702 output->modrm = (addrbits != 16 ? 5 : 6) | ((rfield & 7) << 3);
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001703 output->rip = globalbits == 64;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00001704 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001705 } else { /* it's an indirection */
1706 int i = input->indexreg, b = input->basereg, s = input->scale;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001707 int32_t o = input->offset, seg = input->segment;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001708 int hb = input->hintbase, ht = input->hinttype;
1709 int t;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001710 int it, bt;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001711 int32_t ix, bx; /* register flags */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001712
H. Peter Anvine2c80182005-01-15 22:15:51 +00001713 if (s == 0)
1714 i = -1; /* make this easy, at least */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001715
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001716 if (i >= EXPR_REG_START && i < REG_ENUM_LIMIT) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001717 it = regvals[i];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001718 ix = reg_flags[i];
1719 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001720 it = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001721 ix = 0;
1722 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001723
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001724 if (b != -1 && b >= EXPR_REG_START && b < REG_ENUM_LIMIT) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001725 bt = regvals[b];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001726 bx = reg_flags[b];
1727 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001728 bt = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001729 bx = 0;
1730 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001731
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001732 /* check for a 32/64-bit memory reference... */
1733 if ((ix|bx) & (BITS32|BITS64)) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001734 /* it must be a 32/64-bit memory reference. Firstly we have
1735 * to check that all registers involved are type E/Rxx. */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001736 int32_t sok = BITS32|BITS64;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001737
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001738 if (it != -1) {
1739 if (!(REG64 & ~ix) || !(REG32 & ~ix))
1740 sok &= ix;
1741 else
1742 return NULL;
1743 }
1744
1745 if (bt != -1) {
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001746 if (REG_GPR & ~bx)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001747 return NULL; /* Invalid register */
H. Peter Anvina57e8d42007-05-30 03:44:02 +00001748 if (~sok & bx & SIZE_MASK)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001749 return NULL; /* Invalid size */
1750 sok &= ~bx;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001751 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001752
H. Peter Anvine2c80182005-01-15 22:15:51 +00001753 /* While we're here, ensure the user didn't specify WORD. */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001754 if (input->addr_size == 16 ||
1755 (input->addr_size == 32 && !(sok & BITS32)) ||
1756 (input->addr_size == 64 && !(sok & BITS64)))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001757 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001758
Keith Kaniosb7a89542007-04-12 02:40:54 +00001759 /* now reorganize base/index */
1760 if (s == 1 && bt != it && bt != -1 && it != -1 &&
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001761 ((hb == b && ht == EAH_NOTBASE)
1762 || (hb == i && ht == EAH_MAKEBASE))) {
1763 /* swap if hints say so */
1764 t = bt, bt = it, it = t;
1765 t = bx, bx = ix, ix = t;
1766 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001767 if (bt == it) /* convert EAX+2*EAX to 3*EAX */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001768 bt = -1, bx = 0, s++;
1769 if (bt == -1 && s == 1 && !(hb == it && ht == EAH_NOTBASE)) {
1770 /* make single reg base, unless hint */
1771 bt = it, bx = ix, it = -1, ix = 0;
1772 }
H. Peter Anvinf5843c62007-09-10 18:59:26 +00001773 if (((s == 2 && it != REG_NUM_ESP
H. Peter Anvine2c80182005-01-15 22:15:51 +00001774 && !(input->eaflags & EAF_TIMESTWO)) || s == 3
Keith Kaniosb7a89542007-04-12 02:40:54 +00001775 || s == 5 || s == 9) && bt == -1)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001776 bt = it, bx = ix, s--; /* convert 3*EAX to EAX+2*EAX */
Keith Kanios48af1772007-08-17 07:37:52 +00001777 if (it == -1 && (bt & 7) != REG_NUM_ESP
H. Peter Anvine2c80182005-01-15 22:15:51 +00001778 && (input->eaflags & EAF_TIMESTWO))
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001779 it = bt, ix = bx, bt = -1, bx = 0, s = 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001780 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
Keith Kanios48af1772007-08-17 07:37:52 +00001781 if (s == 1 && it == REG_NUM_ESP) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001782 /* swap ESP into base if scale is 1 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001783 t = it, it = bt, bt = t;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001784 t = ix, ix = bx, bx = t;
1785 }
Keith Kanios48af1772007-08-17 07:37:52 +00001786 if (it == REG_NUM_ESP
Keith Kaniosb7a89542007-04-12 02:40:54 +00001787 || (s != 1 && s != 2 && s != 4 && s != 8 && it != -1))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001788 return NULL; /* wrong, for various reasons */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001789
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001790 output->rex |= rexflags(it, ix, REX_X);
1791 output->rex |= rexflags(bt, bx, REX_B);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001792
Keith Kanios48af1772007-08-17 07:37:52 +00001793 if (it == -1 && (bt & 7) != REG_NUM_ESP) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001794 /* no SIB needed */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001795 int mod, rm;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001796
1797 if (bt == -1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001798 rm = 5;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001799 mod = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001800 } else {
1801 rm = (bt & 7);
Keith Kanios48af1772007-08-17 07:37:52 +00001802 if (rm != REG_NUM_EBP && o == 0 &&
Keith Kaniosb7a89542007-04-12 02:40:54 +00001803 seg == NO_SEG && !forw_ref &&
1804 !(input->eaflags &
1805 (EAF_BYTEOFFS | EAF_WORDOFFS)))
1806 mod = 0;
1807 else if (input->eaflags & EAF_BYTEOFFS ||
1808 (o >= -128 && o <= 127 && seg == NO_SEG
1809 && !forw_ref
1810 && !(input->eaflags & EAF_WORDOFFS)))
1811 mod = 1;
1812 else
1813 mod = 2;
1814 }
H. Peter Anvinea838272002-04-30 20:51:53 +00001815
H. Peter Anvine2c80182005-01-15 22:15:51 +00001816 output->sib_present = FALSE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001817 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
1818 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001819 } else {
1820 /* we need a SIB */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001821 int mod, scale, index, base;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001822
1823 if (it == -1)
1824 index = 4, s = 1;
1825 else
1826 index = (it & 7);
1827
H. Peter Anvine2c80182005-01-15 22:15:51 +00001828 switch (s) {
1829 case 1:
1830 scale = 0;
1831 break;
1832 case 2:
1833 scale = 1;
1834 break;
1835 case 4:
1836 scale = 2;
1837 break;
1838 case 8:
1839 scale = 3;
1840 break;
1841 default: /* then what the smeg is it? */
1842 return NULL; /* panic */
1843 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001844
1845 if (bt == -1) {
1846 base = 5;
1847 mod = 0;
1848 } else {
1849 base = (bt & 7);
Keith Kanios48af1772007-08-17 07:37:52 +00001850 if (base != REG_NUM_EBP && o == 0 &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00001851 seg == NO_SEG && !forw_ref &&
1852 !(input->eaflags &
Keith Kaniosb7a89542007-04-12 02:40:54 +00001853 (EAF_BYTEOFFS | EAF_WORDOFFS)))
1854 mod = 0;
1855 else if (input->eaflags & EAF_BYTEOFFS ||
1856 (o >= -128 && o <= 127 && seg == NO_SEG
1857 && !forw_ref
1858 && !(input->eaflags & EAF_WORDOFFS)))
1859 mod = 1;
1860 else
1861 mod = 2;
1862 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001863
H. Peter Anvine2c80182005-01-15 22:15:51 +00001864 output->sib_present = TRUE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001865 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
1866 output->modrm = (mod << 6) | ((rfield & 7) << 3) | 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001867 output->sib = (scale << 6) | (index << 3) | base;
1868 }
1869 } else { /* it's 16-bit */
1870 int mod, rm;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001871
1872 /* check for 64-bit long mode */
1873 if (addrbits == 64)
1874 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001875
H. Peter Anvine2c80182005-01-15 22:15:51 +00001876 /* check all registers are BX, BP, SI or DI */
1877 if ((b != -1 && b != R_BP && b != R_BX && b != R_SI
1878 && b != R_DI) || (i != -1 && i != R_BP && i != R_BX
1879 && i != R_SI && i != R_DI))
1880 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001881
Keith Kaniosb7a89542007-04-12 02:40:54 +00001882 /* ensure the user didn't specify DWORD/QWORD */
1883 if (input->addr_size == 32 || input->addr_size == 64)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001884 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001885
H. Peter Anvine2c80182005-01-15 22:15:51 +00001886 if (s != 1 && i != -1)
1887 return NULL; /* no can do, in 16-bit EA */
1888 if (b == -1 && i != -1) {
1889 int tmp = b;
1890 b = i;
1891 i = tmp;
1892 } /* swap */
1893 if ((b == R_SI || b == R_DI) && i != -1) {
1894 int tmp = b;
1895 b = i;
1896 i = tmp;
1897 }
1898 /* have BX/BP as base, SI/DI index */
1899 if (b == i)
1900 return NULL; /* shouldn't ever happen, in theory */
1901 if (i != -1 && b != -1 &&
1902 (i == R_BP || i == R_BX || b == R_SI || b == R_DI))
1903 return NULL; /* invalid combinations */
1904 if (b == -1) /* pure offset: handled above */
1905 return NULL; /* so if it gets to here, panic! */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001906
H. Peter Anvine2c80182005-01-15 22:15:51 +00001907 rm = -1;
1908 if (i != -1)
1909 switch (i * 256 + b) {
1910 case R_SI * 256 + R_BX:
1911 rm = 0;
1912 break;
1913 case R_DI * 256 + R_BX:
1914 rm = 1;
1915 break;
1916 case R_SI * 256 + R_BP:
1917 rm = 2;
1918 break;
1919 case R_DI * 256 + R_BP:
1920 rm = 3;
1921 break;
1922 } else
1923 switch (b) {
1924 case R_SI:
1925 rm = 4;
1926 break;
1927 case R_DI:
1928 rm = 5;
1929 break;
1930 case R_BP:
1931 rm = 6;
1932 break;
1933 case R_BX:
1934 rm = 7;
1935 break;
1936 }
1937 if (rm == -1) /* can't happen, in theory */
1938 return NULL; /* so panic if it does */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001939
H. Peter Anvine2c80182005-01-15 22:15:51 +00001940 if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
1941 !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
1942 mod = 0;
1943 else if (input->eaflags & EAF_BYTEOFFS ||
1944 (o >= -128 && o <= 127 && seg == NO_SEG
1945 && !forw_ref
1946 && !(input->eaflags & EAF_WORDOFFS)))
1947 mod = 1;
1948 else
1949 mod = 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001950
H. Peter Anvine2c80182005-01-15 22:15:51 +00001951 output->sib_present = FALSE; /* no SIB - it's 16-bit */
1952 output->bytes = mod; /* bytes of offset needed */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001953 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001954 }
1955 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001956 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001957
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001958 output->size = 1 + output->sib_present + output->bytes;
1959 return output;
1960}
1961
H. Peter Anvine2c80182005-01-15 22:15:51 +00001962static int chsize(operand * input, int addrbits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001963{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001964 if (!(MEMORY & ~input->type)) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001965 int32_t i, b;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001966
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001967 if (input->indexreg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001968 || input->indexreg >= REG_ENUM_LIMIT)
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00001969 i = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001970 else
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001971 i = reg_flags[input->indexreg];
Keith Kaniosb7a89542007-04-12 02:40:54 +00001972
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001973 if (input->basereg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001974 || input->basereg >= REG_ENUM_LIMIT)
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00001975 b = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001976 else
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001977 b = reg_flags[input->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001978
H. Peter Anvine2c80182005-01-15 22:15:51 +00001979 if (input->scale == 0)
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00001980 i = 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001981
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00001982 if (!i && !b) /* pure offset */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001983 return (input->addr_size != 0 && input->addr_size != addrbits);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001984
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001985 if (!(REG32 & ~i) || !(REG32 & ~b))
Keith Kaniosb7a89542007-04-12 02:40:54 +00001986 return (addrbits != 32);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001987 else
1988 return (addrbits == 32);
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001989 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001990 return 0;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001991 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001992}