blob: 0c63eb97ce6f6383396ad58524d603f155558eb9 [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.
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.
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 */
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 Anvinea6e34d2002-04-30 20:51:32 +0000551 struct itemplate *temp;
552
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;
877 case 0370:
878 case 0371:
879 case 0372:
880 break;
881 case 0373:
882 length++;
883 break;
884 default: /* can't do it by 'case' statements */
885 if (c >= 0100 && c <= 0277) { /* it's an EA */
886 ea ea_data;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000887 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000888 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000889 ea_data.rex = 0; /* Ensure ea.REX is initially 0 */
890
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000891 if (c <= 0177) {
892 /* pick rfield from operand b */
893 rflags = regflag(&ins->oprs[c & 7]);
894 rfield = regvals[ins->oprs[c & 7].basereg];
895 } else {
896 rflags = 0;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000897 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000898 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000899
H. Peter Anvine2c80182005-01-15 22:15:51 +0000900 if (!process_ea
Keith Kaniosb7a89542007-04-12 02:40:54 +0000901 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000902 rfield, rflags, ins->forw_ref)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000903 errfunc(ERR_NONFATAL, "invalid effective address");
904 return -1;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000905 } else {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000906 ins->rex |= ea_data.rex;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000907 length += ea_data.size;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000908 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000909 } else
910 errfunc(ERR_PANIC, "internal instruction table corrupt"
911 ": instruction code 0x%02X given", c);
912 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000913
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000914 ins->rex &= rex_mask;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000915 if (ins->rex & REX_REAL) {
916 if (ins->rex & REX_H) {
917 errfunc(ERR_NONFATAL, "cannot use high register in rex instruction");
918 return -1;
919 } else if (bits == 64 ||
920 ((ins->rex & REX_L) &&
921 !(ins->rex & (REX_P|REX_W|REX_X|REX_B)) &&
922 cpu >= IF_X86_64)) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000923 length++;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000924 } else {
925 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
926 return -1;
927 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000928 }
929
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000930 return length;
931}
Keith Kaniosb7a89542007-04-12 02:40:54 +0000932
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000933#define EMIT_REX() \
934 if((ins->rex & REX_REAL) && (bits == 64)) { \
935 ins->rex = (ins->rex & REX_REAL)|REX_P; \
936 out(offset, segment, &ins->rex, OUT_RAWDATA+1, NO_SEG, NO_SEG); \
937 ins->rex = 0; \
938 offset += 1; \
939 }
940
Keith Kaniosb7a89542007-04-12 02:40:54 +0000941static void gencode(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000942 insn * ins, const char *codes, int32_t insn_end)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000943{
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000944 static char condval[] = { /* conditional opcodes */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000945 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
946 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
947 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000948 };
Keith Kaniosb7a89542007-04-12 02:40:54 +0000949 uint8_t c;
950 uint8_t bytes[4];
951 int32_t size;
952 int64_t data;
953
H. Peter Anvineba20a72002-04-30 20:53:55 +0000954 while (*codes)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000955 switch (c = *codes++) {
956 case 01:
957 case 02:
958 case 03:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000959 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +0000960 out(offset, segment, codes, OUT_RAWDATA + c, NO_SEG, NO_SEG);
961 codes += c;
962 offset += c;
963 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000964
H. Peter Anvine2c80182005-01-15 22:15:51 +0000965 case 04:
966 case 06:
967 switch (ins->oprs[0].basereg) {
968 case R_CS:
969 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0);
970 break;
971 case R_DS:
972 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0);
973 break;
974 case R_ES:
975 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0);
976 break;
977 case R_SS:
978 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0);
979 break;
980 default:
981 errfunc(ERR_PANIC,
982 "bizarre 8086 segment register received");
983 }
984 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
985 offset++;
986 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000987
H. Peter Anvine2c80182005-01-15 22:15:51 +0000988 case 05:
989 case 07:
990 switch (ins->oprs[0].basereg) {
991 case R_FS:
992 bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0);
993 break;
994 case R_GS:
995 bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0);
996 break;
997 default:
998 errfunc(ERR_PANIC,
999 "bizarre 386 segment register received");
1000 }
1001 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1002 offset++;
1003 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001004
H. Peter Anvine2c80182005-01-15 22:15:51 +00001005 case 010:
1006 case 011:
1007 case 012:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001008 EMIT_REX();
Keith Kaniosb7a89542007-04-12 02:40:54 +00001009 bytes[0] = *codes++ + ((regval(&ins->oprs[c - 010])) & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001010 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1011 offset += 1;
1012 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001013
H. Peter Anvine2c80182005-01-15 22:15:51 +00001014 case 017:
1015 bytes[0] = 0;
1016 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1017 offset += 1;
1018 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001019
H. Peter Anvine2c80182005-01-15 22:15:51 +00001020 case 014:
1021 case 015:
1022 case 016:
1023 if (ins->oprs[c - 014].offset < -128
1024 || ins->oprs[c - 014].offset > 127) {
1025 errfunc(ERR_WARNING, "signed byte value exceeds bounds");
1026 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001027
H. Peter Anvine2c80182005-01-15 22:15:51 +00001028 if (ins->oprs[c - 014].segment != NO_SEG) {
1029 data = ins->oprs[c - 014].offset;
1030 out(offset, segment, &data, OUT_ADDRESS + 1,
1031 ins->oprs[c - 014].segment, ins->oprs[c - 014].wrt);
1032 } else {
1033 bytes[0] = ins->oprs[c - 014].offset;
1034 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1035 NO_SEG);
1036 }
1037 offset += 1;
1038 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001039
H. Peter Anvine2c80182005-01-15 22:15:51 +00001040 case 020:
1041 case 021:
1042 case 022:
1043 if (ins->oprs[c - 020].offset < -256
1044 || ins->oprs[c - 020].offset > 255) {
1045 errfunc(ERR_WARNING, "byte value exceeds bounds");
1046 }
1047 if (ins->oprs[c - 020].segment != NO_SEG) {
1048 data = ins->oprs[c - 020].offset;
1049 out(offset, segment, &data, OUT_ADDRESS + 1,
1050 ins->oprs[c - 020].segment, ins->oprs[c - 020].wrt);
1051 } else {
1052 bytes[0] = ins->oprs[c - 020].offset;
1053 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1054 NO_SEG);
1055 }
1056 offset += 1;
1057 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001058
H. Peter Anvine2c80182005-01-15 22:15:51 +00001059 case 024:
1060 case 025:
1061 case 026:
1062 if (ins->oprs[c - 024].offset < 0
1063 || ins->oprs[c - 024].offset > 255)
1064 errfunc(ERR_WARNING, "unsigned byte value exceeds bounds");
1065 if (ins->oprs[c - 024].segment != NO_SEG) {
1066 data = ins->oprs[c - 024].offset;
1067 out(offset, segment, &data, OUT_ADDRESS + 1,
1068 ins->oprs[c - 024].segment, ins->oprs[c - 024].wrt);
1069 } else {
1070 bytes[0] = ins->oprs[c - 024].offset;
1071 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1072 NO_SEG);
1073 }
1074 offset += 1;
1075 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001076
H. Peter Anvine2c80182005-01-15 22:15:51 +00001077 case 030:
1078 case 031:
1079 case 032:
1080 if (ins->oprs[c - 030].segment == NO_SEG &&
1081 ins->oprs[c - 030].wrt == NO_SEG &&
1082 (ins->oprs[c - 030].offset < -65536L ||
1083 ins->oprs[c - 030].offset > 65535L)) {
1084 errfunc(ERR_WARNING, "word value exceeds bounds");
1085 }
1086 data = ins->oprs[c - 030].offset;
1087 out(offset, segment, &data, OUT_ADDRESS + 2,
1088 ins->oprs[c - 030].segment, ins->oprs[c - 030].wrt);
1089 offset += 2;
1090 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001091
H. Peter Anvine2c80182005-01-15 22:15:51 +00001092 case 034:
1093 case 035:
1094 case 036:
1095 if (ins->oprs[c - 034].type & (BITS16 | BITS32))
1096 size = (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
1097 else
1098 size = (bits == 16) ? 2 : 4;
1099 data = ins->oprs[c - 034].offset;
1100 if (size == 2 && (data < -65536L || data > 65535L))
1101 errfunc(ERR_WARNING, "word value exceeds bounds");
1102 out(offset, segment, &data, OUT_ADDRESS + size,
1103 ins->oprs[c - 034].segment, ins->oprs[c - 034].wrt);
1104 offset += size;
1105 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001106
H. Peter Anvine2c80182005-01-15 22:15:51 +00001107 case 037:
1108 if (ins->oprs[0].segment == NO_SEG)
1109 errfunc(ERR_NONFATAL, "value referenced by FAR is not"
1110 " relocatable");
1111 data = 0L;
1112 out(offset, segment, &data, OUT_ADDRESS + 2,
1113 outfmt->segbase(1 + ins->oprs[0].segment),
1114 ins->oprs[0].wrt);
1115 offset += 2;
1116 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001117
H. Peter Anvine2c80182005-01-15 22:15:51 +00001118 case 040:
1119 case 041:
1120 case 042:
1121 data = ins->oprs[c - 040].offset;
1122 out(offset, segment, &data, OUT_ADDRESS + 4,
1123 ins->oprs[c - 040].segment, ins->oprs[c - 040].wrt);
1124 offset += 4;
1125 break;
H. Peter Anvin3ba46772002-05-27 23:19:35 +00001126
H. Peter Anvine2c80182005-01-15 22:15:51 +00001127 case 044:
1128 case 045:
1129 case 046:
1130 data = ins->oprs[c - 044].offset;
1131 size = ((ins->oprs[c - 044].addr_size ?
Keith Kaniosb7a89542007-04-12 02:40:54 +00001132 ins->oprs[c - 044].addr_size : bits) >> 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001133 if (size == 2 && (data < -65536L || data > 65535L))
1134 errfunc(ERR_WARNING, "word value exceeds bounds");
1135 out(offset, segment, &data, OUT_ADDRESS + size,
1136 ins->oprs[c - 044].segment, ins->oprs[c - 044].wrt);
1137 offset += size;
1138 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001139
H. Peter Anvine2c80182005-01-15 22:15:51 +00001140 case 050:
1141 case 051:
1142 case 052:
1143 if (ins->oprs[c - 050].segment != segment)
1144 errfunc(ERR_NONFATAL,
1145 "short relative jump outside segment");
1146 data = ins->oprs[c - 050].offset - insn_end;
1147 if (data > 127 || data < -128)
1148 errfunc(ERR_NONFATAL, "short jump is out of range");
1149 bytes[0] = data;
1150 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1151 offset += 1;
1152 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001153
1154 case 054:
1155 case 055:
1156 case 056:
1157 data = (int64_t)ins->oprs[c - 054].offset;
1158 out(offset, segment, &data, OUT_ADDRESS + 8,
1159 ins->oprs[c - 054].segment, ins->oprs[c - 054].wrt);
1160 offset += 8;
1161 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001162
H. Peter Anvine2c80182005-01-15 22:15:51 +00001163 case 060:
1164 case 061:
1165 case 062:
1166 if (ins->oprs[c - 060].segment != segment) {
1167 data = ins->oprs[c - 060].offset;
1168 out(offset, segment, &data,
1169 OUT_REL2ADR + insn_end - offset,
1170 ins->oprs[c - 060].segment, ins->oprs[c - 060].wrt);
1171 } else {
1172 data = ins->oprs[c - 060].offset - insn_end;
1173 out(offset, segment, &data,
1174 OUT_ADDRESS + 2, NO_SEG, NO_SEG);
1175 }
1176 offset += 2;
1177 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001178
H. Peter Anvine2c80182005-01-15 22:15:51 +00001179 case 064:
1180 case 065:
1181 case 066:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001182 if (ins->oprs[c - 064].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001183 size = (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
1184 else
1185 size = (bits == 16) ? 2 : 4;
1186 if (ins->oprs[c - 064].segment != segment) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001187 int32_t reltype = (size == 2 ? OUT_REL2ADR : OUT_REL4ADR);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001188 data = ins->oprs[c - 064].offset;
1189 out(offset, segment, &data, reltype + insn_end - offset,
1190 ins->oprs[c - 064].segment, ins->oprs[c - 064].wrt);
1191 } else {
1192 data = ins->oprs[c - 064].offset - insn_end;
1193 out(offset, segment, &data,
1194 OUT_ADDRESS + size, NO_SEG, NO_SEG);
1195 }
1196 offset += size;
1197 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001198
H. Peter Anvine2c80182005-01-15 22:15:51 +00001199 case 070:
1200 case 071:
1201 case 072:
1202 if (ins->oprs[c - 070].segment != segment) {
1203 data = ins->oprs[c - 070].offset;
1204 out(offset, segment, &data,
1205 OUT_REL4ADR + insn_end - offset,
1206 ins->oprs[c - 070].segment, ins->oprs[c - 070].wrt);
1207 } else {
1208 data = ins->oprs[c - 070].offset - insn_end;
1209 out(offset, segment, &data,
1210 OUT_ADDRESS + 4, NO_SEG, NO_SEG);
1211 }
1212 offset += 4;
1213 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001214
H. Peter Anvine2c80182005-01-15 22:15:51 +00001215 case 0130:
1216 case 0131:
1217 case 0132:
1218 data = ins->oprs[c - 0130].offset;
1219 if (is_sbyte(ins, c - 0130, 16)) {
1220 bytes[0] = data;
1221 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1222 NO_SEG);
1223 offset++;
1224 } else {
1225 if (ins->oprs[c - 0130].segment == NO_SEG &&
1226 ins->oprs[c - 0130].wrt == NO_SEG &&
1227 (data < -65536L || data > 65535L)) {
1228 errfunc(ERR_WARNING, "word value exceeds bounds");
1229 }
1230 out(offset, segment, &data, OUT_ADDRESS + 2,
1231 ins->oprs[c - 0130].segment, ins->oprs[c - 0130].wrt);
1232 offset += 2;
1233 }
1234 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001235
H. Peter Anvine2c80182005-01-15 22:15:51 +00001236 case 0133:
1237 case 0134:
1238 case 0135:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001239 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001240 codes++;
1241 bytes[0] = *codes++;
1242 if (is_sbyte(ins, c - 0133, 16))
1243 bytes[0] |= 2; /* s-bit */
1244 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1245 offset++;
1246 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001247
H. Peter Anvine2c80182005-01-15 22:15:51 +00001248 case 0140:
1249 case 0141:
1250 case 0142:
1251 data = ins->oprs[c - 0140].offset;
1252 if (is_sbyte(ins, c - 0140, 32)) {
1253 bytes[0] = data;
1254 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1255 NO_SEG);
1256 offset++;
1257 } else {
1258 out(offset, segment, &data, OUT_ADDRESS + 4,
1259 ins->oprs[c - 0140].segment, ins->oprs[c - 0140].wrt);
1260 offset += 4;
1261 }
1262 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001263
H. Peter Anvine2c80182005-01-15 22:15:51 +00001264 case 0143:
1265 case 0144:
1266 case 0145:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001267 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001268 codes++;
1269 bytes[0] = *codes++;
1270 if (is_sbyte(ins, c - 0143, 32))
1271 bytes[0] |= 2; /* s-bit */
1272 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1273 offset++;
1274 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001275
H. Peter Anvine2c80182005-01-15 22:15:51 +00001276 case 0300:
1277 case 0301:
1278 case 0302:
1279 if (chsize(&ins->oprs[c - 0300], bits)) {
1280 *bytes = 0x67;
1281 out(offset, segment, bytes,
1282 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1283 offset += 1;
1284 } else
1285 offset += 0;
1286 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001287
H. Peter Anvine2c80182005-01-15 22:15:51 +00001288 case 0310:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001289 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001290 *bytes = 0x67;
1291 out(offset, segment, bytes,
1292 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1293 offset += 1;
1294 } else
1295 offset += 0;
1296 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001297
H. Peter Anvine2c80182005-01-15 22:15:51 +00001298 case 0311:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001299 if (bits != 32) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001300 *bytes = 0x67;
1301 out(offset, segment, bytes,
1302 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1303 offset += 1;
1304 } else
1305 offset += 0;
1306 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001307
H. Peter Anvine2c80182005-01-15 22:15:51 +00001308 case 0312:
1309 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001310
Keith Kaniosb7a89542007-04-12 02:40:54 +00001311 case 0313:
1312 ins->rex = 0;
1313 break;
1314
H. Peter Anvine2c80182005-01-15 22:15:51 +00001315 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001316 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001317 *bytes = 0x66;
1318 out(offset, segment, bytes,
1319 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1320 offset += 1;
1321 } else
1322 offset += 0;
1323 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001324
H. Peter Anvine2c80182005-01-15 22:15:51 +00001325 case 0321:
1326 if (bits == 16) {
1327 *bytes = 0x66;
1328 out(offset, segment, bytes,
1329 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1330 offset += 1;
1331 } else
1332 offset += 0;
1333 break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001334
H. Peter Anvine2c80182005-01-15 22:15:51 +00001335 case 0322:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001336 case 0323:
1337 break;
1338
1339 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001340 ins->rex |= REX_W;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001341 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001342
H. Peter Anvine2c80182005-01-15 22:15:51 +00001343 case 0330:
1344 *bytes = *codes++ ^ condval[ins->condition];
1345 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1346 offset += 1;
1347 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001348
H. Peter Anvine2c80182005-01-15 22:15:51 +00001349 case 0331:
1350 case 0332:
1351 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001352
H. Peter Anvine2c80182005-01-15 22:15:51 +00001353 case 0333:
1354 *bytes = 0xF3;
1355 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1356 offset += 1;
1357 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001358
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001359 case 0334:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001360 if (ins->rex & REX_R) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001361 *bytes = 0xF0;
1362 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1363 offset += 1;
1364 }
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001365 ins->rex &= ~(REX_L|REX_R);
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001366 break;
1367
H. Peter Anvine2c80182005-01-15 22:15:51 +00001368 case 0340:
1369 case 0341:
1370 case 0342:
1371 if (ins->oprs[0].segment != NO_SEG)
1372 errfunc(ERR_PANIC, "non-constant BSS size in pass two");
1373 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001374 int32_t size = ins->oprs[0].offset << (c - 0340);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001375 if (size > 0)
1376 out(offset, segment, NULL,
1377 OUT_RESERVE + size, NO_SEG, NO_SEG);
1378 offset += size;
1379 }
1380 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001381
H. Peter Anvine2c80182005-01-15 22:15:51 +00001382 case 0370:
1383 case 0371:
1384 case 0372:
1385 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001386
H. Peter Anvine2c80182005-01-15 22:15:51 +00001387 case 0373:
1388 *bytes = bits == 16 ? 3 : 5;
1389 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1390 offset += 1;
1391 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001392
H. Peter Anvine2c80182005-01-15 22:15:51 +00001393 default: /* can't do it by 'case' statements */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001394 if (c >= 0100 && c <= 0277) { /* it's an EA */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001395 ea ea_data;
1396 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001397 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001398 uint8_t *p;
1399 int32_t s;
1400
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001401 if (c <= 0177) {
1402 /* pick rfield from operand b */
1403 rflags = regflag(&ins->oprs[c & 7]);
1404 rfield = regvals[ins->oprs[c & 7].basereg];
1405 } else {
1406 /* rfield is constant */
1407 rflags = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001408 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001409 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001410
1411 if (!process_ea
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001412 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
1413 rfield, rflags, ins->forw_ref)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001414 errfunc(ERR_NONFATAL, "invalid effective address");
1415 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001416
H. Peter Anvine2c80182005-01-15 22:15:51 +00001417 p = bytes;
1418 *p++ = ea_data.modrm;
1419 if (ea_data.sib_present)
1420 *p++ = ea_data.sib;
1421
1422 s = p - bytes;
1423 out(offset, segment, bytes, OUT_RAWDATA + s,
1424 NO_SEG, NO_SEG);
1425
1426 switch (ea_data.bytes) {
1427 case 0:
1428 break;
1429 case 1:
1430 if (ins->oprs[(c >> 3) & 7].segment != NO_SEG) {
1431 data = ins->oprs[(c >> 3) & 7].offset;
1432 out(offset, segment, &data, OUT_ADDRESS + 1,
1433 ins->oprs[(c >> 3) & 7].segment,
1434 ins->oprs[(c >> 3) & 7].wrt);
1435 } else {
1436 *bytes = ins->oprs[(c >> 3) & 7].offset;
1437 out(offset, segment, bytes, OUT_RAWDATA + 1,
1438 NO_SEG, NO_SEG);
1439 }
1440 s++;
1441 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001442 case 8:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001443 case 2:
1444 case 4:
1445 data = ins->oprs[(c >> 3) & 7].offset;
Keith Kaniose83b3182007-04-16 14:31:54 +00001446 if (ea_data.rip && (ins->oprs[(c >> 3) & 7].segment == 0xFFFFFFFF))
1447 ea_data.rip = 0; /* Make distinction between Symbols and Immediates */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001448 out(offset, segment, &data, /* RIP = Relative, not Absolute */
1449 (ea_data.rip ? OUT_REL4ADR : OUT_ADDRESS) + ea_data.bytes,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001450 ins->oprs[(c >> 3) & 7].segment,
1451 ins->oprs[(c >> 3) & 7].wrt);
1452 s += ea_data.bytes;
1453 break;
1454 }
1455 offset += s;
1456 } else
1457 errfunc(ERR_PANIC, "internal instruction table corrupt"
1458 ": instruction code 0x%02X given", c);
1459 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001460}
1461
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001462static int regflag(const operand * o)
1463{
1464 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1465 errfunc(ERR_PANIC, "invalid operand passed to regflag()");
1466 }
1467 return reg_flags[o->basereg];
1468}
1469
1470static int regval(const operand * o)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001471{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001472 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1473 errfunc(ERR_PANIC, "invalid operand passed to regval()");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001474 }
H. Peter Anvin232badb2002-06-06 02:41:20 +00001475 return regvals[o->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001476}
1477
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001478static int op_rexflags(const operand * o, int mask)
1479{
1480 int32_t flags;
1481 int val;
1482
1483 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1484 errfunc(ERR_PANIC, "invalid operand passed to op_rexflags()");
1485 }
1486
1487 flags = reg_flags[o->basereg];
1488 val = regvals[o->basereg];
1489
1490 return rexflags(val, flags, mask);
1491}
1492
1493static int rexflags(int val, int32_t flags, int mask)
1494{
1495 int rex = 0;
1496
1497 if (val >= 8)
1498 rex |= REX_B|REX_X|REX_R;
1499 if (flags & BITS64)
1500 rex |= REX_W;
1501 if (!(REG_HIGH & ~flags)) /* AH, CH, DH, BH */
1502 rex |= REX_H;
1503 else if (!(REG8 & ~flags) && val >= 4) /* SPL, BPL, SIL, DIL */
1504 rex |= REX_P;
1505
1506 return rex & mask;
1507}
1508
Keith Kaniosb7a89542007-04-12 02:40:54 +00001509static int matches(struct itemplate *itemp, insn * instruction, int bits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001510{
H. Peter Anvin34539fb2007-05-30 04:27:58 +00001511 int i, size[3], asize, oprs, ret;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001512
1513 ret = 100;
1514
1515 /*
1516 * Check the opcode
1517 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001518 if (itemp->opcode != instruction->opcode)
1519 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001520
1521 /*
1522 * Count the operands
1523 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001524 if (itemp->operands != instruction->operands)
1525 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001526
1527 /*
1528 * Check that no spurious colons or TOs are present
1529 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001530 for (i = 0; i < itemp->operands; i++)
1531 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON | TO))
1532 return 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001533
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001534 /*
1535 * Check that the operand flags all match up
1536 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001537 for (i = 0; i < itemp->operands; i++)
1538 if (itemp->opd[i] & ~instruction->oprs[i].type ||
1539 ((itemp->opd[i] & SIZE_MASK) &&
1540 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK))) {
H. Peter Anvin5a640e12007-05-29 23:57:12 +00001541 if ((itemp->opd[i] & ~instruction->oprs[i].type & ~SIZE_MASK) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001542 (instruction->oprs[i].type & SIZE_MASK))
1543 return 0;
1544 else
H. Peter Anvine2c80182005-01-15 22:15:51 +00001545 return 1;
1546 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001547
1548 /*
1549 * Check operand sizes
1550 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001551 if (itemp->flags & IF_ARMASK) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001552 size[0] = size[1] = size[2] = 0;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001553
H. Peter Anvine2c80182005-01-15 22:15:51 +00001554 switch (itemp->flags & IF_ARMASK) {
1555 case IF_AR0:
1556 i = 0;
1557 break;
1558 case IF_AR1:
1559 i = 1;
1560 break;
1561 case IF_AR2:
1562 i = 2;
1563 break;
1564 default:
1565 break; /* Shouldn't happen */
1566 }
1567 if (itemp->flags & IF_SB) {
1568 size[i] = BITS8;
1569 } else if (itemp->flags & IF_SW) {
1570 size[i] = BITS16;
1571 } else if (itemp->flags & IF_SD) {
1572 size[i] = BITS32;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001573 } else if (itemp->flags & IF_SQ) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001574 size[i] = BITS64;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001575 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001576 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001577 asize = 0;
1578 if (itemp->flags & IF_SB) {
1579 asize = BITS8;
1580 oprs = itemp->operands;
1581 } else if (itemp->flags & IF_SW) {
1582 asize = BITS16;
1583 oprs = itemp->operands;
1584 } else if (itemp->flags & IF_SD) {
1585 asize = BITS32;
1586 oprs = itemp->operands;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001587 } else if (itemp->flags & IF_SQ) {
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;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001613 }
1614
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001615 /*
1616 * Check template is okay at the set cpu level
1617 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001618 if (((itemp->flags & IF_PLEVEL) > cpu))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001619 return 3;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001620
1621 /*
1622 * Check if instruction is available in long mode
1623 */
1624 if ((itemp->flags & IF_NOLONG) && (bits == 64))
1625 return 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001626
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001627 /*
1628 * Check if special handling needed for Jumps
1629 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001630 if ((uint8_t)(itemp->code[0]) >= 0370)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001631 return 99;
1632
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001633 return ret;
1634}
1635
H. Peter Anvine2c80182005-01-15 22:15:51 +00001636static ea *process_ea(operand * input, ea * output, int addrbits,
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001637 int rfield, int32_t rflags, int forw_ref)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001638{
Keith Kaniosb7a89542007-04-12 02:40:54 +00001639
1640 int rip = FALSE; /* Used for RIP-relative addressing */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001641
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001642 /* REX flags for the rfield operand */
1643 output->rex |= rexflags(rfield, rflags, REX_R|REX_P|REX_W|REX_H);
1644
Keith Kaniosb7a89542007-04-12 02:40:54 +00001645 if (!(REGISTER & ~input->type)) { /* register direct */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001646 int i;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001647 int32_t f;
1648
1649 if (input->basereg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001650 || input->basereg >= REG_ENUM_LIMIT)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001651 return NULL;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001652 f = regflag(input);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001653 i = regvals[input->basereg];
Keith Kaniosb7a89542007-04-12 02:40:54 +00001654
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001655 if (REG_EA & ~f)
1656 return NULL; /* Invalid EA register */
1657
1658 output->rex |= op_rexflags(input, REX_B|REX_P|REX_W|REX_H);
1659
Keith Kaniosb7a89542007-04-12 02:40:54 +00001660 output->sib_present = FALSE; /* no SIB necessary */
1661 output->bytes = 0; /* no offset necessary either */
1662 output->modrm = 0xC0 | ((rfield & 7) << 3) | (i & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001663 } else { /* it's a memory reference */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001664
H. Peter Anvine2c80182005-01-15 22:15:51 +00001665 if (input->basereg == -1
1666 && (input->indexreg == -1 || input->scale == 0)) {
1667 /* it's a pure offset */
1668 if (input->addr_size)
1669 addrbits = input->addr_size;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00001670 if (addrbits == 64) {
1671 int scale, index, base;
1672 output->sib_present = TRUE;
1673 scale = 0;
1674 index = 4;
1675 base = 5;
1676 output->sib = (scale << 6) | (index << 3) | base;
1677 output->bytes = 4;
1678 output->modrm = 4 | ((rfield & 7) << 3);
1679 } else {
1680 output->sib_present = FALSE;
1681 output->bytes = (addrbits != 16 ? 4 : 2);
1682 output->modrm = (addrbits != 16 ? 5 : 6) | ((rfield & 7) << 3);
1683 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001684 } else { /* it's an indirection */
1685 int i = input->indexreg, b = input->basereg, s = input->scale;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001686 int32_t o = input->offset, seg = input->segment;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001687 int hb = input->hintbase, ht = input->hinttype;
1688 int t;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001689 int it, bt;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001690 int32_t ix, bx; /* register flags */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001691
H. Peter Anvine2c80182005-01-15 22:15:51 +00001692 if (s == 0)
1693 i = -1; /* make this easy, at least */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001694
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001695 if (i >= EXPR_REG_START && i < REG_ENUM_LIMIT) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001696 it = regvals[i];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001697 ix = reg_flags[i];
1698 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001699 it = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001700 ix = 0;
1701 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001702
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001703 if (b != -1 && b >= EXPR_REG_START && b < REG_ENUM_LIMIT) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001704 bt = regvals[b];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001705 bx = reg_flags[b];
1706 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001707 bt = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001708 bx = 0;
1709 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001710
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001711 /* check for a 32/64-bit memory reference... */
1712 if ((ix|bx) & (BITS32|BITS64)) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001713 /* it must be a 32/64-bit memory reference. Firstly we have
1714 * to check that all registers involved are type E/Rxx. */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001715 int32_t sok = BITS32|BITS64;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001716
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001717 if (it != -1) {
1718 if (!(REG64 & ~ix) || !(REG32 & ~ix))
1719 sok &= ix;
1720 else
1721 return NULL;
1722 }
1723
1724 if (bt != -1) {
1725 if ((REG_GPR & ~bx) && (IP_REG & ~bx))
1726 return NULL; /* Invalid register */
H. Peter Anvina57e8d42007-05-30 03:44:02 +00001727 if (~sok & bx & SIZE_MASK)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001728 return NULL; /* Invalid size */
1729 sok &= ~bx;
1730 if (!(IP_REG & ~bx)) {
1731 bt = b = -1;
1732 rip = TRUE;
1733 }
1734 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001735
H. Peter Anvine2c80182005-01-15 22:15:51 +00001736 /* While we're here, ensure the user didn't specify WORD. */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001737 if (input->addr_size == 16 ||
1738 (input->addr_size == 32 && !(sok & BITS32)) ||
1739 (input->addr_size == 64 && !(sok & BITS64)))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001740 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001741
Keith Kaniosb7a89542007-04-12 02:40:54 +00001742 /* now reorganize base/index */
1743 if (s == 1 && bt != it && bt != -1 && it != -1 &&
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001744 ((hb == b && ht == EAH_NOTBASE)
1745 || (hb == i && ht == EAH_MAKEBASE))) {
1746 /* swap if hints say so */
1747 t = bt, bt = it, it = t;
1748 t = bx, bx = ix, ix = t;
1749 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001750 if (bt == it) /* convert EAX+2*EAX to 3*EAX */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001751 bt = -1, bx = 0, s++;
1752 if (bt == -1 && s == 1 && !(hb == it && ht == EAH_NOTBASE)) {
1753 /* make single reg base, unless hint */
1754 bt = it, bx = ix, it = -1, ix = 0;
1755 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001756 if (((s == 2 && (it & 7) != (REG_NUM_ESP & 7)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001757 && !(input->eaflags & EAF_TIMESTWO)) || s == 3
Keith Kaniosb7a89542007-04-12 02:40:54 +00001758 || s == 5 || s == 9) && bt == -1)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001759 bt = it, bx = ix, s--; /* convert 3*EAX to EAX+2*EAX */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001760 if (it == -1 && (bt & 7) != (REG_NUM_ESP & 7)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001761 && (input->eaflags & EAF_TIMESTWO))
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001762 it = bt, ix = bx, bt = -1, bx = 0, s = 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001763 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001764 if (s == 1 && (it & 7) == (REG_NUM_ESP & 7)) {
1765 /* swap ESP into base if scale is 1 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001766 t = it, it = bt, bt = t;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001767 t = ix, ix = bx, bx = t;
1768 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001769 if ((it & 7) == (REG_NUM_ESP & 7)
1770 || (s != 1 && s != 2 && s != 4 && s != 8 && it != -1))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001771 return NULL; /* wrong, for various reasons */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001772
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001773 output->rex |= rexflags(it, ix, REX_X);
1774 output->rex |= rexflags(bt, bx, REX_B);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001775
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001776 if (it == -1 && (bt & 7) != (REG_NUM_ESP & 7)) {
1777 /* no SIB needed */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001778 int mod, rm;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001779
1780 if (bt == -1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001781 rm = 5;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001782 mod = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001783 } else {
1784 rm = (bt & 7);
1785 if (rm != (REG_NUM_EBP & 7) && o == 0 &&
1786 seg == NO_SEG && !forw_ref &&
1787 !(input->eaflags &
1788 (EAF_BYTEOFFS | EAF_WORDOFFS)))
1789 mod = 0;
1790 else if (input->eaflags & EAF_BYTEOFFS ||
1791 (o >= -128 && o <= 127 && seg == NO_SEG
1792 && !forw_ref
1793 && !(input->eaflags & EAF_WORDOFFS)))
1794 mod = 1;
1795 else
1796 mod = 2;
1797 }
H. Peter Anvinea838272002-04-30 20:51:53 +00001798
H. Peter Anvine2c80182005-01-15 22:15:51 +00001799 output->sib_present = FALSE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001800 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
1801 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001802 } else {
1803 /* we need a SIB */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001804 int mod, scale, index, base;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001805
1806 if (it == -1)
1807 index = 4, s = 1;
1808 else
1809 index = (it & 7);
1810
H. Peter Anvine2c80182005-01-15 22:15:51 +00001811 switch (s) {
1812 case 1:
1813 scale = 0;
1814 break;
1815 case 2:
1816 scale = 1;
1817 break;
1818 case 4:
1819 scale = 2;
1820 break;
1821 case 8:
1822 scale = 3;
1823 break;
1824 default: /* then what the smeg is it? */
1825 return NULL; /* panic */
1826 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001827
1828 if (bt == -1) {
1829 base = 5;
1830 mod = 0;
1831 } else {
1832 base = (bt & 7);
1833 if (base != (REG_NUM_EBP & 7) && o == 0 &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00001834 seg == NO_SEG && !forw_ref &&
1835 !(input->eaflags &
Keith Kaniosb7a89542007-04-12 02:40:54 +00001836 (EAF_BYTEOFFS | EAF_WORDOFFS)))
1837 mod = 0;
1838 else if (input->eaflags & EAF_BYTEOFFS ||
1839 (o >= -128 && o <= 127 && seg == NO_SEG
1840 && !forw_ref
1841 && !(input->eaflags & EAF_WORDOFFS)))
1842 mod = 1;
1843 else
1844 mod = 2;
1845 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001846
H. Peter Anvine2c80182005-01-15 22:15:51 +00001847 output->sib_present = TRUE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001848 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
1849 output->modrm = (mod << 6) | ((rfield & 7) << 3) | 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001850 output->sib = (scale << 6) | (index << 3) | base;
1851 }
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001852
1853 /* Process RIP-relative Addressing */
1854 if (rip) {
1855 if (globalbits != 64 ||
1856 (output->modrm & 0xC7) != 0x05)
1857 return NULL;
1858 output->rip = TRUE;
1859 } else {
1860 output->rip = FALSE;
1861 /* Actual Disp32 needs blank SIB on x64 */
1862 if (globalbits == 64 &&
1863 !(output->sib_present) &&
1864 ((output->modrm & 0xC7) == 0x05)) {
1865 output->sib_present = TRUE;
1866 /* RM Field = 4 (forward to Base of SIB) */
1867 output->modrm--;
1868 /* Index = 4 (none), Base = 5 */
1869 output->sib = (4 << 3) | 5;
1870 }
1871 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001872 } else { /* it's 16-bit */
1873 int mod, rm;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001874
1875 /* check for 64-bit long mode */
1876 if (addrbits == 64)
1877 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001878
H. Peter Anvine2c80182005-01-15 22:15:51 +00001879 /* check all registers are BX, BP, SI or DI */
1880 if ((b != -1 && b != R_BP && b != R_BX && b != R_SI
1881 && b != R_DI) || (i != -1 && i != R_BP && i != R_BX
1882 && i != R_SI && i != R_DI))
1883 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001884
Keith Kaniosb7a89542007-04-12 02:40:54 +00001885 /* ensure the user didn't specify DWORD/QWORD */
1886 if (input->addr_size == 32 || input->addr_size == 64)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001887 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001888
H. Peter Anvine2c80182005-01-15 22:15:51 +00001889 if (s != 1 && i != -1)
1890 return NULL; /* no can do, in 16-bit EA */
1891 if (b == -1 && i != -1) {
1892 int tmp = b;
1893 b = i;
1894 i = tmp;
1895 } /* swap */
1896 if ((b == R_SI || b == R_DI) && i != -1) {
1897 int tmp = b;
1898 b = i;
1899 i = tmp;
1900 }
1901 /* have BX/BP as base, SI/DI index */
1902 if (b == i)
1903 return NULL; /* shouldn't ever happen, in theory */
1904 if (i != -1 && b != -1 &&
1905 (i == R_BP || i == R_BX || b == R_SI || b == R_DI))
1906 return NULL; /* invalid combinations */
1907 if (b == -1) /* pure offset: handled above */
1908 return NULL; /* so if it gets to here, panic! */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001909
H. Peter Anvine2c80182005-01-15 22:15:51 +00001910 rm = -1;
1911 if (i != -1)
1912 switch (i * 256 + b) {
1913 case R_SI * 256 + R_BX:
1914 rm = 0;
1915 break;
1916 case R_DI * 256 + R_BX:
1917 rm = 1;
1918 break;
1919 case R_SI * 256 + R_BP:
1920 rm = 2;
1921 break;
1922 case R_DI * 256 + R_BP:
1923 rm = 3;
1924 break;
1925 } else
1926 switch (b) {
1927 case R_SI:
1928 rm = 4;
1929 break;
1930 case R_DI:
1931 rm = 5;
1932 break;
1933 case R_BP:
1934 rm = 6;
1935 break;
1936 case R_BX:
1937 rm = 7;
1938 break;
1939 }
1940 if (rm == -1) /* can't happen, in theory */
1941 return NULL; /* so panic if it does */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001942
H. Peter Anvine2c80182005-01-15 22:15:51 +00001943 if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
1944 !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
1945 mod = 0;
1946 else if (input->eaflags & EAF_BYTEOFFS ||
1947 (o >= -128 && o <= 127 && seg == NO_SEG
1948 && !forw_ref
1949 && !(input->eaflags & EAF_WORDOFFS)))
1950 mod = 1;
1951 else
1952 mod = 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001953
H. Peter Anvine2c80182005-01-15 22:15:51 +00001954 output->sib_present = FALSE; /* no SIB - it's 16-bit */
1955 output->bytes = mod; /* bytes of offset needed */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001956 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001957 }
1958 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001959 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001960
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001961 output->size = 1 + output->sib_present + output->bytes;
1962 return output;
1963}
1964
H. Peter Anvine2c80182005-01-15 22:15:51 +00001965static int chsize(operand * input, int addrbits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001966{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001967 if (!(MEMORY & ~input->type)) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001968 int32_t i, b;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001969
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001970 if (input->indexreg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001971 || input->indexreg >= REG_ENUM_LIMIT)
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00001972 i = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001973 else
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001974 i = reg_flags[input->indexreg];
Keith Kaniosb7a89542007-04-12 02:40:54 +00001975
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001976 if (input->basereg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001977 || input->basereg >= REG_ENUM_LIMIT)
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00001978 b = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001979 else
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001980 b = reg_flags[input->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001981
H. Peter Anvine2c80182005-01-15 22:15:51 +00001982 if (input->scale == 0)
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00001983 i = 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001984
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00001985 if (!i && !b) /* pure offset */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001986 return (input->addr_size != 0 && input->addr_size != addrbits);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001987
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001988 if (!(REG32 & ~i) || !(REG32 & ~b))
Keith Kaniosb7a89542007-04-12 02:40:54 +00001989 return (addrbits != 32);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001990 else
1991 return (addrbits == 32);
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001992 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001993 return 0;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001994 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001995}