blob: 5452271297296e34bac346c64e389a8612a3209d [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.
H. Peter Anvincb9b6902007-09-12 21:58:51 -070067 * \332 - REP prefix (0xF2 byte) used as opcode extension.
68 * \333 - REP prefix (0xF3 byte) used as opcode extension.
Keith Kanios48af1772007-08-17 07:37:52 +000069 * \334 - LOCK prefix used instead of REX.R
H. Peter Anvincb9b6902007-09-12 21:58:51 -070070 * \335 - disassemble a rep (0xF3 byte) prefix as repe not rep.
Keith Kaniosb7a89542007-04-12 02:40:54 +000071 * \340 - reserve <operand 0> bytes of uninitialized storage.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000072 * Operand 0 had better be a segmentless constant.
H. Peter Anvin62cb6062007-09-11 22:44:03 +000073 * \364 - operand-size prefix (0x66) not permitted
74 * \365 - address-size prefix (0x67) not permitted
75 * \366 - operand-size prefix (0x66) used as opcode extension
76 * \367 - address-size prefix (0x67) used as opcode extension
H. Peter Anvin788e6c12002-04-30 21:02:01 +000077 * \370,\371,\372 - match only if operand 0 meets byte jump criteria.
78 * 370 is used for Jcc, 371 is used for JMP.
H. Peter Anvinaf535c12002-04-30 20:59:21 +000079 * \373 - assemble 0x03 if bits==16, 0x05 if bits==32;
80 * used for conditional jump over longer jump
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000081 */
82
83#include <stdio.h>
84#include <string.h>
Keith Kaniosb7a89542007-04-12 02:40:54 +000085#include <inttypes.h>
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000086
87#include "nasm.h"
H. Peter Anvin6768eb72002-04-30 20:52:26 +000088#include "nasmlib.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000089#include "assemble.h"
90#include "insns.h"
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +000091#include "preproc.h"
H. Peter Anvin3df97a72007-05-30 03:25:21 +000092#include "regflags.c"
Keith Kaniosb7a89542007-04-12 02:40:54 +000093#include "regvals.c"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000094
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000095typedef struct {
Keith Kaniosb7a89542007-04-12 02:40:54 +000096 int sib_present; /* is a SIB byte necessary? */
97 int bytes; /* # of bytes of offset needed */
98 int size; /* lazy - this is sib+bytes+1 */
99 uint8_t modrm, sib, rex, rip; /* the bytes themselves */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000100} ea;
101
Keith Kaniosb7a89542007-04-12 02:40:54 +0000102static uint32_t cpu; /* cpu level received from nasm.c */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000103static efunc errfunc;
104static struct ofmt *outfmt;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000105static ListGen *list;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000106
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000107static int32_t calcsize(int32_t, int32_t, int, insn *, const char *);
108static void gencode(int32_t, int32_t, int, insn *, const char *, int32_t);
H. Peter Anvin3360d792007-09-11 04:16:57 +0000109static int matches(const struct itemplate *, insn *, int bits);
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000110static int32_t regflag(const operand *);
111static int32_t regval(const operand *);
112static int rexflags(int, int32_t, int);
113static int op_rexflags(const operand *, int);
H. Peter Anvin5b0e3ec2007-07-07 02:01:08 +0000114static ea *process_ea(operand *, ea *, int, int, int32_t, int);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000115static int chsize(operand *, int);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000116
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000117static void assert_no_prefix(insn * ins, int prefix)
118{
119 int j;
120
121 for (j = 0; j < ins->nprefix; j++) {
122 if (ins->prefixes[j] == prefix) {
123 errfunc(ERR_NONFATAL, "invalid %s prefix", prefix_name(prefix));
124 break;
125 }
126 }
127}
128
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000129/*
130 * This routine wrappers the real output format's output routine,
131 * in order to pass a copy of the data off to the listing file
132 * generator at the same time.
133 */
Keith Kaniosb7a89542007-04-12 02:40:54 +0000134static void out(int32_t offset, int32_t segto, const void *data,
135 uint32_t type, int32_t segment, int32_t wrt)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000136{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000137 static int32_t lineno = 0; /* static!!! */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000138 static char *lnfname = NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000139
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000140 if ((type & OUT_TYPMASK) == OUT_ADDRESS) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000141 if (segment != NO_SEG || wrt != NO_SEG) {
142 /*
143 * This address is relocated. We must write it as
144 * OUT_ADDRESS, so there's no work to be done here.
145 */
146 list->output(offset, data, type);
147 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000148 uint8_t p[8], *q = p;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000149 /*
150 * This is a non-relocated address, and we're going to
151 * convert it into RAWDATA format.
152 */
153 if ((type & OUT_SIZMASK) == 4) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000154 WRITELONG(q, *(int32_t *)data);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000155 list->output(offset, p, OUT_RAWDATA + 4);
Keith Kaniosb7a89542007-04-12 02:40:54 +0000156 } else if ((type & OUT_SIZMASK) == 8) {
157 WRITEDLONG(q, *(int64_t *)data);
158 list->output(offset, p, OUT_RAWDATA + 8);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000159 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000160 WRITESHORT(q, *(int32_t *)data);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000161 list->output(offset, p, OUT_RAWDATA + 2);
162 }
163 }
164 } else if ((type & OUT_TYPMASK) == OUT_RAWDATA) {
165 list->output(offset, data, type);
166 } else if ((type & OUT_TYPMASK) == OUT_RESERVE) {
167 list->output(offset, NULL, type);
168 } else if ((type & OUT_TYPMASK) == OUT_REL2ADR ||
169 (type & OUT_TYPMASK) == OUT_REL4ADR) {
170 list->output(offset, data, type);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000171 }
172
Frank Kotlerabebb082003-09-06 04:45:37 +0000173 /*
174 * this call to src_get determines when we call the
175 * debug-format-specific "linenum" function
176 * it updates lineno and lnfname to the current values
177 * returning 0 if "same as last time", -2 if lnfname
178 * changed, and the amount by which lineno changed,
179 * if it did. thus, these variables must be static
180 */
181
H. Peter Anvine2c80182005-01-15 22:15:51 +0000182 if (src_get(&lineno, &lnfname)) {
183 outfmt->current_dfmt->linenum(lnfname, lineno, segto);
H. Peter Anvince616072002-04-30 21:02:23 +0000184 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000185
H. Peter Anvine2c80182005-01-15 22:15:51 +0000186 outfmt->output(segto, data, type, segment, wrt);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000187}
188
Keith Kaniosb7a89542007-04-12 02:40:54 +0000189static int jmp_match(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000190 insn * ins, const char *code)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000191{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000192 int32_t isize;
193 uint8_t c = code[0];
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000194
H. Peter Anvine2c80182005-01-15 22:15:51 +0000195 if (c != 0370 && c != 0371)
196 return 0;
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000197 if (ins->oprs[0].opflags & OPFLAG_FORWARD) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000198 if ((optimizing < 0 || (ins->oprs[0].type & STRICT))
199 && c == 0370)
200 return 1;
201 else
202 return (pass0 == 0); /* match a forward reference */
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000203 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000204 isize = calcsize(segment, offset, bits, ins, code);
205 if (ins->oprs[0].segment != segment)
206 return 0;
207 isize = ins->oprs[0].offset - offset - isize; /* isize is now the delta */
208 if (isize >= -128L && isize <= 127L)
209 return 1; /* it is byte size */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000210
211 return 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000212}
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000213
Keith Kaniosb7a89542007-04-12 02:40:54 +0000214int32_t assemble(int32_t segment, int32_t offset, int bits, uint32_t cp,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000215 insn * instruction, struct ofmt *output, efunc error,
216 ListGen * listgen)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000217{
H. Peter Anvin3360d792007-09-11 04:16:57 +0000218 const struct itemplate *temp;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000219 int j;
220 int size_prob;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000221 int32_t insn_end;
222 int32_t itimes;
223 int32_t start = offset;
224 int32_t wsize = 0; /* size for DB etc. */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000225
H. Peter Anvine2c80182005-01-15 22:15:51 +0000226 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000227 cpu = cp;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000228 outfmt = output; /* likewise */
229 list = listgen; /* and again */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000230
H. Peter Anvine2c80182005-01-15 22:15:51 +0000231 switch (instruction->opcode) {
232 case -1:
233 return 0;
234 case I_DB:
235 wsize = 1;
236 break;
237 case I_DW:
238 wsize = 2;
239 break;
240 case I_DD:
241 wsize = 4;
242 break;
243 case I_DQ:
244 wsize = 8;
245 break;
246 case I_DT:
247 wsize = 10;
248 break;
H. Peter Anvin16b0a332007-09-12 20:27:41 -0700249 default:
250 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000251 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000252
H. Peter Anvineba20a72002-04-30 20:53:55 +0000253 if (wsize) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000254 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000255 int32_t t = instruction->times;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000256 if (t < 0)
257 errfunc(ERR_PANIC,
258 "instruction->times < 0 (%ld) in assemble()", t);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000259
H. Peter Anvine2c80182005-01-15 22:15:51 +0000260 while (t--) { /* repeat TIMES times */
261 for (e = instruction->eops; e; e = e->next) {
262 if (e->type == EOT_DB_NUMBER) {
263 if (wsize == 1) {
264 if (e->segment != NO_SEG)
265 errfunc(ERR_NONFATAL,
266 "one-byte relocation attempted");
267 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000268 uint8_t out_byte = e->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000269 out(offset, segment, &out_byte,
270 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
271 }
Keith Kanios61ff53c2007-04-14 18:54:52 +0000272 } else if (wsize > 8) {
273 errfunc(ERR_NONFATAL, "integer supplied to a DT"
274 " instruction");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000275 } else
276 out(offset, segment, &e->offset,
277 OUT_ADDRESS + wsize, e->segment, e->wrt);
278 offset += wsize;
279 } else if (e->type == EOT_DB_STRING) {
280 int align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000281
H. Peter Anvine2c80182005-01-15 22:15:51 +0000282 out(offset, segment, e->stringval,
283 OUT_RAWDATA + e->stringlen, NO_SEG, NO_SEG);
284 align = e->stringlen % wsize;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000285
H. Peter Anvine2c80182005-01-15 22:15:51 +0000286 if (align) {
287 align = wsize - align;
288 out(offset, segment, "\0\0\0\0\0\0\0\0",
289 OUT_RAWDATA + align, NO_SEG, NO_SEG);
290 }
291 offset += e->stringlen + align;
292 }
293 }
294 if (t > 0 && t == instruction->times - 1) {
295 /*
296 * Dummy call to list->output to give the offset to the
297 * listing module.
298 */
299 list->output(offset, NULL, OUT_RAWDATA);
300 list->uplevel(LIST_TIMES);
301 }
302 }
303 if (instruction->times > 1)
304 list->downlevel(LIST_TIMES);
305 return offset - start;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000306 }
307
H. Peter Anvine2c80182005-01-15 22:15:51 +0000308 if (instruction->opcode == I_INCBIN) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000309 static char fname[FILENAME_MAX];
H. Peter Anvine2c80182005-01-15 22:15:51 +0000310 FILE *fp;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000311 int32_t len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000312 char *prefix = "", *combine;
313 char **pPrevPath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000314
H. Peter Anvine2c80182005-01-15 22:15:51 +0000315 len = FILENAME_MAX - 1;
316 if (len > instruction->eops->stringlen)
317 len = instruction->eops->stringlen;
318 strncpy(fname, instruction->eops->stringval, len);
319 fname[len] = '\0';
H. Peter Anvineba20a72002-04-30 20:53:55 +0000320
Keith Kaniosb7a89542007-04-12 02:40:54 +0000321 while (1) { /* added by alexfru: 'incbin' uses include paths */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000322 combine = nasm_malloc(strlen(prefix) + len + 1);
323 strcpy(combine, prefix);
324 strcat(combine, fname);
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000325
H. Peter Anvine2c80182005-01-15 22:15:51 +0000326 if ((fp = fopen(combine, "rb")) != NULL) {
327 nasm_free(combine);
328 break;
329 }
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000330
H. Peter Anvine2c80182005-01-15 22:15:51 +0000331 nasm_free(combine);
332 pPrevPath = pp_get_include_path_ptr(pPrevPath);
333 if (pPrevPath == NULL)
334 break;
335 prefix = *pPrevPath;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000336 }
337
338 if (fp == NULL)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000339 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
340 fname);
341 else if (fseek(fp, 0L, SEEK_END) < 0)
342 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
343 fname);
344 else {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000345 static char buf[2048];
Keith Kaniosb7a89542007-04-12 02:40:54 +0000346 int32_t t = instruction->times;
347 int32_t base = 0;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000348
H. Peter Anvine2c80182005-01-15 22:15:51 +0000349 len = ftell(fp);
350 if (instruction->eops->next) {
351 base = instruction->eops->next->offset;
352 len -= base;
353 if (instruction->eops->next->next &&
354 len > instruction->eops->next->next->offset)
355 len = instruction->eops->next->next->offset;
356 }
357 /*
358 * Dummy call to list->output to give the offset to the
359 * listing module.
360 */
361 list->output(offset, NULL, OUT_RAWDATA);
362 list->uplevel(LIST_INCBIN);
363 while (t--) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000364 int32_t l;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000365
H. Peter Anvine2c80182005-01-15 22:15:51 +0000366 fseek(fp, base, SEEK_SET);
367 l = len;
368 while (l > 0) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000369 int32_t m =
H. Peter Anvine2c80182005-01-15 22:15:51 +0000370 fread(buf, 1, (l > sizeof(buf) ? sizeof(buf) : l),
371 fp);
372 if (!m) {
373 /*
374 * This shouldn't happen unless the file
375 * actually changes while we are reading
376 * it.
377 */
378 error(ERR_NONFATAL,
379 "`incbin': unexpected EOF while"
380 " reading file `%s'", fname);
381 t = 0; /* Try to exit cleanly */
382 break;
383 }
384 out(offset, segment, buf, OUT_RAWDATA + m,
385 NO_SEG, NO_SEG);
386 l -= m;
387 }
388 }
389 list->downlevel(LIST_INCBIN);
390 if (instruction->times > 1) {
391 /*
392 * Dummy call to list->output to give the offset to the
393 * listing module.
394 */
395 list->output(offset, NULL, OUT_RAWDATA);
396 list->uplevel(LIST_TIMES);
397 list->downlevel(LIST_TIMES);
398 }
399 fclose(fp);
400 return instruction->times * len;
401 }
402 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000403 }
404
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000405 size_prob = FALSE;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000406
407 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++){
408 int m = matches(temp, instruction, bits);
409
H. Peter Anvine2c80182005-01-15 22:15:51 +0000410 if (m == 99)
411 m += jmp_match(segment, offset, bits, instruction, temp->code);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000412
H. Peter Anvine2c80182005-01-15 22:15:51 +0000413 if (m == 100) { /* matches! */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000414 const char *codes = temp->code;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000415 int32_t insn_size = calcsize(segment, offset, bits,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000416 instruction, codes);
417 itimes = instruction->times;
418 if (insn_size < 0) /* shouldn't be, on pass two */
419 error(ERR_PANIC, "errors made it through from pass one");
420 else
421 while (itimes--) {
422 for (j = 0; j < instruction->nprefix; j++) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000423 uint8_t c = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000424 switch (instruction->prefixes[j]) {
425 case P_LOCK:
426 c = 0xF0;
427 break;
428 case P_REPNE:
429 case P_REPNZ:
430 c = 0xF2;
431 break;
432 case P_REPE:
433 case P_REPZ:
434 case P_REP:
435 c = 0xF3;
436 break;
437 case R_CS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000438 if (bits == 64) {
439 error(ERR_WARNING,
440 "cs segment base ignored in 64-bit mode");
441 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000442 c = 0x2E;
443 break;
444 case R_DS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000445 if (bits == 64) {
446 error(ERR_WARNING,
447 "ds segment base ignored in 64-bit mode");
448 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000449 c = 0x3E;
450 break;
451 case R_ES:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000452 if (bits == 64) {
453 error(ERR_WARNING,
454 "es segment base ignored in 64-bit mode");
455 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000456 c = 0x26;
457 break;
458 case R_FS:
459 c = 0x64;
460 break;
461 case R_GS:
462 c = 0x65;
463 break;
464 case R_SS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000465 if (bits == 64) {
466 error(ERR_WARNING,
467 "ss segment base ignored in 64-bit mode");
468 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000469 c = 0x36;
470 break;
471 case R_SEGR6:
472 case R_SEGR7:
473 error(ERR_NONFATAL,
474 "segr6 and segr7 cannot be used as prefixes");
475 break;
476 case P_A16:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000477 if (bits == 64) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000478 error(ERR_NONFATAL,
479 "16-bit addressing is not supported "
480 "in 64-bit mode");
Keith Kaniosb7a89542007-04-12 02:40:54 +0000481 break;
482 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000483 if (bits != 16)
484 c = 0x67;
485 break;
486 case P_A32:
487 if (bits != 32)
488 c = 0x67;
489 break;
490 case P_O16:
491 if (bits != 16)
492 c = 0x66;
493 break;
494 case P_O32:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000495 if (bits == 16)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000496 c = 0x66;
497 break;
498 default:
499 error(ERR_PANIC, "invalid instruction prefix");
500 }
501 if (c != 0) {
502 out(offset, segment, &c, OUT_RAWDATA + 1,
503 NO_SEG, NO_SEG);
504 offset++;
505 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000506 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000507 insn_end = offset + insn_size;
508 gencode(segment, offset, bits, instruction, codes,
509 insn_end);
510 offset += insn_size;
511 if (itimes > 0 && itimes == instruction->times - 1) {
512 /*
513 * Dummy call to list->output to give the offset to the
514 * listing module.
515 */
516 list->output(offset, NULL, OUT_RAWDATA);
517 list->uplevel(LIST_TIMES);
518 }
519 }
520 if (instruction->times > 1)
521 list->downlevel(LIST_TIMES);
522 return offset - start;
523 } else if (m > 0 && m > size_prob) {
524 size_prob = m;
525 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000526// temp++;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000527 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000528
H. Peter Anvine2c80182005-01-15 22:15:51 +0000529 if (temp->opcode == -1) { /* didn't match any instruction */
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000530 switch (size_prob) {
531 case 1:
532 error(ERR_NONFATAL, "operation size not specified");
533 break;
534 case 2:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000535 error(ERR_NONFATAL, "mismatch in operand sizes");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000536 break;
537 case 3:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000538 error(ERR_NONFATAL, "no instruction for this cpu level");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000539 break;
540 case 4:
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000541 error(ERR_NONFATAL, "instruction not supported in 64-bit mode");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000542 break;
543 default:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000544 error(ERR_NONFATAL,
545 "invalid combination of opcode and operands");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000546 break;
547 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000548 }
549 return 0;
550}
551
Keith Kaniosb7a89542007-04-12 02:40:54 +0000552int32_t insn_size(int32_t segment, int32_t offset, int bits, uint32_t cp,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000553 insn * instruction, efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000554{
H. Peter Anvin3360d792007-09-11 04:16:57 +0000555 const struct itemplate *temp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000556
H. Peter Anvine2c80182005-01-15 22:15:51 +0000557 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000558 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000559
560 if (instruction->opcode == -1)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000561 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000562
563 if (instruction->opcode == I_DB ||
H. Peter Anvine2c80182005-01-15 22:15:51 +0000564 instruction->opcode == I_DW ||
565 instruction->opcode == I_DD ||
566 instruction->opcode == I_DQ || instruction->opcode == I_DT) {
567 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000568 int32_t isize, osize, wsize = 0; /* placate gcc */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000569
H. Peter Anvine2c80182005-01-15 22:15:51 +0000570 isize = 0;
571 switch (instruction->opcode) {
572 case I_DB:
573 wsize = 1;
574 break;
575 case I_DW:
576 wsize = 2;
577 break;
578 case I_DD:
579 wsize = 4;
580 break;
581 case I_DQ:
582 wsize = 8;
583 break;
584 case I_DT:
585 wsize = 10;
586 break;
H. Peter Anvin16b0a332007-09-12 20:27:41 -0700587 default:
588 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000589 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000590
H. Peter Anvine2c80182005-01-15 22:15:51 +0000591 for (e = instruction->eops; e; e = e->next) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000592 int32_t align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000593
H. Peter Anvine2c80182005-01-15 22:15:51 +0000594 osize = 0;
595 if (e->type == EOT_DB_NUMBER)
596 osize = 1;
597 else if (e->type == EOT_DB_STRING)
598 osize = e->stringlen;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000599
H. Peter Anvine2c80182005-01-15 22:15:51 +0000600 align = (-osize) % wsize;
601 if (align < 0)
602 align += wsize;
603 isize += osize + align;
604 }
605 return isize * instruction->times;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000606 }
607
H. Peter Anvine2c80182005-01-15 22:15:51 +0000608 if (instruction->opcode == I_INCBIN) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000609 char fname[FILENAME_MAX];
H. Peter Anvine2c80182005-01-15 22:15:51 +0000610 FILE *fp;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000611 int32_t len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000612 char *prefix = "", *combine;
613 char **pPrevPath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000614
H. Peter Anvine2c80182005-01-15 22:15:51 +0000615 len = FILENAME_MAX - 1;
616 if (len > instruction->eops->stringlen)
617 len = instruction->eops->stringlen;
618 strncpy(fname, instruction->eops->stringval, len);
619 fname[len] = '\0';
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000620
H. Peter Anvine2c80182005-01-15 22:15:51 +0000621 while (1) { /* added by alexfru: 'incbin' uses include paths */
622 combine = nasm_malloc(strlen(prefix) + len + 1);
623 strcpy(combine, prefix);
624 strcat(combine, fname);
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000625
H. Peter Anvine2c80182005-01-15 22:15:51 +0000626 if ((fp = fopen(combine, "rb")) != NULL) {
627 nasm_free(combine);
628 break;
629 }
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000630
H. Peter Anvine2c80182005-01-15 22:15:51 +0000631 nasm_free(combine);
632 pPrevPath = pp_get_include_path_ptr(pPrevPath);
633 if (pPrevPath == NULL)
634 break;
635 prefix = *pPrevPath;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000636 }
637
638 if (fp == NULL)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000639 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
640 fname);
641 else if (fseek(fp, 0L, SEEK_END) < 0)
642 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
643 fname);
644 else {
645 len = ftell(fp);
646 fclose(fp);
647 if (instruction->eops->next) {
648 len -= instruction->eops->next->offset;
649 if (instruction->eops->next->next &&
650 len > instruction->eops->next->next->offset) {
651 len = instruction->eops->next->next->offset;
652 }
653 }
654 return instruction->times * len;
655 }
656 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000657 }
658
Keith Kaniosb7a89542007-04-12 02:40:54 +0000659 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++) {
660 int m = matches(temp, instruction, bits);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000661 if (m == 99)
662 m += jmp_match(segment, offset, bits, instruction, temp->code);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000663
H. Peter Anvine2c80182005-01-15 22:15:51 +0000664 if (m == 100) {
665 /* we've matched an instruction. */
Keith Kaniosb7a89542007-04-12 02:40:54 +0000666 int32_t isize;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000667 const char *codes = temp->code;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000668 int j;
669
670 isize = calcsize(segment, offset, bits, instruction, codes);
671 if (isize < 0)
672 return -1;
673 for (j = 0; j < instruction->nprefix; j++) {
674 if ((instruction->prefixes[j] != P_A16 &&
675 instruction->prefixes[j] != P_O16 && bits == 16) ||
676 (instruction->prefixes[j] != P_A32 &&
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000677 instruction->prefixes[j] != P_O32 && bits >= 32)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000678 isize++;
679 }
680 }
681 return isize * instruction->times;
682 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000683 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000684 return -1; /* didn't match any instruction */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000685}
686
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000687/* check that opn[op] is a signed byte of size 16 or 32,
688 and return the signed value*/
H. Peter Anvine2c80182005-01-15 22:15:51 +0000689static int is_sbyte(insn * ins, int op, int size)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000690{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000691 int32_t v;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000692 int ret;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000693
694 ret = !(ins->forw_ref && ins->oprs[op].opflags) && /* dead in the water on forward reference or External */
695 optimizing >= 0 &&
696 !(ins->oprs[op].type & STRICT) &&
697 ins->oprs[op].wrt == NO_SEG && ins->oprs[op].segment == NO_SEG;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000698
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000699 v = ins->oprs[op].offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000700 if (size == 16)
Keith Kaniosb7a89542007-04-12 02:40:54 +0000701 v = (int16_t)v; /* sign extend if 16 bits */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000702
703 return ret && v >= -128L && v <= 127L;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000704}
705
Keith Kaniosb7a89542007-04-12 02:40:54 +0000706static int32_t calcsize(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000707 insn * ins, const char *codes)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000708{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000709 int32_t length = 0;
710 uint8_t c;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000711 int rex_mask = ~0;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000712 ins->rex = 0; /* Ensure REX is reset */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000713
H. Peter Anvine2c80182005-01-15 22:15:51 +0000714 (void)segment; /* Don't warn that this parameter is unused */
715 (void)offset; /* Don't warn that this parameter is unused */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000716
H. Peter Anvine2c80182005-01-15 22:15:51 +0000717 while (*codes)
718 switch (c = *codes++) {
719 case 01:
720 case 02:
721 case 03:
722 codes += c, length += c;
723 break;
724 case 04:
725 case 05:
726 case 06:
727 case 07:
728 length++;
729 break;
730 case 010:
731 case 011:
732 case 012:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000733 ins->rex |=
734 op_rexflags(&ins->oprs[c - 010], REX_B|REX_H|REX_P|REX_W);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000735 codes++, length++;
736 break;
737 case 017:
738 length++;
739 break;
740 case 014:
741 case 015:
742 case 016:
743 length++;
744 break;
745 case 020:
746 case 021:
747 case 022:
748 length++;
749 break;
750 case 024:
751 case 025:
752 case 026:
753 length++;
754 break;
755 case 030:
756 case 031:
757 case 032:
758 length += 2;
759 break;
760 case 034:
761 case 035:
762 case 036:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000763 if (ins->oprs[c - 034].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000764 length += (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
765 else
766 length += (bits == 16) ? 2 : 4;
767 break;
768 case 037:
769 length += 2;
770 break;
771 case 040:
772 case 041:
773 case 042:
774 length += 4;
775 break;
776 case 044:
777 case 045:
778 case 046:
779 length += ((ins->oprs[c - 044].addr_size ?
Keith Kaniosb7a89542007-04-12 02:40:54 +0000780 ins->oprs[c - 044].addr_size : bits) >> 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000781 break;
782 case 050:
783 case 051:
784 case 052:
785 length++;
786 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000787 case 054:
788 case 055:
789 case 056:
790 length += 8; /* MOV reg64/imm */
791 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000792 case 060:
793 case 061:
794 case 062:
795 length += 2;
796 break;
797 case 064:
798 case 065:
799 case 066:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000800 if (ins->oprs[c - 064].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000801 length += (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
802 else
803 length += (bits == 16) ? 2 : 4;
804 break;
805 case 070:
806 case 071:
807 case 072:
808 length += 4;
809 break;
810 case 0130:
811 case 0131:
812 case 0132:
813 length += is_sbyte(ins, c - 0130, 16) ? 1 : 2;
814 break;
815 case 0133:
816 case 0134:
817 case 0135:
818 codes += 2;
819 length++;
820 break;
821 case 0140:
822 case 0141:
823 case 0142:
824 length += is_sbyte(ins, c - 0140, 32) ? 1 : 4;
825 break;
826 case 0143:
827 case 0144:
828 case 0145:
829 codes += 2;
830 length++;
831 break;
832 case 0300:
833 case 0301:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000834 case 0302:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000835 length += chsize(&ins->oprs[c - 0300], bits);
836 break;
837 case 0310:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000838 length += (bits != 16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000839 break;
840 case 0311:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000841 length += (bits != 32);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000842 break;
843 case 0312:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000844 break;
845 case 0313:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000846 break;
847 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000848 length += (bits != 16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000849 break;
850 case 0321:
851 length += (bits == 16);
852 break;
853 case 0322:
854 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000855 case 0323:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000856 rex_mask &= ~REX_W;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000857 break;
858 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000859 ins->rex |= REX_W;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000860 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000861 case 0330:
862 codes++, length++;
863 break;
864 case 0331:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000865 break;
H. Peter Anvincb9b6902007-09-12 21:58:51 -0700866 case 0332:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000867 case 0333:
868 length++;
869 break;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000870 case 0334:
871 assert_no_prefix(ins, P_LOCK);
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000872 ins->rex |= REX_L;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000873 break;
H. Peter Anvincb9b6902007-09-12 21:58:51 -0700874 case 0335:
875 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000876 case 0340:
877 case 0341:
878 case 0342:
879 if (ins->oprs[0].segment != NO_SEG)
880 errfunc(ERR_NONFATAL, "attempt to reserve non-constant"
881 " quantity of BSS space");
882 else
883 length += ins->oprs[0].offset << (c - 0340);
884 break;
H. Peter Anvin62cb6062007-09-11 22:44:03 +0000885 case 0364:
886 case 0365:
887 break;
Keith Kanios48af1772007-08-17 07:37:52 +0000888 case 0366:
H. Peter Anvin62cb6062007-09-11 22:44:03 +0000889 case 0367:
890 length++;
891 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000892 case 0370:
893 case 0371:
894 case 0372:
895 break;
896 case 0373:
897 length++;
898 break;
899 default: /* can't do it by 'case' statements */
900 if (c >= 0100 && c <= 0277) { /* it's an EA */
901 ea ea_data;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000902 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000903 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000904 ea_data.rex = 0; /* Ensure ea.REX is initially 0 */
905
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000906 if (c <= 0177) {
907 /* pick rfield from operand b */
908 rflags = regflag(&ins->oprs[c & 7]);
909 rfield = regvals[ins->oprs[c & 7].basereg];
910 } else {
911 rflags = 0;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000912 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000913 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000914
H. Peter Anvine2c80182005-01-15 22:15:51 +0000915 if (!process_ea
Keith Kaniosb7a89542007-04-12 02:40:54 +0000916 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000917 rfield, rflags, ins->forw_ref)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000918 errfunc(ERR_NONFATAL, "invalid effective address");
919 return -1;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000920 } else {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000921 ins->rex |= ea_data.rex;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000922 length += ea_data.size;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000923 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000924 } else
925 errfunc(ERR_PANIC, "internal instruction table corrupt"
926 ": instruction code 0x%02X given", c);
927 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000928
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000929 ins->rex &= rex_mask;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000930 if (ins->rex & REX_REAL) {
931 if (ins->rex & REX_H) {
932 errfunc(ERR_NONFATAL, "cannot use high register in rex instruction");
933 return -1;
934 } else if (bits == 64 ||
935 ((ins->rex & REX_L) &&
936 !(ins->rex & (REX_P|REX_W|REX_X|REX_B)) &&
937 cpu >= IF_X86_64)) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000938 length++;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000939 } else {
940 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
941 return -1;
942 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000943 }
944
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000945 return length;
946}
Keith Kaniosb7a89542007-04-12 02:40:54 +0000947
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000948#define EMIT_REX() \
949 if((ins->rex & REX_REAL) && (bits == 64)) { \
950 ins->rex = (ins->rex & REX_REAL)|REX_P; \
951 out(offset, segment, &ins->rex, OUT_RAWDATA+1, NO_SEG, NO_SEG); \
952 ins->rex = 0; \
953 offset += 1; \
954 }
955
Keith Kaniosb7a89542007-04-12 02:40:54 +0000956static void gencode(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000957 insn * ins, const char *codes, int32_t insn_end)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000958{
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000959 static char condval[] = { /* conditional opcodes */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000960 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
961 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
962 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000963 };
Keith Kaniosb7a89542007-04-12 02:40:54 +0000964 uint8_t c;
965 uint8_t bytes[4];
966 int32_t size;
967 int64_t data;
968
H. Peter Anvineba20a72002-04-30 20:53:55 +0000969 while (*codes)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000970 switch (c = *codes++) {
971 case 01:
972 case 02:
973 case 03:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000974 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +0000975 out(offset, segment, codes, OUT_RAWDATA + c, NO_SEG, NO_SEG);
976 codes += c;
977 offset += c;
978 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000979
H. Peter Anvine2c80182005-01-15 22:15:51 +0000980 case 04:
981 case 06:
982 switch (ins->oprs[0].basereg) {
983 case R_CS:
984 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0);
985 break;
986 case R_DS:
987 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0);
988 break;
989 case R_ES:
990 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0);
991 break;
992 case R_SS:
993 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0);
994 break;
995 default:
996 errfunc(ERR_PANIC,
997 "bizarre 8086 segment register received");
998 }
999 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1000 offset++;
1001 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001002
H. Peter Anvine2c80182005-01-15 22:15:51 +00001003 case 05:
1004 case 07:
1005 switch (ins->oprs[0].basereg) {
1006 case R_FS:
1007 bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0);
1008 break;
1009 case R_GS:
1010 bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0);
1011 break;
1012 default:
1013 errfunc(ERR_PANIC,
1014 "bizarre 386 segment register received");
1015 }
1016 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1017 offset++;
1018 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001019
H. Peter Anvine2c80182005-01-15 22:15:51 +00001020 case 010:
1021 case 011:
1022 case 012:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001023 EMIT_REX();
Keith Kaniosb7a89542007-04-12 02:40:54 +00001024 bytes[0] = *codes++ + ((regval(&ins->oprs[c - 010])) & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001025 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 017:
1030 bytes[0] = 0;
1031 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1032 offset += 1;
1033 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001034
H. Peter Anvine2c80182005-01-15 22:15:51 +00001035 case 014:
1036 case 015:
1037 case 016:
1038 if (ins->oprs[c - 014].offset < -128
1039 || ins->oprs[c - 014].offset > 127) {
1040 errfunc(ERR_WARNING, "signed byte value exceeds bounds");
1041 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001042
H. Peter Anvine2c80182005-01-15 22:15:51 +00001043 if (ins->oprs[c - 014].segment != NO_SEG) {
1044 data = ins->oprs[c - 014].offset;
1045 out(offset, segment, &data, OUT_ADDRESS + 1,
1046 ins->oprs[c - 014].segment, ins->oprs[c - 014].wrt);
1047 } else {
1048 bytes[0] = ins->oprs[c - 014].offset;
1049 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1050 NO_SEG);
1051 }
1052 offset += 1;
1053 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001054
H. Peter Anvine2c80182005-01-15 22:15:51 +00001055 case 020:
1056 case 021:
1057 case 022:
1058 if (ins->oprs[c - 020].offset < -256
1059 || ins->oprs[c - 020].offset > 255) {
1060 errfunc(ERR_WARNING, "byte value exceeds bounds");
1061 }
1062 if (ins->oprs[c - 020].segment != NO_SEG) {
1063 data = ins->oprs[c - 020].offset;
1064 out(offset, segment, &data, OUT_ADDRESS + 1,
1065 ins->oprs[c - 020].segment, ins->oprs[c - 020].wrt);
1066 } else {
1067 bytes[0] = ins->oprs[c - 020].offset;
1068 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1069 NO_SEG);
1070 }
1071 offset += 1;
1072 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001073
H. Peter Anvine2c80182005-01-15 22:15:51 +00001074 case 024:
1075 case 025:
1076 case 026:
1077 if (ins->oprs[c - 024].offset < 0
1078 || ins->oprs[c - 024].offset > 255)
1079 errfunc(ERR_WARNING, "unsigned byte value exceeds bounds");
1080 if (ins->oprs[c - 024].segment != NO_SEG) {
1081 data = ins->oprs[c - 024].offset;
1082 out(offset, segment, &data, OUT_ADDRESS + 1,
1083 ins->oprs[c - 024].segment, ins->oprs[c - 024].wrt);
1084 } else {
1085 bytes[0] = ins->oprs[c - 024].offset;
1086 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1087 NO_SEG);
1088 }
1089 offset += 1;
1090 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001091
H. Peter Anvine2c80182005-01-15 22:15:51 +00001092 case 030:
1093 case 031:
1094 case 032:
1095 if (ins->oprs[c - 030].segment == NO_SEG &&
1096 ins->oprs[c - 030].wrt == NO_SEG &&
1097 (ins->oprs[c - 030].offset < -65536L ||
1098 ins->oprs[c - 030].offset > 65535L)) {
1099 errfunc(ERR_WARNING, "word value exceeds bounds");
1100 }
1101 data = ins->oprs[c - 030].offset;
1102 out(offset, segment, &data, OUT_ADDRESS + 2,
1103 ins->oprs[c - 030].segment, ins->oprs[c - 030].wrt);
1104 offset += 2;
1105 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001106
H. Peter Anvine2c80182005-01-15 22:15:51 +00001107 case 034:
1108 case 035:
1109 case 036:
1110 if (ins->oprs[c - 034].type & (BITS16 | BITS32))
1111 size = (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
1112 else
1113 size = (bits == 16) ? 2 : 4;
1114 data = ins->oprs[c - 034].offset;
1115 if (size == 2 && (data < -65536L || data > 65535L))
1116 errfunc(ERR_WARNING, "word value exceeds bounds");
1117 out(offset, segment, &data, OUT_ADDRESS + size,
1118 ins->oprs[c - 034].segment, ins->oprs[c - 034].wrt);
1119 offset += size;
1120 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001121
H. Peter Anvine2c80182005-01-15 22:15:51 +00001122 case 037:
1123 if (ins->oprs[0].segment == NO_SEG)
1124 errfunc(ERR_NONFATAL, "value referenced by FAR is not"
1125 " relocatable");
1126 data = 0L;
1127 out(offset, segment, &data, OUT_ADDRESS + 2,
1128 outfmt->segbase(1 + ins->oprs[0].segment),
1129 ins->oprs[0].wrt);
1130 offset += 2;
1131 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001132
H. Peter Anvine2c80182005-01-15 22:15:51 +00001133 case 040:
1134 case 041:
1135 case 042:
1136 data = ins->oprs[c - 040].offset;
1137 out(offset, segment, &data, OUT_ADDRESS + 4,
1138 ins->oprs[c - 040].segment, ins->oprs[c - 040].wrt);
1139 offset += 4;
1140 break;
H. Peter Anvin3ba46772002-05-27 23:19:35 +00001141
H. Peter Anvine2c80182005-01-15 22:15:51 +00001142 case 044:
1143 case 045:
1144 case 046:
1145 data = ins->oprs[c - 044].offset;
1146 size = ((ins->oprs[c - 044].addr_size ?
Keith Kaniosb7a89542007-04-12 02:40:54 +00001147 ins->oprs[c - 044].addr_size : bits) >> 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001148 if (size == 2 && (data < -65536L || data > 65535L))
1149 errfunc(ERR_WARNING, "word value exceeds bounds");
1150 out(offset, segment, &data, OUT_ADDRESS + size,
1151 ins->oprs[c - 044].segment, ins->oprs[c - 044].wrt);
1152 offset += size;
1153 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001154
H. Peter Anvine2c80182005-01-15 22:15:51 +00001155 case 050:
1156 case 051:
1157 case 052:
1158 if (ins->oprs[c - 050].segment != segment)
1159 errfunc(ERR_NONFATAL,
1160 "short relative jump outside segment");
1161 data = ins->oprs[c - 050].offset - insn_end;
1162 if (data > 127 || data < -128)
1163 errfunc(ERR_NONFATAL, "short jump is out of range");
1164 bytes[0] = data;
1165 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1166 offset += 1;
1167 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001168
1169 case 054:
1170 case 055:
1171 case 056:
1172 data = (int64_t)ins->oprs[c - 054].offset;
1173 out(offset, segment, &data, OUT_ADDRESS + 8,
1174 ins->oprs[c - 054].segment, ins->oprs[c - 054].wrt);
1175 offset += 8;
1176 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001177
H. Peter Anvine2c80182005-01-15 22:15:51 +00001178 case 060:
1179 case 061:
1180 case 062:
1181 if (ins->oprs[c - 060].segment != segment) {
1182 data = ins->oprs[c - 060].offset;
1183 out(offset, segment, &data,
1184 OUT_REL2ADR + insn_end - offset,
1185 ins->oprs[c - 060].segment, ins->oprs[c - 060].wrt);
1186 } else {
1187 data = ins->oprs[c - 060].offset - insn_end;
1188 out(offset, segment, &data,
1189 OUT_ADDRESS + 2, NO_SEG, NO_SEG);
1190 }
1191 offset += 2;
1192 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001193
H. Peter Anvine2c80182005-01-15 22:15:51 +00001194 case 064:
1195 case 065:
1196 case 066:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001197 if (ins->oprs[c - 064].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001198 size = (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
1199 else
1200 size = (bits == 16) ? 2 : 4;
1201 if (ins->oprs[c - 064].segment != segment) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001202 int32_t reltype = (size == 2 ? OUT_REL2ADR : OUT_REL4ADR);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001203 data = ins->oprs[c - 064].offset;
1204 out(offset, segment, &data, reltype + insn_end - offset,
1205 ins->oprs[c - 064].segment, ins->oprs[c - 064].wrt);
1206 } else {
1207 data = ins->oprs[c - 064].offset - insn_end;
1208 out(offset, segment, &data,
1209 OUT_ADDRESS + size, NO_SEG, NO_SEG);
1210 }
1211 offset += size;
1212 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001213
H. Peter Anvine2c80182005-01-15 22:15:51 +00001214 case 070:
1215 case 071:
1216 case 072:
1217 if (ins->oprs[c - 070].segment != segment) {
1218 data = ins->oprs[c - 070].offset;
1219 out(offset, segment, &data,
1220 OUT_REL4ADR + insn_end - offset,
1221 ins->oprs[c - 070].segment, ins->oprs[c - 070].wrt);
1222 } else {
1223 data = ins->oprs[c - 070].offset - insn_end;
1224 out(offset, segment, &data,
1225 OUT_ADDRESS + 4, NO_SEG, NO_SEG);
1226 }
1227 offset += 4;
1228 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001229
H. Peter Anvine2c80182005-01-15 22:15:51 +00001230 case 0130:
1231 case 0131:
1232 case 0132:
1233 data = ins->oprs[c - 0130].offset;
1234 if (is_sbyte(ins, c - 0130, 16)) {
1235 bytes[0] = data;
1236 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1237 NO_SEG);
1238 offset++;
1239 } else {
1240 if (ins->oprs[c - 0130].segment == NO_SEG &&
1241 ins->oprs[c - 0130].wrt == NO_SEG &&
1242 (data < -65536L || data > 65535L)) {
1243 errfunc(ERR_WARNING, "word value exceeds bounds");
1244 }
1245 out(offset, segment, &data, OUT_ADDRESS + 2,
1246 ins->oprs[c - 0130].segment, ins->oprs[c - 0130].wrt);
1247 offset += 2;
1248 }
1249 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001250
H. Peter Anvine2c80182005-01-15 22:15:51 +00001251 case 0133:
1252 case 0134:
1253 case 0135:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001254 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001255 codes++;
1256 bytes[0] = *codes++;
1257 if (is_sbyte(ins, c - 0133, 16))
1258 bytes[0] |= 2; /* s-bit */
1259 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1260 offset++;
1261 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001262
H. Peter Anvine2c80182005-01-15 22:15:51 +00001263 case 0140:
1264 case 0141:
1265 case 0142:
1266 data = ins->oprs[c - 0140].offset;
1267 if (is_sbyte(ins, c - 0140, 32)) {
1268 bytes[0] = data;
1269 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1270 NO_SEG);
1271 offset++;
1272 } else {
1273 out(offset, segment, &data, OUT_ADDRESS + 4,
1274 ins->oprs[c - 0140].segment, ins->oprs[c - 0140].wrt);
1275 offset += 4;
1276 }
1277 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001278
H. Peter Anvine2c80182005-01-15 22:15:51 +00001279 case 0143:
1280 case 0144:
1281 case 0145:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001282 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001283 codes++;
1284 bytes[0] = *codes++;
1285 if (is_sbyte(ins, c - 0143, 32))
1286 bytes[0] |= 2; /* s-bit */
1287 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1288 offset++;
1289 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001290
H. Peter Anvine2c80182005-01-15 22:15:51 +00001291 case 0300:
1292 case 0301:
1293 case 0302:
1294 if (chsize(&ins->oprs[c - 0300], bits)) {
1295 *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 0310:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001304 if (bits != 16) {
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 0311:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001314 if (bits != 32) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001315 *bytes = 0x67;
1316 out(offset, segment, bytes,
1317 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1318 offset += 1;
1319 } else
1320 offset += 0;
1321 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001322
H. Peter Anvine2c80182005-01-15 22:15:51 +00001323 case 0312:
1324 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001325
Keith Kaniosb7a89542007-04-12 02:40:54 +00001326 case 0313:
1327 ins->rex = 0;
1328 break;
1329
H. Peter Anvine2c80182005-01-15 22:15:51 +00001330 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001331 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001332 *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 Anvineba20a72002-04-30 20:53:55 +00001339
H. Peter Anvine2c80182005-01-15 22:15:51 +00001340 case 0321:
1341 if (bits == 16) {
1342 *bytes = 0x66;
1343 out(offset, segment, bytes,
1344 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1345 offset += 1;
1346 } else
1347 offset += 0;
1348 break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001349
H. Peter Anvine2c80182005-01-15 22:15:51 +00001350 case 0322:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001351 case 0323:
1352 break;
1353
1354 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001355 ins->rex |= REX_W;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001356 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001357
H. Peter Anvine2c80182005-01-15 22:15:51 +00001358 case 0330:
1359 *bytes = *codes++ ^ condval[ins->condition];
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
H. Peter Anvine2c80182005-01-15 22:15:51 +00001364 case 0331:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001365 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001366
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001367 case 0332:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001368 case 0333:
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001369 *bytes = c - 0332 + 0xF2;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001370 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1371 offset += 1;
1372 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001373
Keith Kanios48af1772007-08-17 07:37:52 +00001374 case 0334:
1375 if (ins->rex & REX_R) {
1376 *bytes = 0xF0;
1377 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1378 offset += 1;
1379 }
1380 ins->rex &= ~(REX_L|REX_R);
1381 break;
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001382
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001383 case 0335:
1384 break;
1385
H. Peter Anvine2c80182005-01-15 22:15:51 +00001386 case 0340:
1387 case 0341:
1388 case 0342:
1389 if (ins->oprs[0].segment != NO_SEG)
1390 errfunc(ERR_PANIC, "non-constant BSS size in pass two");
1391 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001392 int32_t size = ins->oprs[0].offset << (c - 0340);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001393 if (size > 0)
1394 out(offset, segment, NULL,
1395 OUT_RESERVE + size, NO_SEG, NO_SEG);
1396 offset += size;
1397 }
1398 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001399
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001400 case 0364:
1401 case 0365:
1402 break;
1403
Keith Kanios48af1772007-08-17 07:37:52 +00001404 case 0366:
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001405 case 0367:
1406 *bytes = c - 0366 + 0x66;
Keith Kanios48af1772007-08-17 07:37:52 +00001407 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1408 offset += 1;
1409 break;
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001410
H. Peter Anvine2c80182005-01-15 22:15:51 +00001411 case 0370:
1412 case 0371:
1413 case 0372:
1414 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001415
H. Peter Anvine2c80182005-01-15 22:15:51 +00001416 case 0373:
1417 *bytes = bits == 16 ? 3 : 5;
1418 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1419 offset += 1;
1420 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001421
H. Peter Anvine2c80182005-01-15 22:15:51 +00001422 default: /* can't do it by 'case' statements */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001423 if (c >= 0100 && c <= 0277) { /* it's an EA */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001424 ea ea_data;
1425 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001426 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001427 uint8_t *p;
1428 int32_t s;
1429
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001430 if (c <= 0177) {
1431 /* pick rfield from operand b */
1432 rflags = regflag(&ins->oprs[c & 7]);
1433 rfield = regvals[ins->oprs[c & 7].basereg];
1434 } else {
1435 /* rfield is constant */
1436 rflags = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001437 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001438 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001439
1440 if (!process_ea
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001441 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
1442 rfield, rflags, ins->forw_ref)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001443 errfunc(ERR_NONFATAL, "invalid effective address");
1444 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001445
H. Peter Anvine2c80182005-01-15 22:15:51 +00001446 p = bytes;
1447 *p++ = ea_data.modrm;
1448 if (ea_data.sib_present)
1449 *p++ = ea_data.sib;
1450
1451 s = p - bytes;
1452 out(offset, segment, bytes, OUT_RAWDATA + s,
1453 NO_SEG, NO_SEG);
1454
1455 switch (ea_data.bytes) {
1456 case 0:
1457 break;
1458 case 1:
1459 if (ins->oprs[(c >> 3) & 7].segment != NO_SEG) {
1460 data = ins->oprs[(c >> 3) & 7].offset;
1461 out(offset, segment, &data, OUT_ADDRESS + 1,
1462 ins->oprs[(c >> 3) & 7].segment,
1463 ins->oprs[(c >> 3) & 7].wrt);
1464 } else {
1465 *bytes = ins->oprs[(c >> 3) & 7].offset;
1466 out(offset, segment, bytes, OUT_RAWDATA + 1,
1467 NO_SEG, NO_SEG);
1468 }
1469 s++;
1470 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001471 case 8:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001472 case 2:
1473 case 4:
1474 data = ins->oprs[(c >> 3) & 7].offset;
Keith Kaniose83b3182007-04-16 14:31:54 +00001475 if (ea_data.rip && (ins->oprs[(c >> 3) & 7].segment == 0xFFFFFFFF))
1476 ea_data.rip = 0; /* Make distinction between Symbols and Immediates */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001477 out(offset, segment, &data, /* RIP = Relative, not Absolute */
1478 (ea_data.rip ? OUT_REL4ADR : OUT_ADDRESS) + ea_data.bytes,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001479 ins->oprs[(c >> 3) & 7].segment,
1480 ins->oprs[(c >> 3) & 7].wrt);
1481 s += ea_data.bytes;
1482 break;
1483 }
1484 offset += s;
1485 } else
1486 errfunc(ERR_PANIC, "internal instruction table corrupt"
1487 ": instruction code 0x%02X given", c);
1488 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001489}
1490
H. Peter Anvin0ec60e62007-07-07 01:59:52 +00001491static int32_t regflag(const operand * o)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001492{
1493 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1494 errfunc(ERR_PANIC, "invalid operand passed to regflag()");
1495 }
1496 return reg_flags[o->basereg];
1497}
1498
H. Peter Anvin5b0e3ec2007-07-07 02:01:08 +00001499static int32_t regval(const operand * o)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001500{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001501 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1502 errfunc(ERR_PANIC, "invalid operand passed to regval()");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001503 }
H. Peter Anvin232badb2002-06-06 02:41:20 +00001504 return regvals[o->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001505}
1506
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001507static int op_rexflags(const operand * o, int mask)
1508{
1509 int32_t flags;
1510 int val;
1511
1512 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1513 errfunc(ERR_PANIC, "invalid operand passed to op_rexflags()");
1514 }
1515
1516 flags = reg_flags[o->basereg];
1517 val = regvals[o->basereg];
1518
1519 return rexflags(val, flags, mask);
1520}
1521
1522static int rexflags(int val, int32_t flags, int mask)
1523{
1524 int rex = 0;
1525
1526 if (val >= 8)
1527 rex |= REX_B|REX_X|REX_R;
1528 if (flags & BITS64)
1529 rex |= REX_W;
1530 if (!(REG_HIGH & ~flags)) /* AH, CH, DH, BH */
1531 rex |= REX_H;
1532 else if (!(REG8 & ~flags) && val >= 4) /* SPL, BPL, SIL, DIL */
1533 rex |= REX_P;
1534
1535 return rex & mask;
1536}
1537
H. Peter Anvin3360d792007-09-11 04:16:57 +00001538static int matches(const struct itemplate *itemp, insn * instruction, int bits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001539{
H. Peter Anvin34539fb2007-05-30 04:27:58 +00001540 int i, size[3], asize, oprs, ret;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001541
1542 ret = 100;
1543
1544 /*
1545 * Check the opcode
1546 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001547 if (itemp->opcode != instruction->opcode)
1548 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001549
1550 /*
1551 * Count the operands
1552 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001553 if (itemp->operands != instruction->operands)
1554 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001555
1556 /*
1557 * Check that no spurious colons or TOs are present
1558 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001559 for (i = 0; i < itemp->operands; i++)
1560 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON | TO))
1561 return 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001562
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001563 /*
1564 * Check that the operand flags all match up
1565 */
H. Peter Anvin16b0a332007-09-12 20:27:41 -07001566 for (i = 0; i < itemp->operands; i++) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001567 if (itemp->opd[i] & ~instruction->oprs[i].type ||
1568 ((itemp->opd[i] & SIZE_MASK) &&
1569 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK))) {
H. Peter Anvin5a640e12007-05-29 23:57:12 +00001570 if ((itemp->opd[i] & ~instruction->oprs[i].type & ~SIZE_MASK) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001571 (instruction->oprs[i].type & SIZE_MASK))
1572 return 0;
1573 else
H. Peter Anvine2c80182005-01-15 22:15:51 +00001574 return 1;
1575 }
H. Peter Anvin16b0a332007-09-12 20:27:41 -07001576 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001577
1578 /*
1579 * Check operand sizes
1580 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001581 if (itemp->flags & IF_ARMASK) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001582 size[0] = size[1] = size[2] = 0;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001583
H. Peter Anvine2c80182005-01-15 22:15:51 +00001584 switch (itemp->flags & IF_ARMASK) {
1585 case IF_AR0:
1586 i = 0;
1587 break;
1588 case IF_AR1:
1589 i = 1;
1590 break;
1591 case IF_AR2:
1592 i = 2;
1593 break;
1594 default:
1595 break; /* Shouldn't happen */
1596 }
1597 if (itemp->flags & IF_SB) {
1598 size[i] = BITS8;
1599 } else if (itemp->flags & IF_SW) {
1600 size[i] = BITS16;
1601 } else if (itemp->flags & IF_SD) {
1602 size[i] = BITS32;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001603 } else if (itemp->flags & IF_SQ) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001604 size[i] = BITS64;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001605 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001606 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001607 asize = 0;
1608 if (itemp->flags & IF_SB) {
1609 asize = BITS8;
1610 oprs = itemp->operands;
1611 } else if (itemp->flags & IF_SW) {
1612 asize = BITS16;
1613 oprs = itemp->operands;
1614 } else if (itemp->flags & IF_SD) {
1615 asize = BITS32;
1616 oprs = itemp->operands;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001617 } else if (itemp->flags & IF_SQ) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001618 asize = BITS64;
1619 oprs = itemp->operands;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001620 }
1621 size[0] = size[1] = size[2] = asize;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001622 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001623
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001624 if (itemp->flags & (IF_SM | IF_SM2)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001625 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
1626 asize = 0;
1627 for (i = 0; i < oprs; i++) {
1628 if ((asize = itemp->opd[i] & SIZE_MASK) != 0) {
1629 int j;
1630 for (j = 0; j < oprs; j++)
1631 size[j] = asize;
1632 break;
1633 }
1634 }
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001635 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001636 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001637 }
1638
Keith Kaniosb7a89542007-04-12 02:40:54 +00001639 for (i = 0; i < itemp->operands; i++) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001640 if (!(itemp->opd[i] & SIZE_MASK) &&
1641 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001642 return 2;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001643 }
1644
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001645 /*
1646 * Check template is okay at the set cpu level
1647 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001648 if (((itemp->flags & IF_PLEVEL) > cpu))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001649 return 3;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001650
1651 /*
1652 * Check if instruction is available in long mode
1653 */
1654 if ((itemp->flags & IF_NOLONG) && (bits == 64))
1655 return 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001656
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001657 /*
1658 * Check if special handling needed for Jumps
1659 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001660 if ((uint8_t)(itemp->code[0]) >= 0370)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001661 return 99;
1662
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001663 return ret;
1664}
1665
H. Peter Anvine2c80182005-01-15 22:15:51 +00001666static ea *process_ea(operand * input, ea * output, int addrbits,
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001667 int rfield, int32_t rflags, int forw_ref)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001668{
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001669 output->rip = FALSE;
1670
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001671 /* REX flags for the rfield operand */
1672 output->rex |= rexflags(rfield, rflags, REX_R|REX_P|REX_W|REX_H);
1673
Keith Kaniosb7a89542007-04-12 02:40:54 +00001674 if (!(REGISTER & ~input->type)) { /* register direct */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001675 int i;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001676 int32_t f;
1677
1678 if (input->basereg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001679 || input->basereg >= REG_ENUM_LIMIT)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001680 return NULL;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001681 f = regflag(input);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001682 i = regvals[input->basereg];
Keith Kaniosb7a89542007-04-12 02:40:54 +00001683
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001684 if (REG_EA & ~f)
1685 return NULL; /* Invalid EA register */
1686
1687 output->rex |= op_rexflags(input, REX_B|REX_P|REX_W|REX_H);
1688
Keith Kaniosb7a89542007-04-12 02:40:54 +00001689 output->sib_present = FALSE; /* no SIB necessary */
1690 output->bytes = 0; /* no offset necessary either */
1691 output->modrm = 0xC0 | ((rfield & 7) << 3) | (i & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001692 } else { /* it's a memory reference */
1693 if (input->basereg == -1
1694 && (input->indexreg == -1 || input->scale == 0)) {
1695 /* it's a pure offset */
1696 if (input->addr_size)
1697 addrbits = input->addr_size;
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001698
1699 if (globalbits == 64 && (~input->type & IP_REL)) {
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00001700 int scale, index, base;
1701 output->sib_present = TRUE;
1702 scale = 0;
1703 index = 4;
1704 base = 5;
1705 output->sib = (scale << 6) | (index << 3) | base;
1706 output->bytes = 4;
1707 output->modrm = 4 | ((rfield & 7) << 3);
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001708 output->rip = FALSE;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00001709 } else {
1710 output->sib_present = FALSE;
1711 output->bytes = (addrbits != 16 ? 4 : 2);
1712 output->modrm = (addrbits != 16 ? 5 : 6) | ((rfield & 7) << 3);
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001713 output->rip = globalbits == 64;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00001714 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001715 } else { /* it's an indirection */
1716 int i = input->indexreg, b = input->basereg, s = input->scale;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001717 int32_t o = input->offset, seg = input->segment;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001718 int hb = input->hintbase, ht = input->hinttype;
1719 int t;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001720 int it, bt;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001721 int32_t ix, bx; /* register flags */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001722
H. Peter Anvine2c80182005-01-15 22:15:51 +00001723 if (s == 0)
1724 i = -1; /* make this easy, at least */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001725
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001726 if (i >= EXPR_REG_START && i < REG_ENUM_LIMIT) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001727 it = regvals[i];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001728 ix = reg_flags[i];
1729 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001730 it = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001731 ix = 0;
1732 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001733
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001734 if (b != -1 && b >= EXPR_REG_START && b < REG_ENUM_LIMIT) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001735 bt = regvals[b];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001736 bx = reg_flags[b];
1737 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001738 bt = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001739 bx = 0;
1740 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001741
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001742 /* check for a 32/64-bit memory reference... */
1743 if ((ix|bx) & (BITS32|BITS64)) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001744 /* it must be a 32/64-bit memory reference. Firstly we have
1745 * to check that all registers involved are type E/Rxx. */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001746 int32_t sok = BITS32|BITS64;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001747
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001748 if (it != -1) {
1749 if (!(REG64 & ~ix) || !(REG32 & ~ix))
1750 sok &= ix;
1751 else
1752 return NULL;
1753 }
1754
1755 if (bt != -1) {
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001756 if (REG_GPR & ~bx)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001757 return NULL; /* Invalid register */
H. Peter Anvina57e8d42007-05-30 03:44:02 +00001758 if (~sok & bx & SIZE_MASK)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001759 return NULL; /* Invalid size */
1760 sok &= ~bx;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001761 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001762
H. Peter Anvine2c80182005-01-15 22:15:51 +00001763 /* While we're here, ensure the user didn't specify WORD. */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001764 if (input->addr_size == 16 ||
1765 (input->addr_size == 32 && !(sok & BITS32)) ||
1766 (input->addr_size == 64 && !(sok & BITS64)))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001767 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001768
Keith Kaniosb7a89542007-04-12 02:40:54 +00001769 /* now reorganize base/index */
1770 if (s == 1 && bt != it && bt != -1 && it != -1 &&
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001771 ((hb == b && ht == EAH_NOTBASE)
1772 || (hb == i && ht == EAH_MAKEBASE))) {
1773 /* swap if hints say so */
1774 t = bt, bt = it, it = t;
1775 t = bx, bx = ix, ix = t;
1776 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001777 if (bt == it) /* convert EAX+2*EAX to 3*EAX */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001778 bt = -1, bx = 0, s++;
1779 if (bt == -1 && s == 1 && !(hb == it && ht == EAH_NOTBASE)) {
1780 /* make single reg base, unless hint */
1781 bt = it, bx = ix, it = -1, ix = 0;
1782 }
H. Peter Anvinf5843c62007-09-10 18:59:26 +00001783 if (((s == 2 && it != REG_NUM_ESP
H. Peter Anvine2c80182005-01-15 22:15:51 +00001784 && !(input->eaflags & EAF_TIMESTWO)) || s == 3
Keith Kaniosb7a89542007-04-12 02:40:54 +00001785 || s == 5 || s == 9) && bt == -1)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001786 bt = it, bx = ix, s--; /* convert 3*EAX to EAX+2*EAX */
Keith Kanios48af1772007-08-17 07:37:52 +00001787 if (it == -1 && (bt & 7) != REG_NUM_ESP
H. Peter Anvine2c80182005-01-15 22:15:51 +00001788 && (input->eaflags & EAF_TIMESTWO))
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001789 it = bt, ix = bx, bt = -1, bx = 0, s = 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001790 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
Keith Kanios48af1772007-08-17 07:37:52 +00001791 if (s == 1 && it == REG_NUM_ESP) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001792 /* swap ESP into base if scale is 1 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001793 t = it, it = bt, bt = t;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001794 t = ix, ix = bx, bx = t;
1795 }
Keith Kanios48af1772007-08-17 07:37:52 +00001796 if (it == REG_NUM_ESP
Keith Kaniosb7a89542007-04-12 02:40:54 +00001797 || (s != 1 && s != 2 && s != 4 && s != 8 && it != -1))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001798 return NULL; /* wrong, for various reasons */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001799
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001800 output->rex |= rexflags(it, ix, REX_X);
1801 output->rex |= rexflags(bt, bx, REX_B);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001802
Keith Kanios48af1772007-08-17 07:37:52 +00001803 if (it == -1 && (bt & 7) != REG_NUM_ESP) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001804 /* no SIB needed */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001805 int mod, rm;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001806
1807 if (bt == -1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001808 rm = 5;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001809 mod = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001810 } else {
1811 rm = (bt & 7);
Keith Kanios48af1772007-08-17 07:37:52 +00001812 if (rm != REG_NUM_EBP && o == 0 &&
Keith Kaniosb7a89542007-04-12 02:40:54 +00001813 seg == NO_SEG && !forw_ref &&
1814 !(input->eaflags &
1815 (EAF_BYTEOFFS | EAF_WORDOFFS)))
1816 mod = 0;
1817 else if (input->eaflags & EAF_BYTEOFFS ||
1818 (o >= -128 && o <= 127 && seg == NO_SEG
1819 && !forw_ref
1820 && !(input->eaflags & EAF_WORDOFFS)))
1821 mod = 1;
1822 else
1823 mod = 2;
1824 }
H. Peter Anvinea838272002-04-30 20:51:53 +00001825
H. Peter Anvine2c80182005-01-15 22:15:51 +00001826 output->sib_present = FALSE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001827 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
1828 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001829 } else {
1830 /* we need a SIB */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001831 int mod, scale, index, base;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001832
1833 if (it == -1)
1834 index = 4, s = 1;
1835 else
1836 index = (it & 7);
1837
H. Peter Anvine2c80182005-01-15 22:15:51 +00001838 switch (s) {
1839 case 1:
1840 scale = 0;
1841 break;
1842 case 2:
1843 scale = 1;
1844 break;
1845 case 4:
1846 scale = 2;
1847 break;
1848 case 8:
1849 scale = 3;
1850 break;
1851 default: /* then what the smeg is it? */
1852 return NULL; /* panic */
1853 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001854
1855 if (bt == -1) {
1856 base = 5;
1857 mod = 0;
1858 } else {
1859 base = (bt & 7);
Keith Kanios48af1772007-08-17 07:37:52 +00001860 if (base != REG_NUM_EBP && o == 0 &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00001861 seg == NO_SEG && !forw_ref &&
1862 !(input->eaflags &
Keith Kaniosb7a89542007-04-12 02:40:54 +00001863 (EAF_BYTEOFFS | EAF_WORDOFFS)))
1864 mod = 0;
1865 else if (input->eaflags & EAF_BYTEOFFS ||
1866 (o >= -128 && o <= 127 && seg == NO_SEG
1867 && !forw_ref
1868 && !(input->eaflags & EAF_WORDOFFS)))
1869 mod = 1;
1870 else
1871 mod = 2;
1872 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001873
H. Peter Anvine2c80182005-01-15 22:15:51 +00001874 output->sib_present = TRUE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001875 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
1876 output->modrm = (mod << 6) | ((rfield & 7) << 3) | 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001877 output->sib = (scale << 6) | (index << 3) | base;
1878 }
1879 } else { /* it's 16-bit */
1880 int mod, rm;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001881
1882 /* check for 64-bit long mode */
1883 if (addrbits == 64)
1884 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001885
H. Peter Anvine2c80182005-01-15 22:15:51 +00001886 /* check all registers are BX, BP, SI or DI */
1887 if ((b != -1 && b != R_BP && b != R_BX && b != R_SI
1888 && b != R_DI) || (i != -1 && i != R_BP && i != R_BX
1889 && i != R_SI && i != R_DI))
1890 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001891
Keith Kaniosb7a89542007-04-12 02:40:54 +00001892 /* ensure the user didn't specify DWORD/QWORD */
1893 if (input->addr_size == 32 || input->addr_size == 64)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001894 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001895
H. Peter Anvine2c80182005-01-15 22:15:51 +00001896 if (s != 1 && i != -1)
1897 return NULL; /* no can do, in 16-bit EA */
1898 if (b == -1 && i != -1) {
1899 int tmp = b;
1900 b = i;
1901 i = tmp;
1902 } /* swap */
1903 if ((b == R_SI || b == R_DI) && i != -1) {
1904 int tmp = b;
1905 b = i;
1906 i = tmp;
1907 }
1908 /* have BX/BP as base, SI/DI index */
1909 if (b == i)
1910 return NULL; /* shouldn't ever happen, in theory */
1911 if (i != -1 && b != -1 &&
1912 (i == R_BP || i == R_BX || b == R_SI || b == R_DI))
1913 return NULL; /* invalid combinations */
1914 if (b == -1) /* pure offset: handled above */
1915 return NULL; /* so if it gets to here, panic! */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001916
H. Peter Anvine2c80182005-01-15 22:15:51 +00001917 rm = -1;
1918 if (i != -1)
1919 switch (i * 256 + b) {
1920 case R_SI * 256 + R_BX:
1921 rm = 0;
1922 break;
1923 case R_DI * 256 + R_BX:
1924 rm = 1;
1925 break;
1926 case R_SI * 256 + R_BP:
1927 rm = 2;
1928 break;
1929 case R_DI * 256 + R_BP:
1930 rm = 3;
1931 break;
1932 } else
1933 switch (b) {
1934 case R_SI:
1935 rm = 4;
1936 break;
1937 case R_DI:
1938 rm = 5;
1939 break;
1940 case R_BP:
1941 rm = 6;
1942 break;
1943 case R_BX:
1944 rm = 7;
1945 break;
1946 }
1947 if (rm == -1) /* can't happen, in theory */
1948 return NULL; /* so panic if it does */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001949
H. Peter Anvine2c80182005-01-15 22:15:51 +00001950 if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
1951 !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
1952 mod = 0;
1953 else if (input->eaflags & EAF_BYTEOFFS ||
1954 (o >= -128 && o <= 127 && seg == NO_SEG
1955 && !forw_ref
1956 && !(input->eaflags & EAF_WORDOFFS)))
1957 mod = 1;
1958 else
1959 mod = 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001960
H. Peter Anvine2c80182005-01-15 22:15:51 +00001961 output->sib_present = FALSE; /* no SIB - it's 16-bit */
1962 output->bytes = mod; /* bytes of offset needed */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001963 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001964 }
1965 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001966 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001967
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001968 output->size = 1 + output->sib_present + output->bytes;
1969 return output;
1970}
1971
H. Peter Anvine2c80182005-01-15 22:15:51 +00001972static int chsize(operand * input, int addrbits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001973{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001974 if (!(MEMORY & ~input->type)) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001975 int32_t i, b;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001976
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001977 if (input->indexreg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001978 || input->indexreg >= REG_ENUM_LIMIT)
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00001979 i = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001980 else
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001981 i = reg_flags[input->indexreg];
Keith Kaniosb7a89542007-04-12 02:40:54 +00001982
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001983 if (input->basereg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001984 || input->basereg >= REG_ENUM_LIMIT)
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00001985 b = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001986 else
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001987 b = reg_flags[input->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001988
H. Peter Anvine2c80182005-01-15 22:15:51 +00001989 if (input->scale == 0)
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00001990 i = 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001991
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00001992 if (!i && !b) /* pure offset */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001993 return (input->addr_size != 0 && input->addr_size != addrbits);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001994
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001995 if (!(REG32 & ~i) || !(REG32 & ~b))
Keith Kaniosb7a89542007-04-12 02:40:54 +00001996 return (addrbits != 32);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001997 else
1998 return (addrbits == 32);
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001999 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002000 return 0;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002001 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002002}