blob: 409124bb36e6da6ca36cefc698b771219670a1ce [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.
H. Peter Anvinaf535c12002-04-30 20:59:21 +000054 * \312 - (disassembler only) marker on LOOP, LOOPxx instructions.
Keith Kaniosb7a89542007-04-12 02:40:54 +000055 * \313 - indicates fixed 64-bit address size, no REX required.
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)
Keith Kaniosb7a89542007-04-12 02:40:54 +000061 * \323 - indicates fixed 64-bit operand size, REX on extensions, only.
62 * \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.
H. Peter Anvinef7468f2002-04-30 20:57:59 +000065 * \331 - instruction not valid with REP prefix. Hint for
66 * disassembler only; for SSE instructions.
67 * \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.
H. Peter Anvin0db11e22007-04-17 20:23:11 +000070 * \334 - LOCK prefix used instead of REX.R
Keith Kaniosb7a89542007-04-12 02:40:54 +000071 * \340 - reserve <operand 0> bytes of uninitialized storage.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000072 * Operand 0 had better be a segmentless constant.
H. Peter Anvin788e6c12002-04-30 21:02:01 +000073 * \370,\371,\372 - match only if operand 0 meets byte jump criteria.
74 * 370 is used for Jcc, 371 is used for JMP.
H. Peter Anvinaf535c12002-04-30 20:59:21 +000075 * \373 - assemble 0x03 if bits==16, 0x05 if bits==32;
76 * used for conditional jump over longer jump
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000077 */
78
79#include <stdio.h>
80#include <string.h>
Keith Kaniosb7a89542007-04-12 02:40:54 +000081#include <inttypes.h>
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000082
83#include "nasm.h"
H. Peter Anvin6768eb72002-04-30 20:52:26 +000084#include "nasmlib.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000085#include "assemble.h"
86#include "insns.h"
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +000087#include "preproc.h"
H. Peter Anvin3df97a72007-05-30 03:25:21 +000088#include "regflags.c"
Keith Kaniosb7a89542007-04-12 02:40:54 +000089#include "regvals.c"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000090
91extern struct itemplate *nasm_instructions[];
92
93typedef 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);
Keith Kaniosb7a89542007-04-12 02:40:54 +0000107static int matches(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);
112static ea *process_ea(operand *, ea *, int, int, int, 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 Anvinea6e34d2002-04-30 20:51:32 +0000216 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 */
526 if (size_prob == 1) /* would have matched, but for size */
527 error(ERR_NONFATAL, "operation size not specified");
528 else if (size_prob == 2)
529 error(ERR_NONFATAL, "mismatch in operand sizes");
530 else if (size_prob == 3)
531 error(ERR_NONFATAL, "no instruction for this cpu level");
Keith Kaniosb7a89542007-04-12 02:40:54 +0000532 else if (size_prob == 4)
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000533 error(ERR_NONFATAL, "instruction not supported in 64-bit mode");
534 else if (size_prob == 5)
535 error(ERR_NONFATAL, "invalid operands in non-64-bit mode");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000536 else
537 error(ERR_NONFATAL,
538 "invalid combination of opcode and operands");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000539 }
540 return 0;
541}
542
Keith Kaniosb7a89542007-04-12 02:40:54 +0000543int32_t insn_size(int32_t segment, int32_t offset, int bits, uint32_t cp,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000544 insn * instruction, efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000545{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000546 struct itemplate *temp;
547
H. Peter Anvine2c80182005-01-15 22:15:51 +0000548 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000549 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000550
551 if (instruction->opcode == -1)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000552 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000553
554 if (instruction->opcode == I_DB ||
H. Peter Anvine2c80182005-01-15 22:15:51 +0000555 instruction->opcode == I_DW ||
556 instruction->opcode == I_DD ||
557 instruction->opcode == I_DQ || instruction->opcode == I_DT) {
558 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000559 int32_t isize, osize, wsize = 0; /* placate gcc */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000560
H. Peter Anvine2c80182005-01-15 22:15:51 +0000561 isize = 0;
562 switch (instruction->opcode) {
563 case I_DB:
564 wsize = 1;
565 break;
566 case I_DW:
567 wsize = 2;
568 break;
569 case I_DD:
570 wsize = 4;
571 break;
572 case I_DQ:
573 wsize = 8;
574 break;
575 case I_DT:
576 wsize = 10;
577 break;
578 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000579
H. Peter Anvine2c80182005-01-15 22:15:51 +0000580 for (e = instruction->eops; e; e = e->next) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000581 int32_t align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000582
H. Peter Anvine2c80182005-01-15 22:15:51 +0000583 osize = 0;
584 if (e->type == EOT_DB_NUMBER)
585 osize = 1;
586 else if (e->type == EOT_DB_STRING)
587 osize = e->stringlen;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000588
H. Peter Anvine2c80182005-01-15 22:15:51 +0000589 align = (-osize) % wsize;
590 if (align < 0)
591 align += wsize;
592 isize += osize + align;
593 }
594 return isize * instruction->times;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000595 }
596
H. Peter Anvine2c80182005-01-15 22:15:51 +0000597 if (instruction->opcode == I_INCBIN) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000598 char fname[FILENAME_MAX];
H. Peter Anvine2c80182005-01-15 22:15:51 +0000599 FILE *fp;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000600 int32_t len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000601 char *prefix = "", *combine;
602 char **pPrevPath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000603
H. Peter Anvine2c80182005-01-15 22:15:51 +0000604 len = FILENAME_MAX - 1;
605 if (len > instruction->eops->stringlen)
606 len = instruction->eops->stringlen;
607 strncpy(fname, instruction->eops->stringval, len);
608 fname[len] = '\0';
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000609
H. Peter Anvine2c80182005-01-15 22:15:51 +0000610 while (1) { /* added by alexfru: 'incbin' uses include paths */
611 combine = nasm_malloc(strlen(prefix) + len + 1);
612 strcpy(combine, prefix);
613 strcat(combine, fname);
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000614
H. Peter Anvine2c80182005-01-15 22:15:51 +0000615 if ((fp = fopen(combine, "rb")) != NULL) {
616 nasm_free(combine);
617 break;
618 }
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000619
H. Peter Anvine2c80182005-01-15 22:15:51 +0000620 nasm_free(combine);
621 pPrevPath = pp_get_include_path_ptr(pPrevPath);
622 if (pPrevPath == NULL)
623 break;
624 prefix = *pPrevPath;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000625 }
626
627 if (fp == NULL)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000628 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
629 fname);
630 else if (fseek(fp, 0L, SEEK_END) < 0)
631 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
632 fname);
633 else {
634 len = ftell(fp);
635 fclose(fp);
636 if (instruction->eops->next) {
637 len -= instruction->eops->next->offset;
638 if (instruction->eops->next->next &&
639 len > instruction->eops->next->next->offset) {
640 len = instruction->eops->next->next->offset;
641 }
642 }
643 return instruction->times * len;
644 }
645 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000646 }
647
Keith Kaniosb7a89542007-04-12 02:40:54 +0000648 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++) {
649 int m = matches(temp, instruction, bits);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000650 if (m == 99)
651 m += jmp_match(segment, offset, bits, instruction, temp->code);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000652
H. Peter Anvine2c80182005-01-15 22:15:51 +0000653 if (m == 100) {
654 /* we've matched an instruction. */
Keith Kaniosb7a89542007-04-12 02:40:54 +0000655 int32_t isize;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000656 const char *codes = temp->code;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000657 int j;
658
659 isize = calcsize(segment, offset, bits, instruction, codes);
660 if (isize < 0)
661 return -1;
662 for (j = 0; j < instruction->nprefix; j++) {
663 if ((instruction->prefixes[j] != P_A16 &&
664 instruction->prefixes[j] != P_O16 && bits == 16) ||
665 (instruction->prefixes[j] != P_A32 &&
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000666 instruction->prefixes[j] != P_O32 && bits >= 32)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000667 isize++;
668 }
669 }
670 return isize * instruction->times;
671 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000672 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000673 return -1; /* didn't match any instruction */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000674}
675
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000676/* check that opn[op] is a signed byte of size 16 or 32,
677 and return the signed value*/
H. Peter Anvine2c80182005-01-15 22:15:51 +0000678static int is_sbyte(insn * ins, int op, int size)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000679{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000680 int32_t v;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000681 int ret;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000682
683 ret = !(ins->forw_ref && ins->oprs[op].opflags) && /* dead in the water on forward reference or External */
684 optimizing >= 0 &&
685 !(ins->oprs[op].type & STRICT) &&
686 ins->oprs[op].wrt == NO_SEG && ins->oprs[op].segment == NO_SEG;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000687
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000688 v = ins->oprs[op].offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000689 if (size == 16)
Keith Kaniosb7a89542007-04-12 02:40:54 +0000690 v = (int16_t)v; /* sign extend if 16 bits */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000691
692 return ret && v >= -128L && v <= 127L;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000693}
694
Keith Kaniosb7a89542007-04-12 02:40:54 +0000695static int32_t calcsize(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000696 insn * ins, const char *codes)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000697{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000698 int32_t length = 0;
699 uint8_t c;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000700 int rex_mask = ~0;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000701 ins->rex = 0; /* Ensure REX is reset */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000702
H. Peter Anvine2c80182005-01-15 22:15:51 +0000703 (void)segment; /* Don't warn that this parameter is unused */
704 (void)offset; /* Don't warn that this parameter is unused */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000705
H. Peter Anvine2c80182005-01-15 22:15:51 +0000706 while (*codes)
707 switch (c = *codes++) {
708 case 01:
709 case 02:
710 case 03:
711 codes += c, length += c;
712 break;
713 case 04:
714 case 05:
715 case 06:
716 case 07:
717 length++;
718 break;
719 case 010:
720 case 011:
721 case 012:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000722 ins->rex |=
723 op_rexflags(&ins->oprs[c - 010], REX_B|REX_H|REX_P|REX_W);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000724 codes++, length++;
725 break;
726 case 017:
727 length++;
728 break;
729 case 014:
730 case 015:
731 case 016:
732 length++;
733 break;
734 case 020:
735 case 021:
736 case 022:
737 length++;
738 break;
739 case 024:
740 case 025:
741 case 026:
742 length++;
743 break;
744 case 030:
745 case 031:
746 case 032:
747 length += 2;
748 break;
749 case 034:
750 case 035:
751 case 036:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000752 if (ins->oprs[c - 034].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000753 length += (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
754 else
755 length += (bits == 16) ? 2 : 4;
756 break;
757 case 037:
758 length += 2;
759 break;
760 case 040:
761 case 041:
762 case 042:
763 length += 4;
764 break;
765 case 044:
766 case 045:
767 case 046:
768 length += ((ins->oprs[c - 044].addr_size ?
Keith Kaniosb7a89542007-04-12 02:40:54 +0000769 ins->oprs[c - 044].addr_size : bits) >> 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000770 break;
771 case 050:
772 case 051:
773 case 052:
774 length++;
775 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000776 case 054:
777 case 055:
778 case 056:
779 length += 8; /* MOV reg64/imm */
780 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000781 case 060:
782 case 061:
783 case 062:
784 length += 2;
785 break;
786 case 064:
787 case 065:
788 case 066:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000789 if (ins->oprs[c - 064].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000790 length += (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
791 else
792 length += (bits == 16) ? 2 : 4;
793 break;
794 case 070:
795 case 071:
796 case 072:
797 length += 4;
798 break;
799 case 0130:
800 case 0131:
801 case 0132:
802 length += is_sbyte(ins, c - 0130, 16) ? 1 : 2;
803 break;
804 case 0133:
805 case 0134:
806 case 0135:
807 codes += 2;
808 length++;
809 break;
810 case 0140:
811 case 0141:
812 case 0142:
813 length += is_sbyte(ins, c - 0140, 32) ? 1 : 4;
814 break;
815 case 0143:
816 case 0144:
817 case 0145:
818 codes += 2;
819 length++;
820 break;
821 case 0300:
822 case 0301:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000823 case 0302:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000824 length += chsize(&ins->oprs[c - 0300], bits);
825 break;
826 case 0310:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000827 length += (bits != 16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000828 break;
829 case 0311:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000830 length += (bits != 32);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000831 break;
832 case 0312:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000833 break;
834 case 0313:
835 length -= 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000836 break;
837 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000838 length += (bits != 16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000839 break;
840 case 0321:
841 length += (bits == 16);
842 break;
843 case 0322:
844 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000845 case 0323:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000846 rex_mask &= ~REX_W;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000847 break;
848 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000849 ins->rex |= REX_W;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000850 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000851 case 0330:
852 codes++, length++;
853 break;
854 case 0331:
855 case 0332:
856 break;
857 case 0333:
858 length++;
859 break;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000860 case 0334:
861 assert_no_prefix(ins, P_LOCK);
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000862 ins->rex |= REX_L;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000863 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000864 case 0340:
865 case 0341:
866 case 0342:
867 if (ins->oprs[0].segment != NO_SEG)
868 errfunc(ERR_NONFATAL, "attempt to reserve non-constant"
869 " quantity of BSS space");
870 else
871 length += ins->oprs[0].offset << (c - 0340);
872 break;
873 case 0370:
874 case 0371:
875 case 0372:
876 break;
877 case 0373:
878 length++;
879 break;
880 default: /* can't do it by 'case' statements */
881 if (c >= 0100 && c <= 0277) { /* it's an EA */
882 ea ea_data;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000883 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000884 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000885 ea_data.rex = 0; /* Ensure ea.REX is initially 0 */
886
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000887 if (c <= 0177) {
888 /* pick rfield from operand b */
889 rflags = regflag(&ins->oprs[c & 7]);
890 rfield = regvals[ins->oprs[c & 7].basereg];
891 } else {
892 rflags = 0;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000893 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000894 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000895
H. Peter Anvine2c80182005-01-15 22:15:51 +0000896 if (!process_ea
Keith Kaniosb7a89542007-04-12 02:40:54 +0000897 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000898 rfield, rflags, ins->forw_ref)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000899 errfunc(ERR_NONFATAL, "invalid effective address");
900 return -1;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000901 } else {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000902 ins->rex |= ea_data.rex;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000903 length += ea_data.size;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000904 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000905 } else
906 errfunc(ERR_PANIC, "internal instruction table corrupt"
907 ": instruction code 0x%02X given", c);
908 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000909
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000910 ins->rex &= rex_mask;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000911 if (ins->rex & REX_REAL) {
912 if (ins->rex & REX_H) {
913 errfunc(ERR_NONFATAL, "cannot use high register in rex instruction");
914 return -1;
915 } else if (bits == 64 ||
916 ((ins->rex & REX_L) &&
917 !(ins->rex & (REX_P|REX_W|REX_X|REX_B)) &&
918 cpu >= IF_X86_64)) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000919 length++;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000920 } else {
921 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
922 return -1;
923 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000924 }
925
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000926 return length;
927}
Keith Kaniosb7a89542007-04-12 02:40:54 +0000928
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000929#define EMIT_REX() \
930 if((ins->rex & REX_REAL) && (bits == 64)) { \
931 ins->rex = (ins->rex & REX_REAL)|REX_P; \
932 out(offset, segment, &ins->rex, OUT_RAWDATA+1, NO_SEG, NO_SEG); \
933 ins->rex = 0; \
934 offset += 1; \
935 }
936
Keith Kaniosb7a89542007-04-12 02:40:54 +0000937static void gencode(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000938 insn * ins, const char *codes, int32_t insn_end)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000939{
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000940 static char condval[] = { /* conditional opcodes */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000941 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
942 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
943 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000944 };
Keith Kaniosb7a89542007-04-12 02:40:54 +0000945 uint8_t c;
946 uint8_t bytes[4];
947 int32_t size;
948 int64_t data;
949
H. Peter Anvineba20a72002-04-30 20:53:55 +0000950 while (*codes)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000951 switch (c = *codes++) {
952 case 01:
953 case 02:
954 case 03:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000955 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +0000956 out(offset, segment, codes, OUT_RAWDATA + c, NO_SEG, NO_SEG);
957 codes += c;
958 offset += c;
959 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000960
H. Peter Anvine2c80182005-01-15 22:15:51 +0000961 case 04:
962 case 06:
963 switch (ins->oprs[0].basereg) {
964 case R_CS:
965 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0);
966 break;
967 case R_DS:
968 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0);
969 break;
970 case R_ES:
971 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0);
972 break;
973 case R_SS:
974 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0);
975 break;
976 default:
977 errfunc(ERR_PANIC,
978 "bizarre 8086 segment register received");
979 }
980 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
981 offset++;
982 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000983
H. Peter Anvine2c80182005-01-15 22:15:51 +0000984 case 05:
985 case 07:
986 switch (ins->oprs[0].basereg) {
987 case R_FS:
988 bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0);
989 break;
990 case R_GS:
991 bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0);
992 break;
993 default:
994 errfunc(ERR_PANIC,
995 "bizarre 386 segment register received");
996 }
997 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
998 offset++;
999 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001000
H. Peter Anvine2c80182005-01-15 22:15:51 +00001001 case 010:
1002 case 011:
1003 case 012:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001004 EMIT_REX();
Keith Kaniosb7a89542007-04-12 02:40:54 +00001005 bytes[0] = *codes++ + ((regval(&ins->oprs[c - 010])) & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001006 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1007 offset += 1;
1008 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001009
H. Peter Anvine2c80182005-01-15 22:15:51 +00001010 case 017:
1011 bytes[0] = 0;
1012 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1013 offset += 1;
1014 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001015
H. Peter Anvine2c80182005-01-15 22:15:51 +00001016 case 014:
1017 case 015:
1018 case 016:
1019 if (ins->oprs[c - 014].offset < -128
1020 || ins->oprs[c - 014].offset > 127) {
1021 errfunc(ERR_WARNING, "signed byte value exceeds bounds");
1022 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001023
H. Peter Anvine2c80182005-01-15 22:15:51 +00001024 if (ins->oprs[c - 014].segment != NO_SEG) {
1025 data = ins->oprs[c - 014].offset;
1026 out(offset, segment, &data, OUT_ADDRESS + 1,
1027 ins->oprs[c - 014].segment, ins->oprs[c - 014].wrt);
1028 } else {
1029 bytes[0] = ins->oprs[c - 014].offset;
1030 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1031 NO_SEG);
1032 }
1033 offset += 1;
1034 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001035
H. Peter Anvine2c80182005-01-15 22:15:51 +00001036 case 020:
1037 case 021:
1038 case 022:
1039 if (ins->oprs[c - 020].offset < -256
1040 || ins->oprs[c - 020].offset > 255) {
1041 errfunc(ERR_WARNING, "byte value exceeds bounds");
1042 }
1043 if (ins->oprs[c - 020].segment != NO_SEG) {
1044 data = ins->oprs[c - 020].offset;
1045 out(offset, segment, &data, OUT_ADDRESS + 1,
1046 ins->oprs[c - 020].segment, ins->oprs[c - 020].wrt);
1047 } else {
1048 bytes[0] = ins->oprs[c - 020].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 024:
1056 case 025:
1057 case 026:
1058 if (ins->oprs[c - 024].offset < 0
1059 || ins->oprs[c - 024].offset > 255)
1060 errfunc(ERR_WARNING, "unsigned byte value exceeds bounds");
1061 if (ins->oprs[c - 024].segment != NO_SEG) {
1062 data = ins->oprs[c - 024].offset;
1063 out(offset, segment, &data, OUT_ADDRESS + 1,
1064 ins->oprs[c - 024].segment, ins->oprs[c - 024].wrt);
1065 } else {
1066 bytes[0] = ins->oprs[c - 024].offset;
1067 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1068 NO_SEG);
1069 }
1070 offset += 1;
1071 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001072
H. Peter Anvine2c80182005-01-15 22:15:51 +00001073 case 030:
1074 case 031:
1075 case 032:
1076 if (ins->oprs[c - 030].segment == NO_SEG &&
1077 ins->oprs[c - 030].wrt == NO_SEG &&
1078 (ins->oprs[c - 030].offset < -65536L ||
1079 ins->oprs[c - 030].offset > 65535L)) {
1080 errfunc(ERR_WARNING, "word value exceeds bounds");
1081 }
1082 data = ins->oprs[c - 030].offset;
1083 out(offset, segment, &data, OUT_ADDRESS + 2,
1084 ins->oprs[c - 030].segment, ins->oprs[c - 030].wrt);
1085 offset += 2;
1086 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001087
H. Peter Anvine2c80182005-01-15 22:15:51 +00001088 case 034:
1089 case 035:
1090 case 036:
1091 if (ins->oprs[c - 034].type & (BITS16 | BITS32))
1092 size = (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
1093 else
1094 size = (bits == 16) ? 2 : 4;
1095 data = ins->oprs[c - 034].offset;
1096 if (size == 2 && (data < -65536L || data > 65535L))
1097 errfunc(ERR_WARNING, "word value exceeds bounds");
1098 out(offset, segment, &data, OUT_ADDRESS + size,
1099 ins->oprs[c - 034].segment, ins->oprs[c - 034].wrt);
1100 offset += size;
1101 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001102
H. Peter Anvine2c80182005-01-15 22:15:51 +00001103 case 037:
1104 if (ins->oprs[0].segment == NO_SEG)
1105 errfunc(ERR_NONFATAL, "value referenced by FAR is not"
1106 " relocatable");
1107 data = 0L;
1108 out(offset, segment, &data, OUT_ADDRESS + 2,
1109 outfmt->segbase(1 + ins->oprs[0].segment),
1110 ins->oprs[0].wrt);
1111 offset += 2;
1112 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001113
H. Peter Anvine2c80182005-01-15 22:15:51 +00001114 case 040:
1115 case 041:
1116 case 042:
1117 data = ins->oprs[c - 040].offset;
1118 out(offset, segment, &data, OUT_ADDRESS + 4,
1119 ins->oprs[c - 040].segment, ins->oprs[c - 040].wrt);
1120 offset += 4;
1121 break;
H. Peter Anvin3ba46772002-05-27 23:19:35 +00001122
H. Peter Anvine2c80182005-01-15 22:15:51 +00001123 case 044:
1124 case 045:
1125 case 046:
1126 data = ins->oprs[c - 044].offset;
1127 size = ((ins->oprs[c - 044].addr_size ?
Keith Kaniosb7a89542007-04-12 02:40:54 +00001128 ins->oprs[c - 044].addr_size : bits) >> 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001129 if (size == 2 && (data < -65536L || data > 65535L))
1130 errfunc(ERR_WARNING, "word value exceeds bounds");
1131 out(offset, segment, &data, OUT_ADDRESS + size,
1132 ins->oprs[c - 044].segment, ins->oprs[c - 044].wrt);
1133 offset += size;
1134 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001135
H. Peter Anvine2c80182005-01-15 22:15:51 +00001136 case 050:
1137 case 051:
1138 case 052:
1139 if (ins->oprs[c - 050].segment != segment)
1140 errfunc(ERR_NONFATAL,
1141 "short relative jump outside segment");
1142 data = ins->oprs[c - 050].offset - insn_end;
1143 if (data > 127 || data < -128)
1144 errfunc(ERR_NONFATAL, "short jump is out of range");
1145 bytes[0] = data;
1146 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1147 offset += 1;
1148 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001149
1150 case 054:
1151 case 055:
1152 case 056:
1153 data = (int64_t)ins->oprs[c - 054].offset;
1154 out(offset, segment, &data, OUT_ADDRESS + 8,
1155 ins->oprs[c - 054].segment, ins->oprs[c - 054].wrt);
1156 offset += 8;
1157 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001158
H. Peter Anvine2c80182005-01-15 22:15:51 +00001159 case 060:
1160 case 061:
1161 case 062:
1162 if (ins->oprs[c - 060].segment != segment) {
1163 data = ins->oprs[c - 060].offset;
1164 out(offset, segment, &data,
1165 OUT_REL2ADR + insn_end - offset,
1166 ins->oprs[c - 060].segment, ins->oprs[c - 060].wrt);
1167 } else {
1168 data = ins->oprs[c - 060].offset - insn_end;
1169 out(offset, segment, &data,
1170 OUT_ADDRESS + 2, NO_SEG, NO_SEG);
1171 }
1172 offset += 2;
1173 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001174
H. Peter Anvine2c80182005-01-15 22:15:51 +00001175 case 064:
1176 case 065:
1177 case 066:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001178 if (ins->oprs[c - 064].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001179 size = (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
1180 else
1181 size = (bits == 16) ? 2 : 4;
1182 if (ins->oprs[c - 064].segment != segment) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001183 int32_t reltype = (size == 2 ? OUT_REL2ADR : OUT_REL4ADR);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001184 data = ins->oprs[c - 064].offset;
1185 out(offset, segment, &data, reltype + insn_end - offset,
1186 ins->oprs[c - 064].segment, ins->oprs[c - 064].wrt);
1187 } else {
1188 data = ins->oprs[c - 064].offset - insn_end;
1189 out(offset, segment, &data,
1190 OUT_ADDRESS + size, NO_SEG, NO_SEG);
1191 }
1192 offset += size;
1193 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001194
H. Peter Anvine2c80182005-01-15 22:15:51 +00001195 case 070:
1196 case 071:
1197 case 072:
1198 if (ins->oprs[c - 070].segment != segment) {
1199 data = ins->oprs[c - 070].offset;
1200 out(offset, segment, &data,
1201 OUT_REL4ADR + insn_end - offset,
1202 ins->oprs[c - 070].segment, ins->oprs[c - 070].wrt);
1203 } else {
1204 data = ins->oprs[c - 070].offset - insn_end;
1205 out(offset, segment, &data,
1206 OUT_ADDRESS + 4, NO_SEG, NO_SEG);
1207 }
1208 offset += 4;
1209 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001210
H. Peter Anvine2c80182005-01-15 22:15:51 +00001211 case 0130:
1212 case 0131:
1213 case 0132:
1214 data = ins->oprs[c - 0130].offset;
1215 if (is_sbyte(ins, c - 0130, 16)) {
1216 bytes[0] = data;
1217 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1218 NO_SEG);
1219 offset++;
1220 } else {
1221 if (ins->oprs[c - 0130].segment == NO_SEG &&
1222 ins->oprs[c - 0130].wrt == NO_SEG &&
1223 (data < -65536L || data > 65535L)) {
1224 errfunc(ERR_WARNING, "word value exceeds bounds");
1225 }
1226 out(offset, segment, &data, OUT_ADDRESS + 2,
1227 ins->oprs[c - 0130].segment, ins->oprs[c - 0130].wrt);
1228 offset += 2;
1229 }
1230 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001231
H. Peter Anvine2c80182005-01-15 22:15:51 +00001232 case 0133:
1233 case 0134:
1234 case 0135:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001235 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001236 codes++;
1237 bytes[0] = *codes++;
1238 if (is_sbyte(ins, c - 0133, 16))
1239 bytes[0] |= 2; /* s-bit */
1240 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1241 offset++;
1242 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001243
H. Peter Anvine2c80182005-01-15 22:15:51 +00001244 case 0140:
1245 case 0141:
1246 case 0142:
1247 data = ins->oprs[c - 0140].offset;
1248 if (is_sbyte(ins, c - 0140, 32)) {
1249 bytes[0] = data;
1250 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1251 NO_SEG);
1252 offset++;
1253 } else {
1254 out(offset, segment, &data, OUT_ADDRESS + 4,
1255 ins->oprs[c - 0140].segment, ins->oprs[c - 0140].wrt);
1256 offset += 4;
1257 }
1258 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001259
H. Peter Anvine2c80182005-01-15 22:15:51 +00001260 case 0143:
1261 case 0144:
1262 case 0145:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001263 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001264 codes++;
1265 bytes[0] = *codes++;
1266 if (is_sbyte(ins, c - 0143, 32))
1267 bytes[0] |= 2; /* s-bit */
1268 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1269 offset++;
1270 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001271
H. Peter Anvine2c80182005-01-15 22:15:51 +00001272 case 0300:
1273 case 0301:
1274 case 0302:
1275 if (chsize(&ins->oprs[c - 0300], bits)) {
1276 *bytes = 0x67;
1277 out(offset, segment, bytes,
1278 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1279 offset += 1;
1280 } else
1281 offset += 0;
1282 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001283
H. Peter Anvine2c80182005-01-15 22:15:51 +00001284 case 0310:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001285 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001286 *bytes = 0x67;
1287 out(offset, segment, bytes,
1288 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1289 offset += 1;
1290 } else
1291 offset += 0;
1292 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001293
H. Peter Anvine2c80182005-01-15 22:15:51 +00001294 case 0311:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001295 if (bits != 32) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001296 *bytes = 0x67;
1297 out(offset, segment, bytes,
1298 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1299 offset += 1;
1300 } else
1301 offset += 0;
1302 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001303
H. Peter Anvine2c80182005-01-15 22:15:51 +00001304 case 0312:
1305 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001306
Keith Kaniosb7a89542007-04-12 02:40:54 +00001307 case 0313:
1308 ins->rex = 0;
1309 break;
1310
H. Peter Anvine2c80182005-01-15 22:15:51 +00001311 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001312 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001313 *bytes = 0x66;
1314 out(offset, segment, bytes,
1315 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1316 offset += 1;
1317 } else
1318 offset += 0;
1319 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001320
H. Peter Anvine2c80182005-01-15 22:15:51 +00001321 case 0321:
1322 if (bits == 16) {
1323 *bytes = 0x66;
1324 out(offset, segment, bytes,
1325 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1326 offset += 1;
1327 } else
1328 offset += 0;
1329 break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001330
H. Peter Anvine2c80182005-01-15 22:15:51 +00001331 case 0322:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001332 case 0323:
1333 break;
1334
1335 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001336 ins->rex |= REX_W;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001337 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001338
H. Peter Anvine2c80182005-01-15 22:15:51 +00001339 case 0330:
1340 *bytes = *codes++ ^ condval[ins->condition];
1341 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1342 offset += 1;
1343 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001344
H. Peter Anvine2c80182005-01-15 22:15:51 +00001345 case 0331:
1346 case 0332:
1347 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001348
H. Peter Anvine2c80182005-01-15 22:15:51 +00001349 case 0333:
1350 *bytes = 0xF3;
1351 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1352 offset += 1;
1353 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001354
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001355 case 0334:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001356 if (ins->rex & REX_R) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001357 *bytes = 0xF0;
1358 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1359 offset += 1;
1360 }
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001361 ins->rex &= ~(REX_L|REX_R);
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001362 break;
1363
H. Peter Anvine2c80182005-01-15 22:15:51 +00001364 case 0340:
1365 case 0341:
1366 case 0342:
1367 if (ins->oprs[0].segment != NO_SEG)
1368 errfunc(ERR_PANIC, "non-constant BSS size in pass two");
1369 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001370 int32_t size = ins->oprs[0].offset << (c - 0340);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001371 if (size > 0)
1372 out(offset, segment, NULL,
1373 OUT_RESERVE + size, NO_SEG, NO_SEG);
1374 offset += size;
1375 }
1376 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001377
H. Peter Anvine2c80182005-01-15 22:15:51 +00001378 case 0370:
1379 case 0371:
1380 case 0372:
1381 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001382
H. Peter Anvine2c80182005-01-15 22:15:51 +00001383 case 0373:
1384 *bytes = bits == 16 ? 3 : 5;
1385 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1386 offset += 1;
1387 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001388
H. Peter Anvine2c80182005-01-15 22:15:51 +00001389 default: /* can't do it by 'case' statements */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001390 if (c >= 0100 && c <= 0277) { /* it's an EA */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001391 ea ea_data;
1392 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001393 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001394 uint8_t *p;
1395 int32_t s;
1396
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001397 if (c <= 0177) {
1398 /* pick rfield from operand b */
1399 rflags = regflag(&ins->oprs[c & 7]);
1400 rfield = regvals[ins->oprs[c & 7].basereg];
1401 } else {
1402 /* rfield is constant */
1403 rflags = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001404 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001405 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001406
1407 if (!process_ea
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001408 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
1409 rfield, rflags, ins->forw_ref)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001410 errfunc(ERR_NONFATAL, "invalid effective address");
1411 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001412
H. Peter Anvine2c80182005-01-15 22:15:51 +00001413 p = bytes;
1414 *p++ = ea_data.modrm;
1415 if (ea_data.sib_present)
1416 *p++ = ea_data.sib;
1417
1418 s = p - bytes;
1419 out(offset, segment, bytes, OUT_RAWDATA + s,
1420 NO_SEG, NO_SEG);
1421
1422 switch (ea_data.bytes) {
1423 case 0:
1424 break;
1425 case 1:
1426 if (ins->oprs[(c >> 3) & 7].segment != NO_SEG) {
1427 data = ins->oprs[(c >> 3) & 7].offset;
1428 out(offset, segment, &data, OUT_ADDRESS + 1,
1429 ins->oprs[(c >> 3) & 7].segment,
1430 ins->oprs[(c >> 3) & 7].wrt);
1431 } else {
1432 *bytes = ins->oprs[(c >> 3) & 7].offset;
1433 out(offset, segment, bytes, OUT_RAWDATA + 1,
1434 NO_SEG, NO_SEG);
1435 }
1436 s++;
1437 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001438 case 8:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001439 case 2:
1440 case 4:
1441 data = ins->oprs[(c >> 3) & 7].offset;
Keith Kaniose83b3182007-04-16 14:31:54 +00001442 if (ea_data.rip && (ins->oprs[(c >> 3) & 7].segment == 0xFFFFFFFF))
1443 ea_data.rip = 0; /* Make distinction between Symbols and Immediates */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001444 out(offset, segment, &data, /* RIP = Relative, not Absolute */
1445 (ea_data.rip ? OUT_REL4ADR : OUT_ADDRESS) + ea_data.bytes,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001446 ins->oprs[(c >> 3) & 7].segment,
1447 ins->oprs[(c >> 3) & 7].wrt);
1448 s += ea_data.bytes;
1449 break;
1450 }
1451 offset += s;
1452 } else
1453 errfunc(ERR_PANIC, "internal instruction table corrupt"
1454 ": instruction code 0x%02X given", c);
1455 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001456}
1457
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001458static int regflag(const operand * o)
1459{
1460 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1461 errfunc(ERR_PANIC, "invalid operand passed to regflag()");
1462 }
1463 return reg_flags[o->basereg];
1464}
1465
1466static int regval(const operand * o)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001467{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001468 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1469 errfunc(ERR_PANIC, "invalid operand passed to regval()");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001470 }
H. Peter Anvin232badb2002-06-06 02:41:20 +00001471 return regvals[o->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001472}
1473
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001474static int op_rexflags(const operand * o, int mask)
1475{
1476 int32_t flags;
1477 int val;
1478
1479 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1480 errfunc(ERR_PANIC, "invalid operand passed to op_rexflags()");
1481 }
1482
1483 flags = reg_flags[o->basereg];
1484 val = regvals[o->basereg];
1485
1486 return rexflags(val, flags, mask);
1487}
1488
1489static int rexflags(int val, int32_t flags, int mask)
1490{
1491 int rex = 0;
1492
1493 if (val >= 8)
1494 rex |= REX_B|REX_X|REX_R;
1495 if (flags & BITS64)
1496 rex |= REX_W;
1497 if (!(REG_HIGH & ~flags)) /* AH, CH, DH, BH */
1498 rex |= REX_H;
1499 else if (!(REG8 & ~flags) && val >= 4) /* SPL, BPL, SIL, DIL */
1500 rex |= REX_P;
1501
1502 return rex & mask;
1503}
1504
Keith Kaniosb7a89542007-04-12 02:40:54 +00001505static int matches(struct itemplate *itemp, insn * instruction, int bits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001506{
Keith Kaniosb7a89542007-04-12 02:40:54 +00001507 int i, b, x, size[3], asize, oprs, ret;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001508
1509 ret = 100;
1510
1511 /*
1512 * Check the opcode
1513 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001514 if (itemp->opcode != instruction->opcode)
1515 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001516
1517 /*
1518 * Count the operands
1519 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001520 if (itemp->operands != instruction->operands)
1521 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001522
1523 /*
1524 * Check that no spurious colons or TOs are present
1525 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001526 for (i = 0; i < itemp->operands; i++)
1527 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON | TO))
1528 return 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001529
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001530 /*
1531 * Check that the operand flags all match up
1532 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001533 for (i = 0; i < itemp->operands; i++)
1534 if (itemp->opd[i] & ~instruction->oprs[i].type ||
1535 ((itemp->opd[i] & SIZE_MASK) &&
1536 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK))) {
H. Peter Anvin5a640e12007-05-29 23:57:12 +00001537 if ((itemp->opd[i] & ~instruction->oprs[i].type & ~SIZE_MASK) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001538 (instruction->oprs[i].type & SIZE_MASK))
1539 return 0;
1540 else
H. Peter Anvine2c80182005-01-15 22:15:51 +00001541 return 1;
1542 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001543
1544 /*
1545 * Check operand sizes
1546 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001547 if (itemp->flags & IF_ARMASK) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001548 size[0] = size[1] = size[2] = 0;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001549
H. Peter Anvine2c80182005-01-15 22:15:51 +00001550 switch (itemp->flags & IF_ARMASK) {
1551 case IF_AR0:
1552 i = 0;
1553 break;
1554 case IF_AR1:
1555 i = 1;
1556 break;
1557 case IF_AR2:
1558 i = 2;
1559 break;
1560 default:
1561 break; /* Shouldn't happen */
1562 }
1563 if (itemp->flags & IF_SB) {
1564 size[i] = BITS8;
1565 } else if (itemp->flags & IF_SW) {
1566 size[i] = BITS16;
1567 } else if (itemp->flags & IF_SD) {
1568 size[i] = BITS32;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001569 } else if (itemp->flags & IF_SQ) {
1570 if (bits != 64)
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001571 return 5;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001572 size[i] = BITS64;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001573 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001574 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001575 asize = 0;
1576 if (itemp->flags & IF_SB) {
1577 asize = BITS8;
1578 oprs = itemp->operands;
1579 } else if (itemp->flags & IF_SW) {
1580 asize = BITS16;
1581 oprs = itemp->operands;
1582 } else if (itemp->flags & IF_SD) {
1583 asize = BITS32;
1584 oprs = itemp->operands;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001585 } else if (itemp->flags & IF_SQ) {
1586 if (bits != 64)
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001587 return 5;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001588 asize = BITS64;
1589 oprs = itemp->operands;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001590 }
1591 size[0] = size[1] = size[2] = asize;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001592 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001593
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001594 if (itemp->flags & (IF_SM | IF_SM2)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001595 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
1596 asize = 0;
1597 for (i = 0; i < oprs; i++) {
1598 if ((asize = itemp->opd[i] & SIZE_MASK) != 0) {
1599 int j;
1600 for (j = 0; j < oprs; j++)
1601 size[j] = asize;
1602 break;
1603 }
1604 }
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001605 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001606 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001607 }
1608
Keith Kaniosb7a89542007-04-12 02:40:54 +00001609 for (i = 0; i < itemp->operands; i++) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001610 if (!(itemp->opd[i] & SIZE_MASK) &&
1611 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001612 return 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001613
Keith Kaniosb7a89542007-04-12 02:40:54 +00001614 if ( (((itemp->opd[i] & SIZE_MASK) == BITS64) ||
1615 ((instruction->oprs[i].type & SIZE_MASK) == BITS64))
1616 && bits != 64)
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001617 return 5;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001618
1619 x = instruction->oprs[i].indexreg;
1620 b = instruction->oprs[i].basereg;
1621
1622 if (x != -1 && x >= EXPR_REG_START && x < REG_ENUM_LIMIT)
1623 x = regvals[x];
1624 if (b != -1 && b >= EXPR_REG_START && b < REG_ENUM_LIMIT)
1625 b = regvals[b];
1626
1627 if (((b >= 0400 && b <= 0500) || (x >= 0400 && x < 0500)) && bits != 64)
1628 return 2;
1629 }
1630
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001631 /*
1632 * Check template is okay at the set cpu level
1633 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001634 if (((itemp->flags & IF_PLEVEL) > cpu))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001635 return 3;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001636
1637 /*
1638 * Check if instruction is available in long mode
1639 */
1640 if ((itemp->flags & IF_NOLONG) && (bits == 64))
1641 return 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001642
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001643 /*
1644 * Check if special handling needed for Jumps
1645 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001646 if ((uint8_t)(itemp->code[0]) >= 0370)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001647 return 99;
1648
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001649 return ret;
1650}
1651
H. Peter Anvine2c80182005-01-15 22:15:51 +00001652static ea *process_ea(operand * input, ea * output, int addrbits,
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001653 int rfield, int32_t rflags, int forw_ref)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001654{
Keith Kaniosb7a89542007-04-12 02:40:54 +00001655
1656 int rip = FALSE; /* Used for RIP-relative addressing */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001657
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001658 /* REX flags for the rfield operand */
1659 output->rex |= rexflags(rfield, rflags, REX_R|REX_P|REX_W|REX_H);
1660
Keith Kaniosb7a89542007-04-12 02:40:54 +00001661 if (!(REGISTER & ~input->type)) { /* register direct */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001662 int i;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001663 int32_t f;
1664
1665 if (input->basereg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001666 || input->basereg >= REG_ENUM_LIMIT)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001667 return NULL;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001668 f = regflag(input);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001669 i = regvals[input->basereg];
Keith Kaniosb7a89542007-04-12 02:40:54 +00001670
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001671 if (REG_EA & ~f)
1672 return NULL; /* Invalid EA register */
1673
1674 output->rex |= op_rexflags(input, REX_B|REX_P|REX_W|REX_H);
1675
Keith Kaniosb7a89542007-04-12 02:40:54 +00001676 output->sib_present = FALSE; /* no SIB necessary */
1677 output->bytes = 0; /* no offset necessary either */
1678 output->modrm = 0xC0 | ((rfield & 7) << 3) | (i & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001679 } else { /* it's a memory reference */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001680
H. Peter Anvine2c80182005-01-15 22:15:51 +00001681 if (input->basereg == -1
1682 && (input->indexreg == -1 || input->scale == 0)) {
1683 /* it's a pure offset */
1684 if (input->addr_size)
1685 addrbits = input->addr_size;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001686
H. Peter Anvine2c80182005-01-15 22:15:51 +00001687 output->sib_present = FALSE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001688 output->bytes = (addrbits != 16 ? 4 : 2);
1689 output->modrm = (addrbits != 16 ? 5 : 6) | ((rfield & 7) << 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001690 } else { /* it's an indirection */
1691 int i = input->indexreg, b = input->basereg, s = input->scale;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001692 int32_t o = input->offset, seg = input->segment;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001693 int hb = input->hintbase, ht = input->hinttype;
1694 int t;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001695 int it, bt;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001696 int32_t ix, bx; /* register flags */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001697
H. Peter Anvine2c80182005-01-15 22:15:51 +00001698 if (s == 0)
1699 i = -1; /* make this easy, at least */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001700
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001701 if (i >= EXPR_REG_START && i < REG_ENUM_LIMIT) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001702 it = regvals[i];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001703 ix = reg_flags[i];
1704 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001705 it = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001706 ix = 0;
1707 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001708
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001709 if (b != -1 && b >= EXPR_REG_START && b < REG_ENUM_LIMIT) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001710 bt = regvals[b];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001711 bx = reg_flags[b];
1712 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001713 bt = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001714 bx = 0;
1715 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001716
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001717 /* check for a 32/64-bit memory reference... */
1718 if ((ix|bx) & (BITS32|BITS64)) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001719 /* it must be a 32/64-bit memory reference. Firstly we have
1720 * to check that all registers involved are type E/Rxx. */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001721 int32_t sok = BITS32|BITS64;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001722
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001723 if (it != -1) {
1724 if (!(REG64 & ~ix) || !(REG32 & ~ix))
1725 sok &= ix;
1726 else
1727 return NULL;
1728 }
1729
1730 if (bt != -1) {
1731 if ((REG_GPR & ~bx) && (IP_REG & ~bx))
1732 return NULL; /* Invalid register */
1733 if (sok & ~bx)
1734 return NULL; /* Invalid size */
1735 sok &= ~bx;
1736 if (!(IP_REG & ~bx)) {
1737 bt = b = -1;
1738 rip = TRUE;
1739 }
1740 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001741
H. Peter Anvine2c80182005-01-15 22:15:51 +00001742 /* While we're here, ensure the user didn't specify WORD. */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001743 if (input->addr_size == 16 ||
1744 (input->addr_size == 32 && !(sok & BITS32)) ||
1745 (input->addr_size == 64 && !(sok & BITS64)))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001746 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001747
Keith Kaniosb7a89542007-04-12 02:40:54 +00001748 /* now reorganize base/index */
1749 if (s == 1 && bt != it && bt != -1 && it != -1 &&
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001750 ((hb == b && ht == EAH_NOTBASE)
1751 || (hb == i && ht == EAH_MAKEBASE))) {
1752 /* swap if hints say so */
1753 t = bt, bt = it, it = t;
1754 t = bx, bx = ix, ix = t;
1755 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001756 if (bt == it) /* convert EAX+2*EAX to 3*EAX */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001757 bt = -1, bx = 0, s++;
1758 if (bt == -1 && s == 1 && !(hb == it && ht == EAH_NOTBASE)) {
1759 /* make single reg base, unless hint */
1760 bt = it, bx = ix, it = -1, ix = 0;
1761 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001762 if (((s == 2 && (it & 7) != (REG_NUM_ESP & 7)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001763 && !(input->eaflags & EAF_TIMESTWO)) || s == 3
Keith Kaniosb7a89542007-04-12 02:40:54 +00001764 || s == 5 || s == 9) && bt == -1)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001765 bt = it, bx = ix, s--; /* convert 3*EAX to EAX+2*EAX */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001766 if (it == -1 && (bt & 7) != (REG_NUM_ESP & 7)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001767 && (input->eaflags & EAF_TIMESTWO))
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001768 it = bt, ix = bx, bt = -1, bx = 0, s = 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001769 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001770 if (s == 1 && (it & 7) == (REG_NUM_ESP & 7)) {
1771 /* swap ESP into base if scale is 1 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001772 t = it, it = bt, bt = t;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001773 t = ix, ix = bx, bx = t;
1774 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001775 if ((it & 7) == (REG_NUM_ESP & 7)
1776 || (s != 1 && s != 2 && s != 4 && s != 8 && it != -1))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001777 return NULL; /* wrong, for various reasons */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001778
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001779 output->rex |= rexflags(it, ix, REX_X);
1780 output->rex |= rexflags(bt, bx, REX_B);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001781
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001782 if (it == -1 && (bt & 7) != (REG_NUM_ESP & 7)) {
1783 /* no SIB needed */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001784 int mod, rm;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001785
1786 if (bt == -1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001787 rm = 5;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001788 mod = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001789 } else {
1790 rm = (bt & 7);
1791 if (rm != (REG_NUM_EBP & 7) && o == 0 &&
1792 seg == NO_SEG && !forw_ref &&
1793 !(input->eaflags &
1794 (EAF_BYTEOFFS | EAF_WORDOFFS)))
1795 mod = 0;
1796 else if (input->eaflags & EAF_BYTEOFFS ||
1797 (o >= -128 && o <= 127 && seg == NO_SEG
1798 && !forw_ref
1799 && !(input->eaflags & EAF_WORDOFFS)))
1800 mod = 1;
1801 else
1802 mod = 2;
1803 }
H. Peter Anvinea838272002-04-30 20:51:53 +00001804
H. Peter Anvine2c80182005-01-15 22:15:51 +00001805 output->sib_present = FALSE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001806 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
1807 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001808 } else {
1809 /* we need a SIB */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001810 int mod, scale, index, base;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001811
1812 if (it == -1)
1813 index = 4, s = 1;
1814 else
1815 index = (it & 7);
1816
H. Peter Anvine2c80182005-01-15 22:15:51 +00001817 switch (s) {
1818 case 1:
1819 scale = 0;
1820 break;
1821 case 2:
1822 scale = 1;
1823 break;
1824 case 4:
1825 scale = 2;
1826 break;
1827 case 8:
1828 scale = 3;
1829 break;
1830 default: /* then what the smeg is it? */
1831 return NULL; /* panic */
1832 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001833
1834 if (bt == -1) {
1835 base = 5;
1836 mod = 0;
1837 } else {
1838 base = (bt & 7);
1839 if (base != (REG_NUM_EBP & 7) && o == 0 &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00001840 seg == NO_SEG && !forw_ref &&
1841 !(input->eaflags &
Keith Kaniosb7a89542007-04-12 02:40:54 +00001842 (EAF_BYTEOFFS | EAF_WORDOFFS)))
1843 mod = 0;
1844 else if (input->eaflags & EAF_BYTEOFFS ||
1845 (o >= -128 && o <= 127 && seg == NO_SEG
1846 && !forw_ref
1847 && !(input->eaflags & EAF_WORDOFFS)))
1848 mod = 1;
1849 else
1850 mod = 2;
1851 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001852
H. Peter Anvine2c80182005-01-15 22:15:51 +00001853 output->sib_present = TRUE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001854 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
1855 output->modrm = (mod << 6) | ((rfield & 7) << 3) | 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001856 output->sib = (scale << 6) | (index << 3) | base;
1857 }
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001858
1859 /* Process RIP-relative Addressing */
1860 if (rip) {
1861 if (globalbits != 64 ||
1862 (output->modrm & 0xC7) != 0x05)
1863 return NULL;
1864 output->rip = TRUE;
1865 } else {
1866 output->rip = FALSE;
1867 /* Actual Disp32 needs blank SIB on x64 */
1868 if (globalbits == 64 &&
1869 !(output->sib_present) &&
1870 ((output->modrm & 0xC7) == 0x05)) {
1871 output->sib_present = TRUE;
1872 /* RM Field = 4 (forward to Base of SIB) */
1873 output->modrm--;
1874 /* Index = 4 (none), Base = 5 */
1875 output->sib = (4 << 3) | 5;
1876 }
1877 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001878 } else { /* it's 16-bit */
1879 int mod, rm;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001880
1881 /* check for 64-bit long mode */
1882 if (addrbits == 64)
1883 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001884
H. Peter Anvine2c80182005-01-15 22:15:51 +00001885 /* check all registers are BX, BP, SI or DI */
1886 if ((b != -1 && b != R_BP && b != R_BX && b != R_SI
1887 && b != R_DI) || (i != -1 && i != R_BP && i != R_BX
1888 && i != R_SI && i != R_DI))
1889 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001890
Keith Kaniosb7a89542007-04-12 02:40:54 +00001891 /* ensure the user didn't specify DWORD/QWORD */
1892 if (input->addr_size == 32 || input->addr_size == 64)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001893 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001894
H. Peter Anvine2c80182005-01-15 22:15:51 +00001895 if (s != 1 && i != -1)
1896 return NULL; /* no can do, in 16-bit EA */
1897 if (b == -1 && i != -1) {
1898 int tmp = b;
1899 b = i;
1900 i = tmp;
1901 } /* swap */
1902 if ((b == R_SI || b == R_DI) && i != -1) {
1903 int tmp = b;
1904 b = i;
1905 i = tmp;
1906 }
1907 /* have BX/BP as base, SI/DI index */
1908 if (b == i)
1909 return NULL; /* shouldn't ever happen, in theory */
1910 if (i != -1 && b != -1 &&
1911 (i == R_BP || i == R_BX || b == R_SI || b == R_DI))
1912 return NULL; /* invalid combinations */
1913 if (b == -1) /* pure offset: handled above */
1914 return NULL; /* so if it gets to here, panic! */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001915
H. Peter Anvine2c80182005-01-15 22:15:51 +00001916 rm = -1;
1917 if (i != -1)
1918 switch (i * 256 + b) {
1919 case R_SI * 256 + R_BX:
1920 rm = 0;
1921 break;
1922 case R_DI * 256 + R_BX:
1923 rm = 1;
1924 break;
1925 case R_SI * 256 + R_BP:
1926 rm = 2;
1927 break;
1928 case R_DI * 256 + R_BP:
1929 rm = 3;
1930 break;
1931 } else
1932 switch (b) {
1933 case R_SI:
1934 rm = 4;
1935 break;
1936 case R_DI:
1937 rm = 5;
1938 break;
1939 case R_BP:
1940 rm = 6;
1941 break;
1942 case R_BX:
1943 rm = 7;
1944 break;
1945 }
1946 if (rm == -1) /* can't happen, in theory */
1947 return NULL; /* so panic if it does */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001948
H. Peter Anvine2c80182005-01-15 22:15:51 +00001949 if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
1950 !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
1951 mod = 0;
1952 else if (input->eaflags & EAF_BYTEOFFS ||
1953 (o >= -128 && o <= 127 && seg == NO_SEG
1954 && !forw_ref
1955 && !(input->eaflags & EAF_WORDOFFS)))
1956 mod = 1;
1957 else
1958 mod = 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001959
H. Peter Anvine2c80182005-01-15 22:15:51 +00001960 output->sib_present = FALSE; /* no SIB - it's 16-bit */
1961 output->bytes = mod; /* bytes of offset needed */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001962 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001963 }
1964 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001965 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001966
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001967 output->size = 1 + output->sib_present + output->bytes;
1968 return output;
1969}
1970
H. Peter Anvine2c80182005-01-15 22:15:51 +00001971static int chsize(operand * input, int addrbits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001972{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001973 if (!(MEMORY & ~input->type)) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001974 int32_t i, b;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001975
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001976 if (input->indexreg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001977 || input->indexreg >= REG_ENUM_LIMIT)
1978 i = -1;
1979 else
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001980 i = reg_flags[input->indexreg];
Keith Kaniosb7a89542007-04-12 02:40:54 +00001981
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001982 if (input->basereg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001983 || input->basereg >= REG_ENUM_LIMIT)
1984 b = -1;
1985 else
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001986 b = reg_flags[input->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001987
H. Peter Anvine2c80182005-01-15 22:15:51 +00001988 if (input->scale == 0)
1989 i = -1;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001990
H. Peter Anvine2c80182005-01-15 22:15:51 +00001991 if (i == -1 && b == -1) /* pure offset */
1992 return (input->addr_size != 0 && input->addr_size != addrbits);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001993
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001994 if (!(REG32 & ~i) || !(REG32 & ~b))
Keith Kaniosb7a89542007-04-12 02:40:54 +00001995 return (addrbits != 32);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001996 else
1997 return (addrbits == 32);
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001998 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001999 return 0;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002000 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002001}