blob: efb022072ea3aafdd4b3369dca46adec4c0150b1 [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.
54 * \30x - might be an 0x67 byte, depending on the address size of
55 * the memory reference in operand x.
56 * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
57 * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
Keith Kanios48af1772007-08-17 07:37:52 +000058 * \312 - (disassembler only) marker on LOOP, LOOPxx instructions.
H. Peter Anvince2b3972007-05-30 22:21:11 +000059 * \313 - indicates fixed 64-bit address size, 0x67 invalid.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000060 * \320 - indicates fixed 16-bit operand size, i.e. optional 0x66.
61 * \321 - indicates fixed 32-bit operand size, i.e. optional 0x66.
62 * \322 - indicates that this instruction is only valid when the
63 * operand size is the default (instruction to disassembler,
64 * generates no code in the assembler)
H. Peter Anvince2b3972007-05-30 22:21:11 +000065 * \323 - indicates fixed 64-bit operand size, REX on extensions only.
Keith Kaniosb7a89542007-04-12 02:40:54 +000066 * \324 - indicates 64-bit operand size requiring REX prefix.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000067 * \330 - a literal byte follows in the code stream, to be added
68 * to the condition code value of the instruction.
Keith Kanios48af1772007-08-17 07:37:52 +000069 * \331 - instruction not valid with REP prefix. Hint for
H. Peter Anvinef7468f2002-04-30 20:57:59 +000070 * disassembler only; for SSE instructions.
H. Peter Anvincb9b6902007-09-12 21:58:51 -070071 * \332 - REP prefix (0xF2 byte) used as opcode extension.
72 * \333 - REP prefix (0xF3 byte) used as opcode extension.
Keith Kanios48af1772007-08-17 07:37:52 +000073 * \334 - LOCK prefix used instead of REX.R
H. Peter Anvincb9b6902007-09-12 21:58:51 -070074 * \335 - disassemble a rep (0xF3 byte) prefix as repe not rep.
Keith Kaniosb7a89542007-04-12 02:40:54 +000075 * \340 - reserve <operand 0> bytes of uninitialized storage.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000076 * Operand 0 had better be a segmentless constant.
H. Peter Anvin62cb6062007-09-11 22:44:03 +000077 * \364 - operand-size prefix (0x66) not permitted
78 * \365 - address-size prefix (0x67) not permitted
79 * \366 - operand-size prefix (0x66) used as opcode extension
80 * \367 - address-size prefix (0x67) used as opcode extension
H. Peter Anvin788e6c12002-04-30 21:02:01 +000081 * \370,\371,\372 - match only if operand 0 meets byte jump criteria.
82 * 370 is used for Jcc, 371 is used for JMP.
H. Peter Anvinaf535c12002-04-30 20:59:21 +000083 * \373 - assemble 0x03 if bits==16, 0x05 if bits==32;
84 * used for conditional jump over longer jump
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000085 */
86
87#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 Anvine2c80182005-01-15 22:15:51 +0000119static int chsize(operand *, int);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000120
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000121static void assert_no_prefix(insn * ins, int prefix)
122{
123 int j;
124
125 for (j = 0; j < ins->nprefix; j++) {
126 if (ins->prefixes[j] == prefix) {
127 errfunc(ERR_NONFATAL, "invalid %s prefix", prefix_name(prefix));
128 break;
129 }
130 }
131}
132
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000133/*
134 * This routine wrappers the real output format's output routine,
135 * in order to pass a copy of the data off to the listing file
136 * generator at the same time.
137 */
Keith Kaniosb7a89542007-04-12 02:40:54 +0000138static void out(int32_t offset, int32_t segto, const void *data,
139 uint32_t type, int32_t segment, int32_t wrt)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000140{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000141 static int32_t lineno = 0; /* static!!! */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000142 static char *lnfname = NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000143
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000144 if ((type & OUT_TYPMASK) == OUT_ADDRESS) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000145 if (segment != NO_SEG || wrt != NO_SEG) {
146 /*
147 * This address is relocated. We must write it as
148 * OUT_ADDRESS, so there's no work to be done here.
149 */
150 list->output(offset, data, type);
151 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000152 uint8_t p[8], *q = p;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000153 /*
154 * This is a non-relocated address, and we're going to
155 * convert it into RAWDATA format.
156 */
157 if ((type & OUT_SIZMASK) == 4) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000158 WRITELONG(q, *(int32_t *)data);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000159 list->output(offset, p, OUT_RAWDATA + 4);
Keith Kaniosb7a89542007-04-12 02:40:54 +0000160 } else if ((type & OUT_SIZMASK) == 8) {
161 WRITEDLONG(q, *(int64_t *)data);
162 list->output(offset, p, OUT_RAWDATA + 8);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000163 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000164 WRITESHORT(q, *(int32_t *)data);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000165 list->output(offset, p, OUT_RAWDATA + 2);
166 }
167 }
168 } else if ((type & OUT_TYPMASK) == OUT_RAWDATA) {
169 list->output(offset, data, type);
170 } else if ((type & OUT_TYPMASK) == OUT_RESERVE) {
171 list->output(offset, NULL, type);
172 } else if ((type & OUT_TYPMASK) == OUT_REL2ADR ||
173 (type & OUT_TYPMASK) == OUT_REL4ADR) {
174 list->output(offset, data, type);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000175 }
176
Frank Kotlerabebb082003-09-06 04:45:37 +0000177 /*
178 * this call to src_get determines when we call the
179 * debug-format-specific "linenum" function
180 * it updates lineno and lnfname to the current values
181 * returning 0 if "same as last time", -2 if lnfname
182 * changed, and the amount by which lineno changed,
183 * if it did. thus, these variables must be static
184 */
185
H. Peter Anvine2c80182005-01-15 22:15:51 +0000186 if (src_get(&lineno, &lnfname)) {
187 outfmt->current_dfmt->linenum(lnfname, lineno, segto);
H. Peter Anvince616072002-04-30 21:02:23 +0000188 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000189
H. Peter Anvine2c80182005-01-15 22:15:51 +0000190 outfmt->output(segto, data, type, segment, wrt);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000191}
192
Keith Kaniosb7a89542007-04-12 02:40:54 +0000193static int jmp_match(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000194 insn * ins, const char *code)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000195{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000196 int32_t isize;
197 uint8_t c = code[0];
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000198
H. Peter Anvine2c80182005-01-15 22:15:51 +0000199 if (c != 0370 && c != 0371)
200 return 0;
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000201 if (ins->oprs[0].opflags & OPFLAG_FORWARD) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000202 if ((optimizing < 0 || (ins->oprs[0].type & STRICT))
203 && c == 0370)
204 return 1;
205 else
206 return (pass0 == 0); /* match a forward reference */
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000207 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000208 isize = calcsize(segment, offset, bits, ins, code);
209 if (ins->oprs[0].segment != segment)
210 return 0;
211 isize = ins->oprs[0].offset - offset - isize; /* isize is now the delta */
212 if (isize >= -128L && isize <= 127L)
213 return 1; /* it is byte size */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000214
215 return 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000216}
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000217
Keith Kaniosb7a89542007-04-12 02:40:54 +0000218int32_t assemble(int32_t segment, int32_t offset, int bits, uint32_t cp,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000219 insn * instruction, struct ofmt *output, efunc error,
220 ListGen * listgen)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000221{
H. Peter Anvin3360d792007-09-11 04:16:57 +0000222 const struct itemplate *temp;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000223 int j;
224 int size_prob;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000225 int32_t insn_end;
226 int32_t itimes;
227 int32_t start = offset;
228 int32_t wsize = 0; /* size for DB etc. */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000229
H. Peter Anvine2c80182005-01-15 22:15:51 +0000230 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000231 cpu = cp;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000232 outfmt = output; /* likewise */
233 list = listgen; /* and again */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000234
H. Peter Anvine2c80182005-01-15 22:15:51 +0000235 switch (instruction->opcode) {
236 case -1:
237 return 0;
238 case I_DB:
239 wsize = 1;
240 break;
241 case I_DW:
242 wsize = 2;
243 break;
244 case I_DD:
245 wsize = 4;
246 break;
247 case I_DQ:
248 wsize = 8;
249 break;
250 case I_DT:
251 wsize = 10;
252 break;
H. Peter Anvincfbe7c32007-09-18 17:49:09 -0700253 case I_DO:
254 wsize = 16;
255 break;
H. Peter Anvin16b0a332007-09-12 20:27:41 -0700256 default:
257 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000258 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000259
H. Peter Anvineba20a72002-04-30 20:53:55 +0000260 if (wsize) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000261 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000262 int32_t t = instruction->times;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000263 if (t < 0)
264 errfunc(ERR_PANIC,
265 "instruction->times < 0 (%ld) in assemble()", t);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000266
H. Peter Anvine2c80182005-01-15 22:15:51 +0000267 while (t--) { /* repeat TIMES times */
268 for (e = instruction->eops; e; e = e->next) {
269 if (e->type == EOT_DB_NUMBER) {
270 if (wsize == 1) {
271 if (e->segment != NO_SEG)
272 errfunc(ERR_NONFATAL,
273 "one-byte relocation attempted");
274 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000275 uint8_t out_byte = e->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000276 out(offset, segment, &out_byte,
277 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
278 }
Keith Kanios61ff53c2007-04-14 18:54:52 +0000279 } else if (wsize > 8) {
280 errfunc(ERR_NONFATAL, "integer supplied to a DT"
281 " instruction");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000282 } else
283 out(offset, segment, &e->offset,
284 OUT_ADDRESS + wsize, e->segment, e->wrt);
285 offset += wsize;
286 } else if (e->type == EOT_DB_STRING) {
287 int align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000288
H. Peter Anvine2c80182005-01-15 22:15:51 +0000289 out(offset, segment, e->stringval,
290 OUT_RAWDATA + e->stringlen, NO_SEG, NO_SEG);
291 align = e->stringlen % wsize;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000292
H. Peter Anvine2c80182005-01-15 22:15:51 +0000293 if (align) {
294 align = wsize - align;
295 out(offset, segment, "\0\0\0\0\0\0\0\0",
296 OUT_RAWDATA + align, NO_SEG, NO_SEG);
297 }
298 offset += e->stringlen + align;
299 }
300 }
301 if (t > 0 && t == instruction->times - 1) {
302 /*
303 * Dummy call to list->output to give the offset to the
304 * listing module.
305 */
306 list->output(offset, NULL, OUT_RAWDATA);
307 list->uplevel(LIST_TIMES);
308 }
309 }
310 if (instruction->times > 1)
311 list->downlevel(LIST_TIMES);
312 return offset - start;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000313 }
314
H. Peter Anvine2c80182005-01-15 22:15:51 +0000315 if (instruction->opcode == I_INCBIN) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000316 static char fname[FILENAME_MAX];
H. Peter Anvine2c80182005-01-15 22:15:51 +0000317 FILE *fp;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000318 int32_t len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000319 char *prefix = "", *combine;
320 char **pPrevPath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000321
H. Peter Anvine2c80182005-01-15 22:15:51 +0000322 len = FILENAME_MAX - 1;
323 if (len > instruction->eops->stringlen)
324 len = instruction->eops->stringlen;
325 strncpy(fname, instruction->eops->stringval, len);
326 fname[len] = '\0';
H. Peter Anvineba20a72002-04-30 20:53:55 +0000327
Keith Kaniosb7a89542007-04-12 02:40:54 +0000328 while (1) { /* added by alexfru: 'incbin' uses include paths */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000329 combine = nasm_malloc(strlen(prefix) + len + 1);
330 strcpy(combine, prefix);
331 strcat(combine, fname);
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000332
H. Peter Anvine2c80182005-01-15 22:15:51 +0000333 if ((fp = fopen(combine, "rb")) != NULL) {
334 nasm_free(combine);
335 break;
336 }
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000337
H. Peter Anvine2c80182005-01-15 22:15:51 +0000338 nasm_free(combine);
339 pPrevPath = pp_get_include_path_ptr(pPrevPath);
340 if (pPrevPath == NULL)
341 break;
342 prefix = *pPrevPath;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000343 }
344
345 if (fp == NULL)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000346 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
347 fname);
348 else if (fseek(fp, 0L, SEEK_END) < 0)
349 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
350 fname);
351 else {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000352 static char buf[2048];
Keith Kaniosb7a89542007-04-12 02:40:54 +0000353 int32_t t = instruction->times;
354 int32_t base = 0;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000355
H. Peter Anvine2c80182005-01-15 22:15:51 +0000356 len = ftell(fp);
357 if (instruction->eops->next) {
358 base = instruction->eops->next->offset;
359 len -= base;
360 if (instruction->eops->next->next &&
361 len > instruction->eops->next->next->offset)
362 len = instruction->eops->next->next->offset;
363 }
364 /*
365 * Dummy call to list->output to give the offset to the
366 * listing module.
367 */
368 list->output(offset, NULL, OUT_RAWDATA);
369 list->uplevel(LIST_INCBIN);
370 while (t--) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000371 int32_t l;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000372
H. Peter Anvine2c80182005-01-15 22:15:51 +0000373 fseek(fp, base, SEEK_SET);
374 l = len;
375 while (l > 0) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000376 int32_t m =
H. Peter Anvine2c80182005-01-15 22:15:51 +0000377 fread(buf, 1, (l > sizeof(buf) ? sizeof(buf) : l),
378 fp);
379 if (!m) {
380 /*
381 * This shouldn't happen unless the file
382 * actually changes while we are reading
383 * it.
384 */
385 error(ERR_NONFATAL,
386 "`incbin': unexpected EOF while"
387 " reading file `%s'", fname);
388 t = 0; /* Try to exit cleanly */
389 break;
390 }
391 out(offset, segment, buf, OUT_RAWDATA + m,
392 NO_SEG, NO_SEG);
393 l -= m;
394 }
395 }
396 list->downlevel(LIST_INCBIN);
397 if (instruction->times > 1) {
398 /*
399 * Dummy call to list->output to give the offset to the
400 * listing module.
401 */
402 list->output(offset, NULL, OUT_RAWDATA);
403 list->uplevel(LIST_TIMES);
404 list->downlevel(LIST_TIMES);
405 }
406 fclose(fp);
407 return instruction->times * len;
408 }
409 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000410 }
411
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000412 size_prob = FALSE;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000413
414 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++){
415 int m = matches(temp, instruction, bits);
416
H. Peter Anvine2c80182005-01-15 22:15:51 +0000417 if (m == 99)
418 m += jmp_match(segment, offset, bits, instruction, temp->code);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000419
H. Peter Anvine2c80182005-01-15 22:15:51 +0000420 if (m == 100) { /* matches! */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000421 const char *codes = temp->code;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000422 int32_t insn_size = calcsize(segment, offset, bits,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000423 instruction, codes);
424 itimes = instruction->times;
425 if (insn_size < 0) /* shouldn't be, on pass two */
426 error(ERR_PANIC, "errors made it through from pass one");
427 else
428 while (itimes--) {
429 for (j = 0; j < instruction->nprefix; j++) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000430 uint8_t c = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000431 switch (instruction->prefixes[j]) {
432 case P_LOCK:
433 c = 0xF0;
434 break;
435 case P_REPNE:
436 case P_REPNZ:
437 c = 0xF2;
438 break;
439 case P_REPE:
440 case P_REPZ:
441 case P_REP:
442 c = 0xF3;
443 break;
444 case R_CS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000445 if (bits == 64) {
446 error(ERR_WARNING,
447 "cs segment base ignored in 64-bit mode");
448 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000449 c = 0x2E;
450 break;
451 case R_DS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000452 if (bits == 64) {
453 error(ERR_WARNING,
454 "ds segment base ignored in 64-bit mode");
455 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000456 c = 0x3E;
457 break;
458 case R_ES:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000459 if (bits == 64) {
460 error(ERR_WARNING,
461 "es segment base ignored in 64-bit mode");
462 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000463 c = 0x26;
464 break;
465 case R_FS:
466 c = 0x64;
467 break;
468 case R_GS:
469 c = 0x65;
470 break;
471 case R_SS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000472 if (bits == 64) {
473 error(ERR_WARNING,
474 "ss segment base ignored in 64-bit mode");
475 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000476 c = 0x36;
477 break;
478 case R_SEGR6:
479 case R_SEGR7:
480 error(ERR_NONFATAL,
481 "segr6 and segr7 cannot be used as prefixes");
482 break;
483 case P_A16:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000484 if (bits == 64) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000485 error(ERR_NONFATAL,
486 "16-bit addressing is not supported "
487 "in 64-bit mode");
Keith Kaniosb7a89542007-04-12 02:40:54 +0000488 break;
489 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000490 if (bits != 16)
491 c = 0x67;
492 break;
493 case P_A32:
494 if (bits != 32)
495 c = 0x67;
496 break;
497 case P_O16:
498 if (bits != 16)
499 c = 0x66;
500 break;
501 case P_O32:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000502 if (bits == 16)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000503 c = 0x66;
504 break;
505 default:
506 error(ERR_PANIC, "invalid instruction prefix");
507 }
508 if (c != 0) {
509 out(offset, segment, &c, OUT_RAWDATA + 1,
510 NO_SEG, NO_SEG);
511 offset++;
512 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000513 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000514 insn_end = offset + insn_size;
515 gencode(segment, offset, bits, instruction, codes,
516 insn_end);
517 offset += insn_size;
518 if (itimes > 0 && itimes == instruction->times - 1) {
519 /*
520 * Dummy call to list->output to give the offset to the
521 * listing module.
522 */
523 list->output(offset, NULL, OUT_RAWDATA);
524 list->uplevel(LIST_TIMES);
525 }
526 }
527 if (instruction->times > 1)
528 list->downlevel(LIST_TIMES);
529 return offset - start;
530 } else if (m > 0 && m > size_prob) {
531 size_prob = m;
532 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000533// temp++;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000534 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000535
H. Peter Anvine2c80182005-01-15 22:15:51 +0000536 if (temp->opcode == -1) { /* didn't match any instruction */
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000537 switch (size_prob) {
538 case 1:
539 error(ERR_NONFATAL, "operation size not specified");
540 break;
541 case 2:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000542 error(ERR_NONFATAL, "mismatch in operand sizes");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000543 break;
544 case 3:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000545 error(ERR_NONFATAL, "no instruction for this cpu level");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000546 break;
547 case 4:
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000548 error(ERR_NONFATAL, "instruction not supported in 64-bit mode");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000549 break;
550 default:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000551 error(ERR_NONFATAL,
552 "invalid combination of opcode and operands");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000553 break;
554 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000555 }
556 return 0;
557}
558
Keith Kaniosb7a89542007-04-12 02:40:54 +0000559int32_t insn_size(int32_t segment, int32_t offset, int bits, uint32_t cp,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000560 insn * instruction, efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000561{
H. Peter Anvin3360d792007-09-11 04:16:57 +0000562 const struct itemplate *temp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000563
H. Peter Anvine2c80182005-01-15 22:15:51 +0000564 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000565 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000566
567 if (instruction->opcode == -1)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000568 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000569
H. Peter Anvincfbe7c32007-09-18 17:49:09 -0700570 if (instruction->opcode == I_DB || instruction->opcode == I_DW ||
571 instruction->opcode == I_DD || instruction->opcode == I_DQ ||
572 instruction->opcode == I_DT || instruction->opcode == I_DO) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000573 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000574 int32_t isize, osize, wsize = 0; /* placate gcc */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000575
H. Peter Anvine2c80182005-01-15 22:15:51 +0000576 isize = 0;
577 switch (instruction->opcode) {
578 case I_DB:
579 wsize = 1;
580 break;
581 case I_DW:
582 wsize = 2;
583 break;
584 case I_DD:
585 wsize = 4;
586 break;
587 case I_DQ:
588 wsize = 8;
589 break;
590 case I_DT:
591 wsize = 10;
592 break;
H. Peter Anvincfbe7c32007-09-18 17:49:09 -0700593 case I_DO:
594 wsize = 16;
595 break;
H. Peter Anvin16b0a332007-09-12 20:27:41 -0700596 default:
597 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000598 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000599
H. Peter Anvine2c80182005-01-15 22:15:51 +0000600 for (e = instruction->eops; e; e = e->next) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000601 int32_t align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000602
H. Peter Anvine2c80182005-01-15 22:15:51 +0000603 osize = 0;
604 if (e->type == EOT_DB_NUMBER)
605 osize = 1;
606 else if (e->type == EOT_DB_STRING)
607 osize = e->stringlen;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000608
H. Peter Anvine2c80182005-01-15 22:15:51 +0000609 align = (-osize) % wsize;
610 if (align < 0)
611 align += wsize;
612 isize += osize + align;
613 }
614 return isize * instruction->times;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000615 }
616
H. Peter Anvine2c80182005-01-15 22:15:51 +0000617 if (instruction->opcode == I_INCBIN) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000618 char fname[FILENAME_MAX];
H. Peter Anvine2c80182005-01-15 22:15:51 +0000619 FILE *fp;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000620 int32_t len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000621 char *prefix = "", *combine;
622 char **pPrevPath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000623
H. Peter Anvine2c80182005-01-15 22:15:51 +0000624 len = FILENAME_MAX - 1;
625 if (len > instruction->eops->stringlen)
626 len = instruction->eops->stringlen;
627 strncpy(fname, instruction->eops->stringval, len);
628 fname[len] = '\0';
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000629
H. Peter Anvine2c80182005-01-15 22:15:51 +0000630 while (1) { /* added by alexfru: 'incbin' uses include paths */
631 combine = nasm_malloc(strlen(prefix) + len + 1);
632 strcpy(combine, prefix);
633 strcat(combine, fname);
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000634
H. Peter Anvine2c80182005-01-15 22:15:51 +0000635 if ((fp = fopen(combine, "rb")) != NULL) {
636 nasm_free(combine);
637 break;
638 }
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000639
H. Peter Anvine2c80182005-01-15 22:15:51 +0000640 nasm_free(combine);
641 pPrevPath = pp_get_include_path_ptr(pPrevPath);
642 if (pPrevPath == NULL)
643 break;
644 prefix = *pPrevPath;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000645 }
646
647 if (fp == NULL)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000648 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
649 fname);
650 else if (fseek(fp, 0L, SEEK_END) < 0)
651 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
652 fname);
653 else {
654 len = ftell(fp);
655 fclose(fp);
656 if (instruction->eops->next) {
657 len -= instruction->eops->next->offset;
658 if (instruction->eops->next->next &&
659 len > instruction->eops->next->next->offset) {
660 len = instruction->eops->next->next->offset;
661 }
662 }
663 return instruction->times * len;
664 }
665 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000666 }
667
Keith Kaniosb7a89542007-04-12 02:40:54 +0000668 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++) {
669 int m = matches(temp, instruction, bits);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000670 if (m == 99)
671 m += jmp_match(segment, offset, bits, instruction, temp->code);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000672
H. Peter Anvine2c80182005-01-15 22:15:51 +0000673 if (m == 100) {
674 /* we've matched an instruction. */
Keith Kaniosb7a89542007-04-12 02:40:54 +0000675 int32_t isize;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000676 const char *codes = temp->code;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000677 int j;
678
679 isize = calcsize(segment, offset, bits, instruction, codes);
680 if (isize < 0)
681 return -1;
682 for (j = 0; j < instruction->nprefix; j++) {
683 if ((instruction->prefixes[j] != P_A16 &&
684 instruction->prefixes[j] != P_O16 && bits == 16) ||
685 (instruction->prefixes[j] != P_A32 &&
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000686 instruction->prefixes[j] != P_O32 && bits >= 32)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000687 isize++;
688 }
689 }
690 return isize * instruction->times;
691 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000692 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000693 return -1; /* didn't match any instruction */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000694}
695
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000696/* check that opn[op] is a signed byte of size 16 or 32,
697 and return the signed value*/
H. Peter Anvine2c80182005-01-15 22:15:51 +0000698static int is_sbyte(insn * ins, int op, int size)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000699{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000700 int32_t v;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000701 int ret;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000702
703 ret = !(ins->forw_ref && ins->oprs[op].opflags) && /* dead in the water on forward reference or External */
704 optimizing >= 0 &&
705 !(ins->oprs[op].type & STRICT) &&
706 ins->oprs[op].wrt == NO_SEG && ins->oprs[op].segment == NO_SEG;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000707
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000708 v = ins->oprs[op].offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000709 if (size == 16)
Keith Kaniosb7a89542007-04-12 02:40:54 +0000710 v = (int16_t)v; /* sign extend if 16 bits */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000711
712 return ret && v >= -128L && v <= 127L;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000713}
714
Keith Kaniosb7a89542007-04-12 02:40:54 +0000715static int32_t calcsize(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000716 insn * ins, const char *codes)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000717{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000718 int32_t length = 0;
719 uint8_t c;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000720 int rex_mask = ~0;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000721 ins->rex = 0; /* Ensure REX is reset */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000722
H. Peter Anvine2c80182005-01-15 22:15:51 +0000723 (void)segment; /* Don't warn that this parameter is unused */
724 (void)offset; /* Don't warn that this parameter is unused */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000725
H. Peter Anvine2c80182005-01-15 22:15:51 +0000726 while (*codes)
727 switch (c = *codes++) {
728 case 01:
729 case 02:
730 case 03:
731 codes += c, length += c;
732 break;
733 case 04:
734 case 05:
735 case 06:
736 case 07:
737 length++;
738 break;
739 case 010:
740 case 011:
741 case 012:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700742 case 013:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000743 ins->rex |=
744 op_rexflags(&ins->oprs[c - 010], REX_B|REX_H|REX_P|REX_W);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000745 codes++, length++;
746 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000747 case 014:
748 case 015:
749 case 016:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700750 case 017:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000751 length++;
752 break;
753 case 020:
754 case 021:
755 case 022:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700756 case 023:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000757 length++;
758 break;
759 case 024:
760 case 025:
761 case 026:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700762 case 027:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000763 length++;
764 break;
765 case 030:
766 case 031:
767 case 032:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700768 case 033:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000769 length += 2;
770 break;
771 case 034:
772 case 035:
773 case 036:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700774 case 037:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000775 if (ins->oprs[c - 034].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000776 length += (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
777 else
778 length += (bits == 16) ? 2 : 4;
779 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000780 case 040:
781 case 041:
782 case 042:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700783 case 043:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000784 length += 4;
785 break;
786 case 044:
787 case 045:
788 case 046:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700789 case 047:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000790 length += ((ins->oprs[c - 044].addr_size ?
Keith Kaniosb7a89542007-04-12 02:40:54 +0000791 ins->oprs[c - 044].addr_size : bits) >> 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000792 break;
793 case 050:
794 case 051:
795 case 052:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700796 case 053:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000797 length++;
798 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000799 case 054:
800 case 055:
801 case 056:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700802 case 057:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000803 length += 8; /* MOV reg64/imm */
804 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000805 case 060:
806 case 061:
807 case 062:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700808 case 063:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000809 length += 2;
810 break;
811 case 064:
812 case 065:
813 case 066:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700814 case 067:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000815 if (ins->oprs[c - 064].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000816 length += (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
817 else
818 length += (bits == 16) ? 2 : 4;
819 break;
820 case 070:
821 case 071:
822 case 072:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700823 case 073:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000824 length += 4;
825 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700826 case 074:
827 case 075:
828 case 076:
829 case 077:
830 length += 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000831 break;
832 case 0140:
833 case 0141:
834 case 0142:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700835 case 0143:
836 length += is_sbyte(ins, c - 0140, 16) ? 1 : 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000837 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000838 case 0144:
839 case 0145:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700840 case 0146:
841 case 0147:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000842 codes += 2;
843 length++;
844 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700845 case 0150:
846 case 0151:
847 case 0152:
848 case 0153:
849 length += is_sbyte(ins, c - 0150, 32) ? 1 : 4;
850 break;
851 case 0154:
852 case 0155:
853 case 0156:
854 case 0157:
855 codes += 2;
856 length++;
857 break;
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700858 case 0160:
859 case 0161:
860 case 0162:
861 case 0163:
862 length++;
863 ins->rex |= REX_D;
H. Peter Anvincf5180a2007-09-17 17:25:27 -0700864 ins->drexdst = regval(&ins->oprs[c & 3]);
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700865 break;
866 case 0164:
867 case 0165:
868 case 0166:
869 case 0167:
870 length++;
871 ins->rex |= REX_D|REX_OC;
H. Peter Anvincf5180a2007-09-17 17:25:27 -0700872 ins->drexdst = regval(&ins->oprs[c & 3]);
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700873 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700874 case 0170:
875 length++;
876 break;
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700877 case 0171:
878 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000879 case 0300:
880 case 0301:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000881 case 0302:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700882 case 0303:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000883 length += chsize(&ins->oprs[c - 0300], bits);
884 break;
885 case 0310:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000886 length += (bits != 16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000887 break;
888 case 0311:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000889 length += (bits != 32);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000890 break;
891 case 0312:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000892 break;
893 case 0313:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000894 break;
895 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000896 length += (bits != 16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000897 break;
898 case 0321:
899 length += (bits == 16);
900 break;
901 case 0322:
902 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000903 case 0323:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000904 rex_mask &= ~REX_W;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000905 break;
906 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000907 ins->rex |= REX_W;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000908 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000909 case 0330:
910 codes++, length++;
911 break;
912 case 0331:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000913 break;
H. Peter Anvincb9b6902007-09-12 21:58:51 -0700914 case 0332:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000915 case 0333:
916 length++;
917 break;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000918 case 0334:
919 assert_no_prefix(ins, P_LOCK);
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000920 ins->rex |= REX_L;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000921 break;
H. Peter Anvincb9b6902007-09-12 21:58:51 -0700922 case 0335:
923 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000924 case 0340:
925 case 0341:
926 case 0342:
927 if (ins->oprs[0].segment != NO_SEG)
928 errfunc(ERR_NONFATAL, "attempt to reserve non-constant"
929 " quantity of BSS space");
930 else
931 length += ins->oprs[0].offset << (c - 0340);
932 break;
H. Peter Anvin62cb6062007-09-11 22:44:03 +0000933 case 0364:
934 case 0365:
935 break;
Keith Kanios48af1772007-08-17 07:37:52 +0000936 case 0366:
H. Peter Anvin62cb6062007-09-11 22:44:03 +0000937 case 0367:
938 length++;
939 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000940 case 0370:
941 case 0371:
942 case 0372:
943 break;
944 case 0373:
945 length++;
946 break;
947 default: /* can't do it by 'case' statements */
948 if (c >= 0100 && c <= 0277) { /* it's an EA */
949 ea ea_data;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000950 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000951 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000952 ea_data.rex = 0; /* Ensure ea.REX is initially 0 */
953
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000954 if (c <= 0177) {
955 /* pick rfield from operand b */
956 rflags = regflag(&ins->oprs[c & 7]);
957 rfield = regvals[ins->oprs[c & 7].basereg];
958 } else {
959 rflags = 0;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000960 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000961 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000962
H. Peter Anvine2c80182005-01-15 22:15:51 +0000963 if (!process_ea
Keith Kaniosb7a89542007-04-12 02:40:54 +0000964 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000965 rfield, rflags, ins->forw_ref)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000966 errfunc(ERR_NONFATAL, "invalid effective address");
967 return -1;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000968 } else {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000969 ins->rex |= ea_data.rex;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000970 length += ea_data.size;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000971 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000972 } else
973 errfunc(ERR_PANIC, "internal instruction table corrupt"
974 ": instruction code 0x%02X given", c);
975 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000976
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000977 ins->rex &= rex_mask;
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700978
979 if (ins->rex & REX_D) {
980 if (ins->rex & REX_H) {
981 errfunc(ERR_NONFATAL, "cannot use high register in drex instruction");
982 return -1;
983 }
H. Peter Anvincf5180a2007-09-17 17:25:27 -0700984 if (bits != 64 && ((ins->rex & (REX_W|REX_X|REX_B)) ||
985 ins->drexdst > 7)) {
986 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
987 return -1;
988 }
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700989 length++;
990 } else if (ins->rex & REX_REAL) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000991 if (ins->rex & REX_H) {
992 errfunc(ERR_NONFATAL, "cannot use high register in rex instruction");
993 return -1;
994 } else if (bits == 64 ||
995 ((ins->rex & REX_L) &&
996 !(ins->rex & (REX_P|REX_W|REX_X|REX_B)) &&
997 cpu >= IF_X86_64)) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000998 length++;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000999 } else {
H. Peter Anvincf5180a2007-09-17 17:25:27 -07001000 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
1001 return -1;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +00001002 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001003 }
1004
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001005 return length;
1006}
Keith Kaniosb7a89542007-04-12 02:40:54 +00001007
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001008#define EMIT_REX() \
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001009 if (!(ins->rex & REX_D) && (ins->rex & REX_REAL) && (bits == 64)) { \
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001010 ins->rex = (ins->rex & REX_REAL)|REX_P; \
1011 out(offset, segment, &ins->rex, OUT_RAWDATA+1, NO_SEG, NO_SEG); \
1012 ins->rex = 0; \
1013 offset += 1; \
1014 }
1015
Keith Kaniosb7a89542007-04-12 02:40:54 +00001016static void gencode(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001017 insn * ins, const char *codes, int32_t insn_end)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001018{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001019 static char condval[] = { /* conditional opcodes */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001020 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
1021 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
1022 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001023 };
Keith Kaniosb7a89542007-04-12 02:40:54 +00001024 uint8_t c;
1025 uint8_t bytes[4];
1026 int32_t size;
1027 int64_t data;
1028
H. Peter Anvineba20a72002-04-30 20:53:55 +00001029 while (*codes)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001030 switch (c = *codes++) {
1031 case 01:
1032 case 02:
1033 case 03:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001034 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001035 out(offset, segment, codes, OUT_RAWDATA + c, NO_SEG, NO_SEG);
1036 codes += c;
1037 offset += c;
1038 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001039
H. Peter Anvine2c80182005-01-15 22:15:51 +00001040 case 04:
1041 case 06:
1042 switch (ins->oprs[0].basereg) {
1043 case R_CS:
1044 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0);
1045 break;
1046 case R_DS:
1047 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0);
1048 break;
1049 case R_ES:
1050 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0);
1051 break;
1052 case R_SS:
1053 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0);
1054 break;
1055 default:
1056 errfunc(ERR_PANIC,
1057 "bizarre 8086 segment register received");
1058 }
1059 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1060 offset++;
1061 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001062
H. Peter Anvine2c80182005-01-15 22:15:51 +00001063 case 05:
1064 case 07:
1065 switch (ins->oprs[0].basereg) {
1066 case R_FS:
1067 bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0);
1068 break;
1069 case R_GS:
1070 bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0);
1071 break;
1072 default:
1073 errfunc(ERR_PANIC,
1074 "bizarre 386 segment register received");
1075 }
1076 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1077 offset++;
1078 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001079
H. Peter Anvine2c80182005-01-15 22:15:51 +00001080 case 010:
1081 case 011:
1082 case 012:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001083 case 013:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001084 EMIT_REX();
Keith Kaniosb7a89542007-04-12 02:40:54 +00001085 bytes[0] = *codes++ + ((regval(&ins->oprs[c - 010])) & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001086 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1087 offset += 1;
1088 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001089
H. Peter Anvine2c80182005-01-15 22:15:51 +00001090 case 014:
1091 case 015:
1092 case 016:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001093 case 017:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001094 if (ins->oprs[c - 014].offset < -128
1095 || ins->oprs[c - 014].offset > 127) {
1096 errfunc(ERR_WARNING, "signed byte value exceeds bounds");
1097 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001098
H. Peter Anvine2c80182005-01-15 22:15:51 +00001099 if (ins->oprs[c - 014].segment != NO_SEG) {
1100 data = ins->oprs[c - 014].offset;
1101 out(offset, segment, &data, OUT_ADDRESS + 1,
1102 ins->oprs[c - 014].segment, ins->oprs[c - 014].wrt);
1103 } else {
1104 bytes[0] = ins->oprs[c - 014].offset;
1105 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1106 NO_SEG);
1107 }
1108 offset += 1;
1109 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001110
H. Peter Anvine2c80182005-01-15 22:15:51 +00001111 case 020:
1112 case 021:
1113 case 022:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001114 case 023:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001115 if (ins->oprs[c - 020].offset < -256
1116 || ins->oprs[c - 020].offset > 255) {
1117 errfunc(ERR_WARNING, "byte value exceeds bounds");
1118 }
1119 if (ins->oprs[c - 020].segment != NO_SEG) {
1120 data = ins->oprs[c - 020].offset;
1121 out(offset, segment, &data, OUT_ADDRESS + 1,
1122 ins->oprs[c - 020].segment, ins->oprs[c - 020].wrt);
1123 } else {
1124 bytes[0] = ins->oprs[c - 020].offset;
1125 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1126 NO_SEG);
1127 }
1128 offset += 1;
1129 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001130
H. Peter Anvine2c80182005-01-15 22:15:51 +00001131 case 024:
1132 case 025:
1133 case 026:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001134 case 027:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001135 if (ins->oprs[c - 024].offset < 0
1136 || ins->oprs[c - 024].offset > 255)
1137 errfunc(ERR_WARNING, "unsigned byte value exceeds bounds");
1138 if (ins->oprs[c - 024].segment != NO_SEG) {
1139 data = ins->oprs[c - 024].offset;
1140 out(offset, segment, &data, OUT_ADDRESS + 1,
1141 ins->oprs[c - 024].segment, ins->oprs[c - 024].wrt);
1142 } else {
1143 bytes[0] = ins->oprs[c - 024].offset;
1144 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1145 NO_SEG);
1146 }
1147 offset += 1;
1148 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001149
H. Peter Anvine2c80182005-01-15 22:15:51 +00001150 case 030:
1151 case 031:
1152 case 032:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001153 case 033:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001154 if (ins->oprs[c - 030].segment == NO_SEG &&
1155 ins->oprs[c - 030].wrt == NO_SEG &&
1156 (ins->oprs[c - 030].offset < -65536L ||
1157 ins->oprs[c - 030].offset > 65535L)) {
1158 errfunc(ERR_WARNING, "word value exceeds bounds");
1159 }
1160 data = ins->oprs[c - 030].offset;
1161 out(offset, segment, &data, OUT_ADDRESS + 2,
1162 ins->oprs[c - 030].segment, ins->oprs[c - 030].wrt);
1163 offset += 2;
1164 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001165
H. Peter Anvine2c80182005-01-15 22:15:51 +00001166 case 034:
1167 case 035:
1168 case 036:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001169 case 037:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001170 if (ins->oprs[c - 034].type & (BITS16 | BITS32))
1171 size = (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
1172 else
1173 size = (bits == 16) ? 2 : 4;
1174 data = ins->oprs[c - 034].offset;
1175 if (size == 2 && (data < -65536L || data > 65535L))
1176 errfunc(ERR_WARNING, "word value exceeds bounds");
1177 out(offset, segment, &data, OUT_ADDRESS + size,
1178 ins->oprs[c - 034].segment, ins->oprs[c - 034].wrt);
1179 offset += size;
1180 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001181
H. Peter Anvine2c80182005-01-15 22:15:51 +00001182 case 040:
1183 case 041:
1184 case 042:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001185 case 043:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001186 data = ins->oprs[c - 040].offset;
1187 out(offset, segment, &data, OUT_ADDRESS + 4,
1188 ins->oprs[c - 040].segment, ins->oprs[c - 040].wrt);
1189 offset += 4;
1190 break;
H. Peter Anvin3ba46772002-05-27 23:19:35 +00001191
H. Peter Anvine2c80182005-01-15 22:15:51 +00001192 case 044:
1193 case 045:
1194 case 046:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001195 case 047:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001196 data = ins->oprs[c - 044].offset;
1197 size = ((ins->oprs[c - 044].addr_size ?
Keith Kaniosb7a89542007-04-12 02:40:54 +00001198 ins->oprs[c - 044].addr_size : bits) >> 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001199 if (size == 2 && (data < -65536L || data > 65535L))
1200 errfunc(ERR_WARNING, "word value exceeds bounds");
1201 out(offset, segment, &data, OUT_ADDRESS + size,
1202 ins->oprs[c - 044].segment, ins->oprs[c - 044].wrt);
1203 offset += size;
1204 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001205
H. Peter Anvine2c80182005-01-15 22:15:51 +00001206 case 050:
1207 case 051:
1208 case 052:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001209 case 053:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001210 if (ins->oprs[c - 050].segment != segment)
1211 errfunc(ERR_NONFATAL,
1212 "short relative jump outside segment");
1213 data = ins->oprs[c - 050].offset - insn_end;
1214 if (data > 127 || data < -128)
1215 errfunc(ERR_NONFATAL, "short jump is out of range");
1216 bytes[0] = data;
1217 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1218 offset += 1;
1219 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001220
1221 case 054:
1222 case 055:
1223 case 056:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001224 case 057:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001225 data = (int64_t)ins->oprs[c - 054].offset;
1226 out(offset, segment, &data, OUT_ADDRESS + 8,
1227 ins->oprs[c - 054].segment, ins->oprs[c - 054].wrt);
1228 offset += 8;
1229 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001230
H. Peter Anvine2c80182005-01-15 22:15:51 +00001231 case 060:
1232 case 061:
1233 case 062:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001234 case 063:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001235 if (ins->oprs[c - 060].segment != segment) {
1236 data = ins->oprs[c - 060].offset;
1237 out(offset, segment, &data,
1238 OUT_REL2ADR + insn_end - offset,
1239 ins->oprs[c - 060].segment, ins->oprs[c - 060].wrt);
1240 } else {
1241 data = ins->oprs[c - 060].offset - insn_end;
1242 out(offset, segment, &data,
1243 OUT_ADDRESS + 2, NO_SEG, NO_SEG);
1244 }
1245 offset += 2;
1246 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001247
H. Peter Anvine2c80182005-01-15 22:15:51 +00001248 case 064:
1249 case 065:
1250 case 066:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001251 case 067:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001252 if (ins->oprs[c - 064].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001253 size = (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
1254 else
1255 size = (bits == 16) ? 2 : 4;
1256 if (ins->oprs[c - 064].segment != segment) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001257 int32_t reltype = (size == 2 ? OUT_REL2ADR : OUT_REL4ADR);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001258 data = ins->oprs[c - 064].offset;
1259 out(offset, segment, &data, reltype + insn_end - offset,
1260 ins->oprs[c - 064].segment, ins->oprs[c - 064].wrt);
1261 } else {
1262 data = ins->oprs[c - 064].offset - insn_end;
1263 out(offset, segment, &data,
1264 OUT_ADDRESS + size, NO_SEG, NO_SEG);
1265 }
1266 offset += size;
1267 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001268
H. Peter Anvine2c80182005-01-15 22:15:51 +00001269 case 070:
1270 case 071:
1271 case 072:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001272 case 073:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001273 if (ins->oprs[c - 070].segment != segment) {
1274 data = ins->oprs[c - 070].offset;
1275 out(offset, segment, &data,
1276 OUT_REL4ADR + insn_end - offset,
1277 ins->oprs[c - 070].segment, ins->oprs[c - 070].wrt);
1278 } else {
1279 data = ins->oprs[c - 070].offset - insn_end;
1280 out(offset, segment, &data,
1281 OUT_ADDRESS + 4, NO_SEG, NO_SEG);
1282 }
1283 offset += 4;
1284 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001285
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001286 case 074:
1287 case 075:
1288 case 076:
1289 case 077:
1290 if (ins->oprs[c - 074].segment == NO_SEG)
1291 errfunc(ERR_NONFATAL, "value referenced by FAR is not"
1292 " relocatable");
1293 data = 0L;
1294 out(offset, segment, &data, OUT_ADDRESS + 2,
1295 outfmt->segbase(1 + ins->oprs[c - 074].segment),
1296 ins->oprs[c - 074].wrt);
1297 offset += 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001298 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001299
H. Peter Anvine2c80182005-01-15 22:15:51 +00001300 case 0140:
1301 case 0141:
1302 case 0142:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001303 case 0143:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001304 data = ins->oprs[c - 0140].offset;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001305 if (is_sbyte(ins, c - 0140, 16)) {
1306 bytes[0] = data;
1307 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1308 NO_SEG);
1309 offset++;
1310 } else {
1311 if (ins->oprs[c - 0140].segment == NO_SEG &&
1312 ins->oprs[c - 0140].wrt == NO_SEG &&
1313 (data < -65536L || data > 65535L)) {
1314 errfunc(ERR_WARNING, "word value exceeds bounds");
1315 }
1316 out(offset, segment, &data, OUT_ADDRESS + 2,
H. Peter Anvin8f94f982007-09-17 16:31:33 -07001317 ins->oprs[c - 0140].segment, ins->oprs[c - 0140].wrt);
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001318 offset += 2;
1319 }
1320 break;
1321
1322 case 0144:
1323 case 0145:
1324 case 0146:
1325 case 0147:
1326 EMIT_REX();
1327 codes++;
1328 bytes[0] = *codes++;
1329 if (is_sbyte(ins, c - 0144, 16))
1330 bytes[0] |= 2; /* s-bit */
1331 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1332 offset++;
1333 break;
1334
1335 case 0150:
1336 case 0151:
1337 case 0152:
1338 case 0153:
1339 data = ins->oprs[c - 0150].offset;
1340 if (is_sbyte(ins, c - 0150, 32)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001341 bytes[0] = data;
1342 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1343 NO_SEG);
1344 offset++;
1345 } else {
1346 out(offset, segment, &data, OUT_ADDRESS + 4,
H. Peter Anvin8f94f982007-09-17 16:31:33 -07001347 ins->oprs[c - 0150].segment, ins->oprs[c - 0150].wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001348 offset += 4;
1349 }
1350 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001351
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001352 case 0154:
1353 case 0155:
1354 case 0156:
1355 case 0157:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001356 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001357 codes++;
1358 bytes[0] = *codes++;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001359 if (is_sbyte(ins, c - 0154, 32))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001360 bytes[0] |= 2; /* s-bit */
1361 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1362 offset++;
1363 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001364
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001365 case 0160:
1366 case 0161:
1367 case 0162:
1368 case 0163:
1369 case 0164:
1370 case 0165:
1371 case 0166:
1372 case 0167:
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001373 break;
1374
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001375 case 0170:
1376 bytes[0] = 0;
1377 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1378 offset += 1;
1379 break;
1380
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001381 case 0171:
1382 bytes[0] =
1383 (ins->drexdst << 4) |
1384 (ins->rex & REX_OC ? 0x08 : 0) |
1385 (ins->rex & (REX_R|REX_X|REX_B));
1386 ins->rex = 0;
1387 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1388 offset++;
1389 break;
1390
H. Peter Anvine2c80182005-01-15 22:15:51 +00001391 case 0300:
1392 case 0301:
1393 case 0302:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001394 case 0303:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001395 if (chsize(&ins->oprs[c - 0300], bits)) {
1396 *bytes = 0x67;
1397 out(offset, segment, bytes,
1398 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1399 offset += 1;
1400 } else
1401 offset += 0;
1402 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001403
H. Peter Anvine2c80182005-01-15 22:15:51 +00001404 case 0310:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001405 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001406 *bytes = 0x67;
1407 out(offset, segment, bytes,
1408 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1409 offset += 1;
1410 } else
1411 offset += 0;
1412 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001413
H. Peter Anvine2c80182005-01-15 22:15:51 +00001414 case 0311:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001415 if (bits != 32) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001416 *bytes = 0x67;
1417 out(offset, segment, bytes,
1418 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1419 offset += 1;
1420 } else
1421 offset += 0;
1422 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001423
H. Peter Anvine2c80182005-01-15 22:15:51 +00001424 case 0312:
1425 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001426
Keith Kaniosb7a89542007-04-12 02:40:54 +00001427 case 0313:
1428 ins->rex = 0;
1429 break;
1430
H. Peter Anvine2c80182005-01-15 22:15:51 +00001431 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001432 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001433 *bytes = 0x66;
1434 out(offset, segment, bytes,
1435 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1436 offset += 1;
1437 } else
1438 offset += 0;
1439 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001440
H. Peter Anvine2c80182005-01-15 22:15:51 +00001441 case 0321:
1442 if (bits == 16) {
1443 *bytes = 0x66;
1444 out(offset, segment, bytes,
1445 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1446 offset += 1;
1447 } else
1448 offset += 0;
1449 break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001450
H. Peter Anvine2c80182005-01-15 22:15:51 +00001451 case 0322:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001452 case 0323:
1453 break;
1454
1455 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001456 ins->rex |= REX_W;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001457 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001458
H. Peter Anvine2c80182005-01-15 22:15:51 +00001459 case 0330:
1460 *bytes = *codes++ ^ condval[ins->condition];
1461 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1462 offset += 1;
1463 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001464
H. Peter Anvine2c80182005-01-15 22:15:51 +00001465 case 0331:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001466 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001467
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001468 case 0332:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001469 case 0333:
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001470 *bytes = c - 0332 + 0xF2;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001471 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1472 offset += 1;
1473 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001474
Keith Kanios48af1772007-08-17 07:37:52 +00001475 case 0334:
1476 if (ins->rex & REX_R) {
1477 *bytes = 0xF0;
1478 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1479 offset += 1;
1480 }
1481 ins->rex &= ~(REX_L|REX_R);
1482 break;
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001483
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001484 case 0335:
1485 break;
1486
H. Peter Anvine2c80182005-01-15 22:15:51 +00001487 case 0340:
1488 case 0341:
1489 case 0342:
1490 if (ins->oprs[0].segment != NO_SEG)
1491 errfunc(ERR_PANIC, "non-constant BSS size in pass two");
1492 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001493 int32_t size = ins->oprs[0].offset << (c - 0340);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001494 if (size > 0)
1495 out(offset, segment, NULL,
1496 OUT_RESERVE + size, NO_SEG, NO_SEG);
1497 offset += size;
1498 }
1499 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001500
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001501 case 0364:
1502 case 0365:
1503 break;
1504
Keith Kanios48af1772007-08-17 07:37:52 +00001505 case 0366:
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001506 case 0367:
1507 *bytes = c - 0366 + 0x66;
Keith Kanios48af1772007-08-17 07:37:52 +00001508 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1509 offset += 1;
1510 break;
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001511
H. Peter Anvine2c80182005-01-15 22:15:51 +00001512 case 0370:
1513 case 0371:
1514 case 0372:
1515 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001516
H. Peter Anvine2c80182005-01-15 22:15:51 +00001517 case 0373:
1518 *bytes = bits == 16 ? 3 : 5;
1519 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1520 offset += 1;
1521 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001522
H. Peter Anvine2c80182005-01-15 22:15:51 +00001523 default: /* can't do it by 'case' statements */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001524 if (c >= 0100 && c <= 0277) { /* it's an EA */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001525 ea ea_data;
1526 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001527 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001528 uint8_t *p;
1529 int32_t s;
1530
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001531 if (c <= 0177) {
1532 /* pick rfield from operand b */
1533 rflags = regflag(&ins->oprs[c & 7]);
1534 rfield = regvals[ins->oprs[c & 7].basereg];
1535 } else {
1536 /* rfield is constant */
1537 rflags = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001538 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001539 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001540
1541 if (!process_ea
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001542 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
1543 rfield, rflags, ins->forw_ref)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001544 errfunc(ERR_NONFATAL, "invalid effective address");
1545 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001546
H. Peter Anvine2c80182005-01-15 22:15:51 +00001547 p = bytes;
1548 *p++ = ea_data.modrm;
1549 if (ea_data.sib_present)
1550 *p++ = ea_data.sib;
1551
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001552 /* DREX suffixes come between the SIB and the displacement */
1553 if (ins->rex & REX_D) {
1554 *p++ =
1555 (ins->drexdst << 4) |
1556 (ins->rex & REX_OC ? 0x08 : 0) |
1557 (ins->rex & (REX_R|REX_X|REX_B));
1558 ins->rex = 0;
1559 }
1560
H. Peter Anvine2c80182005-01-15 22:15:51 +00001561 s = p - bytes;
1562 out(offset, segment, bytes, OUT_RAWDATA + s,
1563 NO_SEG, NO_SEG);
1564
1565 switch (ea_data.bytes) {
1566 case 0:
1567 break;
1568 case 1:
1569 if (ins->oprs[(c >> 3) & 7].segment != NO_SEG) {
1570 data = ins->oprs[(c >> 3) & 7].offset;
1571 out(offset, segment, &data, OUT_ADDRESS + 1,
1572 ins->oprs[(c >> 3) & 7].segment,
1573 ins->oprs[(c >> 3) & 7].wrt);
1574 } else {
1575 *bytes = ins->oprs[(c >> 3) & 7].offset;
1576 out(offset, segment, bytes, OUT_RAWDATA + 1,
1577 NO_SEG, NO_SEG);
1578 }
1579 s++;
1580 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001581 case 8:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001582 case 2:
1583 case 4:
1584 data = ins->oprs[(c >> 3) & 7].offset;
Keith Kaniose83b3182007-04-16 14:31:54 +00001585 if (ea_data.rip && (ins->oprs[(c >> 3) & 7].segment == 0xFFFFFFFF))
1586 ea_data.rip = 0; /* Make distinction between Symbols and Immediates */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001587 out(offset, segment, &data, /* RIP = Relative, not Absolute */
1588 (ea_data.rip ? OUT_REL4ADR : OUT_ADDRESS) + ea_data.bytes,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001589 ins->oprs[(c >> 3) & 7].segment,
1590 ins->oprs[(c >> 3) & 7].wrt);
1591 s += ea_data.bytes;
1592 break;
1593 }
1594 offset += s;
1595 } else
1596 errfunc(ERR_PANIC, "internal instruction table corrupt"
1597 ": instruction code 0x%02X given", c);
1598 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001599}
1600
H. Peter Anvin0ec60e62007-07-07 01:59:52 +00001601static int32_t regflag(const operand * o)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001602{
1603 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1604 errfunc(ERR_PANIC, "invalid operand passed to regflag()");
1605 }
1606 return reg_flags[o->basereg];
1607}
1608
H. Peter Anvin5b0e3ec2007-07-07 02:01:08 +00001609static int32_t regval(const operand * o)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001610{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001611 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1612 errfunc(ERR_PANIC, "invalid operand passed to regval()");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001613 }
H. Peter Anvin232badb2002-06-06 02:41:20 +00001614 return regvals[o->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001615}
1616
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001617static int op_rexflags(const operand * o, int mask)
1618{
1619 int32_t flags;
1620 int val;
1621
1622 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1623 errfunc(ERR_PANIC, "invalid operand passed to op_rexflags()");
1624 }
1625
1626 flags = reg_flags[o->basereg];
1627 val = regvals[o->basereg];
1628
1629 return rexflags(val, flags, mask);
1630}
1631
1632static int rexflags(int val, int32_t flags, int mask)
1633{
1634 int rex = 0;
1635
1636 if (val >= 8)
1637 rex |= REX_B|REX_X|REX_R;
1638 if (flags & BITS64)
1639 rex |= REX_W;
1640 if (!(REG_HIGH & ~flags)) /* AH, CH, DH, BH */
1641 rex |= REX_H;
1642 else if (!(REG8 & ~flags) && val >= 4) /* SPL, BPL, SIL, DIL */
1643 rex |= REX_P;
1644
1645 return rex & mask;
1646}
1647
H. Peter Anvin3360d792007-09-11 04:16:57 +00001648static int matches(const struct itemplate *itemp, insn * instruction, int bits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001649{
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001650 int i, size[MAX_OPERANDS], asize, oprs, ret;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001651
1652 ret = 100;
1653
1654 /*
1655 * Check the opcode
1656 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001657 if (itemp->opcode != instruction->opcode)
1658 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001659
1660 /*
1661 * Count the operands
1662 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001663 if (itemp->operands != instruction->operands)
1664 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001665
1666 /*
1667 * Check that no spurious colons or TOs are present
1668 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001669 for (i = 0; i < itemp->operands; i++)
1670 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON | TO))
1671 return 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001672
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001673 /*
1674 * Check that the operand flags all match up
1675 */
H. Peter Anvin16b0a332007-09-12 20:27:41 -07001676 for (i = 0; i < itemp->operands; i++) {
H. Peter Anvincf5180a2007-09-17 17:25:27 -07001677 if (itemp->opd[i] & SAME_AS) {
1678 int j = itemp->opd[i] & ~SAME_AS;
1679 if (instruction->oprs[i].type != instruction->oprs[j].type ||
1680 instruction->oprs[i].basereg != instruction->oprs[j].basereg)
1681 return 0;
1682 } else if (itemp->opd[i] & ~instruction->oprs[i].type ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001683 ((itemp->opd[i] & SIZE_MASK) &&
1684 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK))) {
H. Peter Anvin5a640e12007-05-29 23:57:12 +00001685 if ((itemp->opd[i] & ~instruction->oprs[i].type & ~SIZE_MASK) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001686 (instruction->oprs[i].type & SIZE_MASK))
1687 return 0;
1688 else
H. Peter Anvine2c80182005-01-15 22:15:51 +00001689 return 1;
1690 }
H. Peter Anvin16b0a332007-09-12 20:27:41 -07001691 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001692
1693 /*
1694 * Check operand sizes
1695 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001696 if (itemp->flags & IF_ARMASK) {
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001697 memset(size, 0, sizeof size);
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001698
H. Peter Anvine2c80182005-01-15 22:15:51 +00001699 switch (itemp->flags & IF_ARMASK) {
1700 case IF_AR0:
1701 i = 0;
1702 break;
1703 case IF_AR1:
1704 i = 1;
1705 break;
1706 case IF_AR2:
1707 i = 2;
1708 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001709 case IF_AR3:
1710 i = 3;
1711 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001712 default:
1713 break; /* Shouldn't happen */
1714 }
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001715 switch (itemp->flags & IF_SMASK) {
1716 case IF_SB:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001717 size[i] = BITS8;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001718 break;
1719 case IF_SW:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001720 size[i] = BITS16;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001721 break;
1722 case IF_SD:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001723 size[i] = BITS32;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001724 break;
1725 case IF_SQ:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001726 size[i] = BITS64;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001727 break;
H. Peter Anvin41c9f6f2007-09-18 13:01:32 -07001728 case IF_SO:
1729 size[i] = BITS128;
1730 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001731 default:
1732 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001733 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001734 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001735 asize = 0;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001736 switch (itemp->flags & IF_SMASK) {
1737 case IF_SB:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001738 asize = BITS8;
1739 oprs = itemp->operands;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001740 break;
1741 case IF_SW:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001742 asize = BITS16;
1743 oprs = itemp->operands;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001744 break;
1745 case IF_SD:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001746 asize = BITS32;
1747 oprs = itemp->operands;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001748 break;
1749 case IF_SQ:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001750 asize = BITS64;
1751 oprs = itemp->operands;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001752 break;
H. Peter Anvin41c9f6f2007-09-18 13:01:32 -07001753 case IF_SO:
1754 asize = BITS128;
1755 oprs = itemp->operands;
1756 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001757 default:
1758 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001759 }
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001760 for (i = 0; i < MAX_OPERANDS; i++)
1761 size[i] = asize;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001762 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001763
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001764 if (itemp->flags & (IF_SM | IF_SM2)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001765 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
1766 asize = 0;
1767 for (i = 0; i < oprs; i++) {
1768 if ((asize = itemp->opd[i] & SIZE_MASK) != 0) {
1769 int j;
1770 for (j = 0; j < oprs; j++)
1771 size[j] = asize;
1772 break;
1773 }
1774 }
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001775 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001776 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001777 }
1778
Keith Kaniosb7a89542007-04-12 02:40:54 +00001779 for (i = 0; i < itemp->operands; i++) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001780 if (!(itemp->opd[i] & SIZE_MASK) &&
1781 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001782 return 2;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001783 }
1784
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001785 /*
1786 * Check template is okay at the set cpu level
1787 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001788 if (((itemp->flags & IF_PLEVEL) > cpu))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001789 return 3;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001790
1791 /*
1792 * Check if instruction is available in long mode
1793 */
1794 if ((itemp->flags & IF_NOLONG) && (bits == 64))
1795 return 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001796
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001797 /*
1798 * Check if special handling needed for Jumps
1799 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001800 if ((uint8_t)(itemp->code[0]) >= 0370)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001801 return 99;
1802
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001803 return ret;
1804}
1805
H. Peter Anvine2c80182005-01-15 22:15:51 +00001806static ea *process_ea(operand * input, ea * output, int addrbits,
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001807 int rfield, int32_t rflags, int forw_ref)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001808{
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001809 output->rip = FALSE;
1810
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001811 /* REX flags for the rfield operand */
1812 output->rex |= rexflags(rfield, rflags, REX_R|REX_P|REX_W|REX_H);
1813
Keith Kaniosb7a89542007-04-12 02:40:54 +00001814 if (!(REGISTER & ~input->type)) { /* register direct */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001815 int i;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001816 int32_t f;
1817
1818 if (input->basereg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001819 || input->basereg >= REG_ENUM_LIMIT)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001820 return NULL;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001821 f = regflag(input);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001822 i = regvals[input->basereg];
Keith Kaniosb7a89542007-04-12 02:40:54 +00001823
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001824 if (REG_EA & ~f)
1825 return NULL; /* Invalid EA register */
1826
1827 output->rex |= op_rexflags(input, REX_B|REX_P|REX_W|REX_H);
1828
Keith Kaniosb7a89542007-04-12 02:40:54 +00001829 output->sib_present = FALSE; /* no SIB necessary */
1830 output->bytes = 0; /* no offset necessary either */
1831 output->modrm = 0xC0 | ((rfield & 7) << 3) | (i & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001832 } else { /* it's a memory reference */
1833 if (input->basereg == -1
1834 && (input->indexreg == -1 || input->scale == 0)) {
1835 /* it's a pure offset */
1836 if (input->addr_size)
1837 addrbits = input->addr_size;
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001838
1839 if (globalbits == 64 && (~input->type & IP_REL)) {
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00001840 int scale, index, base;
1841 output->sib_present = TRUE;
1842 scale = 0;
1843 index = 4;
1844 base = 5;
1845 output->sib = (scale << 6) | (index << 3) | base;
1846 output->bytes = 4;
1847 output->modrm = 4 | ((rfield & 7) << 3);
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001848 output->rip = FALSE;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00001849 } else {
1850 output->sib_present = FALSE;
1851 output->bytes = (addrbits != 16 ? 4 : 2);
1852 output->modrm = (addrbits != 16 ? 5 : 6) | ((rfield & 7) << 3);
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001853 output->rip = globalbits == 64;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00001854 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001855 } else { /* it's an indirection */
1856 int i = input->indexreg, b = input->basereg, s = input->scale;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001857 int32_t o = input->offset, seg = input->segment;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001858 int hb = input->hintbase, ht = input->hinttype;
1859 int t;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001860 int it, bt;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001861 int32_t ix, bx; /* register flags */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001862
H. Peter Anvine2c80182005-01-15 22:15:51 +00001863 if (s == 0)
1864 i = -1; /* make this easy, at least */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001865
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001866 if (i >= EXPR_REG_START && i < REG_ENUM_LIMIT) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001867 it = regvals[i];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001868 ix = reg_flags[i];
1869 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001870 it = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001871 ix = 0;
1872 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001873
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001874 if (b != -1 && b >= EXPR_REG_START && b < REG_ENUM_LIMIT) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001875 bt = regvals[b];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001876 bx = reg_flags[b];
1877 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001878 bt = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001879 bx = 0;
1880 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001881
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001882 /* check for a 32/64-bit memory reference... */
1883 if ((ix|bx) & (BITS32|BITS64)) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001884 /* it must be a 32/64-bit memory reference. Firstly we have
1885 * to check that all registers involved are type E/Rxx. */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001886 int32_t sok = BITS32|BITS64;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001887
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001888 if (it != -1) {
1889 if (!(REG64 & ~ix) || !(REG32 & ~ix))
1890 sok &= ix;
1891 else
1892 return NULL;
1893 }
1894
1895 if (bt != -1) {
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001896 if (REG_GPR & ~bx)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001897 return NULL; /* Invalid register */
H. Peter Anvina57e8d42007-05-30 03:44:02 +00001898 if (~sok & bx & SIZE_MASK)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001899 return NULL; /* Invalid size */
1900 sok &= ~bx;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001901 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001902
H. Peter Anvine2c80182005-01-15 22:15:51 +00001903 /* While we're here, ensure the user didn't specify WORD. */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001904 if (input->addr_size == 16 ||
1905 (input->addr_size == 32 && !(sok & BITS32)) ||
1906 (input->addr_size == 64 && !(sok & BITS64)))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001907 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001908
Keith Kaniosb7a89542007-04-12 02:40:54 +00001909 /* now reorganize base/index */
1910 if (s == 1 && bt != it && bt != -1 && it != -1 &&
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001911 ((hb == b && ht == EAH_NOTBASE)
1912 || (hb == i && ht == EAH_MAKEBASE))) {
1913 /* swap if hints say so */
1914 t = bt, bt = it, it = t;
1915 t = bx, bx = ix, ix = t;
1916 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001917 if (bt == it) /* convert EAX+2*EAX to 3*EAX */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001918 bt = -1, bx = 0, s++;
1919 if (bt == -1 && s == 1 && !(hb == it && ht == EAH_NOTBASE)) {
1920 /* make single reg base, unless hint */
1921 bt = it, bx = ix, it = -1, ix = 0;
1922 }
H. Peter Anvinf5843c62007-09-10 18:59:26 +00001923 if (((s == 2 && it != REG_NUM_ESP
H. Peter Anvine2c80182005-01-15 22:15:51 +00001924 && !(input->eaflags & EAF_TIMESTWO)) || s == 3
Keith Kaniosb7a89542007-04-12 02:40:54 +00001925 || s == 5 || s == 9) && bt == -1)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001926 bt = it, bx = ix, s--; /* convert 3*EAX to EAX+2*EAX */
Keith Kanios48af1772007-08-17 07:37:52 +00001927 if (it == -1 && (bt & 7) != REG_NUM_ESP
H. Peter Anvine2c80182005-01-15 22:15:51 +00001928 && (input->eaflags & EAF_TIMESTWO))
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001929 it = bt, ix = bx, bt = -1, bx = 0, s = 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001930 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
Keith Kanios48af1772007-08-17 07:37:52 +00001931 if (s == 1 && it == REG_NUM_ESP) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001932 /* swap ESP into base if scale is 1 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001933 t = it, it = bt, bt = t;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001934 t = ix, ix = bx, bx = t;
1935 }
Keith Kanios48af1772007-08-17 07:37:52 +00001936 if (it == REG_NUM_ESP
Keith Kaniosb7a89542007-04-12 02:40:54 +00001937 || (s != 1 && s != 2 && s != 4 && s != 8 && it != -1))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001938 return NULL; /* wrong, for various reasons */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001939
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001940 output->rex |= rexflags(it, ix, REX_X);
1941 output->rex |= rexflags(bt, bx, REX_B);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001942
Keith Kanios48af1772007-08-17 07:37:52 +00001943 if (it == -1 && (bt & 7) != REG_NUM_ESP) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001944 /* no SIB needed */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001945 int mod, rm;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001946
1947 if (bt == -1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001948 rm = 5;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001949 mod = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001950 } else {
1951 rm = (bt & 7);
Keith Kanios48af1772007-08-17 07:37:52 +00001952 if (rm != REG_NUM_EBP && o == 0 &&
Keith Kaniosb7a89542007-04-12 02:40:54 +00001953 seg == NO_SEG && !forw_ref &&
1954 !(input->eaflags &
1955 (EAF_BYTEOFFS | EAF_WORDOFFS)))
1956 mod = 0;
1957 else if (input->eaflags & EAF_BYTEOFFS ||
1958 (o >= -128 && o <= 127 && seg == NO_SEG
1959 && !forw_ref
1960 && !(input->eaflags & EAF_WORDOFFS)))
1961 mod = 1;
1962 else
1963 mod = 2;
1964 }
H. Peter Anvinea838272002-04-30 20:51:53 +00001965
H. Peter Anvine2c80182005-01-15 22:15:51 +00001966 output->sib_present = FALSE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001967 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
1968 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001969 } else {
1970 /* we need a SIB */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001971 int mod, scale, index, base;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001972
1973 if (it == -1)
1974 index = 4, s = 1;
1975 else
1976 index = (it & 7);
1977
H. Peter Anvine2c80182005-01-15 22:15:51 +00001978 switch (s) {
1979 case 1:
1980 scale = 0;
1981 break;
1982 case 2:
1983 scale = 1;
1984 break;
1985 case 4:
1986 scale = 2;
1987 break;
1988 case 8:
1989 scale = 3;
1990 break;
1991 default: /* then what the smeg is it? */
1992 return NULL; /* panic */
1993 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001994
1995 if (bt == -1) {
1996 base = 5;
1997 mod = 0;
1998 } else {
1999 base = (bt & 7);
Keith Kanios48af1772007-08-17 07:37:52 +00002000 if (base != REG_NUM_EBP && o == 0 &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00002001 seg == NO_SEG && !forw_ref &&
2002 !(input->eaflags &
Keith Kaniosb7a89542007-04-12 02:40:54 +00002003 (EAF_BYTEOFFS | EAF_WORDOFFS)))
2004 mod = 0;
2005 else if (input->eaflags & EAF_BYTEOFFS ||
2006 (o >= -128 && o <= 127 && seg == NO_SEG
2007 && !forw_ref
2008 && !(input->eaflags & EAF_WORDOFFS)))
2009 mod = 1;
2010 else
2011 mod = 2;
2012 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002013
H. Peter Anvine2c80182005-01-15 22:15:51 +00002014 output->sib_present = TRUE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002015 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
2016 output->modrm = (mod << 6) | ((rfield & 7) << 3) | 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002017 output->sib = (scale << 6) | (index << 3) | base;
2018 }
2019 } else { /* it's 16-bit */
2020 int mod, rm;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002021
2022 /* check for 64-bit long mode */
2023 if (addrbits == 64)
2024 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002025
H. Peter Anvine2c80182005-01-15 22:15:51 +00002026 /* check all registers are BX, BP, SI or DI */
2027 if ((b != -1 && b != R_BP && b != R_BX && b != R_SI
2028 && b != R_DI) || (i != -1 && i != R_BP && i != R_BX
2029 && i != R_SI && i != R_DI))
2030 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002031
Keith Kaniosb7a89542007-04-12 02:40:54 +00002032 /* ensure the user didn't specify DWORD/QWORD */
2033 if (input->addr_size == 32 || input->addr_size == 64)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002034 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002035
H. Peter Anvine2c80182005-01-15 22:15:51 +00002036 if (s != 1 && i != -1)
2037 return NULL; /* no can do, in 16-bit EA */
2038 if (b == -1 && i != -1) {
2039 int tmp = b;
2040 b = i;
2041 i = tmp;
2042 } /* swap */
2043 if ((b == R_SI || b == R_DI) && i != -1) {
2044 int tmp = b;
2045 b = i;
2046 i = tmp;
2047 }
2048 /* have BX/BP as base, SI/DI index */
2049 if (b == i)
2050 return NULL; /* shouldn't ever happen, in theory */
2051 if (i != -1 && b != -1 &&
2052 (i == R_BP || i == R_BX || b == R_SI || b == R_DI))
2053 return NULL; /* invalid combinations */
2054 if (b == -1) /* pure offset: handled above */
2055 return NULL; /* so if it gets to here, panic! */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002056
H. Peter Anvine2c80182005-01-15 22:15:51 +00002057 rm = -1;
2058 if (i != -1)
2059 switch (i * 256 + b) {
2060 case R_SI * 256 + R_BX:
2061 rm = 0;
2062 break;
2063 case R_DI * 256 + R_BX:
2064 rm = 1;
2065 break;
2066 case R_SI * 256 + R_BP:
2067 rm = 2;
2068 break;
2069 case R_DI * 256 + R_BP:
2070 rm = 3;
2071 break;
2072 } else
2073 switch (b) {
2074 case R_SI:
2075 rm = 4;
2076 break;
2077 case R_DI:
2078 rm = 5;
2079 break;
2080 case R_BP:
2081 rm = 6;
2082 break;
2083 case R_BX:
2084 rm = 7;
2085 break;
2086 }
2087 if (rm == -1) /* can't happen, in theory */
2088 return NULL; /* so panic if it does */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002089
H. Peter Anvine2c80182005-01-15 22:15:51 +00002090 if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
2091 !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
2092 mod = 0;
2093 else if (input->eaflags & EAF_BYTEOFFS ||
2094 (o >= -128 && o <= 127 && seg == NO_SEG
2095 && !forw_ref
2096 && !(input->eaflags & EAF_WORDOFFS)))
2097 mod = 1;
2098 else
2099 mod = 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002100
H. Peter Anvine2c80182005-01-15 22:15:51 +00002101 output->sib_present = FALSE; /* no SIB - it's 16-bit */
2102 output->bytes = mod; /* bytes of offset needed */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002103 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002104 }
2105 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002106 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00002107
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002108 output->size = 1 + output->sib_present + output->bytes;
2109 return output;
2110}
2111
H. Peter Anvine2c80182005-01-15 22:15:51 +00002112static int chsize(operand * input, int addrbits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002113{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002114 if (!(MEMORY & ~input->type)) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002115 int32_t i, b;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002116
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002117 if (input->indexreg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002118 || input->indexreg >= REG_ENUM_LIMIT)
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00002119 i = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002120 else
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002121 i = reg_flags[input->indexreg];
Keith Kaniosb7a89542007-04-12 02:40:54 +00002122
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002123 if (input->basereg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002124 || input->basereg >= REG_ENUM_LIMIT)
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00002125 b = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002126 else
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002127 b = reg_flags[input->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002128
H. Peter Anvine2c80182005-01-15 22:15:51 +00002129 if (input->scale == 0)
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00002130 i = 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002131
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00002132 if (!i && !b) /* pure offset */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002133 return (input->addr_size != 0 && input->addr_size != addrbits);
Keith Kaniosb7a89542007-04-12 02:40:54 +00002134
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002135 if (!(REG32 & ~i) || !(REG32 & ~b))
Keith Kaniosb7a89542007-04-12 02:40:54 +00002136 return (addrbits != 32);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002137 else
2138 return (addrbits == 32);
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002139 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002140 return 0;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002141 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002142}