blob: c3a90492ac5301965c7d0df8d985e9e0fe2dc341 [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
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070015 * \10..\13 - a literal byte follows in the code stream, to be added
16 * to the register value of operand 0..3
17 * \14..\17 - a signed byte immediate operand, from operand 0..3
18 * \20..\23 - a byte immediate operand, from operand 0..3
19 * \24..\27 - an unsigned byte immediate operand, from operand 0..3
20 * \30..\33 - a word immediate operand, from operand 0..3
21 * \34..\37 - select between \3[0-3] and \4[0-3] depending on 16/32 bit
H. Peter Anvin3ba46772002-05-27 23:19:35 +000022 * assembly mode or the operand-size override on the operand
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070023 * \40..\43 - a long immediate operand, from operand 0..3
24 * \44..\47 - select between \3[0-3], \4[0-3] and \5[4-7]
H. Peter Anvinb061d592007-04-16 02:02:06 +000025 * depending on assembly mode or the address-size override
26 * on the operand.
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070027 * \50..\53 - a byte relative operand, from operand 0..3
28 * \54..\57 - a qword immediate operand, from operand 0..3
29 * \60..\63 - a word relative operand, from operand 0..3
30 * \64..\67 - select between \6[0-3] and \7[0-3] depending on 16/32 bit
H. Peter Anvin17799b42002-05-21 03:31:21 +000031 * assembly mode or the operand-size override on the operand
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070032 * \70..\73 - a long relative operand, from operand 0..3
33 * \74..\77 - a word constant, from the _segment_ part of operand 0..3
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000034 * \1ab - a ModRM, calculated on EA in operand a, with the spare
35 * field the register value of operand b.
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070036 * \140..\143 - an immediate word or signed byte for operand 0..3
37 * \144..\147 - or 2 (s-field) into next opcode byte if operand 0..3
H. Peter Anvinaf535c12002-04-30 20:59:21 +000038 * is a signed byte rather than a word.
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070039 * \150..\153 - an immediate dword or signed byte for operand 0..3
40 * \154..\157 - or 2 (s-field) into next opcode byte if operand 0..3
H. Peter Anvinaf535c12002-04-30 20:59:21 +000041 * is a signed byte rather than a dword.
H. Peter Anvin401c07e2007-09-17 16:55:04 -070042 * \160..\163 - this instruction uses DREX rather than REX, with the
43 * OC0 field set to 0, and the dest field taken from
44 * operand 0..3.
45 * \164..\167 - this instruction uses DREX rather than REX, with the
46 * OC0 field set to 1, and the dest field taken from
47 * operand 0..3.
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070048 * \170 - encodes the literal byte 0. (Some compilers don't take
49 * kindly to a zero byte in the _middle_ of a compile time
50 * string constant, so I had to put this hack in.)
H. Peter Anvin401c07e2007-09-17 16:55:04 -070051 * \171 - placement of DREX suffix in the absence of an EA
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000052 * \2ab - a ModRM, calculated on EA in operand a, with the spare
53 * field equal to digit b.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000054 * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
55 * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
Keith Kanios48af1772007-08-17 07:37:52 +000056 * \312 - (disassembler only) marker on LOOP, LOOPxx instructions.
H. Peter Anvince2b3972007-05-30 22:21:11 +000057 * \313 - indicates fixed 64-bit address size, 0x67 invalid.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000058 * \320 - indicates fixed 16-bit operand size, i.e. optional 0x66.
59 * \321 - indicates fixed 32-bit operand size, i.e. optional 0x66.
60 * \322 - indicates that this instruction is only valid when the
61 * operand size is the default (instruction to disassembler,
62 * generates no code in the assembler)
H. Peter Anvince2b3972007-05-30 22:21:11 +000063 * \323 - indicates fixed 64-bit operand size, REX on extensions only.
Keith Kaniosb7a89542007-04-12 02:40:54 +000064 * \324 - indicates 64-bit operand size requiring REX prefix.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000065 * \330 - a literal byte follows in the code stream, to be added
66 * to the condition code value of the instruction.
Keith Kanios48af1772007-08-17 07:37:52 +000067 * \331 - instruction not valid with REP prefix. Hint for
H. Peter Anvinef7468f2002-04-30 20:57:59 +000068 * disassembler only; for SSE instructions.
H. Peter Anvincb9b6902007-09-12 21:58:51 -070069 * \332 - REP prefix (0xF2 byte) used as opcode extension.
70 * \333 - REP prefix (0xF3 byte) used as opcode extension.
Keith Kanios48af1772007-08-17 07:37:52 +000071 * \334 - LOCK prefix used instead of REX.R
H. Peter Anvincb9b6902007-09-12 21:58:51 -070072 * \335 - disassemble a rep (0xF3 byte) prefix as repe not rep.
Keith Kaniosb7a89542007-04-12 02:40:54 +000073 * \340 - reserve <operand 0> bytes of uninitialized storage.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000074 * Operand 0 had better be a segmentless constant.
H. Peter Anvin62cb6062007-09-11 22:44:03 +000075 * \364 - operand-size prefix (0x66) not permitted
76 * \365 - address-size prefix (0x67) not permitted
77 * \366 - operand-size prefix (0x66) used as opcode extension
78 * \367 - address-size prefix (0x67) used as opcode extension
H. Peter Anvin788e6c12002-04-30 21:02:01 +000079 * \370,\371,\372 - match only if operand 0 meets byte jump criteria.
80 * 370 is used for Jcc, 371 is used for JMP.
H. Peter Anvinaf535c12002-04-30 20:59:21 +000081 * \373 - assemble 0x03 if bits==16, 0x05 if bits==32;
82 * used for conditional jump over longer jump
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000083 */
84
H. Peter Anvinfe501952007-10-02 21:53:51 -070085#include "compiler.h"
86
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000087#include <stdio.h>
88#include <string.h>
Keith Kaniosb7a89542007-04-12 02:40:54 +000089#include <inttypes.h>
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000090
91#include "nasm.h"
H. Peter Anvin6768eb72002-04-30 20:52:26 +000092#include "nasmlib.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000093#include "assemble.h"
94#include "insns.h"
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +000095#include "preproc.h"
H. Peter Anvin3df97a72007-05-30 03:25:21 +000096#include "regflags.c"
Keith Kaniosb7a89542007-04-12 02:40:54 +000097#include "regvals.c"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000098
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000099typedef struct {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000100 int sib_present; /* is a SIB byte necessary? */
101 int bytes; /* # of bytes of offset needed */
102 int size; /* lazy - this is sib+bytes+1 */
103 uint8_t modrm, sib, rex, rip; /* the bytes themselves */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000104} ea;
105
Keith Kaniosb7a89542007-04-12 02:40:54 +0000106static uint32_t cpu; /* cpu level received from nasm.c */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000107static efunc errfunc;
108static struct ofmt *outfmt;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000109static ListGen *list;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000110
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000111static int32_t calcsize(int32_t, int32_t, int, insn *, const char *);
112static void gencode(int32_t, int32_t, int, insn *, const char *, int32_t);
H. Peter Anvin3360d792007-09-11 04:16:57 +0000113static int matches(const struct itemplate *, insn *, int bits);
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000114static int32_t regflag(const operand *);
115static int32_t regval(const operand *);
116static int rexflags(int, int32_t, int);
117static int op_rexflags(const operand *, int);
H. Peter Anvin5b0e3ec2007-07-07 02:01:08 +0000118static ea *process_ea(operand *, ea *, int, int, int32_t, int);
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700119static void add_asp(insn *, int);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000120
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700121static int has_prefix(insn * ins, enum prefixes prefix)
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000122{
123 int j;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000124 for (j = 0; j < ins->nprefix; j++) {
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700125 if (ins->prefixes[j] == prefix)
126 return 1;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000127 }
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700128 return 0;
129}
130
131static void assert_no_prefix(insn * ins, enum prefixes prefix)
132{
133 if (has_prefix(ins, prefix))
134 errfunc(ERR_NONFATAL, "invalid %s prefix", prefix_name(prefix));
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000135}
136
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000137/*
138 * This routine wrappers the real output format's output routine,
139 * in order to pass a copy of the data off to the listing file
140 * generator at the same time.
141 */
Keith Kaniosb7a89542007-04-12 02:40:54 +0000142static void out(int32_t offset, int32_t segto, const void *data,
143 uint32_t type, int32_t segment, int32_t wrt)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000144{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000145 static int32_t lineno = 0; /* static!!! */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000146 static char *lnfname = NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000147
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000148 if ((type & OUT_TYPMASK) == OUT_ADDRESS) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000149 if (segment != NO_SEG || wrt != NO_SEG) {
150 /*
151 * This address is relocated. We must write it as
152 * OUT_ADDRESS, so there's no work to be done here.
153 */
154 list->output(offset, data, type);
155 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000156 uint8_t p[8], *q = p;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000157 /*
158 * This is a non-relocated address, and we're going to
159 * convert it into RAWDATA format.
160 */
161 if ((type & OUT_SIZMASK) == 4) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000162 WRITELONG(q, *(int32_t *)data);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000163 list->output(offset, p, OUT_RAWDATA + 4);
Keith Kaniosb7a89542007-04-12 02:40:54 +0000164 } else if ((type & OUT_SIZMASK) == 8) {
165 WRITEDLONG(q, *(int64_t *)data);
166 list->output(offset, p, OUT_RAWDATA + 8);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000167 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000168 WRITESHORT(q, *(int32_t *)data);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000169 list->output(offset, p, OUT_RAWDATA + 2);
170 }
171 }
172 } else if ((type & OUT_TYPMASK) == OUT_RAWDATA) {
173 list->output(offset, data, type);
174 } else if ((type & OUT_TYPMASK) == OUT_RESERVE) {
175 list->output(offset, NULL, type);
176 } else if ((type & OUT_TYPMASK) == OUT_REL2ADR ||
177 (type & OUT_TYPMASK) == OUT_REL4ADR) {
178 list->output(offset, data, type);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000179 }
180
Frank Kotlerabebb082003-09-06 04:45:37 +0000181 /*
182 * this call to src_get determines when we call the
183 * debug-format-specific "linenum" function
184 * it updates lineno and lnfname to the current values
185 * returning 0 if "same as last time", -2 if lnfname
186 * changed, and the amount by which lineno changed,
187 * if it did. thus, these variables must be static
188 */
189
H. Peter Anvine2c80182005-01-15 22:15:51 +0000190 if (src_get(&lineno, &lnfname)) {
191 outfmt->current_dfmt->linenum(lnfname, lineno, segto);
H. Peter Anvince616072002-04-30 21:02:23 +0000192 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000193
H. Peter Anvine2c80182005-01-15 22:15:51 +0000194 outfmt->output(segto, data, type, segment, wrt);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000195}
196
Keith Kaniosb7a89542007-04-12 02:40:54 +0000197static int jmp_match(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000198 insn * ins, const char *code)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000199{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000200 int32_t isize;
201 uint8_t c = code[0];
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000202
H. Peter Anvine2c80182005-01-15 22:15:51 +0000203 if (c != 0370 && c != 0371)
204 return 0;
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000205 if (ins->oprs[0].opflags & OPFLAG_FORWARD) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000206 if ((optimizing < 0 || (ins->oprs[0].type & STRICT))
207 && c == 0370)
208 return 1;
209 else
210 return (pass0 == 0); /* match a forward reference */
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000211 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000212 isize = calcsize(segment, offset, bits, ins, code);
213 if (ins->oprs[0].segment != segment)
214 return 0;
215 isize = ins->oprs[0].offset - offset - isize; /* isize is now the delta */
216 if (isize >= -128L && isize <= 127L)
217 return 1; /* it is byte size */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000218
219 return 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000220}
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000221
Keith Kaniosb7a89542007-04-12 02:40:54 +0000222int32_t assemble(int32_t segment, int32_t offset, int bits, uint32_t cp,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000223 insn * instruction, struct ofmt *output, efunc error,
224 ListGen * listgen)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000225{
H. Peter Anvin3360d792007-09-11 04:16:57 +0000226 const struct itemplate *temp;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000227 int j;
228 int size_prob;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000229 int32_t insn_end;
230 int32_t itimes;
231 int32_t start = offset;
232 int32_t wsize = 0; /* size for DB etc. */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000233
H. Peter Anvine2c80182005-01-15 22:15:51 +0000234 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000235 cpu = cp;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000236 outfmt = output; /* likewise */
237 list = listgen; /* and again */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000238
H. Peter Anvine2c80182005-01-15 22:15:51 +0000239 switch (instruction->opcode) {
240 case -1:
241 return 0;
242 case I_DB:
243 wsize = 1;
244 break;
245 case I_DW:
246 wsize = 2;
247 break;
248 case I_DD:
249 wsize = 4;
250 break;
251 case I_DQ:
252 wsize = 8;
253 break;
254 case I_DT:
255 wsize = 10;
256 break;
H. Peter Anvincfbe7c32007-09-18 17:49:09 -0700257 case I_DO:
258 wsize = 16;
259 break;
H. Peter Anvin16b0a332007-09-12 20:27:41 -0700260 default:
261 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000262 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000263
H. Peter Anvineba20a72002-04-30 20:53:55 +0000264 if (wsize) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000265 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000266 int32_t t = instruction->times;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000267 if (t < 0)
268 errfunc(ERR_PANIC,
269 "instruction->times < 0 (%ld) in assemble()", t);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000270
H. Peter Anvine2c80182005-01-15 22:15:51 +0000271 while (t--) { /* repeat TIMES times */
272 for (e = instruction->eops; e; e = e->next) {
273 if (e->type == EOT_DB_NUMBER) {
274 if (wsize == 1) {
275 if (e->segment != NO_SEG)
276 errfunc(ERR_NONFATAL,
277 "one-byte relocation attempted");
278 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000279 uint8_t out_byte = e->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000280 out(offset, segment, &out_byte,
281 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
282 }
Keith Kanios61ff53c2007-04-14 18:54:52 +0000283 } else if (wsize > 8) {
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700284 errfunc(ERR_NONFATAL, "integer supplied to a DT or DO"
Keith Kanios61ff53c2007-04-14 18:54:52 +0000285 " instruction");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000286 } else
287 out(offset, segment, &e->offset,
288 OUT_ADDRESS + wsize, e->segment, e->wrt);
289 offset += wsize;
290 } else if (e->type == EOT_DB_STRING) {
291 int align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000292
H. Peter Anvine2c80182005-01-15 22:15:51 +0000293 out(offset, segment, e->stringval,
294 OUT_RAWDATA + e->stringlen, NO_SEG, NO_SEG);
295 align = e->stringlen % wsize;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000296
H. Peter Anvine2c80182005-01-15 22:15:51 +0000297 if (align) {
298 align = wsize - align;
299 out(offset, segment, "\0\0\0\0\0\0\0\0",
300 OUT_RAWDATA + align, NO_SEG, NO_SEG);
301 }
302 offset += e->stringlen + align;
303 }
304 }
305 if (t > 0 && t == instruction->times - 1) {
306 /*
307 * Dummy call to list->output to give the offset to the
308 * listing module.
309 */
310 list->output(offset, NULL, OUT_RAWDATA);
311 list->uplevel(LIST_TIMES);
312 }
313 }
314 if (instruction->times > 1)
315 list->downlevel(LIST_TIMES);
316 return offset - start;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000317 }
318
H. Peter Anvine2c80182005-01-15 22:15:51 +0000319 if (instruction->opcode == I_INCBIN) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000320 static char fname[FILENAME_MAX];
H. Peter Anvine2c80182005-01-15 22:15:51 +0000321 FILE *fp;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000322 int32_t len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000323 char *prefix = "", *combine;
324 char **pPrevPath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000325
H. Peter Anvine2c80182005-01-15 22:15:51 +0000326 len = FILENAME_MAX - 1;
327 if (len > instruction->eops->stringlen)
328 len = instruction->eops->stringlen;
329 strncpy(fname, instruction->eops->stringval, len);
330 fname[len] = '\0';
H. Peter Anvineba20a72002-04-30 20:53:55 +0000331
Keith Kaniosb7a89542007-04-12 02:40:54 +0000332 while (1) { /* added by alexfru: 'incbin' uses include paths */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000333 combine = nasm_malloc(strlen(prefix) + len + 1);
334 strcpy(combine, prefix);
335 strcat(combine, fname);
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000336
H. Peter Anvine2c80182005-01-15 22:15:51 +0000337 if ((fp = fopen(combine, "rb")) != NULL) {
338 nasm_free(combine);
339 break;
340 }
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000341
H. Peter Anvine2c80182005-01-15 22:15:51 +0000342 nasm_free(combine);
343 pPrevPath = pp_get_include_path_ptr(pPrevPath);
344 if (pPrevPath == NULL)
345 break;
346 prefix = *pPrevPath;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000347 }
348
349 if (fp == NULL)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000350 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
351 fname);
352 else if (fseek(fp, 0L, SEEK_END) < 0)
353 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
354 fname);
355 else {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000356 static char buf[2048];
Keith Kaniosb7a89542007-04-12 02:40:54 +0000357 int32_t t = instruction->times;
358 int32_t base = 0;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000359
H. Peter Anvine2c80182005-01-15 22:15:51 +0000360 len = ftell(fp);
361 if (instruction->eops->next) {
362 base = instruction->eops->next->offset;
363 len -= base;
364 if (instruction->eops->next->next &&
365 len > instruction->eops->next->next->offset)
366 len = instruction->eops->next->next->offset;
367 }
368 /*
369 * Dummy call to list->output to give the offset to the
370 * listing module.
371 */
372 list->output(offset, NULL, OUT_RAWDATA);
373 list->uplevel(LIST_INCBIN);
374 while (t--) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000375 int32_t l;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000376
H. Peter Anvine2c80182005-01-15 22:15:51 +0000377 fseek(fp, base, SEEK_SET);
378 l = len;
379 while (l > 0) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000380 int32_t m =
H. Peter Anvine2c80182005-01-15 22:15:51 +0000381 fread(buf, 1, (l > sizeof(buf) ? sizeof(buf) : l),
382 fp);
383 if (!m) {
384 /*
385 * This shouldn't happen unless the file
386 * actually changes while we are reading
387 * it.
388 */
389 error(ERR_NONFATAL,
390 "`incbin': unexpected EOF while"
391 " reading file `%s'", fname);
392 t = 0; /* Try to exit cleanly */
393 break;
394 }
395 out(offset, segment, buf, OUT_RAWDATA + m,
396 NO_SEG, NO_SEG);
397 l -= m;
398 }
399 }
400 list->downlevel(LIST_INCBIN);
401 if (instruction->times > 1) {
402 /*
403 * Dummy call to list->output to give the offset to the
404 * listing module.
405 */
406 list->output(offset, NULL, OUT_RAWDATA);
407 list->uplevel(LIST_TIMES);
408 list->downlevel(LIST_TIMES);
409 }
410 fclose(fp);
411 return instruction->times * len;
412 }
413 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000414 }
415
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700416 /* Check to see if we need an address-size prefix */
417 add_asp(instruction, bits);
418
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000419 size_prob = FALSE;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000420
421 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++){
422 int m = matches(temp, instruction, bits);
423
H. Peter Anvine2c80182005-01-15 22:15:51 +0000424 if (m == 99)
425 m += jmp_match(segment, offset, bits, instruction, temp->code);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000426
H. Peter Anvine2c80182005-01-15 22:15:51 +0000427 if (m == 100) { /* matches! */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000428 const char *codes = temp->code;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000429 int32_t insn_size = calcsize(segment, offset, bits,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000430 instruction, codes);
431 itimes = instruction->times;
432 if (insn_size < 0) /* shouldn't be, on pass two */
433 error(ERR_PANIC, "errors made it through from pass one");
434 else
435 while (itimes--) {
436 for (j = 0; j < instruction->nprefix; j++) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000437 uint8_t c = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000438 switch (instruction->prefixes[j]) {
439 case P_LOCK:
440 c = 0xF0;
441 break;
442 case P_REPNE:
443 case P_REPNZ:
444 c = 0xF2;
445 break;
446 case P_REPE:
447 case P_REPZ:
448 case P_REP:
449 c = 0xF3;
450 break;
451 case R_CS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000452 if (bits == 64) {
453 error(ERR_WARNING,
454 "cs segment base ignored in 64-bit mode");
455 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000456 c = 0x2E;
457 break;
458 case R_DS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000459 if (bits == 64) {
460 error(ERR_WARNING,
461 "ds segment base ignored in 64-bit mode");
462 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000463 c = 0x3E;
464 break;
465 case R_ES:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000466 if (bits == 64) {
467 error(ERR_WARNING,
468 "es segment base ignored in 64-bit mode");
469 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000470 c = 0x26;
471 break;
472 case R_FS:
473 c = 0x64;
474 break;
475 case R_GS:
476 c = 0x65;
477 break;
478 case R_SS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000479 if (bits == 64) {
480 error(ERR_WARNING,
481 "ss segment base ignored in 64-bit mode");
482 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000483 c = 0x36;
484 break;
485 case R_SEGR6:
486 case R_SEGR7:
487 error(ERR_NONFATAL,
488 "segr6 and segr7 cannot be used as prefixes");
489 break;
490 case P_A16:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000491 if (bits == 64) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000492 error(ERR_NONFATAL,
493 "16-bit addressing is not supported "
494 "in 64-bit mode");
Keith Kaniosb7a89542007-04-12 02:40:54 +0000495 break;
496 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000497 if (bits != 16)
498 c = 0x67;
499 break;
500 case P_A32:
501 if (bits != 32)
502 c = 0x67;
503 break;
504 case P_O16:
505 if (bits != 16)
506 c = 0x66;
507 break;
508 case P_O32:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000509 if (bits == 16)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000510 c = 0x66;
511 break;
512 default:
513 error(ERR_PANIC, "invalid instruction prefix");
514 }
515 if (c != 0) {
516 out(offset, segment, &c, OUT_RAWDATA + 1,
517 NO_SEG, NO_SEG);
518 offset++;
519 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000520 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000521 insn_end = offset + insn_size;
522 gencode(segment, offset, bits, instruction, codes,
523 insn_end);
524 offset += insn_size;
525 if (itimes > 0 && itimes == instruction->times - 1) {
526 /*
527 * Dummy call to list->output to give the offset to the
528 * listing module.
529 */
530 list->output(offset, NULL, OUT_RAWDATA);
531 list->uplevel(LIST_TIMES);
532 }
533 }
534 if (instruction->times > 1)
535 list->downlevel(LIST_TIMES);
536 return offset - start;
537 } else if (m > 0 && m > size_prob) {
538 size_prob = m;
539 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000540// temp++;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000541 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000542
H. Peter Anvine2c80182005-01-15 22:15:51 +0000543 if (temp->opcode == -1) { /* didn't match any instruction */
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000544 switch (size_prob) {
545 case 1:
546 error(ERR_NONFATAL, "operation size not specified");
547 break;
548 case 2:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000549 error(ERR_NONFATAL, "mismatch in operand sizes");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000550 break;
551 case 3:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000552 error(ERR_NONFATAL, "no instruction for this cpu level");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000553 break;
554 case 4:
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000555 error(ERR_NONFATAL, "instruction not supported in 64-bit mode");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000556 break;
557 default:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000558 error(ERR_NONFATAL,
559 "invalid combination of opcode and operands");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000560 break;
561 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000562 }
563 return 0;
564}
565
Keith Kaniosb7a89542007-04-12 02:40:54 +0000566int32_t insn_size(int32_t segment, int32_t offset, int bits, uint32_t cp,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000567 insn * instruction, efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000568{
H. Peter Anvin3360d792007-09-11 04:16:57 +0000569 const struct itemplate *temp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000570
H. Peter Anvine2c80182005-01-15 22:15:51 +0000571 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000572 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000573
574 if (instruction->opcode == -1)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000575 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000576
H. Peter Anvincfbe7c32007-09-18 17:49:09 -0700577 if (instruction->opcode == I_DB || instruction->opcode == I_DW ||
578 instruction->opcode == I_DD || instruction->opcode == I_DQ ||
579 instruction->opcode == I_DT || instruction->opcode == I_DO) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000580 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000581 int32_t isize, osize, wsize = 0; /* placate gcc */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000582
H. Peter Anvine2c80182005-01-15 22:15:51 +0000583 isize = 0;
584 switch (instruction->opcode) {
585 case I_DB:
586 wsize = 1;
587 break;
588 case I_DW:
589 wsize = 2;
590 break;
591 case I_DD:
592 wsize = 4;
593 break;
594 case I_DQ:
595 wsize = 8;
596 break;
597 case I_DT:
598 wsize = 10;
599 break;
H. Peter Anvincfbe7c32007-09-18 17:49:09 -0700600 case I_DO:
601 wsize = 16;
602 break;
H. Peter Anvin16b0a332007-09-12 20:27:41 -0700603 default:
604 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000605 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000606
H. Peter Anvine2c80182005-01-15 22:15:51 +0000607 for (e = instruction->eops; e; e = e->next) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000608 int32_t align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000609
H. Peter Anvine2c80182005-01-15 22:15:51 +0000610 osize = 0;
611 if (e->type == EOT_DB_NUMBER)
612 osize = 1;
613 else if (e->type == EOT_DB_STRING)
614 osize = e->stringlen;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000615
H. Peter Anvine2c80182005-01-15 22:15:51 +0000616 align = (-osize) % wsize;
617 if (align < 0)
618 align += wsize;
619 isize += osize + align;
620 }
621 return isize * instruction->times;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000622 }
623
H. Peter Anvine2c80182005-01-15 22:15:51 +0000624 if (instruction->opcode == I_INCBIN) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000625 char fname[FILENAME_MAX];
H. Peter Anvine2c80182005-01-15 22:15:51 +0000626 FILE *fp;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000627 int32_t len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000628 char *prefix = "", *combine;
629 char **pPrevPath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000630
H. Peter Anvine2c80182005-01-15 22:15:51 +0000631 len = FILENAME_MAX - 1;
632 if (len > instruction->eops->stringlen)
633 len = instruction->eops->stringlen;
634 strncpy(fname, instruction->eops->stringval, len);
635 fname[len] = '\0';
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000636
H. Peter Anvine2c80182005-01-15 22:15:51 +0000637 while (1) { /* added by alexfru: 'incbin' uses include paths */
638 combine = nasm_malloc(strlen(prefix) + len + 1);
639 strcpy(combine, prefix);
640 strcat(combine, fname);
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000641
H. Peter Anvine2c80182005-01-15 22:15:51 +0000642 if ((fp = fopen(combine, "rb")) != NULL) {
643 nasm_free(combine);
644 break;
645 }
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000646
H. Peter Anvine2c80182005-01-15 22:15:51 +0000647 nasm_free(combine);
648 pPrevPath = pp_get_include_path_ptr(pPrevPath);
649 if (pPrevPath == NULL)
650 break;
651 prefix = *pPrevPath;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000652 }
653
654 if (fp == NULL)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000655 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
656 fname);
657 else if (fseek(fp, 0L, SEEK_END) < 0)
658 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
659 fname);
660 else {
661 len = ftell(fp);
662 fclose(fp);
663 if (instruction->eops->next) {
664 len -= instruction->eops->next->offset;
665 if (instruction->eops->next->next &&
666 len > instruction->eops->next->next->offset) {
667 len = instruction->eops->next->next->offset;
668 }
669 }
670 return instruction->times * len;
671 }
672 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000673 }
674
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700675 /* Check to see if we need an address-size prefix */
676 add_asp(instruction, bits);
677
Keith Kaniosb7a89542007-04-12 02:40:54 +0000678 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++) {
679 int m = matches(temp, instruction, bits);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000680 if (m == 99)
681 m += jmp_match(segment, offset, bits, instruction, temp->code);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000682
H. Peter Anvine2c80182005-01-15 22:15:51 +0000683 if (m == 100) {
684 /* we've matched an instruction. */
Keith Kaniosb7a89542007-04-12 02:40:54 +0000685 int32_t isize;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000686 const char *codes = temp->code;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000687 int j;
688
689 isize = calcsize(segment, offset, bits, instruction, codes);
690 if (isize < 0)
691 return -1;
692 for (j = 0; j < instruction->nprefix; j++) {
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700693 switch (instruction->prefixes[j]) {
694 case P_A16:
695 if (bits != 16)
696 isize++;
697 break;
698 case P_A32:
699 if (bits != 32)
700 isize++;
701 break;
702 case P_O16:
703 if (bits != 16)
704 isize++;
705 break;
706 case P_O32:
707 if (bits == 16)
708 isize++;
709 break;
710 default:
711 isize++;
712 break;
713 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000714 }
715 return isize * instruction->times;
716 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000717 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000718 return -1; /* didn't match any instruction */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000719}
720
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000721/* check that opn[op] is a signed byte of size 16 or 32,
722 and return the signed value*/
H. Peter Anvine2c80182005-01-15 22:15:51 +0000723static int is_sbyte(insn * ins, int op, int size)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000724{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000725 int32_t v;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000726 int ret;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000727
728 ret = !(ins->forw_ref && ins->oprs[op].opflags) && /* dead in the water on forward reference or External */
729 optimizing >= 0 &&
730 !(ins->oprs[op].type & STRICT) &&
731 ins->oprs[op].wrt == NO_SEG && ins->oprs[op].segment == NO_SEG;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000732
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000733 v = ins->oprs[op].offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000734 if (size == 16)
Keith Kaniosb7a89542007-04-12 02:40:54 +0000735 v = (int16_t)v; /* sign extend if 16 bits */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000736
737 return ret && v >= -128L && v <= 127L;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000738}
739
Keith Kaniosb7a89542007-04-12 02:40:54 +0000740static int32_t calcsize(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000741 insn * ins, const char *codes)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000742{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000743 int32_t length = 0;
744 uint8_t c;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000745 int rex_mask = ~0;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000746 ins->rex = 0; /* Ensure REX is reset */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000747
H. Peter Anvine2c80182005-01-15 22:15:51 +0000748 (void)segment; /* Don't warn that this parameter is unused */
749 (void)offset; /* Don't warn that this parameter is unused */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000750
H. Peter Anvine2c80182005-01-15 22:15:51 +0000751 while (*codes)
752 switch (c = *codes++) {
753 case 01:
754 case 02:
755 case 03:
756 codes += c, length += c;
757 break;
758 case 04:
759 case 05:
760 case 06:
761 case 07:
762 length++;
763 break;
764 case 010:
765 case 011:
766 case 012:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700767 case 013:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000768 ins->rex |=
769 op_rexflags(&ins->oprs[c - 010], REX_B|REX_H|REX_P|REX_W);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000770 codes++, length++;
771 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000772 case 014:
773 case 015:
774 case 016:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700775 case 017:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000776 length++;
777 break;
778 case 020:
779 case 021:
780 case 022:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700781 case 023:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000782 length++;
783 break;
784 case 024:
785 case 025:
786 case 026:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700787 case 027:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000788 length++;
789 break;
790 case 030:
791 case 031:
792 case 032:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700793 case 033:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000794 length += 2;
795 break;
796 case 034:
797 case 035:
798 case 036:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700799 case 037:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000800 if (ins->oprs[c - 034].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000801 length += (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
802 else
803 length += (bits == 16) ? 2 : 4;
804 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000805 case 040:
806 case 041:
807 case 042:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700808 case 043:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000809 length += 4;
810 break;
811 case 044:
812 case 045:
813 case 046:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700814 case 047:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000815 length += ((ins->oprs[c - 044].addr_size ?
Keith Kaniosb7a89542007-04-12 02:40:54 +0000816 ins->oprs[c - 044].addr_size : bits) >> 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000817 break;
818 case 050:
819 case 051:
820 case 052:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700821 case 053:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000822 length++;
823 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000824 case 054:
825 case 055:
826 case 056:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700827 case 057:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000828 length += 8; /* MOV reg64/imm */
829 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000830 case 060:
831 case 061:
832 case 062:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700833 case 063:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000834 length += 2;
835 break;
836 case 064:
837 case 065:
838 case 066:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700839 case 067:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000840 if (ins->oprs[c - 064].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000841 length += (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
842 else
843 length += (bits == 16) ? 2 : 4;
844 break;
845 case 070:
846 case 071:
847 case 072:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700848 case 073:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000849 length += 4;
850 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700851 case 074:
852 case 075:
853 case 076:
854 case 077:
855 length += 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000856 break;
857 case 0140:
858 case 0141:
859 case 0142:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700860 case 0143:
861 length += is_sbyte(ins, c - 0140, 16) ? 1 : 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000862 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000863 case 0144:
864 case 0145:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700865 case 0146:
866 case 0147:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000867 codes += 2;
868 length++;
869 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700870 case 0150:
871 case 0151:
872 case 0152:
873 case 0153:
874 length += is_sbyte(ins, c - 0150, 32) ? 1 : 4;
875 break;
876 case 0154:
877 case 0155:
878 case 0156:
879 case 0157:
880 codes += 2;
881 length++;
882 break;
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700883 case 0160:
884 case 0161:
885 case 0162:
886 case 0163:
887 length++;
888 ins->rex |= REX_D;
H. Peter Anvincf5180a2007-09-17 17:25:27 -0700889 ins->drexdst = regval(&ins->oprs[c & 3]);
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700890 break;
891 case 0164:
892 case 0165:
893 case 0166:
894 case 0167:
895 length++;
896 ins->rex |= REX_D|REX_OC;
H. Peter Anvincf5180a2007-09-17 17:25:27 -0700897 ins->drexdst = regval(&ins->oprs[c & 3]);
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700898 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700899 case 0170:
900 length++;
901 break;
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700902 case 0171:
903 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000904 case 0300:
905 case 0301:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000906 case 0302:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700907 case 0303:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000908 break;
909 case 0310:
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700910 if (bits == 64)
911 return -1;
912 length += (bits != 16) && !has_prefix(ins,P_A16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000913 break;
914 case 0311:
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700915 length += (bits != 32) && !has_prefix(ins,P_A32);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000916 break;
917 case 0312:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000918 break;
919 case 0313:
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700920 if (bits != 64 || has_prefix(ins,P_A16) || has_prefix(ins,P_A32))
921 return -1;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000922 break;
923 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000924 length += (bits != 16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000925 break;
926 case 0321:
927 length += (bits == 16);
928 break;
929 case 0322:
930 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000931 case 0323:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000932 rex_mask &= ~REX_W;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000933 break;
934 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000935 ins->rex |= REX_W;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000936 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000937 case 0330:
938 codes++, length++;
939 break;
940 case 0331:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000941 break;
H. Peter Anvincb9b6902007-09-12 21:58:51 -0700942 case 0332:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000943 case 0333:
944 length++;
945 break;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000946 case 0334:
947 assert_no_prefix(ins, P_LOCK);
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000948 ins->rex |= REX_L;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000949 break;
H. Peter Anvincb9b6902007-09-12 21:58:51 -0700950 case 0335:
951 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000952 case 0340:
953 case 0341:
954 case 0342:
955 if (ins->oprs[0].segment != NO_SEG)
956 errfunc(ERR_NONFATAL, "attempt to reserve non-constant"
957 " quantity of BSS space");
958 else
959 length += ins->oprs[0].offset << (c - 0340);
960 break;
H. Peter Anvin62cb6062007-09-11 22:44:03 +0000961 case 0364:
962 case 0365:
963 break;
Keith Kanios48af1772007-08-17 07:37:52 +0000964 case 0366:
H. Peter Anvin62cb6062007-09-11 22:44:03 +0000965 case 0367:
966 length++;
967 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000968 case 0370:
969 case 0371:
970 case 0372:
971 break;
972 case 0373:
973 length++;
974 break;
975 default: /* can't do it by 'case' statements */
976 if (c >= 0100 && c <= 0277) { /* it's an EA */
977 ea ea_data;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000978 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000979 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000980 ea_data.rex = 0; /* Ensure ea.REX is initially 0 */
981
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000982 if (c <= 0177) {
983 /* pick rfield from operand b */
984 rflags = regflag(&ins->oprs[c & 7]);
985 rfield = regvals[ins->oprs[c & 7].basereg];
986 } else {
987 rflags = 0;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000988 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000989 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000990
H. Peter Anvine2c80182005-01-15 22:15:51 +0000991 if (!process_ea
Keith Kaniosb7a89542007-04-12 02:40:54 +0000992 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000993 rfield, rflags, ins->forw_ref)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000994 errfunc(ERR_NONFATAL, "invalid effective address");
995 return -1;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000996 } else {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000997 ins->rex |= ea_data.rex;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000998 length += ea_data.size;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000999 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001000 } else
1001 errfunc(ERR_PANIC, "internal instruction table corrupt"
1002 ": instruction code 0x%02X given", c);
1003 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001004
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001005 ins->rex &= rex_mask;
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001006
1007 if (ins->rex & REX_D) {
1008 if (ins->rex & REX_H) {
1009 errfunc(ERR_NONFATAL, "cannot use high register in drex instruction");
1010 return -1;
1011 }
H. Peter Anvincf5180a2007-09-17 17:25:27 -07001012 if (bits != 64 && ((ins->rex & (REX_W|REX_X|REX_B)) ||
1013 ins->drexdst > 7)) {
1014 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
1015 return -1;
1016 }
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001017 length++;
1018 } else if (ins->rex & REX_REAL) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001019 if (ins->rex & REX_H) {
1020 errfunc(ERR_NONFATAL, "cannot use high register in rex instruction");
1021 return -1;
1022 } else if (bits == 64 ||
1023 ((ins->rex & REX_L) &&
1024 !(ins->rex & (REX_P|REX_W|REX_X|REX_B)) &&
1025 cpu >= IF_X86_64)) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001026 length++;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +00001027 } else {
H. Peter Anvincf5180a2007-09-17 17:25:27 -07001028 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
1029 return -1;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +00001030 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001031 }
1032
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001033 return length;
1034}
Keith Kaniosb7a89542007-04-12 02:40:54 +00001035
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001036#define EMIT_REX() \
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001037 if (!(ins->rex & REX_D) && (ins->rex & REX_REAL) && (bits == 64)) { \
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001038 ins->rex = (ins->rex & REX_REAL)|REX_P; \
1039 out(offset, segment, &ins->rex, OUT_RAWDATA+1, NO_SEG, NO_SEG); \
1040 ins->rex = 0; \
1041 offset += 1; \
1042 }
1043
Keith Kaniosb7a89542007-04-12 02:40:54 +00001044static void gencode(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001045 insn * ins, const char *codes, int32_t insn_end)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001046{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001047 static char condval[] = { /* conditional opcodes */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001048 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
1049 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
1050 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001051 };
Keith Kaniosb7a89542007-04-12 02:40:54 +00001052 uint8_t c;
1053 uint8_t bytes[4];
1054 int32_t size;
1055 int64_t data;
1056
H. Peter Anvineba20a72002-04-30 20:53:55 +00001057 while (*codes)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001058 switch (c = *codes++) {
1059 case 01:
1060 case 02:
1061 case 03:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001062 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001063 out(offset, segment, codes, OUT_RAWDATA + c, NO_SEG, NO_SEG);
1064 codes += c;
1065 offset += c;
1066 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001067
H. Peter Anvine2c80182005-01-15 22:15:51 +00001068 case 04:
1069 case 06:
1070 switch (ins->oprs[0].basereg) {
1071 case R_CS:
1072 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0);
1073 break;
1074 case R_DS:
1075 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0);
1076 break;
1077 case R_ES:
1078 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0);
1079 break;
1080 case R_SS:
1081 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0);
1082 break;
1083 default:
1084 errfunc(ERR_PANIC,
1085 "bizarre 8086 segment register received");
1086 }
1087 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1088 offset++;
1089 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001090
H. Peter Anvine2c80182005-01-15 22:15:51 +00001091 case 05:
1092 case 07:
1093 switch (ins->oprs[0].basereg) {
1094 case R_FS:
1095 bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0);
1096 break;
1097 case R_GS:
1098 bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0);
1099 break;
1100 default:
1101 errfunc(ERR_PANIC,
1102 "bizarre 386 segment register received");
1103 }
1104 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1105 offset++;
1106 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001107
H. Peter Anvine2c80182005-01-15 22:15:51 +00001108 case 010:
1109 case 011:
1110 case 012:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001111 case 013:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001112 EMIT_REX();
Keith Kaniosb7a89542007-04-12 02:40:54 +00001113 bytes[0] = *codes++ + ((regval(&ins->oprs[c - 010])) & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001114 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1115 offset += 1;
1116 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001117
H. Peter Anvine2c80182005-01-15 22:15:51 +00001118 case 014:
1119 case 015:
1120 case 016:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001121 case 017:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001122 if (ins->oprs[c - 014].offset < -128
1123 || ins->oprs[c - 014].offset > 127) {
1124 errfunc(ERR_WARNING, "signed byte value exceeds bounds");
1125 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001126
H. Peter Anvine2c80182005-01-15 22:15:51 +00001127 if (ins->oprs[c - 014].segment != NO_SEG) {
1128 data = ins->oprs[c - 014].offset;
1129 out(offset, segment, &data, OUT_ADDRESS + 1,
1130 ins->oprs[c - 014].segment, ins->oprs[c - 014].wrt);
1131 } else {
1132 bytes[0] = ins->oprs[c - 014].offset;
1133 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1134 NO_SEG);
1135 }
1136 offset += 1;
1137 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001138
H. Peter Anvine2c80182005-01-15 22:15:51 +00001139 case 020:
1140 case 021:
1141 case 022:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001142 case 023:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001143 if (ins->oprs[c - 020].offset < -256
1144 || ins->oprs[c - 020].offset > 255) {
1145 errfunc(ERR_WARNING, "byte value exceeds bounds");
1146 }
1147 if (ins->oprs[c - 020].segment != NO_SEG) {
1148 data = ins->oprs[c - 020].offset;
1149 out(offset, segment, &data, OUT_ADDRESS + 1,
1150 ins->oprs[c - 020].segment, ins->oprs[c - 020].wrt);
1151 } else {
1152 bytes[0] = ins->oprs[c - 020].offset;
1153 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1154 NO_SEG);
1155 }
1156 offset += 1;
1157 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001158
H. Peter Anvine2c80182005-01-15 22:15:51 +00001159 case 024:
1160 case 025:
1161 case 026:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001162 case 027:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001163 if (ins->oprs[c - 024].offset < 0
1164 || ins->oprs[c - 024].offset > 255)
1165 errfunc(ERR_WARNING, "unsigned byte value exceeds bounds");
1166 if (ins->oprs[c - 024].segment != NO_SEG) {
1167 data = ins->oprs[c - 024].offset;
1168 out(offset, segment, &data, OUT_ADDRESS + 1,
1169 ins->oprs[c - 024].segment, ins->oprs[c - 024].wrt);
1170 } else {
1171 bytes[0] = ins->oprs[c - 024].offset;
1172 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1173 NO_SEG);
1174 }
1175 offset += 1;
1176 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001177
H. Peter Anvine2c80182005-01-15 22:15:51 +00001178 case 030:
1179 case 031:
1180 case 032:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001181 case 033:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001182 if (ins->oprs[c - 030].segment == NO_SEG &&
1183 ins->oprs[c - 030].wrt == NO_SEG &&
1184 (ins->oprs[c - 030].offset < -65536L ||
1185 ins->oprs[c - 030].offset > 65535L)) {
1186 errfunc(ERR_WARNING, "word value exceeds bounds");
1187 }
1188 data = ins->oprs[c - 030].offset;
1189 out(offset, segment, &data, OUT_ADDRESS + 2,
1190 ins->oprs[c - 030].segment, ins->oprs[c - 030].wrt);
1191 offset += 2;
1192 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001193
H. Peter Anvine2c80182005-01-15 22:15:51 +00001194 case 034:
1195 case 035:
1196 case 036:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001197 case 037:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001198 if (ins->oprs[c - 034].type & (BITS16 | BITS32))
1199 size = (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
1200 else
1201 size = (bits == 16) ? 2 : 4;
1202 data = ins->oprs[c - 034].offset;
1203 if (size == 2 && (data < -65536L || data > 65535L))
1204 errfunc(ERR_WARNING, "word value exceeds bounds");
1205 out(offset, segment, &data, OUT_ADDRESS + size,
1206 ins->oprs[c - 034].segment, ins->oprs[c - 034].wrt);
1207 offset += size;
1208 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001209
H. Peter Anvine2c80182005-01-15 22:15:51 +00001210 case 040:
1211 case 041:
1212 case 042:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001213 case 043:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001214 data = ins->oprs[c - 040].offset;
1215 out(offset, segment, &data, OUT_ADDRESS + 4,
1216 ins->oprs[c - 040].segment, ins->oprs[c - 040].wrt);
1217 offset += 4;
1218 break;
H. Peter Anvin3ba46772002-05-27 23:19:35 +00001219
H. Peter Anvine2c80182005-01-15 22:15:51 +00001220 case 044:
1221 case 045:
1222 case 046:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001223 case 047:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001224 data = ins->oprs[c - 044].offset;
1225 size = ((ins->oprs[c - 044].addr_size ?
Keith Kaniosb7a89542007-04-12 02:40:54 +00001226 ins->oprs[c - 044].addr_size : bits) >> 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001227 if (size == 2 && (data < -65536L || data > 65535L))
1228 errfunc(ERR_WARNING, "word value exceeds bounds");
1229 out(offset, segment, &data, OUT_ADDRESS + size,
1230 ins->oprs[c - 044].segment, ins->oprs[c - 044].wrt);
1231 offset += size;
1232 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001233
H. Peter Anvine2c80182005-01-15 22:15:51 +00001234 case 050:
1235 case 051:
1236 case 052:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001237 case 053:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001238 if (ins->oprs[c - 050].segment != segment)
1239 errfunc(ERR_NONFATAL,
1240 "short relative jump outside segment");
1241 data = ins->oprs[c - 050].offset - insn_end;
1242 if (data > 127 || data < -128)
1243 errfunc(ERR_NONFATAL, "short jump is out of range");
1244 bytes[0] = data;
1245 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1246 offset += 1;
1247 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001248
1249 case 054:
1250 case 055:
1251 case 056:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001252 case 057:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001253 data = (int64_t)ins->oprs[c - 054].offset;
1254 out(offset, segment, &data, OUT_ADDRESS + 8,
1255 ins->oprs[c - 054].segment, ins->oprs[c - 054].wrt);
1256 offset += 8;
1257 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001258
H. Peter Anvine2c80182005-01-15 22:15:51 +00001259 case 060:
1260 case 061:
1261 case 062:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001262 case 063:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001263 if (ins->oprs[c - 060].segment != segment) {
1264 data = ins->oprs[c - 060].offset;
1265 out(offset, segment, &data,
1266 OUT_REL2ADR + insn_end - offset,
1267 ins->oprs[c - 060].segment, ins->oprs[c - 060].wrt);
1268 } else {
1269 data = ins->oprs[c - 060].offset - insn_end;
1270 out(offset, segment, &data,
1271 OUT_ADDRESS + 2, NO_SEG, NO_SEG);
1272 }
1273 offset += 2;
1274 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001275
H. Peter Anvine2c80182005-01-15 22:15:51 +00001276 case 064:
1277 case 065:
1278 case 066:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001279 case 067:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001280 if (ins->oprs[c - 064].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001281 size = (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
1282 else
1283 size = (bits == 16) ? 2 : 4;
1284 if (ins->oprs[c - 064].segment != segment) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001285 int32_t reltype = (size == 2 ? OUT_REL2ADR : OUT_REL4ADR);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001286 data = ins->oprs[c - 064].offset;
1287 out(offset, segment, &data, reltype + insn_end - offset,
1288 ins->oprs[c - 064].segment, ins->oprs[c - 064].wrt);
1289 } else {
1290 data = ins->oprs[c - 064].offset - insn_end;
1291 out(offset, segment, &data,
1292 OUT_ADDRESS + size, NO_SEG, NO_SEG);
1293 }
1294 offset += size;
1295 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001296
H. Peter Anvine2c80182005-01-15 22:15:51 +00001297 case 070:
1298 case 071:
1299 case 072:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001300 case 073:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001301 if (ins->oprs[c - 070].segment != segment) {
1302 data = ins->oprs[c - 070].offset;
1303 out(offset, segment, &data,
1304 OUT_REL4ADR + insn_end - offset,
1305 ins->oprs[c - 070].segment, ins->oprs[c - 070].wrt);
1306 } else {
1307 data = ins->oprs[c - 070].offset - insn_end;
1308 out(offset, segment, &data,
1309 OUT_ADDRESS + 4, NO_SEG, NO_SEG);
1310 }
1311 offset += 4;
1312 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001313
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001314 case 074:
1315 case 075:
1316 case 076:
1317 case 077:
1318 if (ins->oprs[c - 074].segment == NO_SEG)
1319 errfunc(ERR_NONFATAL, "value referenced by FAR is not"
1320 " relocatable");
1321 data = 0L;
1322 out(offset, segment, &data, OUT_ADDRESS + 2,
1323 outfmt->segbase(1 + ins->oprs[c - 074].segment),
1324 ins->oprs[c - 074].wrt);
1325 offset += 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001326 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001327
H. Peter Anvine2c80182005-01-15 22:15:51 +00001328 case 0140:
1329 case 0141:
1330 case 0142:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001331 case 0143:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001332 data = ins->oprs[c - 0140].offset;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001333 if (is_sbyte(ins, c - 0140, 16)) {
1334 bytes[0] = data;
1335 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1336 NO_SEG);
1337 offset++;
1338 } else {
1339 if (ins->oprs[c - 0140].segment == NO_SEG &&
1340 ins->oprs[c - 0140].wrt == NO_SEG &&
1341 (data < -65536L || data > 65535L)) {
1342 errfunc(ERR_WARNING, "word value exceeds bounds");
1343 }
1344 out(offset, segment, &data, OUT_ADDRESS + 2,
H. Peter Anvin8f94f982007-09-17 16:31:33 -07001345 ins->oprs[c - 0140].segment, ins->oprs[c - 0140].wrt);
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001346 offset += 2;
1347 }
1348 break;
1349
1350 case 0144:
1351 case 0145:
1352 case 0146:
1353 case 0147:
1354 EMIT_REX();
1355 codes++;
1356 bytes[0] = *codes++;
1357 if (is_sbyte(ins, c - 0144, 16))
1358 bytes[0] |= 2; /* s-bit */
1359 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1360 offset++;
1361 break;
1362
1363 case 0150:
1364 case 0151:
1365 case 0152:
1366 case 0153:
1367 data = ins->oprs[c - 0150].offset;
1368 if (is_sbyte(ins, c - 0150, 32)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001369 bytes[0] = data;
1370 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1371 NO_SEG);
1372 offset++;
1373 } else {
1374 out(offset, segment, &data, OUT_ADDRESS + 4,
H. Peter Anvin8f94f982007-09-17 16:31:33 -07001375 ins->oprs[c - 0150].segment, ins->oprs[c - 0150].wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001376 offset += 4;
1377 }
1378 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001379
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001380 case 0154:
1381 case 0155:
1382 case 0156:
1383 case 0157:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001384 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001385 codes++;
1386 bytes[0] = *codes++;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001387 if (is_sbyte(ins, c - 0154, 32))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001388 bytes[0] |= 2; /* s-bit */
1389 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1390 offset++;
1391 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001392
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001393 case 0160:
1394 case 0161:
1395 case 0162:
1396 case 0163:
1397 case 0164:
1398 case 0165:
1399 case 0166:
1400 case 0167:
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001401 break;
1402
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001403 case 0170:
1404 bytes[0] = 0;
1405 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1406 offset += 1;
1407 break;
1408
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001409 case 0171:
1410 bytes[0] =
1411 (ins->drexdst << 4) |
1412 (ins->rex & REX_OC ? 0x08 : 0) |
1413 (ins->rex & (REX_R|REX_X|REX_B));
1414 ins->rex = 0;
1415 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1416 offset++;
1417 break;
1418
H. Peter Anvine2c80182005-01-15 22:15:51 +00001419 case 0300:
1420 case 0301:
1421 case 0302:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001422 case 0303:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001423 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001424
H. Peter Anvine2c80182005-01-15 22:15:51 +00001425 case 0310:
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07001426 if (bits == 32 && !has_prefix(ins,P_A16)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001427 *bytes = 0x67;
1428 out(offset, segment, bytes,
1429 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1430 offset += 1;
1431 } else
1432 offset += 0;
1433 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001434
H. Peter Anvine2c80182005-01-15 22:15:51 +00001435 case 0311:
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07001436 if (bits != 32 && !has_prefix(ins,P_A32)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001437 *bytes = 0x67;
1438 out(offset, segment, bytes,
1439 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1440 offset += 1;
1441 } else
1442 offset += 0;
1443 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001444
H. Peter Anvine2c80182005-01-15 22:15:51 +00001445 case 0312:
1446 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001447
Keith Kaniosb7a89542007-04-12 02:40:54 +00001448 case 0313:
1449 ins->rex = 0;
1450 break;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07001451
H. Peter Anvine2c80182005-01-15 22:15:51 +00001452 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001453 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001454 *bytes = 0x66;
1455 out(offset, segment, bytes,
1456 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1457 offset += 1;
1458 } else
1459 offset += 0;
1460 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001461
H. Peter Anvine2c80182005-01-15 22:15:51 +00001462 case 0321:
1463 if (bits == 16) {
1464 *bytes = 0x66;
1465 out(offset, segment, bytes,
1466 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1467 offset += 1;
1468 } else
1469 offset += 0;
1470 break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001471
H. Peter Anvine2c80182005-01-15 22:15:51 +00001472 case 0322:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001473 case 0323:
1474 break;
1475
1476 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001477 ins->rex |= REX_W;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001478 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001479
H. Peter Anvine2c80182005-01-15 22:15:51 +00001480 case 0330:
1481 *bytes = *codes++ ^ condval[ins->condition];
1482 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1483 offset += 1;
1484 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001485
H. Peter Anvine2c80182005-01-15 22:15:51 +00001486 case 0331:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001487 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001488
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001489 case 0332:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001490 case 0333:
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001491 *bytes = c - 0332 + 0xF2;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001492 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1493 offset += 1;
1494 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001495
Keith Kanios48af1772007-08-17 07:37:52 +00001496 case 0334:
1497 if (ins->rex & REX_R) {
1498 *bytes = 0xF0;
1499 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1500 offset += 1;
1501 }
1502 ins->rex &= ~(REX_L|REX_R);
1503 break;
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001504
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001505 case 0335:
1506 break;
1507
H. Peter Anvine2c80182005-01-15 22:15:51 +00001508 case 0340:
1509 case 0341:
1510 case 0342:
1511 if (ins->oprs[0].segment != NO_SEG)
1512 errfunc(ERR_PANIC, "non-constant BSS size in pass two");
1513 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001514 int32_t size = ins->oprs[0].offset << (c - 0340);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001515 if (size > 0)
1516 out(offset, segment, NULL,
1517 OUT_RESERVE + size, NO_SEG, NO_SEG);
1518 offset += size;
1519 }
1520 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001521
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001522 case 0364:
1523 case 0365:
1524 break;
1525
Keith Kanios48af1772007-08-17 07:37:52 +00001526 case 0366:
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001527 case 0367:
1528 *bytes = c - 0366 + 0x66;
Keith Kanios48af1772007-08-17 07:37:52 +00001529 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1530 offset += 1;
1531 break;
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001532
H. Peter Anvine2c80182005-01-15 22:15:51 +00001533 case 0370:
1534 case 0371:
1535 case 0372:
1536 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001537
H. Peter Anvine2c80182005-01-15 22:15:51 +00001538 case 0373:
1539 *bytes = bits == 16 ? 3 : 5;
1540 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1541 offset += 1;
1542 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001543
H. Peter Anvine2c80182005-01-15 22:15:51 +00001544 default: /* can't do it by 'case' statements */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001545 if (c >= 0100 && c <= 0277) { /* it's an EA */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001546 ea ea_data;
1547 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001548 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001549 uint8_t *p;
1550 int32_t s;
1551
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001552 if (c <= 0177) {
1553 /* pick rfield from operand b */
1554 rflags = regflag(&ins->oprs[c & 7]);
1555 rfield = regvals[ins->oprs[c & 7].basereg];
1556 } else {
1557 /* rfield is constant */
1558 rflags = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001559 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001560 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001561
1562 if (!process_ea
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001563 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
1564 rfield, rflags, ins->forw_ref)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001565 errfunc(ERR_NONFATAL, "invalid effective address");
1566 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001567
H. Peter Anvine2c80182005-01-15 22:15:51 +00001568 p = bytes;
1569 *p++ = ea_data.modrm;
1570 if (ea_data.sib_present)
1571 *p++ = ea_data.sib;
1572
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001573 /* DREX suffixes come between the SIB and the displacement */
1574 if (ins->rex & REX_D) {
1575 *p++ =
1576 (ins->drexdst << 4) |
1577 (ins->rex & REX_OC ? 0x08 : 0) |
1578 (ins->rex & (REX_R|REX_X|REX_B));
1579 ins->rex = 0;
1580 }
1581
H. Peter Anvine2c80182005-01-15 22:15:51 +00001582 s = p - bytes;
1583 out(offset, segment, bytes, OUT_RAWDATA + s,
1584 NO_SEG, NO_SEG);
1585
1586 switch (ea_data.bytes) {
1587 case 0:
1588 break;
1589 case 1:
1590 if (ins->oprs[(c >> 3) & 7].segment != NO_SEG) {
1591 data = ins->oprs[(c >> 3) & 7].offset;
1592 out(offset, segment, &data, OUT_ADDRESS + 1,
1593 ins->oprs[(c >> 3) & 7].segment,
1594 ins->oprs[(c >> 3) & 7].wrt);
1595 } else {
1596 *bytes = ins->oprs[(c >> 3) & 7].offset;
1597 out(offset, segment, bytes, OUT_RAWDATA + 1,
1598 NO_SEG, NO_SEG);
1599 }
1600 s++;
1601 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001602 case 8:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001603 case 2:
1604 case 4:
1605 data = ins->oprs[(c >> 3) & 7].offset;
H. Peter Anvind0b0d282007-09-28 17:17:20 -07001606 out(offset, segment, &data,
1607 (ea_data.rip ? OUT_REL4ADR : OUT_ADDRESS)
1608 + ea_data.bytes,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001609 ins->oprs[(c >> 3) & 7].segment,
1610 ins->oprs[(c >> 3) & 7].wrt);
1611 s += ea_data.bytes;
1612 break;
1613 }
1614 offset += s;
1615 } else
1616 errfunc(ERR_PANIC, "internal instruction table corrupt"
1617 ": instruction code 0x%02X given", c);
1618 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001619}
1620
H. Peter Anvin0ec60e62007-07-07 01:59:52 +00001621static int32_t regflag(const operand * o)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001622{
1623 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1624 errfunc(ERR_PANIC, "invalid operand passed to regflag()");
1625 }
1626 return reg_flags[o->basereg];
1627}
1628
H. Peter Anvin5b0e3ec2007-07-07 02:01:08 +00001629static int32_t regval(const operand * o)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001630{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001631 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1632 errfunc(ERR_PANIC, "invalid operand passed to regval()");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001633 }
H. Peter Anvin232badb2002-06-06 02:41:20 +00001634 return regvals[o->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001635}
1636
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001637static int op_rexflags(const operand * o, int mask)
1638{
1639 int32_t flags;
1640 int val;
1641
1642 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1643 errfunc(ERR_PANIC, "invalid operand passed to op_rexflags()");
1644 }
1645
1646 flags = reg_flags[o->basereg];
1647 val = regvals[o->basereg];
1648
1649 return rexflags(val, flags, mask);
1650}
1651
1652static int rexflags(int val, int32_t flags, int mask)
1653{
1654 int rex = 0;
1655
1656 if (val >= 8)
1657 rex |= REX_B|REX_X|REX_R;
1658 if (flags & BITS64)
1659 rex |= REX_W;
1660 if (!(REG_HIGH & ~flags)) /* AH, CH, DH, BH */
1661 rex |= REX_H;
1662 else if (!(REG8 & ~flags) && val >= 4) /* SPL, BPL, SIL, DIL */
1663 rex |= REX_P;
1664
1665 return rex & mask;
1666}
1667
H. Peter Anvin3360d792007-09-11 04:16:57 +00001668static int matches(const struct itemplate *itemp, insn * instruction, int bits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001669{
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001670 int i, size[MAX_OPERANDS], asize, oprs, ret;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001671
1672 ret = 100;
1673
1674 /*
1675 * Check the opcode
1676 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001677 if (itemp->opcode != instruction->opcode)
1678 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001679
1680 /*
1681 * Count the operands
1682 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001683 if (itemp->operands != instruction->operands)
1684 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001685
1686 /*
1687 * Check that no spurious colons or TOs are present
1688 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001689 for (i = 0; i < itemp->operands; i++)
1690 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON | TO))
1691 return 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001692
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001693 /*
1694 * Check that the operand flags all match up
1695 */
H. Peter Anvin16b0a332007-09-12 20:27:41 -07001696 for (i = 0; i < itemp->operands; i++) {
H. Peter Anvincf5180a2007-09-17 17:25:27 -07001697 if (itemp->opd[i] & SAME_AS) {
1698 int j = itemp->opd[i] & ~SAME_AS;
1699 if (instruction->oprs[i].type != instruction->oprs[j].type ||
1700 instruction->oprs[i].basereg != instruction->oprs[j].basereg)
1701 return 0;
H. Peter Anvin457afd42007-09-25 15:41:19 -07001702 } else if (itemp->opd[i] & ~instruction->oprs[i].type ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001703 ((itemp->opd[i] & SIZE_MASK) &&
1704 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK))) {
H. Peter Anvin5a640e12007-05-29 23:57:12 +00001705 if ((itemp->opd[i] & ~instruction->oprs[i].type & ~SIZE_MASK) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001706 (instruction->oprs[i].type & SIZE_MASK))
1707 return 0;
1708 else
H. Peter Anvine2c80182005-01-15 22:15:51 +00001709 return 1;
1710 }
H. Peter Anvin16b0a332007-09-12 20:27:41 -07001711 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001712
1713 /*
1714 * Check operand sizes
1715 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001716 if (itemp->flags & IF_ARMASK) {
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001717 memset(size, 0, sizeof size);
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001718
H. Peter Anvine2c80182005-01-15 22:15:51 +00001719 switch (itemp->flags & IF_ARMASK) {
1720 case IF_AR0:
1721 i = 0;
1722 break;
1723 case IF_AR1:
1724 i = 1;
1725 break;
1726 case IF_AR2:
1727 i = 2;
1728 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001729 case IF_AR3:
1730 i = 3;
1731 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001732 default:
1733 break; /* Shouldn't happen */
1734 }
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001735 switch (itemp->flags & IF_SMASK) {
1736 case IF_SB:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001737 size[i] = BITS8;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001738 break;
1739 case IF_SW:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001740 size[i] = BITS16;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001741 break;
1742 case IF_SD:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001743 size[i] = BITS32;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001744 break;
1745 case IF_SQ:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001746 size[i] = BITS64;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001747 break;
H. Peter Anvin41c9f6f2007-09-18 13:01:32 -07001748 case IF_SO:
1749 size[i] = BITS128;
1750 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001751 default:
1752 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001753 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001754 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001755 asize = 0;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001756 switch (itemp->flags & IF_SMASK) {
1757 case IF_SB:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001758 asize = BITS8;
1759 oprs = itemp->operands;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001760 break;
1761 case IF_SW:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001762 asize = BITS16;
1763 oprs = itemp->operands;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001764 break;
1765 case IF_SD:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001766 asize = BITS32;
1767 oprs = itemp->operands;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001768 break;
1769 case IF_SQ:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001770 asize = BITS64;
1771 oprs = itemp->operands;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001772 break;
H. Peter Anvin41c9f6f2007-09-18 13:01:32 -07001773 case IF_SO:
1774 asize = BITS128;
1775 oprs = itemp->operands;
1776 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001777 default:
1778 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001779 }
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001780 for (i = 0; i < MAX_OPERANDS; i++)
1781 size[i] = asize;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001782 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001783
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001784 if (itemp->flags & (IF_SM | IF_SM2)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001785 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
1786 asize = 0;
1787 for (i = 0; i < oprs; i++) {
1788 if ((asize = itemp->opd[i] & SIZE_MASK) != 0) {
1789 int j;
1790 for (j = 0; j < oprs; j++)
1791 size[j] = asize;
1792 break;
1793 }
1794 }
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001795 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001796 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001797 }
1798
Keith Kaniosb7a89542007-04-12 02:40:54 +00001799 for (i = 0; i < itemp->operands; i++) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001800 if (!(itemp->opd[i] & SIZE_MASK) &&
1801 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001802 return 2;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001803 }
1804
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001805 /*
1806 * Check template is okay at the set cpu level
1807 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001808 if (((itemp->flags & IF_PLEVEL) > cpu))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001809 return 3;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001810
1811 /*
1812 * Check if instruction is available in long mode
1813 */
1814 if ((itemp->flags & IF_NOLONG) && (bits == 64))
1815 return 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001816
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001817 /*
1818 * Check if special handling needed for Jumps
1819 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001820 if ((uint8_t)(itemp->code[0]) >= 0370)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001821 return 99;
1822
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001823 return ret;
1824}
1825
H. Peter Anvine2c80182005-01-15 22:15:51 +00001826static ea *process_ea(operand * input, ea * output, int addrbits,
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001827 int rfield, int32_t rflags, int forw_ref)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001828{
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001829 output->rip = FALSE;
1830
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001831 /* REX flags for the rfield operand */
1832 output->rex |= rexflags(rfield, rflags, REX_R|REX_P|REX_W|REX_H);
1833
Keith Kaniosb7a89542007-04-12 02:40:54 +00001834 if (!(REGISTER & ~input->type)) { /* register direct */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001835 int i;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001836 int32_t f;
1837
1838 if (input->basereg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001839 || input->basereg >= REG_ENUM_LIMIT)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001840 return NULL;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001841 f = regflag(input);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001842 i = regvals[input->basereg];
Keith Kaniosb7a89542007-04-12 02:40:54 +00001843
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001844 if (REG_EA & ~f)
1845 return NULL; /* Invalid EA register */
1846
1847 output->rex |= op_rexflags(input, REX_B|REX_P|REX_W|REX_H);
1848
Keith Kaniosb7a89542007-04-12 02:40:54 +00001849 output->sib_present = FALSE; /* no SIB necessary */
1850 output->bytes = 0; /* no offset necessary either */
1851 output->modrm = 0xC0 | ((rfield & 7) << 3) | (i & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001852 } else { /* it's a memory reference */
1853 if (input->basereg == -1
1854 && (input->indexreg == -1 || input->scale == 0)) {
1855 /* it's a pure offset */
1856 if (input->addr_size)
1857 addrbits = input->addr_size;
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001858
1859 if (globalbits == 64 && (~input->type & IP_REL)) {
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00001860 int scale, index, base;
1861 output->sib_present = TRUE;
1862 scale = 0;
1863 index = 4;
1864 base = 5;
1865 output->sib = (scale << 6) | (index << 3) | base;
1866 output->bytes = 4;
1867 output->modrm = 4 | ((rfield & 7) << 3);
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001868 output->rip = FALSE;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00001869 } else {
1870 output->sib_present = FALSE;
1871 output->bytes = (addrbits != 16 ? 4 : 2);
1872 output->modrm = (addrbits != 16 ? 5 : 6) | ((rfield & 7) << 3);
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001873 output->rip = globalbits == 64;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00001874 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001875 } else { /* it's an indirection */
1876 int i = input->indexreg, b = input->basereg, s = input->scale;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001877 int32_t o = input->offset, seg = input->segment;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001878 int hb = input->hintbase, ht = input->hinttype;
1879 int t;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001880 int it, bt;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001881 int32_t ix, bx; /* register flags */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001882
H. Peter Anvine2c80182005-01-15 22:15:51 +00001883 if (s == 0)
1884 i = -1; /* make this easy, at least */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001885
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001886 if (i >= EXPR_REG_START && i < REG_ENUM_LIMIT) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001887 it = regvals[i];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001888 ix = reg_flags[i];
1889 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001890 it = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001891 ix = 0;
1892 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001893
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001894 if (b != -1 && b >= EXPR_REG_START && b < REG_ENUM_LIMIT) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001895 bt = regvals[b];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001896 bx = reg_flags[b];
1897 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001898 bt = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001899 bx = 0;
1900 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001901
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001902 /* check for a 32/64-bit memory reference... */
1903 if ((ix|bx) & (BITS32|BITS64)) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001904 /* it must be a 32/64-bit memory reference. Firstly we have
1905 * to check that all registers involved are type E/Rxx. */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001906 int32_t sok = BITS32|BITS64;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001907
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001908 if (it != -1) {
1909 if (!(REG64 & ~ix) || !(REG32 & ~ix))
1910 sok &= ix;
1911 else
1912 return NULL;
1913 }
1914
1915 if (bt != -1) {
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001916 if (REG_GPR & ~bx)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001917 return NULL; /* Invalid register */
H. Peter Anvina57e8d42007-05-30 03:44:02 +00001918 if (~sok & bx & SIZE_MASK)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001919 return NULL; /* Invalid size */
1920 sok &= ~bx;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001921 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001922
H. Peter Anvine2c80182005-01-15 22:15:51 +00001923 /* While we're here, ensure the user didn't specify WORD. */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001924 if (input->addr_size == 16 ||
1925 (input->addr_size == 32 && !(sok & BITS32)) ||
1926 (input->addr_size == 64 && !(sok & BITS64)))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001927 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001928
Keith Kaniosb7a89542007-04-12 02:40:54 +00001929 /* now reorganize base/index */
1930 if (s == 1 && bt != it && bt != -1 && it != -1 &&
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001931 ((hb == b && ht == EAH_NOTBASE)
1932 || (hb == i && ht == EAH_MAKEBASE))) {
1933 /* swap if hints say so */
1934 t = bt, bt = it, it = t;
1935 t = bx, bx = ix, ix = t;
1936 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001937 if (bt == it) /* convert EAX+2*EAX to 3*EAX */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001938 bt = -1, bx = 0, s++;
1939 if (bt == -1 && s == 1 && !(hb == it && ht == EAH_NOTBASE)) {
1940 /* make single reg base, unless hint */
1941 bt = it, bx = ix, it = -1, ix = 0;
1942 }
H. Peter Anvinf5843c62007-09-10 18:59:26 +00001943 if (((s == 2 && it != REG_NUM_ESP
H. Peter Anvine2c80182005-01-15 22:15:51 +00001944 && !(input->eaflags & EAF_TIMESTWO)) || s == 3
Keith Kaniosb7a89542007-04-12 02:40:54 +00001945 || s == 5 || s == 9) && bt == -1)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001946 bt = it, bx = ix, s--; /* convert 3*EAX to EAX+2*EAX */
Keith Kanios48af1772007-08-17 07:37:52 +00001947 if (it == -1 && (bt & 7) != REG_NUM_ESP
H. Peter Anvine2c80182005-01-15 22:15:51 +00001948 && (input->eaflags & EAF_TIMESTWO))
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001949 it = bt, ix = bx, bt = -1, bx = 0, s = 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001950 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
Keith Kanios48af1772007-08-17 07:37:52 +00001951 if (s == 1 && it == REG_NUM_ESP) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001952 /* swap ESP into base if scale is 1 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001953 t = it, it = bt, bt = t;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001954 t = ix, ix = bx, bx = t;
1955 }
Keith Kanios48af1772007-08-17 07:37:52 +00001956 if (it == REG_NUM_ESP
Keith Kaniosb7a89542007-04-12 02:40:54 +00001957 || (s != 1 && s != 2 && s != 4 && s != 8 && it != -1))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001958 return NULL; /* wrong, for various reasons */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001959
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001960 output->rex |= rexflags(it, ix, REX_X);
1961 output->rex |= rexflags(bt, bx, REX_B);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001962
Keith Kanios48af1772007-08-17 07:37:52 +00001963 if (it == -1 && (bt & 7) != REG_NUM_ESP) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001964 /* no SIB needed */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001965 int mod, rm;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001966
1967 if (bt == -1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001968 rm = 5;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001969 mod = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001970 } else {
1971 rm = (bt & 7);
Keith Kanios48af1772007-08-17 07:37:52 +00001972 if (rm != REG_NUM_EBP && o == 0 &&
Keith Kaniosb7a89542007-04-12 02:40:54 +00001973 seg == NO_SEG && !forw_ref &&
1974 !(input->eaflags &
1975 (EAF_BYTEOFFS | EAF_WORDOFFS)))
1976 mod = 0;
1977 else if (input->eaflags & EAF_BYTEOFFS ||
1978 (o >= -128 && o <= 127 && seg == NO_SEG
1979 && !forw_ref
1980 && !(input->eaflags & EAF_WORDOFFS)))
1981 mod = 1;
1982 else
1983 mod = 2;
1984 }
H. Peter Anvinea838272002-04-30 20:51:53 +00001985
H. Peter Anvine2c80182005-01-15 22:15:51 +00001986 output->sib_present = FALSE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001987 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
1988 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001989 } else {
1990 /* we need a SIB */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001991 int mod, scale, index, base;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001992
1993 if (it == -1)
1994 index = 4, s = 1;
1995 else
1996 index = (it & 7);
1997
H. Peter Anvine2c80182005-01-15 22:15:51 +00001998 switch (s) {
1999 case 1:
2000 scale = 0;
2001 break;
2002 case 2:
2003 scale = 1;
2004 break;
2005 case 4:
2006 scale = 2;
2007 break;
2008 case 8:
2009 scale = 3;
2010 break;
2011 default: /* then what the smeg is it? */
2012 return NULL; /* panic */
2013 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00002014
2015 if (bt == -1) {
2016 base = 5;
2017 mod = 0;
2018 } else {
2019 base = (bt & 7);
Keith Kanios48af1772007-08-17 07:37:52 +00002020 if (base != REG_NUM_EBP && o == 0 &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00002021 seg == NO_SEG && !forw_ref &&
2022 !(input->eaflags &
Keith Kaniosb7a89542007-04-12 02:40:54 +00002023 (EAF_BYTEOFFS | EAF_WORDOFFS)))
2024 mod = 0;
2025 else if (input->eaflags & EAF_BYTEOFFS ||
2026 (o >= -128 && o <= 127 && seg == NO_SEG
2027 && !forw_ref
2028 && !(input->eaflags & EAF_WORDOFFS)))
2029 mod = 1;
2030 else
2031 mod = 2;
2032 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002033
H. Peter Anvine2c80182005-01-15 22:15:51 +00002034 output->sib_present = TRUE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002035 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
2036 output->modrm = (mod << 6) | ((rfield & 7) << 3) | 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002037 output->sib = (scale << 6) | (index << 3) | base;
2038 }
2039 } else { /* it's 16-bit */
2040 int mod, rm;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002041
2042 /* check for 64-bit long mode */
2043 if (addrbits == 64)
2044 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002045
H. Peter Anvine2c80182005-01-15 22:15:51 +00002046 /* check all registers are BX, BP, SI or DI */
2047 if ((b != -1 && b != R_BP && b != R_BX && b != R_SI
2048 && b != R_DI) || (i != -1 && i != R_BP && i != R_BX
2049 && i != R_SI && i != R_DI))
2050 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002051
Keith Kaniosb7a89542007-04-12 02:40:54 +00002052 /* ensure the user didn't specify DWORD/QWORD */
2053 if (input->addr_size == 32 || input->addr_size == 64)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002054 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002055
H. Peter Anvine2c80182005-01-15 22:15:51 +00002056 if (s != 1 && i != -1)
2057 return NULL; /* no can do, in 16-bit EA */
2058 if (b == -1 && i != -1) {
2059 int tmp = b;
2060 b = i;
2061 i = tmp;
2062 } /* swap */
2063 if ((b == R_SI || b == R_DI) && i != -1) {
2064 int tmp = b;
2065 b = i;
2066 i = tmp;
2067 }
2068 /* have BX/BP as base, SI/DI index */
2069 if (b == i)
2070 return NULL; /* shouldn't ever happen, in theory */
2071 if (i != -1 && b != -1 &&
2072 (i == R_BP || i == R_BX || b == R_SI || b == R_DI))
2073 return NULL; /* invalid combinations */
2074 if (b == -1) /* pure offset: handled above */
2075 return NULL; /* so if it gets to here, panic! */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002076
H. Peter Anvine2c80182005-01-15 22:15:51 +00002077 rm = -1;
2078 if (i != -1)
2079 switch (i * 256 + b) {
2080 case R_SI * 256 + R_BX:
2081 rm = 0;
2082 break;
2083 case R_DI * 256 + R_BX:
2084 rm = 1;
2085 break;
2086 case R_SI * 256 + R_BP:
2087 rm = 2;
2088 break;
2089 case R_DI * 256 + R_BP:
2090 rm = 3;
2091 break;
2092 } else
2093 switch (b) {
2094 case R_SI:
2095 rm = 4;
2096 break;
2097 case R_DI:
2098 rm = 5;
2099 break;
2100 case R_BP:
2101 rm = 6;
2102 break;
2103 case R_BX:
2104 rm = 7;
2105 break;
2106 }
2107 if (rm == -1) /* can't happen, in theory */
2108 return NULL; /* so panic if it does */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002109
H. Peter Anvine2c80182005-01-15 22:15:51 +00002110 if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
2111 !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
2112 mod = 0;
2113 else if (input->eaflags & EAF_BYTEOFFS ||
2114 (o >= -128 && o <= 127 && seg == NO_SEG
2115 && !forw_ref
2116 && !(input->eaflags & EAF_WORDOFFS)))
2117 mod = 1;
2118 else
2119 mod = 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002120
H. Peter Anvine2c80182005-01-15 22:15:51 +00002121 output->sib_present = FALSE; /* no SIB - it's 16-bit */
2122 output->bytes = mod; /* bytes of offset needed */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002123 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002124 }
2125 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002126 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00002127
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002128 output->size = 1 + output->sib_present + output->bytes;
2129 return output;
2130}
2131
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002132static void add_asp(insn *instruction, int addrbits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002133{
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002134 int j, valid;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002135
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002136 valid = (addrbits == 64) ? 64|32 : 32|16;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002137
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002138 for (j = 0; j < instruction->operands; j++) {
2139 if (!(MEMORY & ~instruction->oprs[j].type)) {
2140 int32_t i, b;
2141
2142 /* Verify as Register */
2143 if (instruction->oprs[j].indexreg < EXPR_REG_START
2144 || instruction->oprs[j].indexreg >= REG_ENUM_LIMIT)
2145 i = 0;
2146 else
2147 i = reg_flags[instruction->oprs[j].indexreg];
2148
2149 /* Verify as Register */
2150 if (instruction->oprs[j].basereg < EXPR_REG_START
2151 || instruction->oprs[j].basereg >= REG_ENUM_LIMIT)
2152 b = 0;
2153 else
2154 b = reg_flags[instruction->oprs[j].basereg];
2155
2156 if (instruction->oprs[j].scale == 0)
2157 i = 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002158
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002159 if (!i && !b) {
2160 if (instruction->oprs[j].addr_size)
2161 valid &= instruction->oprs[j].addr_size;
2162 } else {
2163 if (!(REG16 & ~b))
2164 valid &= 16;
2165 if (!(REG32 & ~b))
2166 valid &= 32;
2167 if (!(REG64 & ~b))
2168 valid &= 64;
2169
2170 if (!(REG16 & ~i))
2171 valid &= 16;
2172 if (!(REG32 & ~i))
2173 valid &= 32;
2174 if (!(REG64 & ~i))
2175 valid &= 64;
2176 }
2177 }
2178 }
2179
2180 if (valid & addrbits) {
2181 /* Don't do anything */
2182 } else if (valid & ((addrbits == 32) ? 16 : 32)) {
2183 /* Add an instruction size prefix */
2184 enum prefixes pref = (addrbits == 32) ? P_A16 : P_A32;
2185 for (j = 0; j < instruction->nprefix; j++) {
2186 if (instruction->prefixes[j] == pref)
2187 return; /* Already there */
2188 }
2189 instruction->prefixes[j] = pref;
2190 instruction->nprefix++;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002191 } else {
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002192 /* Impossible... */
2193 errfunc(ERR_NONFATAL, "impossible combination of address sizes");
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002194 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002195}