blob: 6bffce3fd01299d9f05efb75042f01ac02b11185 [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");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000534 else
535 error(ERR_NONFATAL,
536 "invalid combination of opcode and operands");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000537 }
538 return 0;
539}
540
Keith Kaniosb7a89542007-04-12 02:40:54 +0000541int32_t insn_size(int32_t segment, int32_t offset, int bits, uint32_t cp,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000542 insn * instruction, efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000543{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000544 struct itemplate *temp;
545
H. Peter Anvine2c80182005-01-15 22:15:51 +0000546 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000547 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000548
549 if (instruction->opcode == -1)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000550 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000551
552 if (instruction->opcode == I_DB ||
H. Peter Anvine2c80182005-01-15 22:15:51 +0000553 instruction->opcode == I_DW ||
554 instruction->opcode == I_DD ||
555 instruction->opcode == I_DQ || instruction->opcode == I_DT) {
556 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000557 int32_t isize, osize, wsize = 0; /* placate gcc */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000558
H. Peter Anvine2c80182005-01-15 22:15:51 +0000559 isize = 0;
560 switch (instruction->opcode) {
561 case I_DB:
562 wsize = 1;
563 break;
564 case I_DW:
565 wsize = 2;
566 break;
567 case I_DD:
568 wsize = 4;
569 break;
570 case I_DQ:
571 wsize = 8;
572 break;
573 case I_DT:
574 wsize = 10;
575 break;
576 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000577
H. Peter Anvine2c80182005-01-15 22:15:51 +0000578 for (e = instruction->eops; e; e = e->next) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000579 int32_t align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000580
H. Peter Anvine2c80182005-01-15 22:15:51 +0000581 osize = 0;
582 if (e->type == EOT_DB_NUMBER)
583 osize = 1;
584 else if (e->type == EOT_DB_STRING)
585 osize = e->stringlen;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000586
H. Peter Anvine2c80182005-01-15 22:15:51 +0000587 align = (-osize) % wsize;
588 if (align < 0)
589 align += wsize;
590 isize += osize + align;
591 }
592 return isize * instruction->times;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000593 }
594
H. Peter Anvine2c80182005-01-15 22:15:51 +0000595 if (instruction->opcode == I_INCBIN) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000596 char fname[FILENAME_MAX];
H. Peter Anvine2c80182005-01-15 22:15:51 +0000597 FILE *fp;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000598 int32_t len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000599 char *prefix = "", *combine;
600 char **pPrevPath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000601
H. Peter Anvine2c80182005-01-15 22:15:51 +0000602 len = FILENAME_MAX - 1;
603 if (len > instruction->eops->stringlen)
604 len = instruction->eops->stringlen;
605 strncpy(fname, instruction->eops->stringval, len);
606 fname[len] = '\0';
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000607
H. Peter Anvine2c80182005-01-15 22:15:51 +0000608 while (1) { /* added by alexfru: 'incbin' uses include paths */
609 combine = nasm_malloc(strlen(prefix) + len + 1);
610 strcpy(combine, prefix);
611 strcat(combine, fname);
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000612
H. Peter Anvine2c80182005-01-15 22:15:51 +0000613 if ((fp = fopen(combine, "rb")) != NULL) {
614 nasm_free(combine);
615 break;
616 }
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000617
H. Peter Anvine2c80182005-01-15 22:15:51 +0000618 nasm_free(combine);
619 pPrevPath = pp_get_include_path_ptr(pPrevPath);
620 if (pPrevPath == NULL)
621 break;
622 prefix = *pPrevPath;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000623 }
624
625 if (fp == NULL)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000626 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
627 fname);
628 else if (fseek(fp, 0L, SEEK_END) < 0)
629 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
630 fname);
631 else {
632 len = ftell(fp);
633 fclose(fp);
634 if (instruction->eops->next) {
635 len -= instruction->eops->next->offset;
636 if (instruction->eops->next->next &&
637 len > instruction->eops->next->next->offset) {
638 len = instruction->eops->next->next->offset;
639 }
640 }
641 return instruction->times * len;
642 }
643 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000644 }
645
Keith Kaniosb7a89542007-04-12 02:40:54 +0000646 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++) {
647 int m = matches(temp, instruction, bits);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000648 if (m == 99)
649 m += jmp_match(segment, offset, bits, instruction, temp->code);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000650
H. Peter Anvine2c80182005-01-15 22:15:51 +0000651 if (m == 100) {
652 /* we've matched an instruction. */
Keith Kaniosb7a89542007-04-12 02:40:54 +0000653 int32_t isize;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000654 const char *codes = temp->code;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000655 int j;
656
657 isize = calcsize(segment, offset, bits, instruction, codes);
658 if (isize < 0)
659 return -1;
660 for (j = 0; j < instruction->nprefix; j++) {
661 if ((instruction->prefixes[j] != P_A16 &&
662 instruction->prefixes[j] != P_O16 && bits == 16) ||
663 (instruction->prefixes[j] != P_A32 &&
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000664 instruction->prefixes[j] != P_O32 && bits >= 32)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000665 isize++;
666 }
667 }
668 return isize * instruction->times;
669 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000670 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000671 return -1; /* didn't match any instruction */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000672}
673
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000674/* check that opn[op] is a signed byte of size 16 or 32,
675 and return the signed value*/
H. Peter Anvine2c80182005-01-15 22:15:51 +0000676static int is_sbyte(insn * ins, int op, int size)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000677{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000678 int32_t v;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000679 int ret;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000680
681 ret = !(ins->forw_ref && ins->oprs[op].opflags) && /* dead in the water on forward reference or External */
682 optimizing >= 0 &&
683 !(ins->oprs[op].type & STRICT) &&
684 ins->oprs[op].wrt == NO_SEG && ins->oprs[op].segment == NO_SEG;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000685
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000686 v = ins->oprs[op].offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000687 if (size == 16)
Keith Kaniosb7a89542007-04-12 02:40:54 +0000688 v = (int16_t)v; /* sign extend if 16 bits */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000689
690 return ret && v >= -128L && v <= 127L;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000691}
692
Keith Kaniosb7a89542007-04-12 02:40:54 +0000693static int32_t calcsize(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000694 insn * ins, const char *codes)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000695{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000696 int32_t length = 0;
697 uint8_t c;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000698 int rex_mask = ~0;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000699 ins->rex = 0; /* Ensure REX is reset */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000700
H. Peter Anvine2c80182005-01-15 22:15:51 +0000701 (void)segment; /* Don't warn that this parameter is unused */
702 (void)offset; /* Don't warn that this parameter is unused */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000703
H. Peter Anvine2c80182005-01-15 22:15:51 +0000704 while (*codes)
705 switch (c = *codes++) {
706 case 01:
707 case 02:
708 case 03:
709 codes += c, length += c;
710 break;
711 case 04:
712 case 05:
713 case 06:
714 case 07:
715 length++;
716 break;
717 case 010:
718 case 011:
719 case 012:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000720 ins->rex |=
721 op_rexflags(&ins->oprs[c - 010], REX_B|REX_H|REX_P|REX_W);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000722 codes++, length++;
723 break;
724 case 017:
725 length++;
726 break;
727 case 014:
728 case 015:
729 case 016:
730 length++;
731 break;
732 case 020:
733 case 021:
734 case 022:
735 length++;
736 break;
737 case 024:
738 case 025:
739 case 026:
740 length++;
741 break;
742 case 030:
743 case 031:
744 case 032:
745 length += 2;
746 break;
747 case 034:
748 case 035:
749 case 036:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000750 if (ins->oprs[c - 034].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000751 length += (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
752 else
753 length += (bits == 16) ? 2 : 4;
754 break;
755 case 037:
756 length += 2;
757 break;
758 case 040:
759 case 041:
760 case 042:
761 length += 4;
762 break;
763 case 044:
764 case 045:
765 case 046:
766 length += ((ins->oprs[c - 044].addr_size ?
Keith Kaniosb7a89542007-04-12 02:40:54 +0000767 ins->oprs[c - 044].addr_size : bits) >> 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000768 break;
769 case 050:
770 case 051:
771 case 052:
772 length++;
773 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000774 case 054:
775 case 055:
776 case 056:
777 length += 8; /* MOV reg64/imm */
778 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000779 case 060:
780 case 061:
781 case 062:
782 length += 2;
783 break;
784 case 064:
785 case 065:
786 case 066:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000787 if (ins->oprs[c - 064].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000788 length += (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
789 else
790 length += (bits == 16) ? 2 : 4;
791 break;
792 case 070:
793 case 071:
794 case 072:
795 length += 4;
796 break;
797 case 0130:
798 case 0131:
799 case 0132:
800 length += is_sbyte(ins, c - 0130, 16) ? 1 : 2;
801 break;
802 case 0133:
803 case 0134:
804 case 0135:
805 codes += 2;
806 length++;
807 break;
808 case 0140:
809 case 0141:
810 case 0142:
811 length += is_sbyte(ins, c - 0140, 32) ? 1 : 4;
812 break;
813 case 0143:
814 case 0144:
815 case 0145:
816 codes += 2;
817 length++;
818 break;
819 case 0300:
820 case 0301:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000821 case 0302:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000822 length += chsize(&ins->oprs[c - 0300], bits);
823 break;
824 case 0310:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000825 length += (bits != 16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000826 break;
827 case 0311:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000828 length += (bits != 32);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000829 break;
830 case 0312:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000831 break;
832 case 0313:
833 length -= 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000834 break;
835 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000836 length += (bits != 16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000837 break;
838 case 0321:
839 length += (bits == 16);
840 break;
841 case 0322:
842 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000843 case 0323:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000844 rex_mask &= ~REX_W;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000845 break;
846 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000847 ins->rex |= REX_W;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000848 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000849 case 0330:
850 codes++, length++;
851 break;
852 case 0331:
853 case 0332:
854 break;
855 case 0333:
856 length++;
857 break;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000858 case 0334:
859 assert_no_prefix(ins, P_LOCK);
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000860 ins->rex |= REX_L;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000861 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000862 case 0340:
863 case 0341:
864 case 0342:
865 if (ins->oprs[0].segment != NO_SEG)
866 errfunc(ERR_NONFATAL, "attempt to reserve non-constant"
867 " quantity of BSS space");
868 else
869 length += ins->oprs[0].offset << (c - 0340);
870 break;
871 case 0370:
872 case 0371:
873 case 0372:
874 break;
875 case 0373:
876 length++;
877 break;
878 default: /* can't do it by 'case' statements */
879 if (c >= 0100 && c <= 0277) { /* it's an EA */
880 ea ea_data;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000881 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000882 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000883 ea_data.rex = 0; /* Ensure ea.REX is initially 0 */
884
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000885 if (c <= 0177) {
886 /* pick rfield from operand b */
887 rflags = regflag(&ins->oprs[c & 7]);
888 rfield = regvals[ins->oprs[c & 7].basereg];
889 } else {
890 rflags = 0;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000891 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000892 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000893
H. Peter Anvine2c80182005-01-15 22:15:51 +0000894 if (!process_ea
Keith Kaniosb7a89542007-04-12 02:40:54 +0000895 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000896 rfield, rflags, ins->forw_ref)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000897 errfunc(ERR_NONFATAL, "invalid effective address");
898 return -1;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000899 } else {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000900 ins->rex |= ea_data.rex;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000901 length += ea_data.size;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000902 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000903 } else
904 errfunc(ERR_PANIC, "internal instruction table corrupt"
905 ": instruction code 0x%02X given", c);
906 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000907
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000908 ins->rex &= rex_mask;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000909 if (ins->rex & REX_REAL) {
910 if (ins->rex & REX_H) {
911 errfunc(ERR_NONFATAL, "cannot use high register in rex instruction");
912 return -1;
913 } else if (bits == 64 ||
914 ((ins->rex & REX_L) &&
915 !(ins->rex & (REX_P|REX_W|REX_X|REX_B)) &&
916 cpu >= IF_X86_64)) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000917 length++;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000918 } else {
919 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
920 return -1;
921 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000922 }
923
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000924 return length;
925}
Keith Kaniosb7a89542007-04-12 02:40:54 +0000926
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000927#define EMIT_REX() \
928 if((ins->rex & REX_REAL) && (bits == 64)) { \
929 ins->rex = (ins->rex & REX_REAL)|REX_P; \
930 out(offset, segment, &ins->rex, OUT_RAWDATA+1, NO_SEG, NO_SEG); \
931 ins->rex = 0; \
932 offset += 1; \
933 }
934
Keith Kaniosb7a89542007-04-12 02:40:54 +0000935static void gencode(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000936 insn * ins, const char *codes, int32_t insn_end)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000937{
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000938 static char condval[] = { /* conditional opcodes */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000939 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
940 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
941 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000942 };
Keith Kaniosb7a89542007-04-12 02:40:54 +0000943 uint8_t c;
944 uint8_t bytes[4];
945 int32_t size;
946 int64_t data;
947
H. Peter Anvineba20a72002-04-30 20:53:55 +0000948 while (*codes)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000949 switch (c = *codes++) {
950 case 01:
951 case 02:
952 case 03:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000953 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +0000954 out(offset, segment, codes, OUT_RAWDATA + c, NO_SEG, NO_SEG);
955 codes += c;
956 offset += c;
957 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000958
H. Peter Anvine2c80182005-01-15 22:15:51 +0000959 case 04:
960 case 06:
961 switch (ins->oprs[0].basereg) {
962 case R_CS:
963 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0);
964 break;
965 case R_DS:
966 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0);
967 break;
968 case R_ES:
969 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0);
970 break;
971 case R_SS:
972 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0);
973 break;
974 default:
975 errfunc(ERR_PANIC,
976 "bizarre 8086 segment register received");
977 }
978 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
979 offset++;
980 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000981
H. Peter Anvine2c80182005-01-15 22:15:51 +0000982 case 05:
983 case 07:
984 switch (ins->oprs[0].basereg) {
985 case R_FS:
986 bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0);
987 break;
988 case R_GS:
989 bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0);
990 break;
991 default:
992 errfunc(ERR_PANIC,
993 "bizarre 386 segment register received");
994 }
995 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
996 offset++;
997 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000998
H. Peter Anvine2c80182005-01-15 22:15:51 +0000999 case 010:
1000 case 011:
1001 case 012:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001002 EMIT_REX();
Keith Kaniosb7a89542007-04-12 02:40:54 +00001003 bytes[0] = *codes++ + ((regval(&ins->oprs[c - 010])) & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001004 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1005 offset += 1;
1006 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001007
H. Peter Anvine2c80182005-01-15 22:15:51 +00001008 case 017:
1009 bytes[0] = 0;
1010 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 014:
1015 case 015:
1016 case 016:
1017 if (ins->oprs[c - 014].offset < -128
1018 || ins->oprs[c - 014].offset > 127) {
1019 errfunc(ERR_WARNING, "signed byte value exceeds bounds");
1020 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001021
H. Peter Anvine2c80182005-01-15 22:15:51 +00001022 if (ins->oprs[c - 014].segment != NO_SEG) {
1023 data = ins->oprs[c - 014].offset;
1024 out(offset, segment, &data, OUT_ADDRESS + 1,
1025 ins->oprs[c - 014].segment, ins->oprs[c - 014].wrt);
1026 } else {
1027 bytes[0] = ins->oprs[c - 014].offset;
1028 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1029 NO_SEG);
1030 }
1031 offset += 1;
1032 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001033
H. Peter Anvine2c80182005-01-15 22:15:51 +00001034 case 020:
1035 case 021:
1036 case 022:
1037 if (ins->oprs[c - 020].offset < -256
1038 || ins->oprs[c - 020].offset > 255) {
1039 errfunc(ERR_WARNING, "byte value exceeds bounds");
1040 }
1041 if (ins->oprs[c - 020].segment != NO_SEG) {
1042 data = ins->oprs[c - 020].offset;
1043 out(offset, segment, &data, OUT_ADDRESS + 1,
1044 ins->oprs[c - 020].segment, ins->oprs[c - 020].wrt);
1045 } else {
1046 bytes[0] = ins->oprs[c - 020].offset;
1047 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1048 NO_SEG);
1049 }
1050 offset += 1;
1051 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001052
H. Peter Anvine2c80182005-01-15 22:15:51 +00001053 case 024:
1054 case 025:
1055 case 026:
1056 if (ins->oprs[c - 024].offset < 0
1057 || ins->oprs[c - 024].offset > 255)
1058 errfunc(ERR_WARNING, "unsigned byte value exceeds bounds");
1059 if (ins->oprs[c - 024].segment != NO_SEG) {
1060 data = ins->oprs[c - 024].offset;
1061 out(offset, segment, &data, OUT_ADDRESS + 1,
1062 ins->oprs[c - 024].segment, ins->oprs[c - 024].wrt);
1063 } else {
1064 bytes[0] = ins->oprs[c - 024].offset;
1065 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1066 NO_SEG);
1067 }
1068 offset += 1;
1069 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001070
H. Peter Anvine2c80182005-01-15 22:15:51 +00001071 case 030:
1072 case 031:
1073 case 032:
1074 if (ins->oprs[c - 030].segment == NO_SEG &&
1075 ins->oprs[c - 030].wrt == NO_SEG &&
1076 (ins->oprs[c - 030].offset < -65536L ||
1077 ins->oprs[c - 030].offset > 65535L)) {
1078 errfunc(ERR_WARNING, "word value exceeds bounds");
1079 }
1080 data = ins->oprs[c - 030].offset;
1081 out(offset, segment, &data, OUT_ADDRESS + 2,
1082 ins->oprs[c - 030].segment, ins->oprs[c - 030].wrt);
1083 offset += 2;
1084 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001085
H. Peter Anvine2c80182005-01-15 22:15:51 +00001086 case 034:
1087 case 035:
1088 case 036:
1089 if (ins->oprs[c - 034].type & (BITS16 | BITS32))
1090 size = (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
1091 else
1092 size = (bits == 16) ? 2 : 4;
1093 data = ins->oprs[c - 034].offset;
1094 if (size == 2 && (data < -65536L || data > 65535L))
1095 errfunc(ERR_WARNING, "word value exceeds bounds");
1096 out(offset, segment, &data, OUT_ADDRESS + size,
1097 ins->oprs[c - 034].segment, ins->oprs[c - 034].wrt);
1098 offset += size;
1099 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001100
H. Peter Anvine2c80182005-01-15 22:15:51 +00001101 case 037:
1102 if (ins->oprs[0].segment == NO_SEG)
1103 errfunc(ERR_NONFATAL, "value referenced by FAR is not"
1104 " relocatable");
1105 data = 0L;
1106 out(offset, segment, &data, OUT_ADDRESS + 2,
1107 outfmt->segbase(1 + ins->oprs[0].segment),
1108 ins->oprs[0].wrt);
1109 offset += 2;
1110 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001111
H. Peter Anvine2c80182005-01-15 22:15:51 +00001112 case 040:
1113 case 041:
1114 case 042:
1115 data = ins->oprs[c - 040].offset;
1116 out(offset, segment, &data, OUT_ADDRESS + 4,
1117 ins->oprs[c - 040].segment, ins->oprs[c - 040].wrt);
1118 offset += 4;
1119 break;
H. Peter Anvin3ba46772002-05-27 23:19:35 +00001120
H. Peter Anvine2c80182005-01-15 22:15:51 +00001121 case 044:
1122 case 045:
1123 case 046:
1124 data = ins->oprs[c - 044].offset;
1125 size = ((ins->oprs[c - 044].addr_size ?
Keith Kaniosb7a89542007-04-12 02:40:54 +00001126 ins->oprs[c - 044].addr_size : bits) >> 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001127 if (size == 2 && (data < -65536L || data > 65535L))
1128 errfunc(ERR_WARNING, "word value exceeds bounds");
1129 out(offset, segment, &data, OUT_ADDRESS + size,
1130 ins->oprs[c - 044].segment, ins->oprs[c - 044].wrt);
1131 offset += size;
1132 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001133
H. Peter Anvine2c80182005-01-15 22:15:51 +00001134 case 050:
1135 case 051:
1136 case 052:
1137 if (ins->oprs[c - 050].segment != segment)
1138 errfunc(ERR_NONFATAL,
1139 "short relative jump outside segment");
1140 data = ins->oprs[c - 050].offset - insn_end;
1141 if (data > 127 || data < -128)
1142 errfunc(ERR_NONFATAL, "short jump is out of range");
1143 bytes[0] = data;
1144 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1145 offset += 1;
1146 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001147
1148 case 054:
1149 case 055:
1150 case 056:
1151 data = (int64_t)ins->oprs[c - 054].offset;
1152 out(offset, segment, &data, OUT_ADDRESS + 8,
1153 ins->oprs[c - 054].segment, ins->oprs[c - 054].wrt);
1154 offset += 8;
1155 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001156
H. Peter Anvine2c80182005-01-15 22:15:51 +00001157 case 060:
1158 case 061:
1159 case 062:
1160 if (ins->oprs[c - 060].segment != segment) {
1161 data = ins->oprs[c - 060].offset;
1162 out(offset, segment, &data,
1163 OUT_REL2ADR + insn_end - offset,
1164 ins->oprs[c - 060].segment, ins->oprs[c - 060].wrt);
1165 } else {
1166 data = ins->oprs[c - 060].offset - insn_end;
1167 out(offset, segment, &data,
1168 OUT_ADDRESS + 2, NO_SEG, NO_SEG);
1169 }
1170 offset += 2;
1171 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001172
H. Peter Anvine2c80182005-01-15 22:15:51 +00001173 case 064:
1174 case 065:
1175 case 066:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001176 if (ins->oprs[c - 064].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001177 size = (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
1178 else
1179 size = (bits == 16) ? 2 : 4;
1180 if (ins->oprs[c - 064].segment != segment) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001181 int32_t reltype = (size == 2 ? OUT_REL2ADR : OUT_REL4ADR);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001182 data = ins->oprs[c - 064].offset;
1183 out(offset, segment, &data, reltype + insn_end - offset,
1184 ins->oprs[c - 064].segment, ins->oprs[c - 064].wrt);
1185 } else {
1186 data = ins->oprs[c - 064].offset - insn_end;
1187 out(offset, segment, &data,
1188 OUT_ADDRESS + size, NO_SEG, NO_SEG);
1189 }
1190 offset += size;
1191 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001192
H. Peter Anvine2c80182005-01-15 22:15:51 +00001193 case 070:
1194 case 071:
1195 case 072:
1196 if (ins->oprs[c - 070].segment != segment) {
1197 data = ins->oprs[c - 070].offset;
1198 out(offset, segment, &data,
1199 OUT_REL4ADR + insn_end - offset,
1200 ins->oprs[c - 070].segment, ins->oprs[c - 070].wrt);
1201 } else {
1202 data = ins->oprs[c - 070].offset - insn_end;
1203 out(offset, segment, &data,
1204 OUT_ADDRESS + 4, NO_SEG, NO_SEG);
1205 }
1206 offset += 4;
1207 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001208
H. Peter Anvine2c80182005-01-15 22:15:51 +00001209 case 0130:
1210 case 0131:
1211 case 0132:
1212 data = ins->oprs[c - 0130].offset;
1213 if (is_sbyte(ins, c - 0130, 16)) {
1214 bytes[0] = data;
1215 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1216 NO_SEG);
1217 offset++;
1218 } else {
1219 if (ins->oprs[c - 0130].segment == NO_SEG &&
1220 ins->oprs[c - 0130].wrt == NO_SEG &&
1221 (data < -65536L || data > 65535L)) {
1222 errfunc(ERR_WARNING, "word value exceeds bounds");
1223 }
1224 out(offset, segment, &data, OUT_ADDRESS + 2,
1225 ins->oprs[c - 0130].segment, ins->oprs[c - 0130].wrt);
1226 offset += 2;
1227 }
1228 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001229
H. Peter Anvine2c80182005-01-15 22:15:51 +00001230 case 0133:
1231 case 0134:
1232 case 0135:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001233 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001234 codes++;
1235 bytes[0] = *codes++;
1236 if (is_sbyte(ins, c - 0133, 16))
1237 bytes[0] |= 2; /* s-bit */
1238 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1239 offset++;
1240 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001241
H. Peter Anvine2c80182005-01-15 22:15:51 +00001242 case 0140:
1243 case 0141:
1244 case 0142:
1245 data = ins->oprs[c - 0140].offset;
1246 if (is_sbyte(ins, c - 0140, 32)) {
1247 bytes[0] = data;
1248 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1249 NO_SEG);
1250 offset++;
1251 } else {
1252 out(offset, segment, &data, OUT_ADDRESS + 4,
1253 ins->oprs[c - 0140].segment, ins->oprs[c - 0140].wrt);
1254 offset += 4;
1255 }
1256 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001257
H. Peter Anvine2c80182005-01-15 22:15:51 +00001258 case 0143:
1259 case 0144:
1260 case 0145:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001261 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001262 codes++;
1263 bytes[0] = *codes++;
1264 if (is_sbyte(ins, c - 0143, 32))
1265 bytes[0] |= 2; /* s-bit */
1266 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1267 offset++;
1268 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001269
H. Peter Anvine2c80182005-01-15 22:15:51 +00001270 case 0300:
1271 case 0301:
1272 case 0302:
1273 if (chsize(&ins->oprs[c - 0300], bits)) {
1274 *bytes = 0x67;
1275 out(offset, segment, bytes,
1276 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1277 offset += 1;
1278 } else
1279 offset += 0;
1280 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001281
H. Peter Anvine2c80182005-01-15 22:15:51 +00001282 case 0310:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001283 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001284 *bytes = 0x67;
1285 out(offset, segment, bytes,
1286 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1287 offset += 1;
1288 } else
1289 offset += 0;
1290 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001291
H. Peter Anvine2c80182005-01-15 22:15:51 +00001292 case 0311:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001293 if (bits != 32) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001294 *bytes = 0x67;
1295 out(offset, segment, bytes,
1296 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1297 offset += 1;
1298 } else
1299 offset += 0;
1300 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001301
H. Peter Anvine2c80182005-01-15 22:15:51 +00001302 case 0312:
1303 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001304
Keith Kaniosb7a89542007-04-12 02:40:54 +00001305 case 0313:
1306 ins->rex = 0;
1307 break;
1308
H. Peter Anvine2c80182005-01-15 22:15:51 +00001309 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001310 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001311 *bytes = 0x66;
1312 out(offset, segment, bytes,
1313 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1314 offset += 1;
1315 } else
1316 offset += 0;
1317 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001318
H. Peter Anvine2c80182005-01-15 22:15:51 +00001319 case 0321:
1320 if (bits == 16) {
1321 *bytes = 0x66;
1322 out(offset, segment, bytes,
1323 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1324 offset += 1;
1325 } else
1326 offset += 0;
1327 break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001328
H. Peter Anvine2c80182005-01-15 22:15:51 +00001329 case 0322:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001330 case 0323:
1331 break;
1332
1333 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001334 ins->rex |= REX_W;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001335 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001336
H. Peter Anvine2c80182005-01-15 22:15:51 +00001337 case 0330:
1338 *bytes = *codes++ ^ condval[ins->condition];
1339 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1340 offset += 1;
1341 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001342
H. Peter Anvine2c80182005-01-15 22:15:51 +00001343 case 0331:
1344 case 0332:
1345 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001346
H. Peter Anvine2c80182005-01-15 22:15:51 +00001347 case 0333:
1348 *bytes = 0xF3;
1349 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1350 offset += 1;
1351 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001352
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001353 case 0334:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001354 if (ins->rex & REX_R) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001355 *bytes = 0xF0;
1356 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1357 offset += 1;
1358 }
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001359 ins->rex &= ~(REX_L|REX_R);
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001360 break;
1361
H. Peter Anvine2c80182005-01-15 22:15:51 +00001362 case 0340:
1363 case 0341:
1364 case 0342:
1365 if (ins->oprs[0].segment != NO_SEG)
1366 errfunc(ERR_PANIC, "non-constant BSS size in pass two");
1367 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001368 int32_t size = ins->oprs[0].offset << (c - 0340);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001369 if (size > 0)
1370 out(offset, segment, NULL,
1371 OUT_RESERVE + size, NO_SEG, NO_SEG);
1372 offset += size;
1373 }
1374 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001375
H. Peter Anvine2c80182005-01-15 22:15:51 +00001376 case 0370:
1377 case 0371:
1378 case 0372:
1379 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001380
H. Peter Anvine2c80182005-01-15 22:15:51 +00001381 case 0373:
1382 *bytes = bits == 16 ? 3 : 5;
1383 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1384 offset += 1;
1385 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001386
H. Peter Anvine2c80182005-01-15 22:15:51 +00001387 default: /* can't do it by 'case' statements */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001388 if (c >= 0100 && c <= 0277) { /* it's an EA */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001389 ea ea_data;
1390 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001391 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001392 uint8_t *p;
1393 int32_t s;
1394
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001395 if (c <= 0177) {
1396 /* pick rfield from operand b */
1397 rflags = regflag(&ins->oprs[c & 7]);
1398 rfield = regvals[ins->oprs[c & 7].basereg];
1399 } else {
1400 /* rfield is constant */
1401 rflags = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001402 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001403 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001404
1405 if (!process_ea
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001406 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
1407 rfield, rflags, ins->forw_ref)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001408 errfunc(ERR_NONFATAL, "invalid effective address");
1409 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001410
H. Peter Anvine2c80182005-01-15 22:15:51 +00001411 p = bytes;
1412 *p++ = ea_data.modrm;
1413 if (ea_data.sib_present)
1414 *p++ = ea_data.sib;
1415
1416 s = p - bytes;
1417 out(offset, segment, bytes, OUT_RAWDATA + s,
1418 NO_SEG, NO_SEG);
1419
1420 switch (ea_data.bytes) {
1421 case 0:
1422 break;
1423 case 1:
1424 if (ins->oprs[(c >> 3) & 7].segment != NO_SEG) {
1425 data = ins->oprs[(c >> 3) & 7].offset;
1426 out(offset, segment, &data, OUT_ADDRESS + 1,
1427 ins->oprs[(c >> 3) & 7].segment,
1428 ins->oprs[(c >> 3) & 7].wrt);
1429 } else {
1430 *bytes = ins->oprs[(c >> 3) & 7].offset;
1431 out(offset, segment, bytes, OUT_RAWDATA + 1,
1432 NO_SEG, NO_SEG);
1433 }
1434 s++;
1435 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001436 case 8:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001437 case 2:
1438 case 4:
1439 data = ins->oprs[(c >> 3) & 7].offset;
Keith Kaniose83b3182007-04-16 14:31:54 +00001440 if (ea_data.rip && (ins->oprs[(c >> 3) & 7].segment == 0xFFFFFFFF))
1441 ea_data.rip = 0; /* Make distinction between Symbols and Immediates */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001442 out(offset, segment, &data, /* RIP = Relative, not Absolute */
1443 (ea_data.rip ? OUT_REL4ADR : OUT_ADDRESS) + ea_data.bytes,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001444 ins->oprs[(c >> 3) & 7].segment,
1445 ins->oprs[(c >> 3) & 7].wrt);
1446 s += ea_data.bytes;
1447 break;
1448 }
1449 offset += s;
1450 } else
1451 errfunc(ERR_PANIC, "internal instruction table corrupt"
1452 ": instruction code 0x%02X given", c);
1453 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001454}
1455
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001456static int regflag(const operand * o)
1457{
1458 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1459 errfunc(ERR_PANIC, "invalid operand passed to regflag()");
1460 }
1461 return reg_flags[o->basereg];
1462}
1463
1464static int regval(const operand * o)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001465{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001466 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1467 errfunc(ERR_PANIC, "invalid operand passed to regval()");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001468 }
H. Peter Anvin232badb2002-06-06 02:41:20 +00001469 return regvals[o->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001470}
1471
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001472static int op_rexflags(const operand * o, int mask)
1473{
1474 int32_t flags;
1475 int val;
1476
1477 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1478 errfunc(ERR_PANIC, "invalid operand passed to op_rexflags()");
1479 }
1480
1481 flags = reg_flags[o->basereg];
1482 val = regvals[o->basereg];
1483
1484 return rexflags(val, flags, mask);
1485}
1486
1487static int rexflags(int val, int32_t flags, int mask)
1488{
1489 int rex = 0;
1490
1491 if (val >= 8)
1492 rex |= REX_B|REX_X|REX_R;
1493 if (flags & BITS64)
1494 rex |= REX_W;
1495 if (!(REG_HIGH & ~flags)) /* AH, CH, DH, BH */
1496 rex |= REX_H;
1497 else if (!(REG8 & ~flags) && val >= 4) /* SPL, BPL, SIL, DIL */
1498 rex |= REX_P;
1499
1500 return rex & mask;
1501}
1502
Keith Kaniosb7a89542007-04-12 02:40:54 +00001503static int matches(struct itemplate *itemp, insn * instruction, int bits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001504{
Keith Kaniosb7a89542007-04-12 02:40:54 +00001505 int i, b, x, size[3], asize, oprs, ret;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001506
1507 ret = 100;
1508
1509 /*
1510 * Check the opcode
1511 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001512 if (itemp->opcode != instruction->opcode)
1513 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001514
1515 /*
1516 * Count the operands
1517 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001518 if (itemp->operands != instruction->operands)
1519 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001520
1521 /*
1522 * Check that no spurious colons or TOs are present
1523 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001524 for (i = 0; i < itemp->operands; i++)
1525 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON | TO))
1526 return 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001527
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001528 /*
1529 * Check that the operand flags all match up
1530 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001531 for (i = 0; i < itemp->operands; i++)
1532 if (itemp->opd[i] & ~instruction->oprs[i].type ||
1533 ((itemp->opd[i] & SIZE_MASK) &&
1534 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK))) {
H. Peter Anvin5a640e12007-05-29 23:57:12 +00001535 if ((itemp->opd[i] & ~instruction->oprs[i].type & ~SIZE_MASK) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001536 (instruction->oprs[i].type & SIZE_MASK))
1537 return 0;
1538 else
H. Peter Anvine2c80182005-01-15 22:15:51 +00001539 return 1;
1540 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001541
1542 /*
1543 * Check operand sizes
1544 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001545 if (itemp->flags & IF_ARMASK) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001546 size[0] = size[1] = size[2] = 0;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001547
H. Peter Anvine2c80182005-01-15 22:15:51 +00001548 switch (itemp->flags & IF_ARMASK) {
1549 case IF_AR0:
1550 i = 0;
1551 break;
1552 case IF_AR1:
1553 i = 1;
1554 break;
1555 case IF_AR2:
1556 i = 2;
1557 break;
1558 default:
1559 break; /* Shouldn't happen */
1560 }
1561 if (itemp->flags & IF_SB) {
1562 size[i] = BITS8;
1563 } else if (itemp->flags & IF_SW) {
1564 size[i] = BITS16;
1565 } else if (itemp->flags & IF_SD) {
1566 size[i] = BITS32;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001567 } else if (itemp->flags & IF_SQ) {
1568 if (bits != 64)
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001569 return 5;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001570 size[i] = BITS64;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001571 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001572 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001573 asize = 0;
1574 if (itemp->flags & IF_SB) {
1575 asize = BITS8;
1576 oprs = itemp->operands;
1577 } else if (itemp->flags & IF_SW) {
1578 asize = BITS16;
1579 oprs = itemp->operands;
1580 } else if (itemp->flags & IF_SD) {
1581 asize = BITS32;
1582 oprs = itemp->operands;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001583 } else if (itemp->flags & IF_SQ) {
1584 if (bits != 64)
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001585 return 5;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001586 asize = BITS64;
1587 oprs = itemp->operands;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001588 }
1589 size[0] = size[1] = size[2] = asize;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001590 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001591
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001592 if (itemp->flags & (IF_SM | IF_SM2)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001593 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
1594 asize = 0;
1595 for (i = 0; i < oprs; i++) {
1596 if ((asize = itemp->opd[i] & SIZE_MASK) != 0) {
1597 int j;
1598 for (j = 0; j < oprs; j++)
1599 size[j] = asize;
1600 break;
1601 }
1602 }
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001603 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001604 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001605 }
1606
Keith Kaniosb7a89542007-04-12 02:40:54 +00001607 for (i = 0; i < itemp->operands; i++) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001608 if (!(itemp->opd[i] & SIZE_MASK) &&
1609 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001610 return 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001611
Keith Kaniosb7a89542007-04-12 02:40:54 +00001612 x = instruction->oprs[i].indexreg;
1613 b = instruction->oprs[i].basereg;
1614
1615 if (x != -1 && x >= EXPR_REG_START && x < REG_ENUM_LIMIT)
1616 x = regvals[x];
1617 if (b != -1 && b >= EXPR_REG_START && b < REG_ENUM_LIMIT)
1618 b = regvals[b];
1619
1620 if (((b >= 0400 && b <= 0500) || (x >= 0400 && x < 0500)) && bits != 64)
1621 return 2;
1622 }
1623
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001624 /*
1625 * Check template is okay at the set cpu level
1626 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001627 if (((itemp->flags & IF_PLEVEL) > cpu))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001628 return 3;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001629
1630 /*
1631 * Check if instruction is available in long mode
1632 */
1633 if ((itemp->flags & IF_NOLONG) && (bits == 64))
1634 return 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001635
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001636 /*
1637 * Check if special handling needed for Jumps
1638 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001639 if ((uint8_t)(itemp->code[0]) >= 0370)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001640 return 99;
1641
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001642 return ret;
1643}
1644
H. Peter Anvine2c80182005-01-15 22:15:51 +00001645static ea *process_ea(operand * input, ea * output, int addrbits,
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001646 int rfield, int32_t rflags, int forw_ref)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001647{
Keith Kaniosb7a89542007-04-12 02:40:54 +00001648
1649 int rip = FALSE; /* Used for RIP-relative addressing */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001650
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001651 /* REX flags for the rfield operand */
1652 output->rex |= rexflags(rfield, rflags, REX_R|REX_P|REX_W|REX_H);
1653
Keith Kaniosb7a89542007-04-12 02:40:54 +00001654 if (!(REGISTER & ~input->type)) { /* register direct */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001655 int i;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001656 int32_t f;
1657
1658 if (input->basereg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001659 || input->basereg >= REG_ENUM_LIMIT)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001660 return NULL;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001661 f = regflag(input);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001662 i = regvals[input->basereg];
Keith Kaniosb7a89542007-04-12 02:40:54 +00001663
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001664 if (REG_EA & ~f)
1665 return NULL; /* Invalid EA register */
1666
1667 output->rex |= op_rexflags(input, REX_B|REX_P|REX_W|REX_H);
1668
Keith Kaniosb7a89542007-04-12 02:40:54 +00001669 output->sib_present = FALSE; /* no SIB necessary */
1670 output->bytes = 0; /* no offset necessary either */
1671 output->modrm = 0xC0 | ((rfield & 7) << 3) | (i & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001672 } else { /* it's a memory reference */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001673
H. Peter Anvine2c80182005-01-15 22:15:51 +00001674 if (input->basereg == -1
1675 && (input->indexreg == -1 || input->scale == 0)) {
1676 /* it's a pure offset */
1677 if (input->addr_size)
1678 addrbits = input->addr_size;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001679
H. Peter Anvine2c80182005-01-15 22:15:51 +00001680 output->sib_present = FALSE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001681 output->bytes = (addrbits != 16 ? 4 : 2);
1682 output->modrm = (addrbits != 16 ? 5 : 6) | ((rfield & 7) << 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001683 } else { /* it's an indirection */
1684 int i = input->indexreg, b = input->basereg, s = input->scale;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001685 int32_t o = input->offset, seg = input->segment;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001686 int hb = input->hintbase, ht = input->hinttype;
1687 int t;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001688 int it, bt;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001689 int32_t ix, bx; /* register flags */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001690
H. Peter Anvine2c80182005-01-15 22:15:51 +00001691 if (s == 0)
1692 i = -1; /* make this easy, at least */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001693
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001694 if (i >= EXPR_REG_START && i < REG_ENUM_LIMIT) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001695 it = regvals[i];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001696 ix = reg_flags[i];
1697 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001698 it = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001699 ix = 0;
1700 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001701
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001702 if (b != -1 && b >= EXPR_REG_START && b < REG_ENUM_LIMIT) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001703 bt = regvals[b];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001704 bx = reg_flags[b];
1705 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001706 bt = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001707 bx = 0;
1708 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001709
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001710 /* check for a 32/64-bit memory reference... */
1711 if ((ix|bx) & (BITS32|BITS64)) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001712 /* it must be a 32/64-bit memory reference. Firstly we have
1713 * to check that all registers involved are type E/Rxx. */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001714 int32_t sok = BITS32|BITS64;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001715
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001716 if (it != -1) {
1717 if (!(REG64 & ~ix) || !(REG32 & ~ix))
1718 sok &= ix;
1719 else
1720 return NULL;
1721 }
1722
1723 if (bt != -1) {
1724 if ((REG_GPR & ~bx) && (IP_REG & ~bx))
1725 return NULL; /* Invalid register */
H. Peter Anvina57e8d42007-05-30 03:44:02 +00001726 if (~sok & bx & SIZE_MASK)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001727 return NULL; /* Invalid size */
1728 sok &= ~bx;
1729 if (!(IP_REG & ~bx)) {
1730 bt = b = -1;
1731 rip = TRUE;
1732 }
1733 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001734
H. Peter Anvine2c80182005-01-15 22:15:51 +00001735 /* While we're here, ensure the user didn't specify WORD. */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001736 if (input->addr_size == 16 ||
1737 (input->addr_size == 32 && !(sok & BITS32)) ||
1738 (input->addr_size == 64 && !(sok & BITS64)))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001739 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001740
Keith Kaniosb7a89542007-04-12 02:40:54 +00001741 /* now reorganize base/index */
1742 if (s == 1 && bt != it && bt != -1 && it != -1 &&
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001743 ((hb == b && ht == EAH_NOTBASE)
1744 || (hb == i && ht == EAH_MAKEBASE))) {
1745 /* swap if hints say so */
1746 t = bt, bt = it, it = t;
1747 t = bx, bx = ix, ix = t;
1748 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001749 if (bt == it) /* convert EAX+2*EAX to 3*EAX */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001750 bt = -1, bx = 0, s++;
1751 if (bt == -1 && s == 1 && !(hb == it && ht == EAH_NOTBASE)) {
1752 /* make single reg base, unless hint */
1753 bt = it, bx = ix, it = -1, ix = 0;
1754 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001755 if (((s == 2 && (it & 7) != (REG_NUM_ESP & 7)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001756 && !(input->eaflags & EAF_TIMESTWO)) || s == 3
Keith Kaniosb7a89542007-04-12 02:40:54 +00001757 || s == 5 || s == 9) && bt == -1)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001758 bt = it, bx = ix, s--; /* convert 3*EAX to EAX+2*EAX */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001759 if (it == -1 && (bt & 7) != (REG_NUM_ESP & 7)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001760 && (input->eaflags & EAF_TIMESTWO))
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001761 it = bt, ix = bx, bt = -1, bx = 0, s = 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001762 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001763 if (s == 1 && (it & 7) == (REG_NUM_ESP & 7)) {
1764 /* swap ESP into base if scale is 1 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001765 t = it, it = bt, bt = t;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001766 t = ix, ix = bx, bx = t;
1767 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001768 if ((it & 7) == (REG_NUM_ESP & 7)
1769 || (s != 1 && s != 2 && s != 4 && s != 8 && it != -1))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001770 return NULL; /* wrong, for various reasons */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001771
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001772 output->rex |= rexflags(it, ix, REX_X);
1773 output->rex |= rexflags(bt, bx, REX_B);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001774
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001775 if (it == -1 && (bt & 7) != (REG_NUM_ESP & 7)) {
1776 /* no SIB needed */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001777 int mod, rm;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001778
1779 if (bt == -1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001780 rm = 5;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001781 mod = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001782 } else {
1783 rm = (bt & 7);
1784 if (rm != (REG_NUM_EBP & 7) && o == 0 &&
1785 seg == NO_SEG && !forw_ref &&
1786 !(input->eaflags &
1787 (EAF_BYTEOFFS | EAF_WORDOFFS)))
1788 mod = 0;
1789 else if (input->eaflags & EAF_BYTEOFFS ||
1790 (o >= -128 && o <= 127 && seg == NO_SEG
1791 && !forw_ref
1792 && !(input->eaflags & EAF_WORDOFFS)))
1793 mod = 1;
1794 else
1795 mod = 2;
1796 }
H. Peter Anvinea838272002-04-30 20:51:53 +00001797
H. Peter Anvine2c80182005-01-15 22:15:51 +00001798 output->sib_present = FALSE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001799 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
1800 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001801 } else {
1802 /* we need a SIB */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001803 int mod, scale, index, base;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001804
1805 if (it == -1)
1806 index = 4, s = 1;
1807 else
1808 index = (it & 7);
1809
H. Peter Anvine2c80182005-01-15 22:15:51 +00001810 switch (s) {
1811 case 1:
1812 scale = 0;
1813 break;
1814 case 2:
1815 scale = 1;
1816 break;
1817 case 4:
1818 scale = 2;
1819 break;
1820 case 8:
1821 scale = 3;
1822 break;
1823 default: /* then what the smeg is it? */
1824 return NULL; /* panic */
1825 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001826
1827 if (bt == -1) {
1828 base = 5;
1829 mod = 0;
1830 } else {
1831 base = (bt & 7);
1832 if (base != (REG_NUM_EBP & 7) && o == 0 &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00001833 seg == NO_SEG && !forw_ref &&
1834 !(input->eaflags &
Keith Kaniosb7a89542007-04-12 02:40:54 +00001835 (EAF_BYTEOFFS | EAF_WORDOFFS)))
1836 mod = 0;
1837 else if (input->eaflags & EAF_BYTEOFFS ||
1838 (o >= -128 && o <= 127 && seg == NO_SEG
1839 && !forw_ref
1840 && !(input->eaflags & EAF_WORDOFFS)))
1841 mod = 1;
1842 else
1843 mod = 2;
1844 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001845
H. Peter Anvine2c80182005-01-15 22:15:51 +00001846 output->sib_present = TRUE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001847 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
1848 output->modrm = (mod << 6) | ((rfield & 7) << 3) | 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001849 output->sib = (scale << 6) | (index << 3) | base;
1850 }
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001851
1852 /* Process RIP-relative Addressing */
1853 if (rip) {
1854 if (globalbits != 64 ||
1855 (output->modrm & 0xC7) != 0x05)
1856 return NULL;
1857 output->rip = TRUE;
1858 } else {
1859 output->rip = FALSE;
1860 /* Actual Disp32 needs blank SIB on x64 */
1861 if (globalbits == 64 &&
1862 !(output->sib_present) &&
1863 ((output->modrm & 0xC7) == 0x05)) {
1864 output->sib_present = TRUE;
1865 /* RM Field = 4 (forward to Base of SIB) */
1866 output->modrm--;
1867 /* Index = 4 (none), Base = 5 */
1868 output->sib = (4 << 3) | 5;
1869 }
1870 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001871 } else { /* it's 16-bit */
1872 int mod, rm;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001873
1874 /* check for 64-bit long mode */
1875 if (addrbits == 64)
1876 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001877
H. Peter Anvine2c80182005-01-15 22:15:51 +00001878 /* check all registers are BX, BP, SI or DI */
1879 if ((b != -1 && b != R_BP && b != R_BX && b != R_SI
1880 && b != R_DI) || (i != -1 && i != R_BP && i != R_BX
1881 && i != R_SI && i != R_DI))
1882 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001883
Keith Kaniosb7a89542007-04-12 02:40:54 +00001884 /* ensure the user didn't specify DWORD/QWORD */
1885 if (input->addr_size == 32 || input->addr_size == 64)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001886 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001887
H. Peter Anvine2c80182005-01-15 22:15:51 +00001888 if (s != 1 && i != -1)
1889 return NULL; /* no can do, in 16-bit EA */
1890 if (b == -1 && i != -1) {
1891 int tmp = b;
1892 b = i;
1893 i = tmp;
1894 } /* swap */
1895 if ((b == R_SI || b == R_DI) && i != -1) {
1896 int tmp = b;
1897 b = i;
1898 i = tmp;
1899 }
1900 /* have BX/BP as base, SI/DI index */
1901 if (b == i)
1902 return NULL; /* shouldn't ever happen, in theory */
1903 if (i != -1 && b != -1 &&
1904 (i == R_BP || i == R_BX || b == R_SI || b == R_DI))
1905 return NULL; /* invalid combinations */
1906 if (b == -1) /* pure offset: handled above */
1907 return NULL; /* so if it gets to here, panic! */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001908
H. Peter Anvine2c80182005-01-15 22:15:51 +00001909 rm = -1;
1910 if (i != -1)
1911 switch (i * 256 + b) {
1912 case R_SI * 256 + R_BX:
1913 rm = 0;
1914 break;
1915 case R_DI * 256 + R_BX:
1916 rm = 1;
1917 break;
1918 case R_SI * 256 + R_BP:
1919 rm = 2;
1920 break;
1921 case R_DI * 256 + R_BP:
1922 rm = 3;
1923 break;
1924 } else
1925 switch (b) {
1926 case R_SI:
1927 rm = 4;
1928 break;
1929 case R_DI:
1930 rm = 5;
1931 break;
1932 case R_BP:
1933 rm = 6;
1934 break;
1935 case R_BX:
1936 rm = 7;
1937 break;
1938 }
1939 if (rm == -1) /* can't happen, in theory */
1940 return NULL; /* so panic if it does */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001941
H. Peter Anvine2c80182005-01-15 22:15:51 +00001942 if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
1943 !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
1944 mod = 0;
1945 else if (input->eaflags & EAF_BYTEOFFS ||
1946 (o >= -128 && o <= 127 && seg == NO_SEG
1947 && !forw_ref
1948 && !(input->eaflags & EAF_WORDOFFS)))
1949 mod = 1;
1950 else
1951 mod = 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001952
H. Peter Anvine2c80182005-01-15 22:15:51 +00001953 output->sib_present = FALSE; /* no SIB - it's 16-bit */
1954 output->bytes = mod; /* bytes of offset needed */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001955 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001956 }
1957 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001958 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001959
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001960 output->size = 1 + output->sib_present + output->bytes;
1961 return output;
1962}
1963
H. Peter Anvine2c80182005-01-15 22:15:51 +00001964static int chsize(operand * input, int addrbits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001965{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001966 if (!(MEMORY & ~input->type)) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001967 int32_t i, b;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001968
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001969 if (input->indexreg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001970 || input->indexreg >= REG_ENUM_LIMIT)
1971 i = -1;
1972 else
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001973 i = reg_flags[input->indexreg];
Keith Kaniosb7a89542007-04-12 02:40:54 +00001974
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001975 if (input->basereg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001976 || input->basereg >= REG_ENUM_LIMIT)
1977 b = -1;
1978 else
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001979 b = reg_flags[input->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001980
H. Peter Anvine2c80182005-01-15 22:15:51 +00001981 if (input->scale == 0)
1982 i = -1;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001983
H. Peter Anvine2c80182005-01-15 22:15:51 +00001984 if (i == -1 && b == -1) /* pure offset */
1985 return (input->addr_size != 0 && input->addr_size != addrbits);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001986
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001987 if (!(REG32 & ~i) || !(REG32 & ~b))
Keith Kaniosb7a89542007-04-12 02:40:54 +00001988 return (addrbits != 32);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001989 else
1990 return (addrbits == 32);
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001991 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001992 return 0;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001993 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001994}