blob: 7ee67b08b5523a6bb816f6400a4f4278f07a44bd [file] [log] [blame]
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001/* assemble.c code generation for the Netwide Assembler
2 *
3 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
4 * Julian Hall. All rights reserved. The software is
5 * redistributable under the licence given in the file "Licence"
6 * distributed in the NASM archive.
7 *
8 * the actual codes (C syntax, i.e. octal):
9 * \0 - terminates the code. (Unless it's a literal of course.)
10 * \1, \2, \3 - that many literal bytes follow in the code stream
11 * \4, \6 - the POP/PUSH (respectively) codes for CS, DS, ES, SS
12 * (POP is never used for CS) depending on operand 0
13 * \5, \7 - the second byte of POP/PUSH codes for FS, GS, depending
14 * on operand 0
15 * \10, \11, \12 - a literal byte follows in the code stream, to be added
16 * to the register value of operand 0, 1 or 2
17 * \17 - encodes the literal byte 0. (Some compilers don't take
18 * kindly to a zero byte in the _middle_ of a compile time
19 * string constant, so I had to put this hack in.)
20 * \14, \15, \16 - a signed byte immediate operand, from operand 0, 1 or 2
21 * \20, \21, \22 - a byte immediate operand, from operand 0, 1 or 2
22 * \24, \25, \26 - an unsigned byte immediate operand, from operand 0, 1 or 2
23 * \30, \31, \32 - a word immediate operand, from operand 0, 1 or 2
24 * \34, \35, \36 - select between \3[012] and \4[012] depending on 16/32 bit
H. Peter Anvin3ba46772002-05-27 23:19:35 +000025 * assembly mode or the operand-size override on the operand
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000026 * \37 - a word constant, from the _segment_ part of operand 0
27 * \40, \41, \42 - a long immediate operand, from operand 0, 1 or 2
H. Peter Anvinb061d592007-04-16 02:02:06 +000028 * \44, \45, \46 - select between \3[012], \4[012] and \5[456]
29 * depending on assembly mode or the address-size override
30 * on the operand.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000031 * \50, \51, \52 - a byte relative operand, from operand 0, 1 or 2
Keith Kaniosb7a89542007-04-12 02:40:54 +000032 * \54, \55, \56 - a qword immediate operand, from operand 0, 1 or 2
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000033 * \60, \61, \62 - a word relative operand, from operand 0, 1 or 2
34 * \64, \65, \66 - select between \6[012] and \7[012] depending on 16/32 bit
H. Peter Anvin17799b42002-05-21 03:31:21 +000035 * assembly mode or the operand-size override on the operand
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000036 * \70, \71, \72 - a long relative operand, from operand 0, 1 or 2
37 * \1ab - a ModRM, calculated on EA in operand a, with the spare
38 * field the register value of operand b.
H. Peter Anvinaf535c12002-04-30 20:59:21 +000039 * \130,\131,\132 - an immediate word or signed byte for operand 0, 1, or 2
40 * \133,\134,\135 - or 2 (s-field) into next opcode byte if operand 0, 1, or 2
41 * is a signed byte rather than a word.
42 * \140,\141,\142 - an immediate dword or signed byte for operand 0, 1, or 2
43 * \143,\144,\145 - or 2 (s-field) into next opcode byte if operand 0, 1, or 2
44 * is a signed byte rather than a dword.
Keith Kaniosb7a89542007-04-12 02:40:54 +000045 * \150,\151,\152 - an immediate qword or signed byte for operand 0, 1, or 2
46 * \153,\154,\155 - or 2 (s-field) into next opcode byte if operand 0, 1, or 2
47 * is a signed byte rather than a qword.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000048 * \2ab - a ModRM, calculated on EA in operand a, with the spare
49 * field equal to digit b.
50 * \30x - might be an 0x67 byte, depending on the address size of
51 * the memory reference in operand x.
52 * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
53 * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
Keith Kanios48af1772007-08-17 07:37:52 +000054 * \312 - (disassembler only) marker on LOOP, LOOPxx instructions.
H. Peter Anvince2b3972007-05-30 22:21:11 +000055 * \313 - indicates fixed 64-bit address size, 0x67 invalid.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000056 * \320 - indicates fixed 16-bit operand size, i.e. optional 0x66.
57 * \321 - indicates fixed 32-bit operand size, i.e. optional 0x66.
58 * \322 - indicates that this instruction is only valid when the
59 * operand size is the default (instruction to disassembler,
60 * generates no code in the assembler)
H. Peter Anvince2b3972007-05-30 22:21:11 +000061 * \323 - indicates fixed 64-bit operand size, REX on extensions only.
Keith Kaniosb7a89542007-04-12 02:40:54 +000062 * \324 - indicates 64-bit operand size requiring REX prefix.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000063 * \330 - a literal byte follows in the code stream, to be added
64 * to the condition code value of the instruction.
Keith Kanios48af1772007-08-17 07:37:52 +000065 * \331 - instruction not valid with REP prefix. Hint for
H. Peter Anvinef7468f2002-04-30 20:57:59 +000066 * disassembler only; for SSE instructions.
Keith Kanios48af1772007-08-17 07:37:52 +000067 * \332 - disassemble a rep (0xF3 byte) prefix as repe not rep.
68 * \333 - REP prefix (0xF3 byte); for SSE instructions. Not encoded
69 * as a literal byte in order to aid the disassembler.
70 * \334 - LOCK prefix used instead of REX.R
Keith Kaniosb7a89542007-04-12 02:40:54 +000071 * \340 - reserve <operand 0> bytes of uninitialized storage.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000072 * Operand 0 had better be a segmentless constant.
Keith Kanios48af1772007-08-17 07:37:52 +000073 * \366 - operand-size override prefix (0x66); to ensure proper
74 REX prefix placement.
H. Peter Anvin788e6c12002-04-30 21:02:01 +000075 * \370,\371,\372 - match only if operand 0 meets byte jump criteria.
76 * 370 is used for Jcc, 371 is used for JMP.
H. Peter Anvinaf535c12002-04-30 20:59:21 +000077 * \373 - assemble 0x03 if bits==16, 0x05 if bits==32;
78 * used for conditional jump over longer jump
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000079 */
80
81#include <stdio.h>
82#include <string.h>
Keith Kaniosb7a89542007-04-12 02:40:54 +000083#include <inttypes.h>
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000084
85#include "nasm.h"
H. Peter Anvin6768eb72002-04-30 20:52:26 +000086#include "nasmlib.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000087#include "assemble.h"
88#include "insns.h"
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +000089#include "preproc.h"
H. Peter Anvin3df97a72007-05-30 03:25:21 +000090#include "regflags.c"
Keith Kaniosb7a89542007-04-12 02:40:54 +000091#include "regvals.c"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000092
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000093typedef struct {
Keith Kaniosb7a89542007-04-12 02:40:54 +000094 int sib_present; /* is a SIB byte necessary? */
95 int bytes; /* # of bytes of offset needed */
96 int size; /* lazy - this is sib+bytes+1 */
97 uint8_t modrm, sib, rex, rip; /* the bytes themselves */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000098} ea;
99
Keith Kaniosb7a89542007-04-12 02:40:54 +0000100static uint32_t cpu; /* cpu level received from nasm.c */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000101static efunc errfunc;
102static struct ofmt *outfmt;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000103static ListGen *list;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000104
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000105static int32_t calcsize(int32_t, int32_t, int, insn *, const char *);
106static void gencode(int32_t, int32_t, int, insn *, const char *, int32_t);
H. Peter Anvin3360d792007-09-11 04:16:57 +0000107static int matches(const struct itemplate *, insn *, int bits);
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000108static int32_t regflag(const operand *);
109static int32_t regval(const operand *);
110static int rexflags(int, int32_t, int);
111static int op_rexflags(const operand *, int);
H. Peter Anvin5b0e3ec2007-07-07 02:01:08 +0000112static ea *process_ea(operand *, ea *, int, int, int32_t, int);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000113static int chsize(operand *, int);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000114
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000115static void assert_no_prefix(insn * ins, int prefix)
116{
117 int j;
118
119 for (j = 0; j < ins->nprefix; j++) {
120 if (ins->prefixes[j] == prefix) {
121 errfunc(ERR_NONFATAL, "invalid %s prefix", prefix_name(prefix));
122 break;
123 }
124 }
125}
126
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000127/*
128 * This routine wrappers the real output format's output routine,
129 * in order to pass a copy of the data off to the listing file
130 * generator at the same time.
131 */
Keith Kaniosb7a89542007-04-12 02:40:54 +0000132static void out(int32_t offset, int32_t segto, const void *data,
133 uint32_t type, int32_t segment, int32_t wrt)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000134{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000135 static int32_t lineno = 0; /* static!!! */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000136 static char *lnfname = NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000137
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000138 if ((type & OUT_TYPMASK) == OUT_ADDRESS) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000139 if (segment != NO_SEG || wrt != NO_SEG) {
140 /*
141 * This address is relocated. We must write it as
142 * OUT_ADDRESS, so there's no work to be done here.
143 */
144 list->output(offset, data, type);
145 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000146 uint8_t p[8], *q = p;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000147 /*
148 * This is a non-relocated address, and we're going to
149 * convert it into RAWDATA format.
150 */
151 if ((type & OUT_SIZMASK) == 4) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000152 WRITELONG(q, *(int32_t *)data);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000153 list->output(offset, p, OUT_RAWDATA + 4);
Keith Kaniosb7a89542007-04-12 02:40:54 +0000154 } else if ((type & OUT_SIZMASK) == 8) {
155 WRITEDLONG(q, *(int64_t *)data);
156 list->output(offset, p, OUT_RAWDATA + 8);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000157 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000158 WRITESHORT(q, *(int32_t *)data);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000159 list->output(offset, p, OUT_RAWDATA + 2);
160 }
161 }
162 } else if ((type & OUT_TYPMASK) == OUT_RAWDATA) {
163 list->output(offset, data, type);
164 } else if ((type & OUT_TYPMASK) == OUT_RESERVE) {
165 list->output(offset, NULL, type);
166 } else if ((type & OUT_TYPMASK) == OUT_REL2ADR ||
167 (type & OUT_TYPMASK) == OUT_REL4ADR) {
168 list->output(offset, data, type);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000169 }
170
Frank Kotlerabebb082003-09-06 04:45:37 +0000171 /*
172 * this call to src_get determines when we call the
173 * debug-format-specific "linenum" function
174 * it updates lineno and lnfname to the current values
175 * returning 0 if "same as last time", -2 if lnfname
176 * changed, and the amount by which lineno changed,
177 * if it did. thus, these variables must be static
178 */
179
H. Peter Anvine2c80182005-01-15 22:15:51 +0000180 if (src_get(&lineno, &lnfname)) {
181 outfmt->current_dfmt->linenum(lnfname, lineno, segto);
H. Peter Anvince616072002-04-30 21:02:23 +0000182 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000183
H. Peter Anvine2c80182005-01-15 22:15:51 +0000184 outfmt->output(segto, data, type, segment, wrt);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000185}
186
Keith Kaniosb7a89542007-04-12 02:40:54 +0000187static int jmp_match(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000188 insn * ins, const char *code)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000189{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000190 int32_t isize;
191 uint8_t c = code[0];
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000192
H. Peter Anvine2c80182005-01-15 22:15:51 +0000193 if (c != 0370 && c != 0371)
194 return 0;
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000195 if (ins->oprs[0].opflags & OPFLAG_FORWARD) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000196 if ((optimizing < 0 || (ins->oprs[0].type & STRICT))
197 && c == 0370)
198 return 1;
199 else
200 return (pass0 == 0); /* match a forward reference */
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000201 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000202 isize = calcsize(segment, offset, bits, ins, code);
203 if (ins->oprs[0].segment != segment)
204 return 0;
205 isize = ins->oprs[0].offset - offset - isize; /* isize is now the delta */
206 if (isize >= -128L && isize <= 127L)
207 return 1; /* it is byte size */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000208
209 return 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000210}
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000211
Keith Kaniosb7a89542007-04-12 02:40:54 +0000212int32_t assemble(int32_t segment, int32_t offset, int bits, uint32_t cp,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000213 insn * instruction, struct ofmt *output, efunc error,
214 ListGen * listgen)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000215{
H. Peter Anvin3360d792007-09-11 04:16:57 +0000216 const struct itemplate *temp;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000217 int j;
218 int size_prob;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000219 int32_t insn_end;
220 int32_t itimes;
221 int32_t start = offset;
222 int32_t wsize = 0; /* size for DB etc. */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000223
H. Peter Anvine2c80182005-01-15 22:15:51 +0000224 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000225 cpu = cp;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000226 outfmt = output; /* likewise */
227 list = listgen; /* and again */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000228
H. Peter Anvine2c80182005-01-15 22:15:51 +0000229 switch (instruction->opcode) {
230 case -1:
231 return 0;
232 case I_DB:
233 wsize = 1;
234 break;
235 case I_DW:
236 wsize = 2;
237 break;
238 case I_DD:
239 wsize = 4;
240 break;
241 case I_DQ:
242 wsize = 8;
243 break;
244 case I_DT:
245 wsize = 10;
246 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000247 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000248
H. Peter Anvineba20a72002-04-30 20:53:55 +0000249 if (wsize) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000250 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000251 int32_t t = instruction->times;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000252 if (t < 0)
253 errfunc(ERR_PANIC,
254 "instruction->times < 0 (%ld) in assemble()", t);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000255
H. Peter Anvine2c80182005-01-15 22:15:51 +0000256 while (t--) { /* repeat TIMES times */
257 for (e = instruction->eops; e; e = e->next) {
258 if (e->type == EOT_DB_NUMBER) {
259 if (wsize == 1) {
260 if (e->segment != NO_SEG)
261 errfunc(ERR_NONFATAL,
262 "one-byte relocation attempted");
263 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000264 uint8_t out_byte = e->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000265 out(offset, segment, &out_byte,
266 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
267 }
Keith Kanios61ff53c2007-04-14 18:54:52 +0000268 } else if (wsize > 8) {
269 errfunc(ERR_NONFATAL, "integer supplied to a DT"
270 " instruction");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000271 } else
272 out(offset, segment, &e->offset,
273 OUT_ADDRESS + wsize, e->segment, e->wrt);
274 offset += wsize;
275 } else if (e->type == EOT_DB_STRING) {
276 int align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000277
H. Peter Anvine2c80182005-01-15 22:15:51 +0000278 out(offset, segment, e->stringval,
279 OUT_RAWDATA + e->stringlen, NO_SEG, NO_SEG);
280 align = e->stringlen % wsize;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000281
H. Peter Anvine2c80182005-01-15 22:15:51 +0000282 if (align) {
283 align = wsize - align;
284 out(offset, segment, "\0\0\0\0\0\0\0\0",
285 OUT_RAWDATA + align, NO_SEG, NO_SEG);
286 }
287 offset += e->stringlen + align;
288 }
289 }
290 if (t > 0 && t == instruction->times - 1) {
291 /*
292 * Dummy call to list->output to give the offset to the
293 * listing module.
294 */
295 list->output(offset, NULL, OUT_RAWDATA);
296 list->uplevel(LIST_TIMES);
297 }
298 }
299 if (instruction->times > 1)
300 list->downlevel(LIST_TIMES);
301 return offset - start;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000302 }
303
H. Peter Anvine2c80182005-01-15 22:15:51 +0000304 if (instruction->opcode == I_INCBIN) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000305 static char fname[FILENAME_MAX];
H. Peter Anvine2c80182005-01-15 22:15:51 +0000306 FILE *fp;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000307 int32_t len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000308 char *prefix = "", *combine;
309 char **pPrevPath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000310
H. Peter Anvine2c80182005-01-15 22:15:51 +0000311 len = FILENAME_MAX - 1;
312 if (len > instruction->eops->stringlen)
313 len = instruction->eops->stringlen;
314 strncpy(fname, instruction->eops->stringval, len);
315 fname[len] = '\0';
H. Peter Anvineba20a72002-04-30 20:53:55 +0000316
Keith Kaniosb7a89542007-04-12 02:40:54 +0000317 while (1) { /* added by alexfru: 'incbin' uses include paths */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000318 combine = nasm_malloc(strlen(prefix) + len + 1);
319 strcpy(combine, prefix);
320 strcat(combine, fname);
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000321
H. Peter Anvine2c80182005-01-15 22:15:51 +0000322 if ((fp = fopen(combine, "rb")) != NULL) {
323 nasm_free(combine);
324 break;
325 }
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000326
H. Peter Anvine2c80182005-01-15 22:15:51 +0000327 nasm_free(combine);
328 pPrevPath = pp_get_include_path_ptr(pPrevPath);
329 if (pPrevPath == NULL)
330 break;
331 prefix = *pPrevPath;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000332 }
333
334 if (fp == NULL)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000335 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
336 fname);
337 else if (fseek(fp, 0L, SEEK_END) < 0)
338 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
339 fname);
340 else {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000341 static char buf[2048];
Keith Kaniosb7a89542007-04-12 02:40:54 +0000342 int32_t t = instruction->times;
343 int32_t base = 0;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000344
H. Peter Anvine2c80182005-01-15 22:15:51 +0000345 len = ftell(fp);
346 if (instruction->eops->next) {
347 base = instruction->eops->next->offset;
348 len -= base;
349 if (instruction->eops->next->next &&
350 len > instruction->eops->next->next->offset)
351 len = instruction->eops->next->next->offset;
352 }
353 /*
354 * Dummy call to list->output to give the offset to the
355 * listing module.
356 */
357 list->output(offset, NULL, OUT_RAWDATA);
358 list->uplevel(LIST_INCBIN);
359 while (t--) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000360 int32_t l;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000361
H. Peter Anvine2c80182005-01-15 22:15:51 +0000362 fseek(fp, base, SEEK_SET);
363 l = len;
364 while (l > 0) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000365 int32_t m =
H. Peter Anvine2c80182005-01-15 22:15:51 +0000366 fread(buf, 1, (l > sizeof(buf) ? sizeof(buf) : l),
367 fp);
368 if (!m) {
369 /*
370 * This shouldn't happen unless the file
371 * actually changes while we are reading
372 * it.
373 */
374 error(ERR_NONFATAL,
375 "`incbin': unexpected EOF while"
376 " reading file `%s'", fname);
377 t = 0; /* Try to exit cleanly */
378 break;
379 }
380 out(offset, segment, buf, OUT_RAWDATA + m,
381 NO_SEG, NO_SEG);
382 l -= m;
383 }
384 }
385 list->downlevel(LIST_INCBIN);
386 if (instruction->times > 1) {
387 /*
388 * Dummy call to list->output to give the offset to the
389 * listing module.
390 */
391 list->output(offset, NULL, OUT_RAWDATA);
392 list->uplevel(LIST_TIMES);
393 list->downlevel(LIST_TIMES);
394 }
395 fclose(fp);
396 return instruction->times * len;
397 }
398 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000399 }
400
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000401 size_prob = FALSE;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000402
403 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++){
404 int m = matches(temp, instruction, bits);
405
H. Peter Anvine2c80182005-01-15 22:15:51 +0000406 if (m == 99)
407 m += jmp_match(segment, offset, bits, instruction, temp->code);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000408
H. Peter Anvine2c80182005-01-15 22:15:51 +0000409 if (m == 100) { /* matches! */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000410 const char *codes = temp->code;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000411 int32_t insn_size = calcsize(segment, offset, bits,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000412 instruction, codes);
413 itimes = instruction->times;
414 if (insn_size < 0) /* shouldn't be, on pass two */
415 error(ERR_PANIC, "errors made it through from pass one");
416 else
417 while (itimes--) {
418 for (j = 0; j < instruction->nprefix; j++) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000419 uint8_t c = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000420 switch (instruction->prefixes[j]) {
421 case P_LOCK:
422 c = 0xF0;
423 break;
424 case P_REPNE:
425 case P_REPNZ:
426 c = 0xF2;
427 break;
428 case P_REPE:
429 case P_REPZ:
430 case P_REP:
431 c = 0xF3;
432 break;
433 case R_CS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000434 if (bits == 64) {
435 error(ERR_WARNING,
436 "cs segment base ignored in 64-bit mode");
437 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000438 c = 0x2E;
439 break;
440 case R_DS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000441 if (bits == 64) {
442 error(ERR_WARNING,
443 "ds segment base ignored in 64-bit mode");
444 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000445 c = 0x3E;
446 break;
447 case R_ES:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000448 if (bits == 64) {
449 error(ERR_WARNING,
450 "es segment base ignored in 64-bit mode");
451 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000452 c = 0x26;
453 break;
454 case R_FS:
455 c = 0x64;
456 break;
457 case R_GS:
458 c = 0x65;
459 break;
460 case R_SS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000461 if (bits == 64) {
462 error(ERR_WARNING,
463 "ss segment base ignored in 64-bit mode");
464 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000465 c = 0x36;
466 break;
467 case R_SEGR6:
468 case R_SEGR7:
469 error(ERR_NONFATAL,
470 "segr6 and segr7 cannot be used as prefixes");
471 break;
472 case P_A16:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000473 if (bits == 64) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000474 error(ERR_NONFATAL,
475 "16-bit addressing is not supported "
476 "in 64-bit mode");
Keith Kaniosb7a89542007-04-12 02:40:54 +0000477 break;
478 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000479 if (bits != 16)
480 c = 0x67;
481 break;
482 case P_A32:
483 if (bits != 32)
484 c = 0x67;
485 break;
486 case P_O16:
487 if (bits != 16)
488 c = 0x66;
489 break;
490 case P_O32:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000491 if (bits == 16)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000492 c = 0x66;
493 break;
494 default:
495 error(ERR_PANIC, "invalid instruction prefix");
496 }
497 if (c != 0) {
498 out(offset, segment, &c, OUT_RAWDATA + 1,
499 NO_SEG, NO_SEG);
500 offset++;
501 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000502 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000503 insn_end = offset + insn_size;
504 gencode(segment, offset, bits, instruction, codes,
505 insn_end);
506 offset += insn_size;
507 if (itimes > 0 && itimes == instruction->times - 1) {
508 /*
509 * Dummy call to list->output to give the offset to the
510 * listing module.
511 */
512 list->output(offset, NULL, OUT_RAWDATA);
513 list->uplevel(LIST_TIMES);
514 }
515 }
516 if (instruction->times > 1)
517 list->downlevel(LIST_TIMES);
518 return offset - start;
519 } else if (m > 0 && m > size_prob) {
520 size_prob = m;
521 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000522// temp++;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000523 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000524
H. Peter Anvine2c80182005-01-15 22:15:51 +0000525 if (temp->opcode == -1) { /* didn't match any instruction */
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000526 switch (size_prob) {
527 case 1:
528 error(ERR_NONFATAL, "operation size not specified");
529 break;
530 case 2:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000531 error(ERR_NONFATAL, "mismatch in operand sizes");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000532 break;
533 case 3:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000534 error(ERR_NONFATAL, "no instruction for this cpu level");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000535 break;
536 case 4:
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000537 error(ERR_NONFATAL, "instruction not supported in 64-bit mode");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000538 break;
539 default:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000540 error(ERR_NONFATAL,
541 "invalid combination of opcode and operands");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000542 break;
543 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000544 }
545 return 0;
546}
547
Keith Kaniosb7a89542007-04-12 02:40:54 +0000548int32_t insn_size(int32_t segment, int32_t offset, int bits, uint32_t cp,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000549 insn * instruction, efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000550{
H. Peter Anvin3360d792007-09-11 04:16:57 +0000551 const struct itemplate *temp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000552
H. Peter Anvine2c80182005-01-15 22:15:51 +0000553 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000554 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000555
556 if (instruction->opcode == -1)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000557 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000558
559 if (instruction->opcode == I_DB ||
H. Peter Anvine2c80182005-01-15 22:15:51 +0000560 instruction->opcode == I_DW ||
561 instruction->opcode == I_DD ||
562 instruction->opcode == I_DQ || instruction->opcode == I_DT) {
563 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000564 int32_t isize, osize, wsize = 0; /* placate gcc */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000565
H. Peter Anvine2c80182005-01-15 22:15:51 +0000566 isize = 0;
567 switch (instruction->opcode) {
568 case I_DB:
569 wsize = 1;
570 break;
571 case I_DW:
572 wsize = 2;
573 break;
574 case I_DD:
575 wsize = 4;
576 break;
577 case I_DQ:
578 wsize = 8;
579 break;
580 case I_DT:
581 wsize = 10;
582 break;
583 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000584
H. Peter Anvine2c80182005-01-15 22:15:51 +0000585 for (e = instruction->eops; e; e = e->next) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000586 int32_t align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000587
H. Peter Anvine2c80182005-01-15 22:15:51 +0000588 osize = 0;
589 if (e->type == EOT_DB_NUMBER)
590 osize = 1;
591 else if (e->type == EOT_DB_STRING)
592 osize = e->stringlen;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000593
H. Peter Anvine2c80182005-01-15 22:15:51 +0000594 align = (-osize) % wsize;
595 if (align < 0)
596 align += wsize;
597 isize += osize + align;
598 }
599 return isize * instruction->times;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000600 }
601
H. Peter Anvine2c80182005-01-15 22:15:51 +0000602 if (instruction->opcode == I_INCBIN) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000603 char fname[FILENAME_MAX];
H. Peter Anvine2c80182005-01-15 22:15:51 +0000604 FILE *fp;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000605 int32_t len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000606 char *prefix = "", *combine;
607 char **pPrevPath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000608
H. Peter Anvine2c80182005-01-15 22:15:51 +0000609 len = FILENAME_MAX - 1;
610 if (len > instruction->eops->stringlen)
611 len = instruction->eops->stringlen;
612 strncpy(fname, instruction->eops->stringval, len);
613 fname[len] = '\0';
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000614
H. Peter Anvine2c80182005-01-15 22:15:51 +0000615 while (1) { /* added by alexfru: 'incbin' uses include paths */
616 combine = nasm_malloc(strlen(prefix) + len + 1);
617 strcpy(combine, prefix);
618 strcat(combine, fname);
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000619
H. Peter Anvine2c80182005-01-15 22:15:51 +0000620 if ((fp = fopen(combine, "rb")) != NULL) {
621 nasm_free(combine);
622 break;
623 }
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000624
H. Peter Anvine2c80182005-01-15 22:15:51 +0000625 nasm_free(combine);
626 pPrevPath = pp_get_include_path_ptr(pPrevPath);
627 if (pPrevPath == NULL)
628 break;
629 prefix = *pPrevPath;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000630 }
631
632 if (fp == NULL)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000633 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
634 fname);
635 else if (fseek(fp, 0L, SEEK_END) < 0)
636 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
637 fname);
638 else {
639 len = ftell(fp);
640 fclose(fp);
641 if (instruction->eops->next) {
642 len -= instruction->eops->next->offset;
643 if (instruction->eops->next->next &&
644 len > instruction->eops->next->next->offset) {
645 len = instruction->eops->next->next->offset;
646 }
647 }
648 return instruction->times * len;
649 }
650 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000651 }
652
Keith Kaniosb7a89542007-04-12 02:40:54 +0000653 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++) {
654 int m = matches(temp, instruction, bits);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000655 if (m == 99)
656 m += jmp_match(segment, offset, bits, instruction, temp->code);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000657
H. Peter Anvine2c80182005-01-15 22:15:51 +0000658 if (m == 100) {
659 /* we've matched an instruction. */
Keith Kaniosb7a89542007-04-12 02:40:54 +0000660 int32_t isize;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000661 const char *codes = temp->code;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000662 int j;
663
664 isize = calcsize(segment, offset, bits, instruction, codes);
665 if (isize < 0)
666 return -1;
667 for (j = 0; j < instruction->nprefix; j++) {
668 if ((instruction->prefixes[j] != P_A16 &&
669 instruction->prefixes[j] != P_O16 && bits == 16) ||
670 (instruction->prefixes[j] != P_A32 &&
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000671 instruction->prefixes[j] != P_O32 && bits >= 32)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000672 isize++;
673 }
674 }
675 return isize * instruction->times;
676 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000677 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000678 return -1; /* didn't match any instruction */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000679}
680
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000681/* check that opn[op] is a signed byte of size 16 or 32,
682 and return the signed value*/
H. Peter Anvine2c80182005-01-15 22:15:51 +0000683static int is_sbyte(insn * ins, int op, int size)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000684{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000685 int32_t v;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000686 int ret;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000687
688 ret = !(ins->forw_ref && ins->oprs[op].opflags) && /* dead in the water on forward reference or External */
689 optimizing >= 0 &&
690 !(ins->oprs[op].type & STRICT) &&
691 ins->oprs[op].wrt == NO_SEG && ins->oprs[op].segment == NO_SEG;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000692
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000693 v = ins->oprs[op].offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000694 if (size == 16)
Keith Kaniosb7a89542007-04-12 02:40:54 +0000695 v = (int16_t)v; /* sign extend if 16 bits */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000696
697 return ret && v >= -128L && v <= 127L;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000698}
699
Keith Kaniosb7a89542007-04-12 02:40:54 +0000700static int32_t calcsize(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000701 insn * ins, const char *codes)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000702{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000703 int32_t length = 0;
704 uint8_t c;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000705 int rex_mask = ~0;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000706 ins->rex = 0; /* Ensure REX is reset */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000707
H. Peter Anvine2c80182005-01-15 22:15:51 +0000708 (void)segment; /* Don't warn that this parameter is unused */
709 (void)offset; /* Don't warn that this parameter is unused */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000710
H. Peter Anvine2c80182005-01-15 22:15:51 +0000711 while (*codes)
712 switch (c = *codes++) {
713 case 01:
714 case 02:
715 case 03:
716 codes += c, length += c;
717 break;
718 case 04:
719 case 05:
720 case 06:
721 case 07:
722 length++;
723 break;
724 case 010:
725 case 011:
726 case 012:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000727 ins->rex |=
728 op_rexflags(&ins->oprs[c - 010], REX_B|REX_H|REX_P|REX_W);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000729 codes++, length++;
730 break;
731 case 017:
732 length++;
733 break;
734 case 014:
735 case 015:
736 case 016:
737 length++;
738 break;
739 case 020:
740 case 021:
741 case 022:
742 length++;
743 break;
744 case 024:
745 case 025:
746 case 026:
747 length++;
748 break;
749 case 030:
750 case 031:
751 case 032:
752 length += 2;
753 break;
754 case 034:
755 case 035:
756 case 036:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000757 if (ins->oprs[c - 034].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000758 length += (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
759 else
760 length += (bits == 16) ? 2 : 4;
761 break;
762 case 037:
763 length += 2;
764 break;
765 case 040:
766 case 041:
767 case 042:
768 length += 4;
769 break;
770 case 044:
771 case 045:
772 case 046:
773 length += ((ins->oprs[c - 044].addr_size ?
Keith Kaniosb7a89542007-04-12 02:40:54 +0000774 ins->oprs[c - 044].addr_size : bits) >> 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000775 break;
776 case 050:
777 case 051:
778 case 052:
779 length++;
780 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000781 case 054:
782 case 055:
783 case 056:
784 length += 8; /* MOV reg64/imm */
785 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000786 case 060:
787 case 061:
788 case 062:
789 length += 2;
790 break;
791 case 064:
792 case 065:
793 case 066:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000794 if (ins->oprs[c - 064].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000795 length += (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
796 else
797 length += (bits == 16) ? 2 : 4;
798 break;
799 case 070:
800 case 071:
801 case 072:
802 length += 4;
803 break;
804 case 0130:
805 case 0131:
806 case 0132:
807 length += is_sbyte(ins, c - 0130, 16) ? 1 : 2;
808 break;
809 case 0133:
810 case 0134:
811 case 0135:
812 codes += 2;
813 length++;
814 break;
815 case 0140:
816 case 0141:
817 case 0142:
818 length += is_sbyte(ins, c - 0140, 32) ? 1 : 4;
819 break;
820 case 0143:
821 case 0144:
822 case 0145:
823 codes += 2;
824 length++;
825 break;
826 case 0300:
827 case 0301:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000828 case 0302:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000829 length += chsize(&ins->oprs[c - 0300], bits);
830 break;
831 case 0310:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000832 length += (bits != 16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000833 break;
834 case 0311:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000835 length += (bits != 32);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000836 break;
837 case 0312:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000838 break;
839 case 0313:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000840 break;
841 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000842 length += (bits != 16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000843 break;
844 case 0321:
845 length += (bits == 16);
846 break;
847 case 0322:
848 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000849 case 0323:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000850 rex_mask &= ~REX_W;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000851 break;
852 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000853 ins->rex |= REX_W;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000854 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000855 case 0330:
856 codes++, length++;
857 break;
858 case 0331:
859 case 0332:
860 break;
861 case 0333:
862 length++;
863 break;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000864 case 0334:
865 assert_no_prefix(ins, P_LOCK);
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000866 ins->rex |= REX_L;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000867 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000868 case 0340:
869 case 0341:
870 case 0342:
871 if (ins->oprs[0].segment != NO_SEG)
872 errfunc(ERR_NONFATAL, "attempt to reserve non-constant"
873 " quantity of BSS space");
874 else
875 length += ins->oprs[0].offset << (c - 0340);
876 break;
Keith Kanios48af1772007-08-17 07:37:52 +0000877 case 0366:
878 length++;
879 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000880 case 0370:
881 case 0371:
882 case 0372:
883 break;
884 case 0373:
885 length++;
886 break;
887 default: /* can't do it by 'case' statements */
888 if (c >= 0100 && c <= 0277) { /* it's an EA */
889 ea ea_data;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000890 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000891 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000892 ea_data.rex = 0; /* Ensure ea.REX is initially 0 */
893
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000894 if (c <= 0177) {
895 /* pick rfield from operand b */
896 rflags = regflag(&ins->oprs[c & 7]);
897 rfield = regvals[ins->oprs[c & 7].basereg];
898 } else {
899 rflags = 0;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000900 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000901 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000902
H. Peter Anvine2c80182005-01-15 22:15:51 +0000903 if (!process_ea
Keith Kaniosb7a89542007-04-12 02:40:54 +0000904 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000905 rfield, rflags, ins->forw_ref)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000906 errfunc(ERR_NONFATAL, "invalid effective address");
907 return -1;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000908 } else {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000909 ins->rex |= ea_data.rex;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000910 length += ea_data.size;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000911 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000912 } else
913 errfunc(ERR_PANIC, "internal instruction table corrupt"
914 ": instruction code 0x%02X given", c);
915 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000916
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000917 ins->rex &= rex_mask;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000918 if (ins->rex & REX_REAL) {
919 if (ins->rex & REX_H) {
920 errfunc(ERR_NONFATAL, "cannot use high register in rex instruction");
921 return -1;
922 } else if (bits == 64 ||
923 ((ins->rex & REX_L) &&
924 !(ins->rex & (REX_P|REX_W|REX_X|REX_B)) &&
925 cpu >= IF_X86_64)) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000926 length++;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000927 } else {
928 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
929 return -1;
930 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000931 }
932
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000933 return length;
934}
Keith Kaniosb7a89542007-04-12 02:40:54 +0000935
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000936#define EMIT_REX() \
937 if((ins->rex & REX_REAL) && (bits == 64)) { \
938 ins->rex = (ins->rex & REX_REAL)|REX_P; \
939 out(offset, segment, &ins->rex, OUT_RAWDATA+1, NO_SEG, NO_SEG); \
940 ins->rex = 0; \
941 offset += 1; \
942 }
943
Keith Kaniosb7a89542007-04-12 02:40:54 +0000944static void gencode(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000945 insn * ins, const char *codes, int32_t insn_end)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000946{
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000947 static char condval[] = { /* conditional opcodes */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000948 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
949 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
950 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000951 };
Keith Kaniosb7a89542007-04-12 02:40:54 +0000952 uint8_t c;
953 uint8_t bytes[4];
954 int32_t size;
955 int64_t data;
956
H. Peter Anvineba20a72002-04-30 20:53:55 +0000957 while (*codes)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000958 switch (c = *codes++) {
959 case 01:
960 case 02:
961 case 03:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000962 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +0000963 out(offset, segment, codes, OUT_RAWDATA + c, NO_SEG, NO_SEG);
964 codes += c;
965 offset += c;
966 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000967
H. Peter Anvine2c80182005-01-15 22:15:51 +0000968 case 04:
969 case 06:
970 switch (ins->oprs[0].basereg) {
971 case R_CS:
972 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0);
973 break;
974 case R_DS:
975 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0);
976 break;
977 case R_ES:
978 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0);
979 break;
980 case R_SS:
981 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0);
982 break;
983 default:
984 errfunc(ERR_PANIC,
985 "bizarre 8086 segment register received");
986 }
987 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
988 offset++;
989 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000990
H. Peter Anvine2c80182005-01-15 22:15:51 +0000991 case 05:
992 case 07:
993 switch (ins->oprs[0].basereg) {
994 case R_FS:
995 bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0);
996 break;
997 case R_GS:
998 bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0);
999 break;
1000 default:
1001 errfunc(ERR_PANIC,
1002 "bizarre 386 segment register received");
1003 }
1004 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1005 offset++;
1006 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001007
H. Peter Anvine2c80182005-01-15 22:15:51 +00001008 case 010:
1009 case 011:
1010 case 012:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001011 EMIT_REX();
Keith Kaniosb7a89542007-04-12 02:40:54 +00001012 bytes[0] = *codes++ + ((regval(&ins->oprs[c - 010])) & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001013 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1014 offset += 1;
1015 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001016
H. Peter Anvine2c80182005-01-15 22:15:51 +00001017 case 017:
1018 bytes[0] = 0;
1019 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 014:
1024 case 015:
1025 case 016:
1026 if (ins->oprs[c - 014].offset < -128
1027 || ins->oprs[c - 014].offset > 127) {
1028 errfunc(ERR_WARNING, "signed byte value exceeds bounds");
1029 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001030
H. Peter Anvine2c80182005-01-15 22:15:51 +00001031 if (ins->oprs[c - 014].segment != NO_SEG) {
1032 data = ins->oprs[c - 014].offset;
1033 out(offset, segment, &data, OUT_ADDRESS + 1,
1034 ins->oprs[c - 014].segment, ins->oprs[c - 014].wrt);
1035 } else {
1036 bytes[0] = ins->oprs[c - 014].offset;
1037 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1038 NO_SEG);
1039 }
1040 offset += 1;
1041 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001042
H. Peter Anvine2c80182005-01-15 22:15:51 +00001043 case 020:
1044 case 021:
1045 case 022:
1046 if (ins->oprs[c - 020].offset < -256
1047 || ins->oprs[c - 020].offset > 255) {
1048 errfunc(ERR_WARNING, "byte value exceeds bounds");
1049 }
1050 if (ins->oprs[c - 020].segment != NO_SEG) {
1051 data = ins->oprs[c - 020].offset;
1052 out(offset, segment, &data, OUT_ADDRESS + 1,
1053 ins->oprs[c - 020].segment, ins->oprs[c - 020].wrt);
1054 } else {
1055 bytes[0] = ins->oprs[c - 020].offset;
1056 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1057 NO_SEG);
1058 }
1059 offset += 1;
1060 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001061
H. Peter Anvine2c80182005-01-15 22:15:51 +00001062 case 024:
1063 case 025:
1064 case 026:
1065 if (ins->oprs[c - 024].offset < 0
1066 || ins->oprs[c - 024].offset > 255)
1067 errfunc(ERR_WARNING, "unsigned byte value exceeds bounds");
1068 if (ins->oprs[c - 024].segment != NO_SEG) {
1069 data = ins->oprs[c - 024].offset;
1070 out(offset, segment, &data, OUT_ADDRESS + 1,
1071 ins->oprs[c - 024].segment, ins->oprs[c - 024].wrt);
1072 } else {
1073 bytes[0] = ins->oprs[c - 024].offset;
1074 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1075 NO_SEG);
1076 }
1077 offset += 1;
1078 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001079
H. Peter Anvine2c80182005-01-15 22:15:51 +00001080 case 030:
1081 case 031:
1082 case 032:
1083 if (ins->oprs[c - 030].segment == NO_SEG &&
1084 ins->oprs[c - 030].wrt == NO_SEG &&
1085 (ins->oprs[c - 030].offset < -65536L ||
1086 ins->oprs[c - 030].offset > 65535L)) {
1087 errfunc(ERR_WARNING, "word value exceeds bounds");
1088 }
1089 data = ins->oprs[c - 030].offset;
1090 out(offset, segment, &data, OUT_ADDRESS + 2,
1091 ins->oprs[c - 030].segment, ins->oprs[c - 030].wrt);
1092 offset += 2;
1093 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001094
H. Peter Anvine2c80182005-01-15 22:15:51 +00001095 case 034:
1096 case 035:
1097 case 036:
1098 if (ins->oprs[c - 034].type & (BITS16 | BITS32))
1099 size = (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
1100 else
1101 size = (bits == 16) ? 2 : 4;
1102 data = ins->oprs[c - 034].offset;
1103 if (size == 2 && (data < -65536L || data > 65535L))
1104 errfunc(ERR_WARNING, "word value exceeds bounds");
1105 out(offset, segment, &data, OUT_ADDRESS + size,
1106 ins->oprs[c - 034].segment, ins->oprs[c - 034].wrt);
1107 offset += size;
1108 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001109
H. Peter Anvine2c80182005-01-15 22:15:51 +00001110 case 037:
1111 if (ins->oprs[0].segment == NO_SEG)
1112 errfunc(ERR_NONFATAL, "value referenced by FAR is not"
1113 " relocatable");
1114 data = 0L;
1115 out(offset, segment, &data, OUT_ADDRESS + 2,
1116 outfmt->segbase(1 + ins->oprs[0].segment),
1117 ins->oprs[0].wrt);
1118 offset += 2;
1119 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001120
H. Peter Anvine2c80182005-01-15 22:15:51 +00001121 case 040:
1122 case 041:
1123 case 042:
1124 data = ins->oprs[c - 040].offset;
1125 out(offset, segment, &data, OUT_ADDRESS + 4,
1126 ins->oprs[c - 040].segment, ins->oprs[c - 040].wrt);
1127 offset += 4;
1128 break;
H. Peter Anvin3ba46772002-05-27 23:19:35 +00001129
H. Peter Anvine2c80182005-01-15 22:15:51 +00001130 case 044:
1131 case 045:
1132 case 046:
1133 data = ins->oprs[c - 044].offset;
1134 size = ((ins->oprs[c - 044].addr_size ?
Keith Kaniosb7a89542007-04-12 02:40:54 +00001135 ins->oprs[c - 044].addr_size : bits) >> 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001136 if (size == 2 && (data < -65536L || data > 65535L))
1137 errfunc(ERR_WARNING, "word value exceeds bounds");
1138 out(offset, segment, &data, OUT_ADDRESS + size,
1139 ins->oprs[c - 044].segment, ins->oprs[c - 044].wrt);
1140 offset += size;
1141 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001142
H. Peter Anvine2c80182005-01-15 22:15:51 +00001143 case 050:
1144 case 051:
1145 case 052:
1146 if (ins->oprs[c - 050].segment != segment)
1147 errfunc(ERR_NONFATAL,
1148 "short relative jump outside segment");
1149 data = ins->oprs[c - 050].offset - insn_end;
1150 if (data > 127 || data < -128)
1151 errfunc(ERR_NONFATAL, "short jump is out of range");
1152 bytes[0] = data;
1153 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1154 offset += 1;
1155 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001156
1157 case 054:
1158 case 055:
1159 case 056:
1160 data = (int64_t)ins->oprs[c - 054].offset;
1161 out(offset, segment, &data, OUT_ADDRESS + 8,
1162 ins->oprs[c - 054].segment, ins->oprs[c - 054].wrt);
1163 offset += 8;
1164 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001165
H. Peter Anvine2c80182005-01-15 22:15:51 +00001166 case 060:
1167 case 061:
1168 case 062:
1169 if (ins->oprs[c - 060].segment != segment) {
1170 data = ins->oprs[c - 060].offset;
1171 out(offset, segment, &data,
1172 OUT_REL2ADR + insn_end - offset,
1173 ins->oprs[c - 060].segment, ins->oprs[c - 060].wrt);
1174 } else {
1175 data = ins->oprs[c - 060].offset - insn_end;
1176 out(offset, segment, &data,
1177 OUT_ADDRESS + 2, NO_SEG, NO_SEG);
1178 }
1179 offset += 2;
1180 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001181
H. Peter Anvine2c80182005-01-15 22:15:51 +00001182 case 064:
1183 case 065:
1184 case 066:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001185 if (ins->oprs[c - 064].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001186 size = (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
1187 else
1188 size = (bits == 16) ? 2 : 4;
1189 if (ins->oprs[c - 064].segment != segment) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001190 int32_t reltype = (size == 2 ? OUT_REL2ADR : OUT_REL4ADR);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001191 data = ins->oprs[c - 064].offset;
1192 out(offset, segment, &data, reltype + insn_end - offset,
1193 ins->oprs[c - 064].segment, ins->oprs[c - 064].wrt);
1194 } else {
1195 data = ins->oprs[c - 064].offset - insn_end;
1196 out(offset, segment, &data,
1197 OUT_ADDRESS + size, NO_SEG, NO_SEG);
1198 }
1199 offset += size;
1200 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001201
H. Peter Anvine2c80182005-01-15 22:15:51 +00001202 case 070:
1203 case 071:
1204 case 072:
1205 if (ins->oprs[c - 070].segment != segment) {
1206 data = ins->oprs[c - 070].offset;
1207 out(offset, segment, &data,
1208 OUT_REL4ADR + insn_end - offset,
1209 ins->oprs[c - 070].segment, ins->oprs[c - 070].wrt);
1210 } else {
1211 data = ins->oprs[c - 070].offset - insn_end;
1212 out(offset, segment, &data,
1213 OUT_ADDRESS + 4, NO_SEG, NO_SEG);
1214 }
1215 offset += 4;
1216 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001217
H. Peter Anvine2c80182005-01-15 22:15:51 +00001218 case 0130:
1219 case 0131:
1220 case 0132:
1221 data = ins->oprs[c - 0130].offset;
1222 if (is_sbyte(ins, c - 0130, 16)) {
1223 bytes[0] = data;
1224 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1225 NO_SEG);
1226 offset++;
1227 } else {
1228 if (ins->oprs[c - 0130].segment == NO_SEG &&
1229 ins->oprs[c - 0130].wrt == NO_SEG &&
1230 (data < -65536L || data > 65535L)) {
1231 errfunc(ERR_WARNING, "word value exceeds bounds");
1232 }
1233 out(offset, segment, &data, OUT_ADDRESS + 2,
1234 ins->oprs[c - 0130].segment, ins->oprs[c - 0130].wrt);
1235 offset += 2;
1236 }
1237 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001238
H. Peter Anvine2c80182005-01-15 22:15:51 +00001239 case 0133:
1240 case 0134:
1241 case 0135:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001242 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001243 codes++;
1244 bytes[0] = *codes++;
1245 if (is_sbyte(ins, c - 0133, 16))
1246 bytes[0] |= 2; /* s-bit */
1247 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1248 offset++;
1249 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001250
H. Peter Anvine2c80182005-01-15 22:15:51 +00001251 case 0140:
1252 case 0141:
1253 case 0142:
1254 data = ins->oprs[c - 0140].offset;
1255 if (is_sbyte(ins, c - 0140, 32)) {
1256 bytes[0] = data;
1257 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1258 NO_SEG);
1259 offset++;
1260 } else {
1261 out(offset, segment, &data, OUT_ADDRESS + 4,
1262 ins->oprs[c - 0140].segment, ins->oprs[c - 0140].wrt);
1263 offset += 4;
1264 }
1265 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001266
H. Peter Anvine2c80182005-01-15 22:15:51 +00001267 case 0143:
1268 case 0144:
1269 case 0145:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001270 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001271 codes++;
1272 bytes[0] = *codes++;
1273 if (is_sbyte(ins, c - 0143, 32))
1274 bytes[0] |= 2; /* s-bit */
1275 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1276 offset++;
1277 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001278
H. Peter Anvine2c80182005-01-15 22:15:51 +00001279 case 0300:
1280 case 0301:
1281 case 0302:
1282 if (chsize(&ins->oprs[c - 0300], bits)) {
1283 *bytes = 0x67;
1284 out(offset, segment, bytes,
1285 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1286 offset += 1;
1287 } else
1288 offset += 0;
1289 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001290
H. Peter Anvine2c80182005-01-15 22:15:51 +00001291 case 0310:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001292 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001293 *bytes = 0x67;
1294 out(offset, segment, bytes,
1295 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1296 offset += 1;
1297 } else
1298 offset += 0;
1299 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001300
H. Peter Anvine2c80182005-01-15 22:15:51 +00001301 case 0311:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001302 if (bits != 32) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001303 *bytes = 0x67;
1304 out(offset, segment, bytes,
1305 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1306 offset += 1;
1307 } else
1308 offset += 0;
1309 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001310
H. Peter Anvine2c80182005-01-15 22:15:51 +00001311 case 0312:
1312 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001313
Keith Kaniosb7a89542007-04-12 02:40:54 +00001314 case 0313:
1315 ins->rex = 0;
1316 break;
1317
H. Peter Anvine2c80182005-01-15 22:15:51 +00001318 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001319 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001320 *bytes = 0x66;
1321 out(offset, segment, bytes,
1322 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1323 offset += 1;
1324 } else
1325 offset += 0;
1326 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001327
H. Peter Anvine2c80182005-01-15 22:15:51 +00001328 case 0321:
1329 if (bits == 16) {
1330 *bytes = 0x66;
1331 out(offset, segment, bytes,
1332 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1333 offset += 1;
1334 } else
1335 offset += 0;
1336 break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001337
H. Peter Anvine2c80182005-01-15 22:15:51 +00001338 case 0322:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001339 case 0323:
1340 break;
1341
1342 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001343 ins->rex |= REX_W;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001344 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001345
H. Peter Anvine2c80182005-01-15 22:15:51 +00001346 case 0330:
1347 *bytes = *codes++ ^ condval[ins->condition];
1348 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1349 offset += 1;
1350 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001351
H. Peter Anvine2c80182005-01-15 22:15:51 +00001352 case 0331:
1353 case 0332:
1354 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001355
H. Peter Anvine2c80182005-01-15 22:15:51 +00001356 case 0333:
1357 *bytes = 0xF3;
1358 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1359 offset += 1;
1360 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001361
Keith Kanios48af1772007-08-17 07:37:52 +00001362 case 0334:
1363 if (ins->rex & REX_R) {
1364 *bytes = 0xF0;
1365 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1366 offset += 1;
1367 }
1368 ins->rex &= ~(REX_L|REX_R);
1369 break;
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001370
H. Peter Anvine2c80182005-01-15 22:15:51 +00001371 case 0340:
1372 case 0341:
1373 case 0342:
1374 if (ins->oprs[0].segment != NO_SEG)
1375 errfunc(ERR_PANIC, "non-constant BSS size in pass two");
1376 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001377 int32_t size = ins->oprs[0].offset << (c - 0340);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001378 if (size > 0)
1379 out(offset, segment, NULL,
1380 OUT_RESERVE + size, NO_SEG, NO_SEG);
1381 offset += size;
1382 }
1383 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001384
Keith Kanios48af1772007-08-17 07:37:52 +00001385 case 0366:
1386 *bytes = 0x66;
1387 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1388 offset += 1;
1389 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001390 case 0370:
1391 case 0371:
1392 case 0372:
1393 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001394
H. Peter Anvine2c80182005-01-15 22:15:51 +00001395 case 0373:
1396 *bytes = bits == 16 ? 3 : 5;
1397 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1398 offset += 1;
1399 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001400
H. Peter Anvine2c80182005-01-15 22:15:51 +00001401 default: /* can't do it by 'case' statements */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001402 if (c >= 0100 && c <= 0277) { /* it's an EA */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001403 ea ea_data;
1404 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001405 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001406 uint8_t *p;
1407 int32_t s;
1408
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001409 if (c <= 0177) {
1410 /* pick rfield from operand b */
1411 rflags = regflag(&ins->oprs[c & 7]);
1412 rfield = regvals[ins->oprs[c & 7].basereg];
1413 } else {
1414 /* rfield is constant */
1415 rflags = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001416 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001417 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001418
1419 if (!process_ea
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001420 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
1421 rfield, rflags, ins->forw_ref)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001422 errfunc(ERR_NONFATAL, "invalid effective address");
1423 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001424
H. Peter Anvine2c80182005-01-15 22:15:51 +00001425 p = bytes;
1426 *p++ = ea_data.modrm;
1427 if (ea_data.sib_present)
1428 *p++ = ea_data.sib;
1429
1430 s = p - bytes;
1431 out(offset, segment, bytes, OUT_RAWDATA + s,
1432 NO_SEG, NO_SEG);
1433
1434 switch (ea_data.bytes) {
1435 case 0:
1436 break;
1437 case 1:
1438 if (ins->oprs[(c >> 3) & 7].segment != NO_SEG) {
1439 data = ins->oprs[(c >> 3) & 7].offset;
1440 out(offset, segment, &data, OUT_ADDRESS + 1,
1441 ins->oprs[(c >> 3) & 7].segment,
1442 ins->oprs[(c >> 3) & 7].wrt);
1443 } else {
1444 *bytes = ins->oprs[(c >> 3) & 7].offset;
1445 out(offset, segment, bytes, OUT_RAWDATA + 1,
1446 NO_SEG, NO_SEG);
1447 }
1448 s++;
1449 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001450 case 8:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001451 case 2:
1452 case 4:
1453 data = ins->oprs[(c >> 3) & 7].offset;
Keith Kaniose83b3182007-04-16 14:31:54 +00001454 if (ea_data.rip && (ins->oprs[(c >> 3) & 7].segment == 0xFFFFFFFF))
1455 ea_data.rip = 0; /* Make distinction between Symbols and Immediates */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001456 out(offset, segment, &data, /* RIP = Relative, not Absolute */
1457 (ea_data.rip ? OUT_REL4ADR : OUT_ADDRESS) + ea_data.bytes,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001458 ins->oprs[(c >> 3) & 7].segment,
1459 ins->oprs[(c >> 3) & 7].wrt);
1460 s += ea_data.bytes;
1461 break;
1462 }
1463 offset += s;
1464 } else
1465 errfunc(ERR_PANIC, "internal instruction table corrupt"
1466 ": instruction code 0x%02X given", c);
1467 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001468}
1469
H. Peter Anvin0ec60e62007-07-07 01:59:52 +00001470static int32_t regflag(const operand * o)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001471{
1472 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1473 errfunc(ERR_PANIC, "invalid operand passed to regflag()");
1474 }
1475 return reg_flags[o->basereg];
1476}
1477
H. Peter Anvin5b0e3ec2007-07-07 02:01:08 +00001478static int32_t regval(const operand * o)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001479{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001480 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1481 errfunc(ERR_PANIC, "invalid operand passed to regval()");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001482 }
H. Peter Anvin232badb2002-06-06 02:41:20 +00001483 return regvals[o->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001484}
1485
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001486static int op_rexflags(const operand * o, int mask)
1487{
1488 int32_t flags;
1489 int val;
1490
1491 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1492 errfunc(ERR_PANIC, "invalid operand passed to op_rexflags()");
1493 }
1494
1495 flags = reg_flags[o->basereg];
1496 val = regvals[o->basereg];
1497
1498 return rexflags(val, flags, mask);
1499}
1500
1501static int rexflags(int val, int32_t flags, int mask)
1502{
1503 int rex = 0;
1504
1505 if (val >= 8)
1506 rex |= REX_B|REX_X|REX_R;
1507 if (flags & BITS64)
1508 rex |= REX_W;
1509 if (!(REG_HIGH & ~flags)) /* AH, CH, DH, BH */
1510 rex |= REX_H;
1511 else if (!(REG8 & ~flags) && val >= 4) /* SPL, BPL, SIL, DIL */
1512 rex |= REX_P;
1513
1514 return rex & mask;
1515}
1516
H. Peter Anvin3360d792007-09-11 04:16:57 +00001517static int matches(const struct itemplate *itemp, insn * instruction, int bits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001518{
H. Peter Anvin34539fb2007-05-30 04:27:58 +00001519 int i, size[3], asize, oprs, ret;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001520
1521 ret = 100;
1522
1523 /*
1524 * Check the opcode
1525 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001526 if (itemp->opcode != instruction->opcode)
1527 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001528
1529 /*
1530 * Count the operands
1531 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001532 if (itemp->operands != instruction->operands)
1533 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001534
1535 /*
1536 * Check that no spurious colons or TOs are present
1537 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001538 for (i = 0; i < itemp->operands; i++)
1539 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON | TO))
1540 return 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001541
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001542 /*
1543 * Check that the operand flags all match up
1544 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001545 for (i = 0; i < itemp->operands; i++)
1546 if (itemp->opd[i] & ~instruction->oprs[i].type ||
1547 ((itemp->opd[i] & SIZE_MASK) &&
1548 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK))) {
H. Peter Anvin5a640e12007-05-29 23:57:12 +00001549 if ((itemp->opd[i] & ~instruction->oprs[i].type & ~SIZE_MASK) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001550 (instruction->oprs[i].type & SIZE_MASK))
1551 return 0;
1552 else
H. Peter Anvine2c80182005-01-15 22:15:51 +00001553 return 1;
1554 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001555
1556 /*
1557 * Check operand sizes
1558 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001559 if (itemp->flags & IF_ARMASK) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001560 size[0] = size[1] = size[2] = 0;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001561
H. Peter Anvine2c80182005-01-15 22:15:51 +00001562 switch (itemp->flags & IF_ARMASK) {
1563 case IF_AR0:
1564 i = 0;
1565 break;
1566 case IF_AR1:
1567 i = 1;
1568 break;
1569 case IF_AR2:
1570 i = 2;
1571 break;
1572 default:
1573 break; /* Shouldn't happen */
1574 }
1575 if (itemp->flags & IF_SB) {
1576 size[i] = BITS8;
1577 } else if (itemp->flags & IF_SW) {
1578 size[i] = BITS16;
1579 } else if (itemp->flags & IF_SD) {
1580 size[i] = BITS32;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001581 } else if (itemp->flags & IF_SQ) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001582 size[i] = BITS64;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001583 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001584 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001585 asize = 0;
1586 if (itemp->flags & IF_SB) {
1587 asize = BITS8;
1588 oprs = itemp->operands;
1589 } else if (itemp->flags & IF_SW) {
1590 asize = BITS16;
1591 oprs = itemp->operands;
1592 } else if (itemp->flags & IF_SD) {
1593 asize = BITS32;
1594 oprs = itemp->operands;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001595 } else if (itemp->flags & IF_SQ) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001596 asize = BITS64;
1597 oprs = itemp->operands;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001598 }
1599 size[0] = size[1] = size[2] = asize;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001600 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001601
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001602 if (itemp->flags & (IF_SM | IF_SM2)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001603 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
1604 asize = 0;
1605 for (i = 0; i < oprs; i++) {
1606 if ((asize = itemp->opd[i] & SIZE_MASK) != 0) {
1607 int j;
1608 for (j = 0; j < oprs; j++)
1609 size[j] = asize;
1610 break;
1611 }
1612 }
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001613 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001614 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001615 }
1616
Keith Kaniosb7a89542007-04-12 02:40:54 +00001617 for (i = 0; i < itemp->operands; i++) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001618 if (!(itemp->opd[i] & SIZE_MASK) &&
1619 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001620 return 2;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001621 }
1622
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001623 /*
1624 * Check template is okay at the set cpu level
1625 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001626 if (((itemp->flags & IF_PLEVEL) > cpu))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001627 return 3;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001628
1629 /*
1630 * Check if instruction is available in long mode
1631 */
1632 if ((itemp->flags & IF_NOLONG) && (bits == 64))
1633 return 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001634
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001635 /*
1636 * Check if special handling needed for Jumps
1637 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001638 if ((uint8_t)(itemp->code[0]) >= 0370)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001639 return 99;
1640
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001641 return ret;
1642}
1643
H. Peter Anvine2c80182005-01-15 22:15:51 +00001644static ea *process_ea(operand * input, ea * output, int addrbits,
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001645 int rfield, int32_t rflags, int forw_ref)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001646{
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001647 output->rip = FALSE;
1648
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001649 /* REX flags for the rfield operand */
1650 output->rex |= rexflags(rfield, rflags, REX_R|REX_P|REX_W|REX_H);
1651
Keith Kaniosb7a89542007-04-12 02:40:54 +00001652 if (!(REGISTER & ~input->type)) { /* register direct */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001653 int i;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001654 int32_t f;
1655
1656 if (input->basereg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001657 || input->basereg >= REG_ENUM_LIMIT)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001658 return NULL;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001659 f = regflag(input);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001660 i = regvals[input->basereg];
Keith Kaniosb7a89542007-04-12 02:40:54 +00001661
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001662 if (REG_EA & ~f)
1663 return NULL; /* Invalid EA register */
1664
1665 output->rex |= op_rexflags(input, REX_B|REX_P|REX_W|REX_H);
1666
Keith Kaniosb7a89542007-04-12 02:40:54 +00001667 output->sib_present = FALSE; /* no SIB necessary */
1668 output->bytes = 0; /* no offset necessary either */
1669 output->modrm = 0xC0 | ((rfield & 7) << 3) | (i & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001670 } else { /* it's a memory reference */
1671 if (input->basereg == -1
1672 && (input->indexreg == -1 || input->scale == 0)) {
1673 /* it's a pure offset */
1674 if (input->addr_size)
1675 addrbits = input->addr_size;
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001676
1677 if (globalbits == 64 && (~input->type & IP_REL)) {
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00001678 int scale, index, base;
1679 output->sib_present = TRUE;
1680 scale = 0;
1681 index = 4;
1682 base = 5;
1683 output->sib = (scale << 6) | (index << 3) | base;
1684 output->bytes = 4;
1685 output->modrm = 4 | ((rfield & 7) << 3);
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001686 output->rip = FALSE;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00001687 } else {
1688 output->sib_present = FALSE;
1689 output->bytes = (addrbits != 16 ? 4 : 2);
1690 output->modrm = (addrbits != 16 ? 5 : 6) | ((rfield & 7) << 3);
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001691 output->rip = globalbits == 64;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00001692 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001693 } else { /* it's an indirection */
1694 int i = input->indexreg, b = input->basereg, s = input->scale;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001695 int32_t o = input->offset, seg = input->segment;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001696 int hb = input->hintbase, ht = input->hinttype;
1697 int t;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001698 int it, bt;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001699 int32_t ix, bx; /* register flags */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001700
H. Peter Anvine2c80182005-01-15 22:15:51 +00001701 if (s == 0)
1702 i = -1; /* make this easy, at least */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001703
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001704 if (i >= EXPR_REG_START && i < REG_ENUM_LIMIT) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001705 it = regvals[i];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001706 ix = reg_flags[i];
1707 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001708 it = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001709 ix = 0;
1710 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001711
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001712 if (b != -1 && b >= EXPR_REG_START && b < REG_ENUM_LIMIT) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001713 bt = regvals[b];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001714 bx = reg_flags[b];
1715 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001716 bt = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001717 bx = 0;
1718 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001719
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001720 /* check for a 32/64-bit memory reference... */
1721 if ((ix|bx) & (BITS32|BITS64)) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001722 /* it must be a 32/64-bit memory reference. Firstly we have
1723 * to check that all registers involved are type E/Rxx. */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001724 int32_t sok = BITS32|BITS64;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001725
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001726 if (it != -1) {
1727 if (!(REG64 & ~ix) || !(REG32 & ~ix))
1728 sok &= ix;
1729 else
1730 return NULL;
1731 }
1732
1733 if (bt != -1) {
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001734 if (REG_GPR & ~bx)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001735 return NULL; /* Invalid register */
H. Peter Anvina57e8d42007-05-30 03:44:02 +00001736 if (~sok & bx & SIZE_MASK)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001737 return NULL; /* Invalid size */
1738 sok &= ~bx;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001739 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001740
H. Peter Anvine2c80182005-01-15 22:15:51 +00001741 /* While we're here, ensure the user didn't specify WORD. */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001742 if (input->addr_size == 16 ||
1743 (input->addr_size == 32 && !(sok & BITS32)) ||
1744 (input->addr_size == 64 && !(sok & BITS64)))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001745 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001746
Keith Kaniosb7a89542007-04-12 02:40:54 +00001747 /* now reorganize base/index */
1748 if (s == 1 && bt != it && bt != -1 && it != -1 &&
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001749 ((hb == b && ht == EAH_NOTBASE)
1750 || (hb == i && ht == EAH_MAKEBASE))) {
1751 /* swap if hints say so */
1752 t = bt, bt = it, it = t;
1753 t = bx, bx = ix, ix = t;
1754 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001755 if (bt == it) /* convert EAX+2*EAX to 3*EAX */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001756 bt = -1, bx = 0, s++;
1757 if (bt == -1 && s == 1 && !(hb == it && ht == EAH_NOTBASE)) {
1758 /* make single reg base, unless hint */
1759 bt = it, bx = ix, it = -1, ix = 0;
1760 }
H. Peter Anvinf5843c62007-09-10 18:59:26 +00001761 if (((s == 2 && it != REG_NUM_ESP
H. Peter Anvine2c80182005-01-15 22:15:51 +00001762 && !(input->eaflags & EAF_TIMESTWO)) || s == 3
Keith Kaniosb7a89542007-04-12 02:40:54 +00001763 || s == 5 || s == 9) && bt == -1)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001764 bt = it, bx = ix, s--; /* convert 3*EAX to EAX+2*EAX */
Keith Kanios48af1772007-08-17 07:37:52 +00001765 if (it == -1 && (bt & 7) != REG_NUM_ESP
H. Peter Anvine2c80182005-01-15 22:15:51 +00001766 && (input->eaflags & EAF_TIMESTWO))
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001767 it = bt, ix = bx, bt = -1, bx = 0, s = 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001768 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
Keith Kanios48af1772007-08-17 07:37:52 +00001769 if (s == 1 && it == REG_NUM_ESP) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001770 /* swap ESP into base if scale is 1 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001771 t = it, it = bt, bt = t;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001772 t = ix, ix = bx, bx = t;
1773 }
Keith Kanios48af1772007-08-17 07:37:52 +00001774 if (it == REG_NUM_ESP
Keith Kaniosb7a89542007-04-12 02:40:54 +00001775 || (s != 1 && s != 2 && s != 4 && s != 8 && it != -1))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001776 return NULL; /* wrong, for various reasons */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001777
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001778 output->rex |= rexflags(it, ix, REX_X);
1779 output->rex |= rexflags(bt, bx, REX_B);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001780
Keith Kanios48af1772007-08-17 07:37:52 +00001781 if (it == -1 && (bt & 7) != REG_NUM_ESP) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001782 /* no SIB needed */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001783 int mod, rm;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001784
1785 if (bt == -1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001786 rm = 5;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001787 mod = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001788 } else {
1789 rm = (bt & 7);
Keith Kanios48af1772007-08-17 07:37:52 +00001790 if (rm != REG_NUM_EBP && o == 0 &&
Keith Kaniosb7a89542007-04-12 02:40:54 +00001791 seg == NO_SEG && !forw_ref &&
1792 !(input->eaflags &
1793 (EAF_BYTEOFFS | EAF_WORDOFFS)))
1794 mod = 0;
1795 else if (input->eaflags & EAF_BYTEOFFS ||
1796 (o >= -128 && o <= 127 && seg == NO_SEG
1797 && !forw_ref
1798 && !(input->eaflags & EAF_WORDOFFS)))
1799 mod = 1;
1800 else
1801 mod = 2;
1802 }
H. Peter Anvinea838272002-04-30 20:51:53 +00001803
H. Peter Anvine2c80182005-01-15 22:15:51 +00001804 output->sib_present = FALSE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001805 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
1806 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001807 } else {
1808 /* we need a SIB */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001809 int mod, scale, index, base;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001810
1811 if (it == -1)
1812 index = 4, s = 1;
1813 else
1814 index = (it & 7);
1815
H. Peter Anvine2c80182005-01-15 22:15:51 +00001816 switch (s) {
1817 case 1:
1818 scale = 0;
1819 break;
1820 case 2:
1821 scale = 1;
1822 break;
1823 case 4:
1824 scale = 2;
1825 break;
1826 case 8:
1827 scale = 3;
1828 break;
1829 default: /* then what the smeg is it? */
1830 return NULL; /* panic */
1831 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001832
1833 if (bt == -1) {
1834 base = 5;
1835 mod = 0;
1836 } else {
1837 base = (bt & 7);
Keith Kanios48af1772007-08-17 07:37:52 +00001838 if (base != REG_NUM_EBP && o == 0 &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00001839 seg == NO_SEG && !forw_ref &&
1840 !(input->eaflags &
Keith Kaniosb7a89542007-04-12 02:40:54 +00001841 (EAF_BYTEOFFS | EAF_WORDOFFS)))
1842 mod = 0;
1843 else if (input->eaflags & EAF_BYTEOFFS ||
1844 (o >= -128 && o <= 127 && seg == NO_SEG
1845 && !forw_ref
1846 && !(input->eaflags & EAF_WORDOFFS)))
1847 mod = 1;
1848 else
1849 mod = 2;
1850 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001851
H. Peter Anvine2c80182005-01-15 22:15:51 +00001852 output->sib_present = TRUE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001853 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
1854 output->modrm = (mod << 6) | ((rfield & 7) << 3) | 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001855 output->sib = (scale << 6) | (index << 3) | base;
1856 }
1857 } else { /* it's 16-bit */
1858 int mod, rm;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001859
1860 /* check for 64-bit long mode */
1861 if (addrbits == 64)
1862 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001863
H. Peter Anvine2c80182005-01-15 22:15:51 +00001864 /* check all registers are BX, BP, SI or DI */
1865 if ((b != -1 && b != R_BP && b != R_BX && b != R_SI
1866 && b != R_DI) || (i != -1 && i != R_BP && i != R_BX
1867 && i != R_SI && i != R_DI))
1868 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001869
Keith Kaniosb7a89542007-04-12 02:40:54 +00001870 /* ensure the user didn't specify DWORD/QWORD */
1871 if (input->addr_size == 32 || input->addr_size == 64)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001872 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001873
H. Peter Anvine2c80182005-01-15 22:15:51 +00001874 if (s != 1 && i != -1)
1875 return NULL; /* no can do, in 16-bit EA */
1876 if (b == -1 && i != -1) {
1877 int tmp = b;
1878 b = i;
1879 i = tmp;
1880 } /* swap */
1881 if ((b == R_SI || b == R_DI) && i != -1) {
1882 int tmp = b;
1883 b = i;
1884 i = tmp;
1885 }
1886 /* have BX/BP as base, SI/DI index */
1887 if (b == i)
1888 return NULL; /* shouldn't ever happen, in theory */
1889 if (i != -1 && b != -1 &&
1890 (i == R_BP || i == R_BX || b == R_SI || b == R_DI))
1891 return NULL; /* invalid combinations */
1892 if (b == -1) /* pure offset: handled above */
1893 return NULL; /* so if it gets to here, panic! */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001894
H. Peter Anvine2c80182005-01-15 22:15:51 +00001895 rm = -1;
1896 if (i != -1)
1897 switch (i * 256 + b) {
1898 case R_SI * 256 + R_BX:
1899 rm = 0;
1900 break;
1901 case R_DI * 256 + R_BX:
1902 rm = 1;
1903 break;
1904 case R_SI * 256 + R_BP:
1905 rm = 2;
1906 break;
1907 case R_DI * 256 + R_BP:
1908 rm = 3;
1909 break;
1910 } else
1911 switch (b) {
1912 case R_SI:
1913 rm = 4;
1914 break;
1915 case R_DI:
1916 rm = 5;
1917 break;
1918 case R_BP:
1919 rm = 6;
1920 break;
1921 case R_BX:
1922 rm = 7;
1923 break;
1924 }
1925 if (rm == -1) /* can't happen, in theory */
1926 return NULL; /* so panic if it does */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001927
H. Peter Anvine2c80182005-01-15 22:15:51 +00001928 if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
1929 !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
1930 mod = 0;
1931 else if (input->eaflags & EAF_BYTEOFFS ||
1932 (o >= -128 && o <= 127 && seg == NO_SEG
1933 && !forw_ref
1934 && !(input->eaflags & EAF_WORDOFFS)))
1935 mod = 1;
1936 else
1937 mod = 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001938
H. Peter Anvine2c80182005-01-15 22:15:51 +00001939 output->sib_present = FALSE; /* no SIB - it's 16-bit */
1940 output->bytes = mod; /* bytes of offset needed */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001941 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001942 }
1943 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001944 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001945
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001946 output->size = 1 + output->sib_present + output->bytes;
1947 return output;
1948}
1949
H. Peter Anvine2c80182005-01-15 22:15:51 +00001950static int chsize(operand * input, int addrbits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001951{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001952 if (!(MEMORY & ~input->type)) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001953 int32_t i, b;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001954
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001955 if (input->indexreg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001956 || input->indexreg >= REG_ENUM_LIMIT)
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00001957 i = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001958 else
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001959 i = reg_flags[input->indexreg];
Keith Kaniosb7a89542007-04-12 02:40:54 +00001960
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001961 if (input->basereg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001962 || input->basereg >= REG_ENUM_LIMIT)
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00001963 b = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001964 else
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001965 b = reg_flags[input->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001966
H. Peter Anvine2c80182005-01-15 22:15:51 +00001967 if (input->scale == 0)
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00001968 i = 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001969
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00001970 if (!i && !b) /* pure offset */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001971 return (input->addr_size != 0 && input->addr_size != addrbits);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001972
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001973 if (!(REG32 & ~i) || !(REG32 & ~b))
Keith Kaniosb7a89542007-04-12 02:40:54 +00001974 return (addrbits != 32);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001975 else
1976 return (addrbits == 32);
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001977 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001978 return 0;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001979 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001980}