blob: 831a9178d38620beab3e13c1389952420959b847 [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 */
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:
840 length -= 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000841 break;
842 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000843 length += (bits != 16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000844 break;
845 case 0321:
846 length += (bits == 16);
847 break;
848 case 0322:
849 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000850 case 0323:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000851 rex_mask &= ~REX_W;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000852 break;
853 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000854 ins->rex |= REX_W;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000855 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000856 case 0330:
857 codes++, length++;
858 break;
859 case 0331:
860 case 0332:
861 break;
862 case 0333:
863 length++;
864 break;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000865 case 0334:
866 assert_no_prefix(ins, P_LOCK);
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000867 ins->rex |= REX_L;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000868 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000869 case 0340:
870 case 0341:
871 case 0342:
872 if (ins->oprs[0].segment != NO_SEG)
873 errfunc(ERR_NONFATAL, "attempt to reserve non-constant"
874 " quantity of BSS space");
875 else
876 length += ins->oprs[0].offset << (c - 0340);
877 break;
878 case 0370:
879 case 0371:
880 case 0372:
881 break;
882 case 0373:
883 length++;
884 break;
885 default: /* can't do it by 'case' statements */
886 if (c >= 0100 && c <= 0277) { /* it's an EA */
887 ea ea_data;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000888 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000889 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000890 ea_data.rex = 0; /* Ensure ea.REX is initially 0 */
891
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000892 if (c <= 0177) {
893 /* pick rfield from operand b */
894 rflags = regflag(&ins->oprs[c & 7]);
895 rfield = regvals[ins->oprs[c & 7].basereg];
896 } else {
897 rflags = 0;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000898 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000899 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000900
H. Peter Anvine2c80182005-01-15 22:15:51 +0000901 if (!process_ea
Keith Kaniosb7a89542007-04-12 02:40:54 +0000902 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000903 rfield, rflags, ins->forw_ref)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000904 errfunc(ERR_NONFATAL, "invalid effective address");
905 return -1;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000906 } else {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000907 ins->rex |= ea_data.rex;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000908 length += ea_data.size;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000909 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000910 } else
911 errfunc(ERR_PANIC, "internal instruction table corrupt"
912 ": instruction code 0x%02X given", c);
913 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000914
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000915 ins->rex &= rex_mask;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000916 if (ins->rex & REX_REAL) {
917 if (ins->rex & REX_H) {
918 errfunc(ERR_NONFATAL, "cannot use high register in rex instruction");
919 return -1;
920 } else if (bits == 64 ||
921 ((ins->rex & REX_L) &&
922 !(ins->rex & (REX_P|REX_W|REX_X|REX_B)) &&
923 cpu >= IF_X86_64)) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000924 length++;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000925 } else {
926 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
927 return -1;
928 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000929 }
930
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000931 return length;
932}
Keith Kaniosb7a89542007-04-12 02:40:54 +0000933
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000934#define EMIT_REX() \
935 if((ins->rex & REX_REAL) && (bits == 64)) { \
936 ins->rex = (ins->rex & REX_REAL)|REX_P; \
937 out(offset, segment, &ins->rex, OUT_RAWDATA+1, NO_SEG, NO_SEG); \
938 ins->rex = 0; \
939 offset += 1; \
940 }
941
Keith Kaniosb7a89542007-04-12 02:40:54 +0000942static void gencode(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000943 insn * ins, const char *codes, int32_t insn_end)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000944{
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000945 static char condval[] = { /* conditional opcodes */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000946 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
947 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
948 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000949 };
Keith Kaniosb7a89542007-04-12 02:40:54 +0000950 uint8_t c;
951 uint8_t bytes[4];
952 int32_t size;
953 int64_t data;
954
H. Peter Anvineba20a72002-04-30 20:53:55 +0000955 while (*codes)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000956 switch (c = *codes++) {
957 case 01:
958 case 02:
959 case 03:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000960 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +0000961 out(offset, segment, codes, OUT_RAWDATA + c, NO_SEG, NO_SEG);
962 codes += c;
963 offset += c;
964 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000965
H. Peter Anvine2c80182005-01-15 22:15:51 +0000966 case 04:
967 case 06:
968 switch (ins->oprs[0].basereg) {
969 case R_CS:
970 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0);
971 break;
972 case R_DS:
973 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0);
974 break;
975 case R_ES:
976 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0);
977 break;
978 case R_SS:
979 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0);
980 break;
981 default:
982 errfunc(ERR_PANIC,
983 "bizarre 8086 segment register received");
984 }
985 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
986 offset++;
987 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000988
H. Peter Anvine2c80182005-01-15 22:15:51 +0000989 case 05:
990 case 07:
991 switch (ins->oprs[0].basereg) {
992 case R_FS:
993 bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0);
994 break;
995 case R_GS:
996 bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0);
997 break;
998 default:
999 errfunc(ERR_PANIC,
1000 "bizarre 386 segment register received");
1001 }
1002 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1003 offset++;
1004 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001005
H. Peter Anvine2c80182005-01-15 22:15:51 +00001006 case 010:
1007 case 011:
1008 case 012:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001009 EMIT_REX();
Keith Kaniosb7a89542007-04-12 02:40:54 +00001010 bytes[0] = *codes++ + ((regval(&ins->oprs[c - 010])) & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001011 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1012 offset += 1;
1013 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001014
H. Peter Anvine2c80182005-01-15 22:15:51 +00001015 case 017:
1016 bytes[0] = 0;
1017 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1018 offset += 1;
1019 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001020
H. Peter Anvine2c80182005-01-15 22:15:51 +00001021 case 014:
1022 case 015:
1023 case 016:
1024 if (ins->oprs[c - 014].offset < -128
1025 || ins->oprs[c - 014].offset > 127) {
1026 errfunc(ERR_WARNING, "signed byte value exceeds bounds");
1027 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001028
H. Peter Anvine2c80182005-01-15 22:15:51 +00001029 if (ins->oprs[c - 014].segment != NO_SEG) {
1030 data = ins->oprs[c - 014].offset;
1031 out(offset, segment, &data, OUT_ADDRESS + 1,
1032 ins->oprs[c - 014].segment, ins->oprs[c - 014].wrt);
1033 } else {
1034 bytes[0] = ins->oprs[c - 014].offset;
1035 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1036 NO_SEG);
1037 }
1038 offset += 1;
1039 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001040
H. Peter Anvine2c80182005-01-15 22:15:51 +00001041 case 020:
1042 case 021:
1043 case 022:
1044 if (ins->oprs[c - 020].offset < -256
1045 || ins->oprs[c - 020].offset > 255) {
1046 errfunc(ERR_WARNING, "byte value exceeds bounds");
1047 }
1048 if (ins->oprs[c - 020].segment != NO_SEG) {
1049 data = ins->oprs[c - 020].offset;
1050 out(offset, segment, &data, OUT_ADDRESS + 1,
1051 ins->oprs[c - 020].segment, ins->oprs[c - 020].wrt);
1052 } else {
1053 bytes[0] = ins->oprs[c - 020].offset;
1054 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1055 NO_SEG);
1056 }
1057 offset += 1;
1058 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001059
H. Peter Anvine2c80182005-01-15 22:15:51 +00001060 case 024:
1061 case 025:
1062 case 026:
1063 if (ins->oprs[c - 024].offset < 0
1064 || ins->oprs[c - 024].offset > 255)
1065 errfunc(ERR_WARNING, "unsigned byte value exceeds bounds");
1066 if (ins->oprs[c - 024].segment != NO_SEG) {
1067 data = ins->oprs[c - 024].offset;
1068 out(offset, segment, &data, OUT_ADDRESS + 1,
1069 ins->oprs[c - 024].segment, ins->oprs[c - 024].wrt);
1070 } else {
1071 bytes[0] = ins->oprs[c - 024].offset;
1072 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1073 NO_SEG);
1074 }
1075 offset += 1;
1076 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001077
H. Peter Anvine2c80182005-01-15 22:15:51 +00001078 case 030:
1079 case 031:
1080 case 032:
1081 if (ins->oprs[c - 030].segment == NO_SEG &&
1082 ins->oprs[c - 030].wrt == NO_SEG &&
1083 (ins->oprs[c - 030].offset < -65536L ||
1084 ins->oprs[c - 030].offset > 65535L)) {
1085 errfunc(ERR_WARNING, "word value exceeds bounds");
1086 }
1087 data = ins->oprs[c - 030].offset;
1088 out(offset, segment, &data, OUT_ADDRESS + 2,
1089 ins->oprs[c - 030].segment, ins->oprs[c - 030].wrt);
1090 offset += 2;
1091 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001092
H. Peter Anvine2c80182005-01-15 22:15:51 +00001093 case 034:
1094 case 035:
1095 case 036:
1096 if (ins->oprs[c - 034].type & (BITS16 | BITS32))
1097 size = (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
1098 else
1099 size = (bits == 16) ? 2 : 4;
1100 data = ins->oprs[c - 034].offset;
1101 if (size == 2 && (data < -65536L || data > 65535L))
1102 errfunc(ERR_WARNING, "word value exceeds bounds");
1103 out(offset, segment, &data, OUT_ADDRESS + size,
1104 ins->oprs[c - 034].segment, ins->oprs[c - 034].wrt);
1105 offset += size;
1106 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001107
H. Peter Anvine2c80182005-01-15 22:15:51 +00001108 case 037:
1109 if (ins->oprs[0].segment == NO_SEG)
1110 errfunc(ERR_NONFATAL, "value referenced by FAR is not"
1111 " relocatable");
1112 data = 0L;
1113 out(offset, segment, &data, OUT_ADDRESS + 2,
1114 outfmt->segbase(1 + ins->oprs[0].segment),
1115 ins->oprs[0].wrt);
1116 offset += 2;
1117 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001118
H. Peter Anvine2c80182005-01-15 22:15:51 +00001119 case 040:
1120 case 041:
1121 case 042:
1122 data = ins->oprs[c - 040].offset;
1123 out(offset, segment, &data, OUT_ADDRESS + 4,
1124 ins->oprs[c - 040].segment, ins->oprs[c - 040].wrt);
1125 offset += 4;
1126 break;
H. Peter Anvin3ba46772002-05-27 23:19:35 +00001127
H. Peter Anvine2c80182005-01-15 22:15:51 +00001128 case 044:
1129 case 045:
1130 case 046:
1131 data = ins->oprs[c - 044].offset;
1132 size = ((ins->oprs[c - 044].addr_size ?
Keith Kaniosb7a89542007-04-12 02:40:54 +00001133 ins->oprs[c - 044].addr_size : bits) >> 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001134 if (size == 2 && (data < -65536L || data > 65535L))
1135 errfunc(ERR_WARNING, "word value exceeds bounds");
1136 out(offset, segment, &data, OUT_ADDRESS + size,
1137 ins->oprs[c - 044].segment, ins->oprs[c - 044].wrt);
1138 offset += size;
1139 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001140
H. Peter Anvine2c80182005-01-15 22:15:51 +00001141 case 050:
1142 case 051:
1143 case 052:
1144 if (ins->oprs[c - 050].segment != segment)
1145 errfunc(ERR_NONFATAL,
1146 "short relative jump outside segment");
1147 data = ins->oprs[c - 050].offset - insn_end;
1148 if (data > 127 || data < -128)
1149 errfunc(ERR_NONFATAL, "short jump is out of range");
1150 bytes[0] = data;
1151 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1152 offset += 1;
1153 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001154
1155 case 054:
1156 case 055:
1157 case 056:
1158 data = (int64_t)ins->oprs[c - 054].offset;
1159 out(offset, segment, &data, OUT_ADDRESS + 8,
1160 ins->oprs[c - 054].segment, ins->oprs[c - 054].wrt);
1161 offset += 8;
1162 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001163
H. Peter Anvine2c80182005-01-15 22:15:51 +00001164 case 060:
1165 case 061:
1166 case 062:
1167 if (ins->oprs[c - 060].segment != segment) {
1168 data = ins->oprs[c - 060].offset;
1169 out(offset, segment, &data,
1170 OUT_REL2ADR + insn_end - offset,
1171 ins->oprs[c - 060].segment, ins->oprs[c - 060].wrt);
1172 } else {
1173 data = ins->oprs[c - 060].offset - insn_end;
1174 out(offset, segment, &data,
1175 OUT_ADDRESS + 2, NO_SEG, NO_SEG);
1176 }
1177 offset += 2;
1178 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001179
H. Peter Anvine2c80182005-01-15 22:15:51 +00001180 case 064:
1181 case 065:
1182 case 066:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001183 if (ins->oprs[c - 064].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001184 size = (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
1185 else
1186 size = (bits == 16) ? 2 : 4;
1187 if (ins->oprs[c - 064].segment != segment) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001188 int32_t reltype = (size == 2 ? OUT_REL2ADR : OUT_REL4ADR);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001189 data = ins->oprs[c - 064].offset;
1190 out(offset, segment, &data, reltype + insn_end - offset,
1191 ins->oprs[c - 064].segment, ins->oprs[c - 064].wrt);
1192 } else {
1193 data = ins->oprs[c - 064].offset - insn_end;
1194 out(offset, segment, &data,
1195 OUT_ADDRESS + size, NO_SEG, NO_SEG);
1196 }
1197 offset += size;
1198 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001199
H. Peter Anvine2c80182005-01-15 22:15:51 +00001200 case 070:
1201 case 071:
1202 case 072:
1203 if (ins->oprs[c - 070].segment != segment) {
1204 data = ins->oprs[c - 070].offset;
1205 out(offset, segment, &data,
1206 OUT_REL4ADR + insn_end - offset,
1207 ins->oprs[c - 070].segment, ins->oprs[c - 070].wrt);
1208 } else {
1209 data = ins->oprs[c - 070].offset - insn_end;
1210 out(offset, segment, &data,
1211 OUT_ADDRESS + 4, NO_SEG, NO_SEG);
1212 }
1213 offset += 4;
1214 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001215
H. Peter Anvine2c80182005-01-15 22:15:51 +00001216 case 0130:
1217 case 0131:
1218 case 0132:
1219 data = ins->oprs[c - 0130].offset;
1220 if (is_sbyte(ins, c - 0130, 16)) {
1221 bytes[0] = data;
1222 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1223 NO_SEG);
1224 offset++;
1225 } else {
1226 if (ins->oprs[c - 0130].segment == NO_SEG &&
1227 ins->oprs[c - 0130].wrt == NO_SEG &&
1228 (data < -65536L || data > 65535L)) {
1229 errfunc(ERR_WARNING, "word value exceeds bounds");
1230 }
1231 out(offset, segment, &data, OUT_ADDRESS + 2,
1232 ins->oprs[c - 0130].segment, ins->oprs[c - 0130].wrt);
1233 offset += 2;
1234 }
1235 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001236
H. Peter Anvine2c80182005-01-15 22:15:51 +00001237 case 0133:
1238 case 0134:
1239 case 0135:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001240 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001241 codes++;
1242 bytes[0] = *codes++;
1243 if (is_sbyte(ins, c - 0133, 16))
1244 bytes[0] |= 2; /* s-bit */
1245 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1246 offset++;
1247 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001248
H. Peter Anvine2c80182005-01-15 22:15:51 +00001249 case 0140:
1250 case 0141:
1251 case 0142:
1252 data = ins->oprs[c - 0140].offset;
1253 if (is_sbyte(ins, c - 0140, 32)) {
1254 bytes[0] = data;
1255 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1256 NO_SEG);
1257 offset++;
1258 } else {
1259 out(offset, segment, &data, OUT_ADDRESS + 4,
1260 ins->oprs[c - 0140].segment, ins->oprs[c - 0140].wrt);
1261 offset += 4;
1262 }
1263 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001264
H. Peter Anvine2c80182005-01-15 22:15:51 +00001265 case 0143:
1266 case 0144:
1267 case 0145:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001268 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001269 codes++;
1270 bytes[0] = *codes++;
1271 if (is_sbyte(ins, c - 0143, 32))
1272 bytes[0] |= 2; /* s-bit */
1273 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1274 offset++;
1275 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001276
H. Peter Anvine2c80182005-01-15 22:15:51 +00001277 case 0300:
1278 case 0301:
1279 case 0302:
1280 if (chsize(&ins->oprs[c - 0300], bits)) {
1281 *bytes = 0x67;
1282 out(offset, segment, bytes,
1283 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1284 offset += 1;
1285 } else
1286 offset += 0;
1287 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001288
H. Peter Anvine2c80182005-01-15 22:15:51 +00001289 case 0310:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001290 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001291 *bytes = 0x67;
1292 out(offset, segment, bytes,
1293 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1294 offset += 1;
1295 } else
1296 offset += 0;
1297 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001298
H. Peter Anvine2c80182005-01-15 22:15:51 +00001299 case 0311:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001300 if (bits != 32) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001301 *bytes = 0x67;
1302 out(offset, segment, bytes,
1303 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1304 offset += 1;
1305 } else
1306 offset += 0;
1307 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001308
H. Peter Anvine2c80182005-01-15 22:15:51 +00001309 case 0312:
1310 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001311
Keith Kaniosb7a89542007-04-12 02:40:54 +00001312 case 0313:
1313 ins->rex = 0;
1314 break;
1315
H. Peter Anvine2c80182005-01-15 22:15:51 +00001316 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001317 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001318 *bytes = 0x66;
1319 out(offset, segment, bytes,
1320 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1321 offset += 1;
1322 } else
1323 offset += 0;
1324 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001325
H. Peter Anvine2c80182005-01-15 22:15:51 +00001326 case 0321:
1327 if (bits == 16) {
1328 *bytes = 0x66;
1329 out(offset, segment, bytes,
1330 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1331 offset += 1;
1332 } else
1333 offset += 0;
1334 break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001335
H. Peter Anvine2c80182005-01-15 22:15:51 +00001336 case 0322:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001337 case 0323:
1338 break;
1339
1340 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001341 ins->rex |= REX_W;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001342 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001343
H. Peter Anvine2c80182005-01-15 22:15:51 +00001344 case 0330:
1345 *bytes = *codes++ ^ condval[ins->condition];
1346 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1347 offset += 1;
1348 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001349
H. Peter Anvine2c80182005-01-15 22:15:51 +00001350 case 0331:
1351 case 0332:
1352 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001353
H. Peter Anvine2c80182005-01-15 22:15:51 +00001354 case 0333:
1355 *bytes = 0xF3;
1356 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1357 offset += 1;
1358 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001359
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001360 case 0334:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001361 if (ins->rex & REX_R) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001362 *bytes = 0xF0;
1363 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1364 offset += 1;
1365 }
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001366 ins->rex &= ~(REX_L|REX_R);
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001367 break;
1368
H. Peter Anvine2c80182005-01-15 22:15:51 +00001369 case 0340:
1370 case 0341:
1371 case 0342:
1372 if (ins->oprs[0].segment != NO_SEG)
1373 errfunc(ERR_PANIC, "non-constant BSS size in pass two");
1374 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001375 int32_t size = ins->oprs[0].offset << (c - 0340);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001376 if (size > 0)
1377 out(offset, segment, NULL,
1378 OUT_RESERVE + size, NO_SEG, NO_SEG);
1379 offset += size;
1380 }
1381 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001382
H. Peter Anvine2c80182005-01-15 22:15:51 +00001383 case 0370:
1384 case 0371:
1385 case 0372:
1386 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001387
H. Peter Anvine2c80182005-01-15 22:15:51 +00001388 case 0373:
1389 *bytes = bits == 16 ? 3 : 5;
1390 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1391 offset += 1;
1392 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001393
H. Peter Anvine2c80182005-01-15 22:15:51 +00001394 default: /* can't do it by 'case' statements */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001395 if (c >= 0100 && c <= 0277) { /* it's an EA */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001396 ea ea_data;
1397 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001398 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001399 uint8_t *p;
1400 int32_t s;
1401
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001402 if (c <= 0177) {
1403 /* pick rfield from operand b */
1404 rflags = regflag(&ins->oprs[c & 7]);
1405 rfield = regvals[ins->oprs[c & 7].basereg];
1406 } else {
1407 /* rfield is constant */
1408 rflags = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001409 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001410 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001411
1412 if (!process_ea
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001413 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
1414 rfield, rflags, ins->forw_ref)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001415 errfunc(ERR_NONFATAL, "invalid effective address");
1416 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001417
H. Peter Anvine2c80182005-01-15 22:15:51 +00001418 p = bytes;
1419 *p++ = ea_data.modrm;
1420 if (ea_data.sib_present)
1421 *p++ = ea_data.sib;
1422
1423 s = p - bytes;
1424 out(offset, segment, bytes, OUT_RAWDATA + s,
1425 NO_SEG, NO_SEG);
1426
1427 switch (ea_data.bytes) {
1428 case 0:
1429 break;
1430 case 1:
1431 if (ins->oprs[(c >> 3) & 7].segment != NO_SEG) {
1432 data = ins->oprs[(c >> 3) & 7].offset;
1433 out(offset, segment, &data, OUT_ADDRESS + 1,
1434 ins->oprs[(c >> 3) & 7].segment,
1435 ins->oprs[(c >> 3) & 7].wrt);
1436 } else {
1437 *bytes = ins->oprs[(c >> 3) & 7].offset;
1438 out(offset, segment, bytes, OUT_RAWDATA + 1,
1439 NO_SEG, NO_SEG);
1440 }
1441 s++;
1442 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001443 case 8:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001444 case 2:
1445 case 4:
1446 data = ins->oprs[(c >> 3) & 7].offset;
Keith Kaniose83b3182007-04-16 14:31:54 +00001447 if (ea_data.rip && (ins->oprs[(c >> 3) & 7].segment == 0xFFFFFFFF))
1448 ea_data.rip = 0; /* Make distinction between Symbols and Immediates */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001449 out(offset, segment, &data, /* RIP = Relative, not Absolute */
1450 (ea_data.rip ? OUT_REL4ADR : OUT_ADDRESS) + ea_data.bytes,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001451 ins->oprs[(c >> 3) & 7].segment,
1452 ins->oprs[(c >> 3) & 7].wrt);
1453 s += ea_data.bytes;
1454 break;
1455 }
1456 offset += s;
1457 } else
1458 errfunc(ERR_PANIC, "internal instruction table corrupt"
1459 ": instruction code 0x%02X given", c);
1460 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001461}
1462
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001463static int regflag(const operand * o)
1464{
1465 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1466 errfunc(ERR_PANIC, "invalid operand passed to regflag()");
1467 }
1468 return reg_flags[o->basereg];
1469}
1470
1471static int regval(const operand * o)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001472{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001473 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1474 errfunc(ERR_PANIC, "invalid operand passed to regval()");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001475 }
H. Peter Anvin232badb2002-06-06 02:41:20 +00001476 return regvals[o->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001477}
1478
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001479static int op_rexflags(const operand * o, int mask)
1480{
1481 int32_t flags;
1482 int val;
1483
1484 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1485 errfunc(ERR_PANIC, "invalid operand passed to op_rexflags()");
1486 }
1487
1488 flags = reg_flags[o->basereg];
1489 val = regvals[o->basereg];
1490
1491 return rexflags(val, flags, mask);
1492}
1493
1494static int rexflags(int val, int32_t flags, int mask)
1495{
1496 int rex = 0;
1497
1498 if (val >= 8)
1499 rex |= REX_B|REX_X|REX_R;
1500 if (flags & BITS64)
1501 rex |= REX_W;
1502 if (!(REG_HIGH & ~flags)) /* AH, CH, DH, BH */
1503 rex |= REX_H;
1504 else if (!(REG8 & ~flags) && val >= 4) /* SPL, BPL, SIL, DIL */
1505 rex |= REX_P;
1506
1507 return rex & mask;
1508}
1509
Keith Kaniosb7a89542007-04-12 02:40:54 +00001510static int matches(struct itemplate *itemp, insn * instruction, int bits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001511{
H. Peter Anvin34539fb2007-05-30 04:27:58 +00001512 int i, size[3], asize, oprs, ret;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001513
1514 ret = 100;
1515
1516 /*
1517 * Check the opcode
1518 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001519 if (itemp->opcode != instruction->opcode)
1520 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001521
1522 /*
1523 * Count the operands
1524 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001525 if (itemp->operands != instruction->operands)
1526 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001527
1528 /*
1529 * Check that no spurious colons or TOs are present
1530 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001531 for (i = 0; i < itemp->operands; i++)
1532 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON | TO))
1533 return 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001534
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001535 /*
1536 * Check that the operand flags all match up
1537 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001538 for (i = 0; i < itemp->operands; i++)
1539 if (itemp->opd[i] & ~instruction->oprs[i].type ||
1540 ((itemp->opd[i] & SIZE_MASK) &&
1541 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK))) {
H. Peter Anvin5a640e12007-05-29 23:57:12 +00001542 if ((itemp->opd[i] & ~instruction->oprs[i].type & ~SIZE_MASK) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001543 (instruction->oprs[i].type & SIZE_MASK))
1544 return 0;
1545 else
H. Peter Anvine2c80182005-01-15 22:15:51 +00001546 return 1;
1547 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001548
1549 /*
1550 * Check operand sizes
1551 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001552 if (itemp->flags & IF_ARMASK) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001553 size[0] = size[1] = size[2] = 0;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001554
H. Peter Anvine2c80182005-01-15 22:15:51 +00001555 switch (itemp->flags & IF_ARMASK) {
1556 case IF_AR0:
1557 i = 0;
1558 break;
1559 case IF_AR1:
1560 i = 1;
1561 break;
1562 case IF_AR2:
1563 i = 2;
1564 break;
1565 default:
1566 break; /* Shouldn't happen */
1567 }
1568 if (itemp->flags & IF_SB) {
1569 size[i] = BITS8;
1570 } else if (itemp->flags & IF_SW) {
1571 size[i] = BITS16;
1572 } else if (itemp->flags & IF_SD) {
1573 size[i] = BITS32;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001574 } else if (itemp->flags & IF_SQ) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001575 size[i] = BITS64;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001576 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001577 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001578 asize = 0;
1579 if (itemp->flags & IF_SB) {
1580 asize = BITS8;
1581 oprs = itemp->operands;
1582 } else if (itemp->flags & IF_SW) {
1583 asize = BITS16;
1584 oprs = itemp->operands;
1585 } else if (itemp->flags & IF_SD) {
1586 asize = BITS32;
1587 oprs = itemp->operands;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001588 } else if (itemp->flags & IF_SQ) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001589 asize = BITS64;
1590 oprs = itemp->operands;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001591 }
1592 size[0] = size[1] = size[2] = asize;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001593 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001594
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001595 if (itemp->flags & (IF_SM | IF_SM2)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001596 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
1597 asize = 0;
1598 for (i = 0; i < oprs; i++) {
1599 if ((asize = itemp->opd[i] & SIZE_MASK) != 0) {
1600 int j;
1601 for (j = 0; j < oprs; j++)
1602 size[j] = asize;
1603 break;
1604 }
1605 }
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001606 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001607 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001608 }
1609
Keith Kaniosb7a89542007-04-12 02:40:54 +00001610 for (i = 0; i < itemp->operands; i++) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001611 if (!(itemp->opd[i] & SIZE_MASK) &&
1612 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001613 return 2;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001614 }
1615
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001616 /*
1617 * Check template is okay at the set cpu level
1618 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001619 if (((itemp->flags & IF_PLEVEL) > cpu))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001620 return 3;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001621
1622 /*
1623 * Check if instruction is available in long mode
1624 */
1625 if ((itemp->flags & IF_NOLONG) && (bits == 64))
1626 return 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001627
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001628 /*
1629 * Check if special handling needed for Jumps
1630 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001631 if ((uint8_t)(itemp->code[0]) >= 0370)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001632 return 99;
1633
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001634 return ret;
1635}
1636
H. Peter Anvine2c80182005-01-15 22:15:51 +00001637static ea *process_ea(operand * input, ea * output, int addrbits,
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001638 int rfield, int32_t rflags, int forw_ref)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001639{
Keith Kaniosb7a89542007-04-12 02:40:54 +00001640
1641 int rip = FALSE; /* Used for RIP-relative addressing */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001642
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001643 /* REX flags for the rfield operand */
1644 output->rex |= rexflags(rfield, rflags, REX_R|REX_P|REX_W|REX_H);
1645
Keith Kaniosb7a89542007-04-12 02:40:54 +00001646 if (!(REGISTER & ~input->type)) { /* register direct */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001647 int i;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001648 int32_t f;
1649
1650 if (input->basereg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001651 || input->basereg >= REG_ENUM_LIMIT)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001652 return NULL;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001653 f = regflag(input);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001654 i = regvals[input->basereg];
Keith Kaniosb7a89542007-04-12 02:40:54 +00001655
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001656 if (REG_EA & ~f)
1657 return NULL; /* Invalid EA register */
1658
1659 output->rex |= op_rexflags(input, REX_B|REX_P|REX_W|REX_H);
1660
Keith Kaniosb7a89542007-04-12 02:40:54 +00001661 output->sib_present = FALSE; /* no SIB necessary */
1662 output->bytes = 0; /* no offset necessary either */
1663 output->modrm = 0xC0 | ((rfield & 7) << 3) | (i & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001664 } else { /* it's a memory reference */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001665
H. Peter Anvine2c80182005-01-15 22:15:51 +00001666 if (input->basereg == -1
1667 && (input->indexreg == -1 || input->scale == 0)) {
1668 /* it's a pure offset */
1669 if (input->addr_size)
1670 addrbits = input->addr_size;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001671
H. Peter Anvine2c80182005-01-15 22:15:51 +00001672 output->sib_present = FALSE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001673 output->bytes = (addrbits != 16 ? 4 : 2);
1674 output->modrm = (addrbits != 16 ? 5 : 6) | ((rfield & 7) << 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001675 } else { /* it's an indirection */
1676 int i = input->indexreg, b = input->basereg, s = input->scale;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001677 int32_t o = input->offset, seg = input->segment;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001678 int hb = input->hintbase, ht = input->hinttype;
1679 int t;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001680 int it, bt;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001681 int32_t ix, bx; /* register flags */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001682
H. Peter Anvine2c80182005-01-15 22:15:51 +00001683 if (s == 0)
1684 i = -1; /* make this easy, at least */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001685
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001686 if (i >= EXPR_REG_START && i < REG_ENUM_LIMIT) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001687 it = regvals[i];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001688 ix = reg_flags[i];
1689 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001690 it = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001691 ix = 0;
1692 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001693
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001694 if (b != -1 && b >= EXPR_REG_START && b < REG_ENUM_LIMIT) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001695 bt = regvals[b];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001696 bx = reg_flags[b];
1697 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001698 bt = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001699 bx = 0;
1700 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001701
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001702 /* check for a 32/64-bit memory reference... */
1703 if ((ix|bx) & (BITS32|BITS64)) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001704 /* it must be a 32/64-bit memory reference. Firstly we have
1705 * to check that all registers involved are type E/Rxx. */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001706 int32_t sok = BITS32|BITS64;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001707
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001708 if (it != -1) {
1709 if (!(REG64 & ~ix) || !(REG32 & ~ix))
1710 sok &= ix;
1711 else
1712 return NULL;
1713 }
1714
1715 if (bt != -1) {
1716 if ((REG_GPR & ~bx) && (IP_REG & ~bx))
1717 return NULL; /* Invalid register */
H. Peter Anvina57e8d42007-05-30 03:44:02 +00001718 if (~sok & bx & SIZE_MASK)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001719 return NULL; /* Invalid size */
1720 sok &= ~bx;
1721 if (!(IP_REG & ~bx)) {
1722 bt = b = -1;
1723 rip = TRUE;
1724 }
1725 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001726
H. Peter Anvine2c80182005-01-15 22:15:51 +00001727 /* While we're here, ensure the user didn't specify WORD. */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001728 if (input->addr_size == 16 ||
1729 (input->addr_size == 32 && !(sok & BITS32)) ||
1730 (input->addr_size == 64 && !(sok & BITS64)))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001731 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001732
Keith Kaniosb7a89542007-04-12 02:40:54 +00001733 /* now reorganize base/index */
1734 if (s == 1 && bt != it && bt != -1 && it != -1 &&
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001735 ((hb == b && ht == EAH_NOTBASE)
1736 || (hb == i && ht == EAH_MAKEBASE))) {
1737 /* swap if hints say so */
1738 t = bt, bt = it, it = t;
1739 t = bx, bx = ix, ix = t;
1740 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001741 if (bt == it) /* convert EAX+2*EAX to 3*EAX */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001742 bt = -1, bx = 0, s++;
1743 if (bt == -1 && s == 1 && !(hb == it && ht == EAH_NOTBASE)) {
1744 /* make single reg base, unless hint */
1745 bt = it, bx = ix, it = -1, ix = 0;
1746 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001747 if (((s == 2 && (it & 7) != (REG_NUM_ESP & 7)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001748 && !(input->eaflags & EAF_TIMESTWO)) || s == 3
Keith Kaniosb7a89542007-04-12 02:40:54 +00001749 || s == 5 || s == 9) && bt == -1)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001750 bt = it, bx = ix, s--; /* convert 3*EAX to EAX+2*EAX */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001751 if (it == -1 && (bt & 7) != (REG_NUM_ESP & 7)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001752 && (input->eaflags & EAF_TIMESTWO))
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001753 it = bt, ix = bx, bt = -1, bx = 0, s = 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001754 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001755 if (s == 1 && (it & 7) == (REG_NUM_ESP & 7)) {
1756 /* swap ESP into base if scale is 1 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001757 t = it, it = bt, bt = t;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001758 t = ix, ix = bx, bx = t;
1759 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001760 if ((it & 7) == (REG_NUM_ESP & 7)
1761 || (s != 1 && s != 2 && s != 4 && s != 8 && it != -1))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001762 return NULL; /* wrong, for various reasons */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001763
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001764 output->rex |= rexflags(it, ix, REX_X);
1765 output->rex |= rexflags(bt, bx, REX_B);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001766
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001767 if (it == -1 && (bt & 7) != (REG_NUM_ESP & 7)) {
1768 /* no SIB needed */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001769 int mod, rm;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001770
1771 if (bt == -1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001772 rm = 5;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001773 mod = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001774 } else {
1775 rm = (bt & 7);
1776 if (rm != (REG_NUM_EBP & 7) && o == 0 &&
1777 seg == NO_SEG && !forw_ref &&
1778 !(input->eaflags &
1779 (EAF_BYTEOFFS | EAF_WORDOFFS)))
1780 mod = 0;
1781 else if (input->eaflags & EAF_BYTEOFFS ||
1782 (o >= -128 && o <= 127 && seg == NO_SEG
1783 && !forw_ref
1784 && !(input->eaflags & EAF_WORDOFFS)))
1785 mod = 1;
1786 else
1787 mod = 2;
1788 }
H. Peter Anvinea838272002-04-30 20:51:53 +00001789
H. Peter Anvine2c80182005-01-15 22:15:51 +00001790 output->sib_present = FALSE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001791 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
1792 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001793 } else {
1794 /* we need a SIB */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001795 int mod, scale, index, base;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001796
1797 if (it == -1)
1798 index = 4, s = 1;
1799 else
1800 index = (it & 7);
1801
H. Peter Anvine2c80182005-01-15 22:15:51 +00001802 switch (s) {
1803 case 1:
1804 scale = 0;
1805 break;
1806 case 2:
1807 scale = 1;
1808 break;
1809 case 4:
1810 scale = 2;
1811 break;
1812 case 8:
1813 scale = 3;
1814 break;
1815 default: /* then what the smeg is it? */
1816 return NULL; /* panic */
1817 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001818
1819 if (bt == -1) {
1820 base = 5;
1821 mod = 0;
1822 } else {
1823 base = (bt & 7);
1824 if (base != (REG_NUM_EBP & 7) && o == 0 &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00001825 seg == NO_SEG && !forw_ref &&
1826 !(input->eaflags &
Keith Kaniosb7a89542007-04-12 02:40:54 +00001827 (EAF_BYTEOFFS | EAF_WORDOFFS)))
1828 mod = 0;
1829 else if (input->eaflags & EAF_BYTEOFFS ||
1830 (o >= -128 && o <= 127 && seg == NO_SEG
1831 && !forw_ref
1832 && !(input->eaflags & EAF_WORDOFFS)))
1833 mod = 1;
1834 else
1835 mod = 2;
1836 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001837
H. Peter Anvine2c80182005-01-15 22:15:51 +00001838 output->sib_present = TRUE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001839 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
1840 output->modrm = (mod << 6) | ((rfield & 7) << 3) | 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001841 output->sib = (scale << 6) | (index << 3) | base;
1842 }
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001843
1844 /* Process RIP-relative Addressing */
1845 if (rip) {
1846 if (globalbits != 64 ||
1847 (output->modrm & 0xC7) != 0x05)
1848 return NULL;
1849 output->rip = TRUE;
1850 } else {
1851 output->rip = FALSE;
1852 /* Actual Disp32 needs blank SIB on x64 */
1853 if (globalbits == 64 &&
1854 !(output->sib_present) &&
1855 ((output->modrm & 0xC7) == 0x05)) {
1856 output->sib_present = TRUE;
1857 /* RM Field = 4 (forward to Base of SIB) */
1858 output->modrm--;
1859 /* Index = 4 (none), Base = 5 */
1860 output->sib = (4 << 3) | 5;
1861 }
1862 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001863 } else { /* it's 16-bit */
1864 int mod, rm;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001865
1866 /* check for 64-bit long mode */
1867 if (addrbits == 64)
1868 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001869
H. Peter Anvine2c80182005-01-15 22:15:51 +00001870 /* check all registers are BX, BP, SI or DI */
1871 if ((b != -1 && b != R_BP && b != R_BX && b != R_SI
1872 && b != R_DI) || (i != -1 && i != R_BP && i != R_BX
1873 && i != R_SI && i != R_DI))
1874 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001875
Keith Kaniosb7a89542007-04-12 02:40:54 +00001876 /* ensure the user didn't specify DWORD/QWORD */
1877 if (input->addr_size == 32 || input->addr_size == 64)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001878 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001879
H. Peter Anvine2c80182005-01-15 22:15:51 +00001880 if (s != 1 && i != -1)
1881 return NULL; /* no can do, in 16-bit EA */
1882 if (b == -1 && i != -1) {
1883 int tmp = b;
1884 b = i;
1885 i = tmp;
1886 } /* swap */
1887 if ((b == R_SI || b == R_DI) && i != -1) {
1888 int tmp = b;
1889 b = i;
1890 i = tmp;
1891 }
1892 /* have BX/BP as base, SI/DI index */
1893 if (b == i)
1894 return NULL; /* shouldn't ever happen, in theory */
1895 if (i != -1 && b != -1 &&
1896 (i == R_BP || i == R_BX || b == R_SI || b == R_DI))
1897 return NULL; /* invalid combinations */
1898 if (b == -1) /* pure offset: handled above */
1899 return NULL; /* so if it gets to here, panic! */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001900
H. Peter Anvine2c80182005-01-15 22:15:51 +00001901 rm = -1;
1902 if (i != -1)
1903 switch (i * 256 + b) {
1904 case R_SI * 256 + R_BX:
1905 rm = 0;
1906 break;
1907 case R_DI * 256 + R_BX:
1908 rm = 1;
1909 break;
1910 case R_SI * 256 + R_BP:
1911 rm = 2;
1912 break;
1913 case R_DI * 256 + R_BP:
1914 rm = 3;
1915 break;
1916 } else
1917 switch (b) {
1918 case R_SI:
1919 rm = 4;
1920 break;
1921 case R_DI:
1922 rm = 5;
1923 break;
1924 case R_BP:
1925 rm = 6;
1926 break;
1927 case R_BX:
1928 rm = 7;
1929 break;
1930 }
1931 if (rm == -1) /* can't happen, in theory */
1932 return NULL; /* so panic if it does */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001933
H. Peter Anvine2c80182005-01-15 22:15:51 +00001934 if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
1935 !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
1936 mod = 0;
1937 else if (input->eaflags & EAF_BYTEOFFS ||
1938 (o >= -128 && o <= 127 && seg == NO_SEG
1939 && !forw_ref
1940 && !(input->eaflags & EAF_WORDOFFS)))
1941 mod = 1;
1942 else
1943 mod = 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001944
H. Peter Anvine2c80182005-01-15 22:15:51 +00001945 output->sib_present = FALSE; /* no SIB - it's 16-bit */
1946 output->bytes = mod; /* bytes of offset needed */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001947 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001948 }
1949 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001950 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001951
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001952 output->size = 1 + output->sib_present + output->bytes;
1953 return output;
1954}
1955
H. Peter Anvine2c80182005-01-15 22:15:51 +00001956static int chsize(operand * input, int addrbits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001957{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001958 if (!(MEMORY & ~input->type)) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001959 int32_t i, b;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001960
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001961 if (input->indexreg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001962 || input->indexreg >= REG_ENUM_LIMIT)
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00001963 i = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001964 else
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001965 i = reg_flags[input->indexreg];
Keith Kaniosb7a89542007-04-12 02:40:54 +00001966
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001967 if (input->basereg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001968 || input->basereg >= REG_ENUM_LIMIT)
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00001969 b = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001970 else
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001971 b = reg_flags[input->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001972
H. Peter Anvine2c80182005-01-15 22:15:51 +00001973 if (input->scale == 0)
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00001974 i = 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001975
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00001976 if (!i && !b) /* pure offset */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001977 return (input->addr_size != 0 && input->addr_size != addrbits);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001978
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001979 if (!(REG32 & ~i) || !(REG32 & ~b))
Keith Kaniosb7a89542007-04-12 02:40:54 +00001980 return (addrbits != 32);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001981 else
1982 return (addrbits == 32);
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001983 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001984 return 0;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001985 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001986}