blob: 928dab6dc9406fcbaddb8b279fa5aaef43b38f98 [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
Beroset095e6a22007-12-29 09:44:23 -05005 * redistributable under the license given in the file "LICENSE"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00006 * 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.)
H. Peter Anvindcffe4b2008-10-10 22:10:31 -070010 * \1..\4 - that many literal bytes follow in the code stream
11 * \5 - add 4 to the primary operand number (b, low octdigit)
12 * \6 - add 4 to the secondary operand number (a, middle octdigit)
13 * \7 - add 4 to both the primary and the secondary operand number
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070014 * \10..\13 - a literal byte follows in the code stream, to be added
15 * to the register value of operand 0..3
16 * \14..\17 - a signed byte immediate operand, from operand 0..3
17 * \20..\23 - a byte immediate operand, from operand 0..3
18 * \24..\27 - an unsigned byte immediate operand, from operand 0..3
19 * \30..\33 - a word immediate operand, from operand 0..3
20 * \34..\37 - select between \3[0-3] and \4[0-3] depending on 16/32 bit
H. Peter Anvin3ba46772002-05-27 23:19:35 +000021 * assembly mode or the operand-size override on the operand
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070022 * \40..\43 - a long immediate operand, from operand 0..3
23 * \44..\47 - select between \3[0-3], \4[0-3] and \5[4-7]
H. Peter Anvinde4b89b2007-10-01 15:41:25 -070024 * depending on the address size of the instruction.
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070025 * \50..\53 - a byte relative operand, from operand 0..3
26 * \54..\57 - a qword immediate operand, from operand 0..3
27 * \60..\63 - a word relative operand, from operand 0..3
28 * \64..\67 - select between \6[0-3] and \7[0-3] depending on 16/32 bit
H. Peter Anvin17799b42002-05-21 03:31:21 +000029 * assembly mode or the operand-size override on the operand
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070030 * \70..\73 - a long relative operand, from operand 0..3
H. Peter Anvinc1377e92008-10-06 23:40:31 -070031 * \74..\77 - a word constant, from the _segment_ part of operand 0..3
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000032 * \1ab - a ModRM, calculated on EA in operand a, with the spare
33 * field the register value of operand b.
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070034 * \140..\143 - an immediate word or signed byte for operand 0..3
H. Peter Anvina30cc072007-11-18 21:55:26 -080035 * \144..\147 - or 2 (s-field) into opcode byte if operand 0..3
36 * is a signed byte rather than a word. Opcode byte follows.
H. Peter Anvinc1377e92008-10-06 23:40:31 -070037 * \150..\153 - an immediate dword or signed byte for operand 0..3
H. Peter Anvina30cc072007-11-18 21:55:26 -080038 * \154..\157 - or 2 (s-field) into opcode byte if operand 0..3
H. Peter Anvin32cd4c22008-04-04 13:34:53 -070039 * is a signed byte rather than a dword. Opcode byte follows.
H. Peter Anvin401c07e2007-09-17 16:55:04 -070040 * \160..\163 - this instruction uses DREX rather than REX, with the
41 * OC0 field set to 0, and the dest field taken from
42 * operand 0..3.
43 * \164..\167 - this instruction uses DREX rather than REX, with the
44 * OC0 field set to 1, and the dest field taken from
45 * operand 0..3.
H. Peter Anvin401c07e2007-09-17 16:55:04 -070046 * \171 - placement of DREX suffix in the absence of an EA
H. Peter Anvind85d2502008-05-04 17:53:31 -070047 * \172\ab - the register number from operand a in bits 7..4, with
H. Peter Anvin52dc3532008-05-20 19:29:04 -070048 * the 4-bit immediate from operand b in bits 3..0.
H. Peter Anvind58656f2008-05-06 20:11:14 -070049 * \173\xab - the register number from operand a in bits 7..4, with
H. Peter Anvin52dc3532008-05-20 19:29:04 -070050 * the value b in bits 3..0.
51 * \174\a - the register number from operand a in bits 7..4, and
52 * an arbitrary value in bits 3..0 (assembled as zero.)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000053 * \2ab - a ModRM, calculated on EA in operand a, with the spare
54 * field equal to digit b.
H. Peter Anvin32cd4c22008-04-04 13:34:53 -070055 * \250..\253 - same as \150..\153, except warn if the 64-bit operand
56 * is not equal to the truncated and sign-extended 32-bit
57 * operand; used for 32-bit immediates in 64-bit mode.
H. Peter Anvin588df782008-10-07 10:05:10 -070058 * \254..\257 - a signed 32-bit operand to be extended to 64 bits.
H. Peter Anvina04019c2009-05-03 21:42:34 -070059 * \260..\263 - this instruction uses VEX/XOP rather than REX, with the
H. Peter Anvind85d2502008-05-04 17:53:31 -070060 * V field taken from operand 0..3.
H. Peter Anvina04019c2009-05-03 21:42:34 -070061 * \270 - this instruction uses VEX/XOP rather than REX, with the
H. Peter Anvind85d2502008-05-04 17:53:31 -070062 * V field set to 1111b.
63 *
H. Peter Anvina04019c2009-05-03 21:42:34 -070064 * VEX/XOP prefixes are followed by the sequence:
65 * \tmm\wlp where mm is the M field; and wlp is:
H. Peter Anvinaaa088f2008-05-12 11:13:41 -070066 * 00 0ww lpp
H. Peter Anvinbd420c72008-05-22 11:24:35 -070067 * [w0] ww = 0 for W = 0
68 * [w1] ww = 1 for W = 1
69 * [wx] ww = 2 for W don't care (always assembled as 0)
70 * [ww] ww = 3 for W used as REX.W
71 *
H. Peter Anvina04019c2009-05-03 21:42:34 -070072 * t = 0 for VEX (C4/C5), t = 1 for XOP (8F).
H. Peter Anvind85d2502008-05-04 17:53:31 -070073 *
H. Peter Anvinc1377e92008-10-06 23:40:31 -070074 * \274..\277 - a signed byte immediate operand, from operand 0..3,
75 * which is to be extended to the operand size.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000076 * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
77 * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
H. Peter Anvind28f07f2009-06-26 16:18:00 -070078 * \312 - (disassembler only) invalid with non-default address size.
H. Peter Anvince2b3972007-05-30 22:21:11 +000079 * \313 - indicates fixed 64-bit address size, 0x67 invalid.
H. Peter Anvin23440102007-11-12 21:02:33 -080080 * \314 - (disassembler only) invalid with REX.B
81 * \315 - (disassembler only) invalid with REX.X
82 * \316 - (disassembler only) invalid with REX.R
83 * \317 - (disassembler only) invalid with REX.W
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000084 * \320 - indicates fixed 16-bit operand size, i.e. optional 0x66.
85 * \321 - indicates fixed 32-bit operand size, i.e. optional 0x66.
86 * \322 - indicates that this instruction is only valid when the
87 * operand size is the default (instruction to disassembler,
88 * generates no code in the assembler)
H. Peter Anvince2b3972007-05-30 22:21:11 +000089 * \323 - indicates fixed 64-bit operand size, REX on extensions only.
Keith Kaniosb7a89542007-04-12 02:40:54 +000090 * \324 - indicates 64-bit operand size requiring REX prefix.
H. Peter Anvin9472dab2009-06-24 21:38:29 -070091 * \325 - instruction which always uses spl/bpl/sil/dil
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000092 * \330 - a literal byte follows in the code stream, to be added
93 * to the condition code value of the instruction.
Keith Kanios48af1772007-08-17 07:37:52 +000094 * \331 - instruction not valid with REP prefix. Hint for
H. Peter Anvinef7468f2002-04-30 20:57:59 +000095 * disassembler only; for SSE instructions.
H. Peter Anvincb9b6902007-09-12 21:58:51 -070096 * \332 - REP prefix (0xF2 byte) used as opcode extension.
97 * \333 - REP prefix (0xF3 byte) used as opcode extension.
H. Peter Anvin9472dab2009-06-24 21:38:29 -070098 * \334 - LOCK prefix used as REX.R (used in non-64-bit mode)
H. Peter Anvincb9b6902007-09-12 21:58:51 -070099 * \335 - disassemble a rep (0xF3 byte) prefix as repe not rep.
H. Peter Anvin962e3052008-08-28 17:47:16 -0700100 * \336 - force a REP(E) prefix (0xF2) even if not specified.
101 * \337 - force a REPNE prefix (0xF3) even if not specified.
102 * \336-\337 are still listed as prefixes in the disassembler.
Keith Kaniosb7a89542007-04-12 02:40:54 +0000103 * \340 - reserve <operand 0> bytes of uninitialized storage.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000104 * Operand 0 had better be a segmentless constant.
H. Peter Anvinc2acf7b2009-02-21 18:22:56 -0800105 * \341 - this instruction needs a WAIT "prefix"
H. Peter Anvinff6e12d2008-10-08 21:17:32 -0700106 * \344,\345 - the PUSH/POP (respectively) codes for CS, DS, ES, SS
107 * (POP is never used for CS) depending on operand 0
108 * \346,\347 - the second byte of PUSH/POP codes for FS, GS, depending
109 * on operand 0
H. Peter Anvinfff5a472008-05-20 09:46:24 -0700110 * \360 - no SSE prefix (== \364\331)
111 * \361 - 66 SSE prefix (== \366\331)
112 * \362 - F2 SSE prefix (== \364\332)
113 * \363 - F3 SSE prefix (== \364\333)
H. Peter Anvin62cb6062007-09-11 22:44:03 +0000114 * \364 - operand-size prefix (0x66) not permitted
115 * \365 - address-size prefix (0x67) not permitted
116 * \366 - operand-size prefix (0x66) used as opcode extension
117 * \367 - address-size prefix (0x67) used as opcode extension
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000118 * \370,\371,\372 - match only if operand 0 meets byte jump criteria.
119 * 370 is used for Jcc, 371 is used for JMP.
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000120 * \373 - assemble 0x03 if bits==16, 0x05 if bits==32;
121 * used for conditional jump over longer jump
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000122 */
123
H. Peter Anvinfe501952007-10-02 21:53:51 -0700124#include "compiler.h"
125
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000126#include <stdio.h>
127#include <string.h>
Keith Kaniosb7a89542007-04-12 02:40:54 +0000128#include <inttypes.h>
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000129
130#include "nasm.h"
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000131#include "nasmlib.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000132#include "assemble.h"
133#include "insns.h"
H. Peter Anvina4835d42008-05-20 14:21:29 -0700134#include "tables.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000135
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000136typedef struct {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000137 int sib_present; /* is a SIB byte necessary? */
138 int bytes; /* # of bytes of offset needed */
139 int size; /* lazy - this is sib+bytes+1 */
140 uint8_t modrm, sib, rex, rip; /* the bytes themselves */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000141} ea;
142
Keith Kaniosb7a89542007-04-12 02:40:54 +0000143static uint32_t cpu; /* cpu level received from nasm.c */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000144static efunc errfunc;
145static struct ofmt *outfmt;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000146static ListGen *list;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000147
H. Peter Anvin3720f7b2008-05-12 11:00:50 -0700148static int64_t calcsize(int32_t, int64_t, int, insn *, const uint8_t *);
H. Peter Anvin833caea2008-10-04 19:02:30 -0700149static void gencode(int32_t segment, int64_t offset, int bits,
150 insn * ins, const struct itemplate *temp,
151 int64_t insn_end);
H. Peter Anvin3360d792007-09-11 04:16:57 +0000152static int matches(const struct itemplate *, insn *, int bits);
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000153static int32_t regflag(const operand *);
154static int32_t regval(const operand *);
155static int rexflags(int, int32_t, int);
156static int op_rexflags(const operand *, int);
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700157static ea *process_ea(operand *, ea *, int, int, int, int32_t);
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700158static void add_asp(insn *, int);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000159
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700160static int has_prefix(insn * ins, enum prefix_pos pos, enum prefixes prefix)
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000161{
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700162 return ins->prefixes[pos] == prefix;
163}
164
165static void assert_no_prefix(insn * ins, enum prefix_pos pos)
166{
167 if (ins->prefixes[pos])
168 errfunc(ERR_NONFATAL, "invalid %s prefix",
169 prefix_name(ins->prefixes[pos]));
170}
171
172static const char *size_name(int size)
173{
174 switch (size) {
175 case 1:
176 return "byte";
177 case 2:
178 return "word";
179 case 4:
180 return "dword";
181 case 8:
182 return "qword";
183 case 10:
184 return "tword";
185 case 16:
186 return "oword";
H. Peter Anvindfb91802008-05-20 11:43:53 -0700187 case 32:
188 return "yword";
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700189 default:
190 return "???";
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000191 }
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700192}
193
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700194static void warn_overflow(int size, const struct operand *o)
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700195{
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700196 if (size < 8 && o->wrt == NO_SEG && o->segment == NO_SEG) {
Charles Craynedd462c82007-11-04 15:28:30 -0800197 int64_t lim = ((int64_t)1 << (size*8))-1;
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700198 int64_t data = o->offset;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000199
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700200 if (data < ~lim || data > lim)
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700201 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700202 "%s data exceeds bounds", size_name(size));
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700203 }
204}
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000205/*
206 * This routine wrappers the real output format's output routine,
207 * in order to pass a copy of the data off to the listing file
208 * generator at the same time.
209 */
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800210static void out(int64_t offset, int32_t segto, const void *data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800211 enum out_type type, uint64_t size,
212 int32_t segment, int32_t wrt)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000213{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000214 static int32_t lineno = 0; /* static!!! */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000215 static char *lnfname = NULL;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800216 uint8_t p[8];
H. Peter Anvineba20a72002-04-30 20:53:55 +0000217
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800218 if (type == OUT_ADDRESS && segment == NO_SEG && wrt == NO_SEG) {
219 /*
220 * This is a non-relocated address, and we're going to
221 * convert it into RAWDATA format.
222 */
223 uint8_t *q = p;
H. Peter Anvind1fb15c2007-11-13 09:37:59 -0800224
225 if (size > 8) {
226 errfunc(ERR_PANIC, "OUT_ADDRESS with size > 8");
227 return;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800228 }
H. Peter Anvind85d2502008-05-04 17:53:31 -0700229
H. Peter Anvind1fb15c2007-11-13 09:37:59 -0800230 WRITEADDR(q, *(int64_t *)data, size);
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800231 data = p;
232 type = OUT_RAWDATA;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000233 }
234
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800235 list->output(offset, data, type, size);
236
Frank Kotlerabebb082003-09-06 04:45:37 +0000237 /*
238 * this call to src_get determines when we call the
239 * debug-format-specific "linenum" function
240 * it updates lineno and lnfname to the current values
241 * returning 0 if "same as last time", -2 if lnfname
242 * changed, and the amount by which lineno changed,
243 * if it did. thus, these variables must be static
244 */
245
H. Peter Anvine2c80182005-01-15 22:15:51 +0000246 if (src_get(&lineno, &lnfname)) {
247 outfmt->current_dfmt->linenum(lnfname, lineno, segto);
H. Peter Anvince616072002-04-30 21:02:23 +0000248 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000249
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800250 outfmt->output(segto, data, type, size, segment, wrt);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000251}
252
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700253static bool jmp_match(int32_t segment, int64_t offset, int bits,
H. Peter Anvin3720f7b2008-05-12 11:00:50 -0700254 insn * ins, const uint8_t *code)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000255{
Charles Crayne5fbbc8c2007-11-07 19:03:46 -0800256 int64_t isize;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000257 uint8_t c = code[0];
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000258
Charles Craynef1aefd82008-09-30 16:11:32 -0700259 if ((c != 0370 && c != 0371) || (ins->oprs[0].type & STRICT))
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700260 return false;
261 if (!optimizing)
262 return false;
263 if (optimizing < 0 && c == 0371)
264 return false;
265
H. Peter Anvine2c80182005-01-15 22:15:51 +0000266 isize = calcsize(segment, offset, bits, ins, code);
Victor van den Elzenccafc3c2009-02-23 04:35:00 +0100267
Victor van den Elzen154e5922009-02-25 17:32:00 +0100268 if (ins->oprs[0].opflags & OPFLAG_UNKNOWN)
Victor van den Elzenccafc3c2009-02-23 04:35:00 +0100269 /* Be optimistic in pass 1 */
270 return true;
271
H. Peter Anvine2c80182005-01-15 22:15:51 +0000272 if (ins->oprs[0].segment != segment)
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700273 return false;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000274
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700275 isize = ins->oprs[0].offset - offset - isize; /* isize is delta */
276 return (isize >= -128 && isize <= 127); /* is it byte size? */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000277}
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000278
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800279int64_t assemble(int32_t segment, int64_t offset, int bits, uint32_t cp,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000280 insn * instruction, struct ofmt *output, efunc error,
281 ListGen * listgen)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000282{
H. Peter Anvin3360d792007-09-11 04:16:57 +0000283 const struct itemplate *temp;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000284 int j;
285 int size_prob;
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800286 int64_t insn_end;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000287 int32_t itimes;
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800288 int64_t start = offset;
289 int64_t wsize = 0; /* size for DB etc. */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000290
H. Peter Anvine2c80182005-01-15 22:15:51 +0000291 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000292 cpu = cp;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000293 outfmt = output; /* likewise */
294 list = listgen; /* and again */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000295
H. Peter Anvine2c80182005-01-15 22:15:51 +0000296 switch (instruction->opcode) {
297 case -1:
298 return 0;
299 case I_DB:
300 wsize = 1;
301 break;
302 case I_DW:
303 wsize = 2;
304 break;
305 case I_DD:
306 wsize = 4;
307 break;
308 case I_DQ:
309 wsize = 8;
310 break;
311 case I_DT:
312 wsize = 10;
313 break;
H. Peter Anvincfbe7c32007-09-18 17:49:09 -0700314 case I_DO:
315 wsize = 16;
316 break;
H. Peter Anvindfb91802008-05-20 11:43:53 -0700317 case I_DY:
318 wsize = 32;
319 break;
H. Peter Anvin16b0a332007-09-12 20:27:41 -0700320 default:
321 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000322 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000323
H. Peter Anvineba20a72002-04-30 20:53:55 +0000324 if (wsize) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000325 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000326 int32_t t = instruction->times;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000327 if (t < 0)
328 errfunc(ERR_PANIC,
329 "instruction->times < 0 (%ld) in assemble()", t);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000330
H. Peter Anvine2c80182005-01-15 22:15:51 +0000331 while (t--) { /* repeat TIMES times */
332 for (e = instruction->eops; e; e = e->next) {
333 if (e->type == EOT_DB_NUMBER) {
334 if (wsize == 1) {
335 if (e->segment != NO_SEG)
336 errfunc(ERR_NONFATAL,
337 "one-byte relocation attempted");
338 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000339 uint8_t out_byte = e->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000340 out(offset, segment, &out_byte,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800341 OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000342 }
Keith Kanios61ff53c2007-04-14 18:54:52 +0000343 } else if (wsize > 8) {
H. Peter Anvin3be5d852008-05-20 14:49:32 -0700344 errfunc(ERR_NONFATAL,
345 "integer supplied to a DT, DO or DY"
Keith Kanios61ff53c2007-04-14 18:54:52 +0000346 " instruction");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000347 } else
348 out(offset, segment, &e->offset,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800349 OUT_ADDRESS, wsize, e->segment, e->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000350 offset += wsize;
H. Peter Anvin518df302008-06-14 16:53:48 -0700351 } else if (e->type == EOT_DB_STRING ||
352 e->type == EOT_DB_STRING_FREE) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000353 int align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000354
H. Peter Anvine2c80182005-01-15 22:15:51 +0000355 out(offset, segment, e->stringval,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800356 OUT_RAWDATA, e->stringlen, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000357 align = e->stringlen % wsize;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000358
H. Peter Anvine2c80182005-01-15 22:15:51 +0000359 if (align) {
360 align = wsize - align;
H. Peter Anvin999868f2009-02-09 11:03:33 +0100361 out(offset, segment, zero_buffer,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800362 OUT_RAWDATA, align, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000363 }
364 offset += e->stringlen + align;
365 }
366 }
367 if (t > 0 && t == instruction->times - 1) {
368 /*
369 * Dummy call to list->output to give the offset to the
370 * listing module.
371 */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800372 list->output(offset, NULL, OUT_RAWDATA, 0);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000373 list->uplevel(LIST_TIMES);
374 }
375 }
376 if (instruction->times > 1)
377 list->downlevel(LIST_TIMES);
378 return offset - start;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000379 }
380
H. Peter Anvine2c80182005-01-15 22:15:51 +0000381 if (instruction->opcode == I_INCBIN) {
H. Peter Anvin518df302008-06-14 16:53:48 -0700382 const char *fname = instruction->eops->stringval;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000383 FILE *fp;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000384
H. Peter Anvin418ca702008-05-30 10:42:30 -0700385 fp = fopen(fname, "rb");
386 if (!fp) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000387 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
388 fname);
H. Peter Anvin418ca702008-05-30 10:42:30 -0700389 } else if (fseek(fp, 0L, SEEK_END) < 0) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000390 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
391 fname);
H. Peter Anvin418ca702008-05-30 10:42:30 -0700392 } else {
H. Peter Anvin518df302008-06-14 16:53:48 -0700393 static char buf[4096];
394 size_t t = instruction->times;
395 size_t base = 0;
396 size_t len;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000397
H. Peter Anvine2c80182005-01-15 22:15:51 +0000398 len = ftell(fp);
399 if (instruction->eops->next) {
400 base = instruction->eops->next->offset;
401 len -= base;
402 if (instruction->eops->next->next &&
H. Peter Anvin518df302008-06-14 16:53:48 -0700403 len > (size_t)instruction->eops->next->next->offset)
404 len = (size_t)instruction->eops->next->next->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000405 }
406 /*
407 * Dummy call to list->output to give the offset to the
408 * listing module.
409 */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800410 list->output(offset, NULL, OUT_RAWDATA, 0);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000411 list->uplevel(LIST_INCBIN);
412 while (t--) {
H. Peter Anvin518df302008-06-14 16:53:48 -0700413 size_t l;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000414
H. Peter Anvine2c80182005-01-15 22:15:51 +0000415 fseek(fp, base, SEEK_SET);
416 l = len;
417 while (l > 0) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000418 int32_t m =
Charles Crayne192d5b52007-10-18 19:02:42 -0700419 fread(buf, 1, (l > (int32_t) sizeof(buf) ? (int32_t) sizeof(buf) : l),
H. Peter Anvine2c80182005-01-15 22:15:51 +0000420 fp);
421 if (!m) {
422 /*
423 * This shouldn't happen unless the file
424 * actually changes while we are reading
425 * it.
426 */
427 error(ERR_NONFATAL,
428 "`incbin': unexpected EOF while"
429 " reading file `%s'", fname);
430 t = 0; /* Try to exit cleanly */
431 break;
432 }
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800433 out(offset, segment, buf, OUT_RAWDATA, m,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000434 NO_SEG, NO_SEG);
435 l -= m;
436 }
437 }
438 list->downlevel(LIST_INCBIN);
439 if (instruction->times > 1) {
440 /*
441 * Dummy call to list->output to give the offset to the
442 * listing module.
443 */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800444 list->output(offset, NULL, OUT_RAWDATA, 0);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000445 list->uplevel(LIST_TIMES);
446 list->downlevel(LIST_TIMES);
447 }
448 fclose(fp);
449 return instruction->times * len;
450 }
451 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000452 }
453
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700454 /* Check to see if we need an address-size prefix */
455 add_asp(instruction, bits);
456
H. Peter Anvin6cda4142008-12-29 20:52:28 -0800457 size_prob = 0;
H. Peter Anvin70653092007-10-19 14:42:29 -0700458
459 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++){
Keith Kaniosb7a89542007-04-12 02:40:54 +0000460 int m = matches(temp, instruction, bits);
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700461 if (m == 100 ||
462 (m == 99 && jmp_match(segment, offset, bits,
463 instruction, temp->code))) {
464 /* Matches! */
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800465 int64_t insn_size = calcsize(segment, offset, bits,
H. Peter Anvin833caea2008-10-04 19:02:30 -0700466 instruction, temp->code);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000467 itimes = instruction->times;
468 if (insn_size < 0) /* shouldn't be, on pass two */
469 error(ERR_PANIC, "errors made it through from pass one");
470 else
471 while (itimes--) {
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700472 for (j = 0; j < MAXPREFIX; j++) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000473 uint8_t c = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000474 switch (instruction->prefixes[j]) {
H. Peter Anvinc2acf7b2009-02-21 18:22:56 -0800475 case P_WAIT:
476 c = 0x9B;
477 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000478 case P_LOCK:
479 c = 0xF0;
480 break;
481 case P_REPNE:
482 case P_REPNZ:
483 c = 0xF2;
484 break;
485 case P_REPE:
486 case P_REPZ:
487 case P_REP:
488 c = 0xF3;
489 break;
490 case R_CS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000491 if (bits == 64) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700492 error(ERR_WARNING | ERR_PASS2,
Charles Crayne1b851dc2007-11-05 21:49:49 -0800493 "cs segment base generated, but will be ignored in 64-bit mode");
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000494 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000495 c = 0x2E;
496 break;
497 case R_DS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000498 if (bits == 64) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700499 error(ERR_WARNING | ERR_PASS2,
Charles Crayne1b851dc2007-11-05 21:49:49 -0800500 "ds segment base generated, but will be ignored in 64-bit mode");
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000501 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000502 c = 0x3E;
503 break;
504 case R_ES:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000505 if (bits == 64) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700506 error(ERR_WARNING | ERR_PASS2,
Charles Crayne1b851dc2007-11-05 21:49:49 -0800507 "es segment base generated, but will be ignored in 64-bit mode");
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000508 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000509 c = 0x26;
510 break;
511 case R_FS:
512 c = 0x64;
513 break;
514 case R_GS:
515 c = 0x65;
516 break;
517 case R_SS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000518 if (bits == 64) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700519 error(ERR_WARNING | ERR_PASS2,
Charles Crayne1b851dc2007-11-05 21:49:49 -0800520 "ss segment base generated, but will be ignored in 64-bit mode");
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000521 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000522 c = 0x36;
523 break;
524 case R_SEGR6:
525 case R_SEGR7:
526 error(ERR_NONFATAL,
527 "segr6 and segr7 cannot be used as prefixes");
528 break;
529 case P_A16:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000530 if (bits == 64) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000531 error(ERR_NONFATAL,
532 "16-bit addressing is not supported "
533 "in 64-bit mode");
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700534 } else if (bits != 16)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000535 c = 0x67;
536 break;
537 case P_A32:
538 if (bits != 32)
539 c = 0x67;
540 break;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700541 case P_A64:
542 if (bits != 64) {
543 error(ERR_NONFATAL,
544 "64-bit addressing is only supported "
545 "in 64-bit mode");
546 }
547 break;
548 case P_ASP:
549 c = 0x67;
550 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000551 case P_O16:
552 if (bits != 16)
553 c = 0x66;
554 break;
555 case P_O32:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000556 if (bits == 16)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000557 c = 0x66;
558 break;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700559 case P_O64:
560 /* REX.W */
561 break;
562 case P_OSP:
563 c = 0x66;
564 break;
565 case P_none:
566 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000567 default:
568 error(ERR_PANIC, "invalid instruction prefix");
569 }
570 if (c != 0) {
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800571 out(offset, segment, &c, OUT_RAWDATA, 1,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000572 NO_SEG, NO_SEG);
573 offset++;
574 }
H. Peter Anvin70653092007-10-19 14:42:29 -0700575 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000576 insn_end = offset + insn_size;
H. Peter Anvin833caea2008-10-04 19:02:30 -0700577 gencode(segment, offset, bits, instruction,
578 temp, insn_end);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000579 offset += insn_size;
580 if (itimes > 0 && itimes == instruction->times - 1) {
581 /*
582 * Dummy call to list->output to give the offset to the
583 * listing module.
584 */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800585 list->output(offset, NULL, OUT_RAWDATA, 0);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000586 list->uplevel(LIST_TIMES);
587 }
588 }
589 if (instruction->times > 1)
590 list->downlevel(LIST_TIMES);
591 return offset - start;
592 } else if (m > 0 && m > size_prob) {
593 size_prob = m;
594 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000595 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000596
H. Peter Anvine2c80182005-01-15 22:15:51 +0000597 if (temp->opcode == -1) { /* didn't match any instruction */
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000598 switch (size_prob) {
599 case 1:
600 error(ERR_NONFATAL, "operation size not specified");
601 break;
602 case 2:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000603 error(ERR_NONFATAL, "mismatch in operand sizes");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000604 break;
605 case 3:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000606 error(ERR_NONFATAL, "no instruction for this cpu level");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000607 break;
608 case 4:
H. Peter Anvin6cda4142008-12-29 20:52:28 -0800609 error(ERR_NONFATAL, "instruction not supported in %d-bit mode",
610 bits);
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000611 break;
612 default:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000613 error(ERR_NONFATAL,
614 "invalid combination of opcode and operands");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000615 break;
616 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000617 }
618 return 0;
619}
620
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800621int64_t insn_size(int32_t segment, int64_t offset, int bits, uint32_t cp,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000622 insn * instruction, efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000623{
H. Peter Anvin3360d792007-09-11 04:16:57 +0000624 const struct itemplate *temp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000625
H. Peter Anvine2c80182005-01-15 22:15:51 +0000626 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000627 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000628
629 if (instruction->opcode == -1)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000630 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000631
H. Peter Anvincfbe7c32007-09-18 17:49:09 -0700632 if (instruction->opcode == I_DB || instruction->opcode == I_DW ||
633 instruction->opcode == I_DD || instruction->opcode == I_DQ ||
H. Peter Anvindfb91802008-05-20 11:43:53 -0700634 instruction->opcode == I_DT || instruction->opcode == I_DO ||
635 instruction->opcode == I_DY) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000636 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000637 int32_t isize, osize, wsize = 0; /* placate gcc */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000638
H. Peter Anvine2c80182005-01-15 22:15:51 +0000639 isize = 0;
640 switch (instruction->opcode) {
641 case I_DB:
642 wsize = 1;
643 break;
644 case I_DW:
645 wsize = 2;
646 break;
647 case I_DD:
648 wsize = 4;
649 break;
650 case I_DQ:
651 wsize = 8;
652 break;
653 case I_DT:
654 wsize = 10;
655 break;
H. Peter Anvincfbe7c32007-09-18 17:49:09 -0700656 case I_DO:
657 wsize = 16;
658 break;
H. Peter Anvindfb91802008-05-20 11:43:53 -0700659 case I_DY:
660 wsize = 32;
661 break;
H. Peter Anvin16b0a332007-09-12 20:27:41 -0700662 default:
663 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000664 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000665
H. Peter Anvine2c80182005-01-15 22:15:51 +0000666 for (e = instruction->eops; e; e = e->next) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000667 int32_t align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000668
H. Peter Anvine2c80182005-01-15 22:15:51 +0000669 osize = 0;
670 if (e->type == EOT_DB_NUMBER)
671 osize = 1;
H. Peter Anvin518df302008-06-14 16:53:48 -0700672 else if (e->type == EOT_DB_STRING ||
673 e->type == EOT_DB_STRING_FREE)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000674 osize = e->stringlen;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000675
H. Peter Anvine2c80182005-01-15 22:15:51 +0000676 align = (-osize) % wsize;
677 if (align < 0)
678 align += wsize;
679 isize += osize + align;
680 }
681 return isize * instruction->times;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000682 }
683
H. Peter Anvine2c80182005-01-15 22:15:51 +0000684 if (instruction->opcode == I_INCBIN) {
H. Peter Anvin518df302008-06-14 16:53:48 -0700685 const char *fname = instruction->eops->stringval;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000686 FILE *fp;
H. Peter Anvin518df302008-06-14 16:53:48 -0700687 size_t len;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000688
H. Peter Anvin418ca702008-05-30 10:42:30 -0700689 fp = fopen(fname, "rb");
690 if (!fp)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000691 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
692 fname);
693 else if (fseek(fp, 0L, SEEK_END) < 0)
694 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
695 fname);
696 else {
697 len = ftell(fp);
698 fclose(fp);
699 if (instruction->eops->next) {
700 len -= instruction->eops->next->offset;
701 if (instruction->eops->next->next &&
H. Peter Anvin518df302008-06-14 16:53:48 -0700702 len > (size_t)instruction->eops->next->next->offset) {
703 len = (size_t)instruction->eops->next->next->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000704 }
705 }
706 return instruction->times * len;
707 }
708 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000709 }
710
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700711 /* Check to see if we need an address-size prefix */
712 add_asp(instruction, bits);
713
Keith Kaniosb7a89542007-04-12 02:40:54 +0000714 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++) {
715 int m = matches(temp, instruction, bits);
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700716 if (m == 100 ||
717 (m == 99 && jmp_match(segment, offset, bits,
718 instruction, temp->code))) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000719 /* we've matched an instruction. */
Charles Crayne5fbbc8c2007-11-07 19:03:46 -0800720 int64_t isize;
H. Peter Anvin3720f7b2008-05-12 11:00:50 -0700721 const uint8_t *codes = temp->code;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000722 int j;
723
724 isize = calcsize(segment, offset, bits, instruction, codes);
725 if (isize < 0)
726 return -1;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700727 for (j = 0; j < MAXPREFIX; j++) {
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700728 switch (instruction->prefixes[j]) {
729 case P_A16:
730 if (bits != 16)
731 isize++;
732 break;
733 case P_A32:
734 if (bits != 32)
735 isize++;
736 break;
737 case P_O16:
738 if (bits != 16)
739 isize++;
740 break;
741 case P_O32:
742 if (bits == 16)
743 isize++;
744 break;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700745 case P_A64:
746 case P_O64:
747 case P_none:
748 break;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700749 default:
750 isize++;
751 break;
752 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000753 }
754 return isize * instruction->times;
755 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000756 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000757 return -1; /* didn't match any instruction */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000758}
759
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700760static bool possible_sbyte(operand *o)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000761{
H. Peter Anvinad6b8592008-10-07 09:56:38 -0700762 return o->wrt == NO_SEG && o->segment == NO_SEG &&
H. Peter Anvine8ab8912009-02-26 16:34:56 -0800763 !(o->opflags & OPFLAG_UNKNOWN) &&
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700764 optimizing >= 0 && !(o->type & STRICT);
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000765}
766
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700767/* check that opn[op] is a signed byte of size 16 or 32 */
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700768static bool is_sbyte16(operand *o)
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700769{
770 int16_t v;
771
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700772 if (!possible_sbyte(o))
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700773 return false;
774
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700775 v = o->offset;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700776 return v >= -128 && v <= 127;
777}
778
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700779static bool is_sbyte32(operand *o)
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700780{
781 int32_t v;
782
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700783 if (!possible_sbyte(o))
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700784 return false;
785
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700786 v = o->offset;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700787 return v >= -128 && v <= 127;
788}
789
H. Peter Anvin507ae032008-10-09 15:37:10 -0700790/* Common construct */
791#define case4(x) case (x): case (x)+1: case (x)+2: case (x)+3
792
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800793static int64_t calcsize(int32_t segment, int64_t offset, int bits,
H. Peter Anvin9f817132008-10-06 19:11:07 -0700794 insn * ins, const uint8_t *codes)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000795{
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800796 int64_t length = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000797 uint8_t c;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000798 int rex_mask = ~0;
H. Peter Anvindcffe4b2008-10-10 22:10:31 -0700799 int op1, op2;
H. Peter Anvin839eca22007-10-29 23:12:47 -0700800 struct operand *opx;
H. Peter Anvindcffe4b2008-10-10 22:10:31 -0700801 uint8_t opex = 0;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000802
H. Peter Anvine3917fc2007-11-01 14:53:32 -0700803 ins->rex = 0; /* Ensure REX is reset */
804
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700805 if (ins->prefixes[PPS_OSIZE] == P_O64)
806 ins->rex |= REX_W;
807
H. Peter Anvine2c80182005-01-15 22:15:51 +0000808 (void)segment; /* Don't warn that this parameter is unused */
809 (void)offset; /* Don't warn that this parameter is unused */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000810
H. Peter Anvin839eca22007-10-29 23:12:47 -0700811 while (*codes) {
812 c = *codes++;
H. Peter Anvindcffe4b2008-10-10 22:10:31 -0700813 op1 = (c & 3) + ((opex & 1) << 2);
814 op2 = ((c >> 3) & 3) + ((opex & 2) << 1);
815 opx = &ins->oprs[op1];
816 opex = 0; /* For the next iteration */
817
H. Peter Anvin839eca22007-10-29 23:12:47 -0700818 switch (c) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000819 case 01:
820 case 02:
821 case 03:
H. Peter Anvindcffe4b2008-10-10 22:10:31 -0700822 case 04:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000823 codes += c, length += c;
824 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700825
H. Peter Anvindcffe4b2008-10-10 22:10:31 -0700826 case 05:
827 case 06:
828 case 07:
829 opex = c;
830 break;
831
H. Peter Anvin507ae032008-10-09 15:37:10 -0700832 case4(010):
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000833 ins->rex |=
H. Peter Anvin839eca22007-10-29 23:12:47 -0700834 op_rexflags(opx, REX_B|REX_H|REX_P|REX_W);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000835 codes++, length++;
836 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700837
838 case4(014):
839 case4(020):
840 case4(024):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000841 length++;
842 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700843
844 case4(030):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000845 length += 2;
846 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700847
848 case4(034):
H. Peter Anvin839eca22007-10-29 23:12:47 -0700849 if (opx->type & (BITS16 | BITS32 | BITS64))
850 length += (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000851 else
852 length += (bits == 16) ? 2 : 4;
853 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700854
855 case4(040):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000856 length += 4;
857 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700858
859 case4(044):
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700860 length += ins->addr_size >> 3;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000861 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700862
863 case4(050):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000864 length++;
865 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700866
867 case4(054):
Keith Kaniosb7a89542007-04-12 02:40:54 +0000868 length += 8; /* MOV reg64/imm */
869 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700870
871 case4(060):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000872 length += 2;
873 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700874
875 case4(064):
H. Peter Anvin839eca22007-10-29 23:12:47 -0700876 if (opx->type & (BITS16 | BITS32 | BITS64))
877 length += (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000878 else
879 length += (bits == 16) ? 2 : 4;
880 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700881
882 case4(070):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000883 length += 4;
884 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700885
886 case4(074):
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700887 length += 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000888 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700889
890 case4(0140):
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700891 length += is_sbyte16(opx) ? 1 : 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000892 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700893
894 case4(0144):
H. Peter Anvina30cc072007-11-18 21:55:26 -0800895 codes++;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000896 length++;
897 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700898
899 case4(0150):
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700900 length += is_sbyte32(opx) ? 1 : 4;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700901 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700902
903 case4(0154):
H. Peter Anvina30cc072007-11-18 21:55:26 -0800904 codes++;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700905 length++;
906 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700907
908 case4(0160):
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700909 length++;
910 ins->rex |= REX_D;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700911 ins->drexdst = regval(opx);
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700912 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700913
914 case4(0164):
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700915 length++;
916 ins->rex |= REX_D|REX_OC;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700917 ins->drexdst = regval(opx);
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700918 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700919
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700920 case 0171:
921 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700922
H. Peter Anvind85d2502008-05-04 17:53:31 -0700923 case 0172:
H. Peter Anvind58656f2008-05-06 20:11:14 -0700924 case 0173:
H. Peter Anvin52dc3532008-05-20 19:29:04 -0700925 case 0174:
H. Peter Anvind85d2502008-05-04 17:53:31 -0700926 codes++;
927 length++;
928 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700929
930 case4(0250):
H. Peter Anvinad6b8592008-10-07 09:56:38 -0700931 length += is_sbyte32(opx) ? 1 : 4;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700932 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700933
934 case4(0254):
H. Peter Anvin588df782008-10-07 10:05:10 -0700935 length += 4;
936 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700937
938 case4(0260):
H. Peter Anvind85d2502008-05-04 17:53:31 -0700939 ins->rex |= REX_V;
940 ins->drexdst = regval(opx);
H. Peter Anvina04019c2009-05-03 21:42:34 -0700941 ins->vex_cm = *codes++;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700942 ins->vex_wlp = *codes++;
943 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700944
H. Peter Anvind85d2502008-05-04 17:53:31 -0700945 case 0270:
H. Peter Anvind85d2502008-05-04 17:53:31 -0700946 ins->rex |= REX_V;
947 ins->drexdst = 0;
H. Peter Anvina04019c2009-05-03 21:42:34 -0700948 ins->vex_cm = *codes++;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700949 ins->vex_wlp = *codes++;
950 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700951
952 case4(0274):
H. Peter Anvinc1377e92008-10-06 23:40:31 -0700953 length++;
954 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700955
956 case4(0300):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000957 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700958
H. Peter Anvine2c80182005-01-15 22:15:51 +0000959 case 0310:
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700960 if (bits == 64)
961 return -1;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700962 length += (bits != 16) && !has_prefix(ins, PPS_ASIZE, P_A16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000963 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700964
H. Peter Anvine2c80182005-01-15 22:15:51 +0000965 case 0311:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700966 length += (bits != 32) && !has_prefix(ins, PPS_ASIZE, P_A32);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000967 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700968
H. Peter Anvine2c80182005-01-15 22:15:51 +0000969 case 0312:
H. Peter Anvin70653092007-10-19 14:42:29 -0700970 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700971
Keith Kaniosb7a89542007-04-12 02:40:54 +0000972 case 0313:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700973 if (bits != 64 || has_prefix(ins, PPS_ASIZE, P_A16) ||
974 has_prefix(ins, PPS_ASIZE, P_A32))
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700975 return -1;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000976 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700977
978 case4(0314):
H. Peter Anvin23440102007-11-12 21:02:33 -0800979 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700980
H. Peter Anvine2c80182005-01-15 22:15:51 +0000981 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000982 length += (bits != 16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000983 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700984
H. Peter Anvine2c80182005-01-15 22:15:51 +0000985 case 0321:
986 length += (bits == 16);
987 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700988
H. Peter Anvine2c80182005-01-15 22:15:51 +0000989 case 0322:
990 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700991
Keith Kaniosb7a89542007-04-12 02:40:54 +0000992 case 0323:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000993 rex_mask &= ~REX_W;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000994 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700995
Keith Kaniosb7a89542007-04-12 02:40:54 +0000996 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000997 ins->rex |= REX_W;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000998 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700999
H. Peter Anvin9472dab2009-06-24 21:38:29 -07001000 case 0325:
1001 ins->rex |= REX_NH;
1002 break;
1003
H. Peter Anvine2c80182005-01-15 22:15:51 +00001004 case 0330:
1005 codes++, length++;
1006 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001007
H. Peter Anvine2c80182005-01-15 22:15:51 +00001008 case 0331:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001009 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001010
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001011 case 0332:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001012 case 0333:
1013 length++;
1014 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001015
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001016 case 0334:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001017 ins->rex |= REX_L;
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001018 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001019
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001020 case 0335:
1021 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001022
H. Peter Anvin962e3052008-08-28 17:47:16 -07001023 case 0336:
1024 if (!ins->prefixes[PPS_LREP])
1025 ins->prefixes[PPS_LREP] = P_REP;
1026 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001027
H. Peter Anvin962e3052008-08-28 17:47:16 -07001028 case 0337:
1029 if (!ins->prefixes[PPS_LREP])
1030 ins->prefixes[PPS_LREP] = P_REPNE;
1031 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001032
H. Peter Anvine2c80182005-01-15 22:15:51 +00001033 case 0340:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001034 if (ins->oprs[0].segment != NO_SEG)
1035 errfunc(ERR_NONFATAL, "attempt to reserve non-constant"
1036 " quantity of BSS space");
1037 else
H. Peter Anvin428fd672007-11-15 10:25:52 -08001038 length += ins->oprs[0].offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001039 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001040
H. Peter Anvinc2acf7b2009-02-21 18:22:56 -08001041 case 0341:
1042 if (!ins->prefixes[PPS_WAIT])
1043 ins->prefixes[PPS_WAIT] = P_WAIT;
1044 break;
1045
H. Peter Anvin507ae032008-10-09 15:37:10 -07001046 case4(0344):
H. Peter Anvinff6e12d2008-10-08 21:17:32 -07001047 length++;
1048 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001049
H. Peter Anvinfff5a472008-05-20 09:46:24 -07001050 case 0360:
1051 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001052
H. Peter Anvinfff5a472008-05-20 09:46:24 -07001053 case 0361:
1054 case 0362:
1055 case 0363:
1056 length++;
1057 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001058
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001059 case 0364:
1060 case 0365:
1061 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001062
Keith Kanios48af1772007-08-17 07:37:52 +00001063 case 0366:
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001064 case 0367:
1065 length++;
1066 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001067
H. Peter Anvine2c80182005-01-15 22:15:51 +00001068 case 0370:
1069 case 0371:
1070 case 0372:
1071 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001072
H. Peter Anvine2c80182005-01-15 22:15:51 +00001073 case 0373:
1074 length++;
1075 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001076
1077 case4(0100):
1078 case4(0110):
1079 case4(0120):
1080 case4(0130):
1081 case4(0200):
1082 case4(0204):
1083 case4(0210):
1084 case4(0214):
1085 case4(0220):
1086 case4(0224):
1087 case4(0230):
1088 case4(0234):
1089 {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001090 ea ea_data;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001091 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001092 int32_t rflags;
H. Peter Anvinae64c9d2008-10-25 00:41:00 -07001093 struct operand *opy = &ins->oprs[op2];
1094
Keith Kaniosb7a89542007-04-12 02:40:54 +00001095 ea_data.rex = 0; /* Ensure ea.REX is initially 0 */
H. Peter Anvin70653092007-10-19 14:42:29 -07001096
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001097 if (c <= 0177) {
H. Peter Anvinae64c9d2008-10-25 00:41:00 -07001098 /* pick rfield from operand b (opx) */
1099 rflags = regflag(opx);
1100 rfield = nasm_regvals[opx->basereg];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001101 } else {
1102 rflags = 0;
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001103 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001104 }
H. Peter Anvinae64c9d2008-10-25 00:41:00 -07001105 if (!process_ea(opy, &ea_data, bits,
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001106 ins->addr_size, rfield, rflags)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001107 errfunc(ERR_NONFATAL, "invalid effective address");
1108 return -1;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001109 } else {
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001110 ins->rex |= ea_data.rex;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001111 length += ea_data.size;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001112 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001113 }
H. Peter Anvin507ae032008-10-09 15:37:10 -07001114 break;
1115
1116 default:
1117 errfunc(ERR_PANIC, "internal instruction table corrupt"
H. Peter Anvin16a856c2009-03-01 00:22:16 -08001118 ": instruction code \\%o (0x%02X) given", c, c);
H. Peter Anvin507ae032008-10-09 15:37:10 -07001119 break;
1120 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001121 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001122
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001123 ins->rex &= rex_mask;
H. Peter Anvin70653092007-10-19 14:42:29 -07001124
H. Peter Anvin9472dab2009-06-24 21:38:29 -07001125 if (ins->rex & REX_NH) {
1126 if (ins->rex & REX_H) {
1127 errfunc(ERR_NONFATAL, "instruction cannot use high registers");
1128 return -1;
1129 }
1130 ins->rex &= ~REX_P; /* Don't force REX prefix due to high reg */
1131 }
1132
H. Peter Anvind85d2502008-05-04 17:53:31 -07001133 if (ins->rex & REX_V) {
1134 int bad32 = REX_R|REX_W|REX_X|REX_B;
1135
1136 if (ins->rex & REX_H) {
1137 errfunc(ERR_NONFATAL, "cannot use high register in vex instruction");
1138 return -1;
1139 }
1140 switch (ins->vex_wlp & 030) {
1141 case 000:
H. Peter Anvinbd420c72008-05-22 11:24:35 -07001142 case 020:
H. Peter Anvind85d2502008-05-04 17:53:31 -07001143 ins->rex &= ~REX_W;
1144 break;
1145 case 010:
1146 ins->rex |= REX_W;
1147 bad32 &= ~REX_W;
1148 break;
H. Peter Anvinbd420c72008-05-22 11:24:35 -07001149 case 030:
H. Peter Anvind85d2502008-05-04 17:53:31 -07001150 /* Follow REX_W */
1151 break;
1152 }
1153
1154 if (bits != 64 && ((ins->rex & bad32) || ins->drexdst > 7)) {
1155 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
1156 return -1;
1157 }
H. Peter Anvina04019c2009-05-03 21:42:34 -07001158 if (ins->vex_cm != 1 || (ins->rex & (REX_W|REX_R|REX_B)))
H. Peter Anvind85d2502008-05-04 17:53:31 -07001159 length += 3;
1160 else
1161 length += 2;
1162 } else if (ins->rex & REX_D) {
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001163 if (ins->rex & REX_H) {
1164 errfunc(ERR_NONFATAL, "cannot use high register in drex instruction");
1165 return -1;
1166 }
H. Peter Anvind85d2502008-05-04 17:53:31 -07001167 if (bits != 64 && ((ins->rex & (REX_R|REX_W|REX_X|REX_B)) ||
H. Peter Anvincf5180a2007-09-17 17:25:27 -07001168 ins->drexdst > 7)) {
1169 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
1170 return -1;
1171 }
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001172 length++;
1173 } else if (ins->rex & REX_REAL) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001174 if (ins->rex & REX_H) {
1175 errfunc(ERR_NONFATAL, "cannot use high register in rex instruction");
1176 return -1;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001177 } else if (bits == 64) {
1178 length++;
1179 } else if ((ins->rex & REX_L) &&
1180 !(ins->rex & (REX_P|REX_W|REX_X|REX_B)) &&
1181 cpu >= IF_X86_64) {
1182 /* LOCK-as-REX.R */
1183 assert_no_prefix(ins, PPS_LREP);
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001184 length++;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +00001185 } else {
H. Peter Anvincf5180a2007-09-17 17:25:27 -07001186 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
1187 return -1;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +00001188 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001189 }
1190
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001191 return length;
1192}
Keith Kaniosb7a89542007-04-12 02:40:54 +00001193
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001194#define EMIT_REX() \
H. Peter Anvind85d2502008-05-04 17:53:31 -07001195 if (!(ins->rex & (REX_D|REX_V)) && (ins->rex & REX_REAL) && (bits == 64)) { \
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001196 ins->rex = (ins->rex & REX_REAL)|REX_P; \
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001197 out(offset, segment, &ins->rex, OUT_RAWDATA, 1, NO_SEG, NO_SEG); \
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001198 ins->rex = 0; \
1199 offset += 1; \
1200 }
1201
Charles Crayne1f8bc4c2007-11-06 18:27:23 -08001202static void gencode(int32_t segment, int64_t offset, int bits,
H. Peter Anvin833caea2008-10-04 19:02:30 -07001203 insn * ins, const struct itemplate *temp,
1204 int64_t insn_end)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001205{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001206 static char condval[] = { /* conditional opcodes */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001207 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
1208 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
1209 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001210 };
Keith Kaniosb7a89542007-04-12 02:40:54 +00001211 uint8_t c;
1212 uint8_t bytes[4];
Charles Crayne1f8bc4c2007-11-06 18:27:23 -08001213 int64_t size;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001214 int64_t data;
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001215 int op1, op2;
H. Peter Anvin839eca22007-10-29 23:12:47 -07001216 struct operand *opx;
H. Peter Anvin833caea2008-10-04 19:02:30 -07001217 const uint8_t *codes = temp->code;
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001218 uint8_t opex = 0;
H. Peter Anvin70653092007-10-19 14:42:29 -07001219
H. Peter Anvin839eca22007-10-29 23:12:47 -07001220 while (*codes) {
1221 c = *codes++;
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001222 op1 = (c & 3) + ((opex & 1) << 2);
1223 op2 = ((c >> 3) & 3) + ((opex & 2) << 1);
1224 opx = &ins->oprs[op1];
1225 opex = 0; /* For the next iteration */
1226
H. Peter Anvin839eca22007-10-29 23:12:47 -07001227 switch (c) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001228 case 01:
1229 case 02:
1230 case 03:
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001231 case 04:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001232 EMIT_REX();
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001233 out(offset, segment, codes, OUT_RAWDATA, c, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001234 codes += c;
1235 offset += c;
1236 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001237
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001238 case 05:
1239 case 06:
1240 case 07:
1241 opex = c;
1242 break;
1243
H. Peter Anvin507ae032008-10-09 15:37:10 -07001244 case4(010):
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001245 EMIT_REX();
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001246 bytes[0] = *codes++ + (regval(opx) & 7);
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001247 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001248 offset += 1;
1249 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001250
H. Peter Anvin507ae032008-10-09 15:37:10 -07001251 case4(014):
H. Peter Anvin6c80ab62008-10-04 18:50:47 -07001252 /* The test for BITS8 and SBYTE here is intended to avoid
1253 warning on optimizer actions due to SBYTE, while still
1254 warn on explicit BYTE directives. Also warn, obviously,
1255 if the optimizer isn't enabled. */
1256 if (((opx->type & BITS8) ||
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001257 !(opx->type & temp->opd[op1] & BYTENESS)) &&
H. Peter Anvin6c80ab62008-10-04 18:50:47 -07001258 (opx->offset < -128 || opx->offset > 127)) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001259 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
H. Peter Anvin72c64372008-01-08 22:13:48 -08001260 "signed byte value exceeds bounds");
H. Peter Anvin6c80ab62008-10-04 18:50:47 -07001261 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001262 if (opx->segment != NO_SEG) {
1263 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001264 out(offset, segment, &data, OUT_ADDRESS, 1,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001265 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001266 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001267 bytes[0] = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001268 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001269 NO_SEG);
1270 }
1271 offset += 1;
1272 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001273
H. Peter Anvin507ae032008-10-09 15:37:10 -07001274 case4(020):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001275 if (opx->offset < -256 || opx->offset > 255) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001276 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
H. Peter Anvin72c64372008-01-08 22:13:48 -08001277 "byte value exceeds bounds");
H. Peter Anvine2c80182005-01-15 22:15:51 +00001278 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001279 if (opx->segment != NO_SEG) {
1280 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001281 out(offset, segment, &data, OUT_ADDRESS, 1,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001282 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001283 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001284 bytes[0] = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001285 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001286 NO_SEG);
1287 }
1288 offset += 1;
1289 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001290
H. Peter Anvin507ae032008-10-09 15:37:10 -07001291 case4(024):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001292 if (opx->offset < 0 || opx->offset > 255)
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001293 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
H. Peter Anvin72c64372008-01-08 22:13:48 -08001294 "unsigned byte value exceeds bounds");
H. Peter Anvin839eca22007-10-29 23:12:47 -07001295 if (opx->segment != NO_SEG) {
1296 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001297 out(offset, segment, &data, OUT_ADDRESS, 1,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001298 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001299 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001300 bytes[0] = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001301 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001302 NO_SEG);
1303 }
1304 offset += 1;
1305 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001306
H. Peter Anvin507ae032008-10-09 15:37:10 -07001307 case4(030):
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001308 warn_overflow(2, opx);
H. Peter Anvin839eca22007-10-29 23:12:47 -07001309 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001310 out(offset, segment, &data, OUT_ADDRESS, 2,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001311 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001312 offset += 2;
1313 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001314
H. Peter Anvin507ae032008-10-09 15:37:10 -07001315 case4(034):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001316 if (opx->type & (BITS16 | BITS32))
1317 size = (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001318 else
1319 size = (bits == 16) ? 2 : 4;
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001320 warn_overflow(size, opx);
H. Peter Anvin839eca22007-10-29 23:12:47 -07001321 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001322 out(offset, segment, &data, OUT_ADDRESS, size,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001323 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001324 offset += size;
1325 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001326
H. Peter Anvin507ae032008-10-09 15:37:10 -07001327 case4(040):
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001328 warn_overflow(4, opx);
H. Peter Anvin839eca22007-10-29 23:12:47 -07001329 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001330 out(offset, segment, &data, OUT_ADDRESS, 4,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001331 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001332 offset += 4;
1333 break;
H. Peter Anvin3ba46772002-05-27 23:19:35 +00001334
H. Peter Anvin507ae032008-10-09 15:37:10 -07001335 case4(044):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001336 data = opx->offset;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001337 size = ins->addr_size >> 3;
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001338 warn_overflow(size, opx);
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001339 out(offset, segment, &data, OUT_ADDRESS, size,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001340 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001341 offset += size;
1342 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001343
H. Peter Anvin507ae032008-10-09 15:37:10 -07001344 case4(050):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001345 if (opx->segment != segment)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001346 errfunc(ERR_NONFATAL,
1347 "short relative jump outside segment");
H. Peter Anvin839eca22007-10-29 23:12:47 -07001348 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001349 if (data > 127 || data < -128)
1350 errfunc(ERR_NONFATAL, "short jump is out of range");
1351 bytes[0] = data;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001352 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001353 offset += 1;
1354 break;
H. Peter Anvin70653092007-10-19 14:42:29 -07001355
H. Peter Anvin507ae032008-10-09 15:37:10 -07001356 case4(054):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001357 data = (int64_t)opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001358 out(offset, segment, &data, OUT_ADDRESS, 8,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001359 opx->segment, opx->wrt);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001360 offset += 8;
1361 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001362
H. Peter Anvin507ae032008-10-09 15:37:10 -07001363 case4(060):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001364 if (opx->segment != segment) {
1365 data = opx->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001366 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001367 OUT_REL2ADR, insn_end - offset,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001368 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001369 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001370 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001371 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001372 OUT_ADDRESS, 2, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001373 }
1374 offset += 2;
1375 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001376
H. Peter Anvin507ae032008-10-09 15:37:10 -07001377 case4(064):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001378 if (opx->type & (BITS16 | BITS32 | BITS64))
1379 size = (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001380 else
1381 size = (bits == 16) ? 2 : 4;
H. Peter Anvin839eca22007-10-29 23:12:47 -07001382 if (opx->segment != segment) {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001383 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001384 out(offset, segment, &data,
1385 size == 2 ? OUT_REL2ADR : OUT_REL4ADR,
1386 insn_end - offset, opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001387 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001388 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001389 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001390 OUT_ADDRESS, size, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001391 }
1392 offset += size;
1393 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001394
H. Peter Anvin507ae032008-10-09 15:37:10 -07001395 case4(070):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001396 if (opx->segment != segment) {
1397 data = opx->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001398 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001399 OUT_REL4ADR, insn_end - offset,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001400 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001401 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001402 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001403 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001404 OUT_ADDRESS, 4, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001405 }
1406 offset += 4;
1407 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001408
H. Peter Anvin507ae032008-10-09 15:37:10 -07001409 case4(074):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001410 if (opx->segment == NO_SEG)
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001411 errfunc(ERR_NONFATAL, "value referenced by FAR is not"
1412 " relocatable");
H. Peter Anvindfb91802008-05-20 11:43:53 -07001413 data = 0;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001414 out(offset, segment, &data, OUT_ADDRESS, 2,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001415 outfmt->segbase(1 + opx->segment),
1416 opx->wrt);
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001417 offset += 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001418 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001419
H. Peter Anvin507ae032008-10-09 15:37:10 -07001420 case4(0140):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001421 data = opx->offset;
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001422 warn_overflow(2, opx);
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001423 if (is_sbyte16(opx)) {
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001424 bytes[0] = data;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001425 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001426 NO_SEG);
1427 offset++;
1428 } else {
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001429 out(offset, segment, &data, OUT_ADDRESS, 2,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001430 opx->segment, opx->wrt);
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001431 offset += 2;
1432 }
1433 break;
1434
H. Peter Anvin507ae032008-10-09 15:37:10 -07001435 case4(0144):
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001436 EMIT_REX();
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001437 bytes[0] = *codes++;
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001438 if (is_sbyte16(opx))
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001439 bytes[0] |= 2; /* s-bit */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001440 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001441 offset++;
1442 break;
1443
H. Peter Anvin507ae032008-10-09 15:37:10 -07001444 case4(0150):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001445 data = opx->offset;
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001446 warn_overflow(4, opx);
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001447 if (is_sbyte32(opx)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001448 bytes[0] = data;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001449 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001450 NO_SEG);
1451 offset++;
1452 } else {
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001453 out(offset, segment, &data, OUT_ADDRESS, 4,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001454 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001455 offset += 4;
1456 }
1457 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001458
H. Peter Anvin507ae032008-10-09 15:37:10 -07001459 case4(0154):
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001460 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001461 bytes[0] = *codes++;
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001462 if (is_sbyte32(opx))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001463 bytes[0] |= 2; /* s-bit */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001464 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001465 offset++;
1466 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001467
H. Peter Anvin507ae032008-10-09 15:37:10 -07001468 case4(0160):
1469 case4(0164):
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001470 break;
1471
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001472 case 0171:
1473 bytes[0] =
1474 (ins->drexdst << 4) |
1475 (ins->rex & REX_OC ? 0x08 : 0) |
1476 (ins->rex & (REX_R|REX_X|REX_B));
1477 ins->rex = 0;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001478 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001479 offset++;
1480 break;
1481
H. Peter Anvind85d2502008-05-04 17:53:31 -07001482 case 0172:
1483 c = *codes++;
1484 opx = &ins->oprs[c >> 3];
H. Peter Anvina4835d42008-05-20 14:21:29 -07001485 bytes[0] = nasm_regvals[opx->basereg] << 4;
H. Peter Anvind85d2502008-05-04 17:53:31 -07001486 opx = &ins->oprs[c & 7];
1487 if (opx->segment != NO_SEG || opx->wrt != NO_SEG) {
1488 errfunc(ERR_NONFATAL,
1489 "non-absolute expression not permitted as argument %d",
1490 c & 7);
1491 } else {
1492 if (opx->offset & ~15) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001493 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
H. Peter Anvind85d2502008-05-04 17:53:31 -07001494 "four-bit argument exceeds bounds");
1495 }
1496 bytes[0] |= opx->offset & 15;
1497 }
1498 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1499 offset++;
1500 break;
1501
H. Peter Anvind58656f2008-05-06 20:11:14 -07001502 case 0173:
1503 c = *codes++;
1504 opx = &ins->oprs[c >> 4];
H. Peter Anvina4835d42008-05-20 14:21:29 -07001505 bytes[0] = nasm_regvals[opx->basereg] << 4;
H. Peter Anvind58656f2008-05-06 20:11:14 -07001506 bytes[0] |= c & 15;
1507 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1508 offset++;
1509 break;
1510
H. Peter Anvin52dc3532008-05-20 19:29:04 -07001511 case 0174:
1512 c = *codes++;
1513 opx = &ins->oprs[c];
1514 bytes[0] = nasm_regvals[opx->basereg] << 4;
1515 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1516 offset++;
1517 break;
1518
H. Peter Anvin507ae032008-10-09 15:37:10 -07001519 case4(0250):
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001520 data = opx->offset;
H. Peter Anvinad6b8592008-10-07 09:56:38 -07001521 if (opx->wrt == NO_SEG && opx->segment == NO_SEG &&
1522 (int32_t)data != (int64_t)data) {
1523 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
1524 "signed dword immediate exceeds bounds");
1525 }
1526 if (is_sbyte32(opx)) {
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001527 bytes[0] = data;
1528 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
1529 NO_SEG);
1530 offset++;
1531 } else {
1532 out(offset, segment, &data, OUT_ADDRESS, 4,
1533 opx->segment, opx->wrt);
1534 offset += 4;
1535 }
1536 break;
1537
H. Peter Anvin507ae032008-10-09 15:37:10 -07001538 case4(0254):
H. Peter Anvin588df782008-10-07 10:05:10 -07001539 data = opx->offset;
1540 if (opx->wrt == NO_SEG && opx->segment == NO_SEG &&
1541 (int32_t)data != (int64_t)data) {
1542 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
1543 "signed dword immediate exceeds bounds");
1544 }
1545 out(offset, segment, &data, OUT_ADDRESS, 4,
1546 opx->segment, opx->wrt);
1547 offset += 4;
1548 break;
1549
H. Peter Anvin507ae032008-10-09 15:37:10 -07001550 case4(0260):
H. Peter Anvind85d2502008-05-04 17:53:31 -07001551 case 0270:
1552 codes += 2;
H. Peter Anvina04019c2009-05-03 21:42:34 -07001553 if (ins->vex_cm != 1 || (ins->rex & (REX_W|REX_X|REX_B))) {
1554 bytes[0] = (ins->vex_cm >> 6) ? 0x8f : 0xc4;
1555 bytes[1] = (ins->vex_cm & 31) | ((~ins->rex & 7) << 5);
H. Peter Anvind85d2502008-05-04 17:53:31 -07001556 bytes[2] = ((ins->rex & REX_W) << (7-3)) |
H. Peter Anvin4d2c38c2008-05-04 23:15:13 -07001557 ((~ins->drexdst & 15)<< 3) | (ins->vex_wlp & 07);
H. Peter Anvind85d2502008-05-04 17:53:31 -07001558 out(offset, segment, &bytes, OUT_RAWDATA, 3, NO_SEG, NO_SEG);
1559 offset += 3;
1560 } else {
1561 bytes[0] = 0xc5;
H. Peter Anvin4d2c38c2008-05-04 23:15:13 -07001562 bytes[1] = ((~ins->rex & REX_R) << (7-2)) |
1563 ((~ins->drexdst & 15) << 3) | (ins->vex_wlp & 07);
H. Peter Anvind85d2502008-05-04 17:53:31 -07001564 out(offset, segment, &bytes, OUT_RAWDATA, 2, NO_SEG, NO_SEG);
1565 offset += 2;
1566 }
1567 break;
1568
H. Peter Anvin507ae032008-10-09 15:37:10 -07001569 case4(0274):
H. Peter Anvinc1377e92008-10-06 23:40:31 -07001570 {
1571 uint64_t uv, um;
1572 int s;
1573
1574 if (ins->rex & REX_W)
1575 s = 64;
1576 else if (ins->prefixes[PPS_OSIZE] == P_O16)
1577 s = 16;
1578 else if (ins->prefixes[PPS_OSIZE] == P_O32)
1579 s = 32;
1580 else
1581 s = bits;
1582
1583 um = (uint64_t)2 << (s-1);
1584 uv = opx->offset;
1585
1586 if (uv > 127 && uv < (uint64_t)-128 &&
1587 (uv < um-128 || uv > um-1)) {
1588 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
1589 "signed byte value exceeds bounds");
1590 }
1591 if (opx->segment != NO_SEG) {
H. Peter Anvin779ed8b2008-10-16 13:01:43 -07001592 data = uv;
H. Peter Anvinc1377e92008-10-06 23:40:31 -07001593 out(offset, segment, &data, OUT_ADDRESS, 1,
1594 opx->segment, opx->wrt);
1595 } else {
H. Peter Anvin779ed8b2008-10-16 13:01:43 -07001596 bytes[0] = uv;
H. Peter Anvinc1377e92008-10-06 23:40:31 -07001597 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
1598 NO_SEG);
1599 }
1600 offset += 1;
1601 break;
1602 }
1603
H. Peter Anvin507ae032008-10-09 15:37:10 -07001604 case4(0300):
H. Peter Anvine2c80182005-01-15 22:15:51 +00001605 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001606
H. Peter Anvine2c80182005-01-15 22:15:51 +00001607 case 0310:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001608 if (bits == 32 && !has_prefix(ins, PPS_ASIZE, P_A16)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001609 *bytes = 0x67;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001610 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001611 offset += 1;
1612 } else
1613 offset += 0;
1614 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001615
H. Peter Anvine2c80182005-01-15 22:15:51 +00001616 case 0311:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001617 if (bits != 32 && !has_prefix(ins, PPS_ASIZE, P_A32)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001618 *bytes = 0x67;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001619 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001620 offset += 1;
1621 } else
1622 offset += 0;
1623 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001624
H. Peter Anvine2c80182005-01-15 22:15:51 +00001625 case 0312:
1626 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001627
Keith Kaniosb7a89542007-04-12 02:40:54 +00001628 case 0313:
1629 ins->rex = 0;
1630 break;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07001631
H. Peter Anvin507ae032008-10-09 15:37:10 -07001632 case4(0314):
H. Peter Anvin23440102007-11-12 21:02:33 -08001633 break;
1634
H. Peter Anvine2c80182005-01-15 22:15:51 +00001635 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001636 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001637 *bytes = 0x66;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001638 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001639 offset += 1;
1640 } else
1641 offset += 0;
1642 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001643
H. Peter Anvine2c80182005-01-15 22:15:51 +00001644 case 0321:
1645 if (bits == 16) {
1646 *bytes = 0x66;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001647 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001648 offset += 1;
1649 } else
1650 offset += 0;
1651 break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001652
H. Peter Anvine2c80182005-01-15 22:15:51 +00001653 case 0322:
H. Peter Anvin70653092007-10-19 14:42:29 -07001654 case 0323:
1655 break;
1656
Keith Kaniosb7a89542007-04-12 02:40:54 +00001657 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001658 ins->rex |= REX_W;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001659 break;
H. Peter Anvin70653092007-10-19 14:42:29 -07001660
H. Peter Anvin9472dab2009-06-24 21:38:29 -07001661 case 0325:
1662 break;
1663
H. Peter Anvine2c80182005-01-15 22:15:51 +00001664 case 0330:
1665 *bytes = *codes++ ^ condval[ins->condition];
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001666 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001667 offset += 1;
1668 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001669
H. Peter Anvine2c80182005-01-15 22:15:51 +00001670 case 0331:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001671 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001672
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001673 case 0332:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001674 case 0333:
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001675 *bytes = c - 0332 + 0xF2;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001676 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001677 offset += 1;
1678 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001679
Keith Kanios48af1772007-08-17 07:37:52 +00001680 case 0334:
1681 if (ins->rex & REX_R) {
1682 *bytes = 0xF0;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001683 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
Keith Kanios48af1772007-08-17 07:37:52 +00001684 offset += 1;
1685 }
1686 ins->rex &= ~(REX_L|REX_R);
1687 break;
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001688
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001689 case 0335:
1690 break;
1691
H. Peter Anvin962e3052008-08-28 17:47:16 -07001692 case 0336:
1693 case 0337:
1694 break;
1695
H. Peter Anvine2c80182005-01-15 22:15:51 +00001696 case 0340:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001697 if (ins->oprs[0].segment != NO_SEG)
1698 errfunc(ERR_PANIC, "non-constant BSS size in pass two");
1699 else {
H. Peter Anvin428fd672007-11-15 10:25:52 -08001700 int64_t size = ins->oprs[0].offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001701 if (size > 0)
1702 out(offset, segment, NULL,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001703 OUT_RESERVE, size, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001704 offset += size;
1705 }
1706 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001707
H. Peter Anvinc2acf7b2009-02-21 18:22:56 -08001708 case 0341:
1709 break;
1710
H. Peter Anvinff6e12d2008-10-08 21:17:32 -07001711 case 0344:
1712 case 0345:
1713 bytes[0] = c & 1;
1714 switch (ins->oprs[0].basereg) {
1715 case R_CS:
1716 bytes[0] += 0x0E;
1717 break;
1718 case R_DS:
1719 bytes[0] += 0x1E;
1720 break;
1721 case R_ES:
1722 bytes[0] += 0x06;
1723 break;
1724 case R_SS:
1725 bytes[0] += 0x16;
1726 break;
1727 default:
1728 errfunc(ERR_PANIC,
1729 "bizarre 8086 segment register received");
1730 }
1731 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1732 offset++;
1733 break;
1734
1735 case 0346:
1736 case 0347:
1737 bytes[0] = c & 1;
1738 switch (ins->oprs[0].basereg) {
1739 case R_FS:
1740 bytes[0] += 0xA0;
1741 break;
1742 case R_GS:
1743 bytes[0] += 0xA8;
1744 break;
1745 default:
1746 errfunc(ERR_PANIC,
1747 "bizarre 386 segment register received");
1748 }
1749 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1750 offset++;
1751 break;
1752
H. Peter Anvinfff5a472008-05-20 09:46:24 -07001753 case 0360:
1754 break;
1755
1756 case 0361:
1757 bytes[0] = 0x66;
1758 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1759 offset += 1;
1760 break;
1761
1762 case 0362:
1763 case 0363:
1764 bytes[0] = c - 0362 + 0xf2;
1765 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1766 offset += 1;
1767 break;
1768
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001769 case 0364:
1770 case 0365:
1771 break;
1772
Keith Kanios48af1772007-08-17 07:37:52 +00001773 case 0366:
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001774 case 0367:
1775 *bytes = c - 0366 + 0x66;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001776 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
Keith Kanios48af1772007-08-17 07:37:52 +00001777 offset += 1;
1778 break;
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001779
H. Peter Anvine2c80182005-01-15 22:15:51 +00001780 case 0370:
1781 case 0371:
1782 case 0372:
1783 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001784
H. Peter Anvine2c80182005-01-15 22:15:51 +00001785 case 0373:
1786 *bytes = bits == 16 ? 3 : 5;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001787 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001788 offset += 1;
1789 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001790
H. Peter Anvin507ae032008-10-09 15:37:10 -07001791 case4(0100):
1792 case4(0110):
1793 case4(0120):
1794 case4(0130):
1795 case4(0200):
1796 case4(0204):
1797 case4(0210):
1798 case4(0214):
1799 case4(0220):
1800 case4(0224):
1801 case4(0230):
1802 case4(0234):
1803 {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001804 ea ea_data;
1805 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001806 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001807 uint8_t *p;
1808 int32_t s;
H. Peter Anvin9f817132008-10-06 19:11:07 -07001809 enum out_type type;
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001810 struct operand *opy = &ins->oprs[op2];
H. Peter Anvin70653092007-10-19 14:42:29 -07001811
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001812 if (c <= 0177) {
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001813 /* pick rfield from operand b (opx) */
1814 rflags = regflag(opx);
1815 rfield = nasm_regvals[opx->basereg];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001816 } else {
1817 /* rfield is constant */
1818 rflags = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001819 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001820 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001821
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001822 if (!process_ea(opy, &ea_data, bits, ins->addr_size,
1823 rfield, rflags)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001824 errfunc(ERR_NONFATAL, "invalid effective address");
1825 }
H. Peter Anvin70653092007-10-19 14:42:29 -07001826
Charles Crayne7e975552007-11-03 22:06:13 -07001827
H. Peter Anvine2c80182005-01-15 22:15:51 +00001828 p = bytes;
1829 *p++ = ea_data.modrm;
1830 if (ea_data.sib_present)
1831 *p++ = ea_data.sib;
1832
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001833 /* DREX suffixes come between the SIB and the displacement */
1834 if (ins->rex & REX_D) {
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001835 *p++ = (ins->drexdst << 4) |
1836 (ins->rex & REX_OC ? 0x08 : 0) |
1837 (ins->rex & (REX_R|REX_X|REX_B));
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001838 ins->rex = 0;
1839 }
1840
H. Peter Anvine2c80182005-01-15 22:15:51 +00001841 s = p - bytes;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001842 out(offset, segment, bytes, OUT_RAWDATA, s, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001843
Victor van den Elzencf9332c2008-10-01 12:18:28 +02001844 /*
1845 * Make sure the address gets the right offset in case
1846 * the line breaks in the .lst file (BR 1197827)
1847 */
1848 offset += s;
1849 s = 0;
1850
H. Peter Anvine2c80182005-01-15 22:15:51 +00001851 switch (ea_data.bytes) {
1852 case 0:
1853 break;
1854 case 1:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001855 case 2:
1856 case 4:
Victor van den Elzen352fe062008-12-10 13:04:58 +01001857 case 8:
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001858 data = opy->offset;
1859 warn_overflow(ea_data.bytes, opy);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001860 s += ea_data.bytes;
H. Peter Anvin9f817132008-10-06 19:11:07 -07001861 if (ea_data.rip) {
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001862 if (opy->segment == segment) {
H. Peter Anvine286c7e2008-10-22 11:15:00 -07001863 data -= insn_end;
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001864 out(offset, segment, &data, OUT_ADDRESS,
1865 ea_data.bytes, NO_SEG, NO_SEG);
H. Peter Anvine286c7e2008-10-22 11:15:00 -07001866 } else {
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001867 out(offset, segment, &data, OUT_REL4ADR,
1868 insn_end - offset, opy->segment, opy->wrt);
H. Peter Anvine286c7e2008-10-22 11:15:00 -07001869 }
H. Peter Anvin9f817132008-10-06 19:11:07 -07001870 } else {
1871 type = OUT_ADDRESS;
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001872 out(offset, segment, &data, OUT_ADDRESS,
1873 ea_data.bytes, opy->segment, opy->wrt);
H. Peter Anvin9f817132008-10-06 19:11:07 -07001874 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001875 break;
Victor van den Elzen352fe062008-12-10 13:04:58 +01001876 default:
1877 /* Impossible! */
1878 errfunc(ERR_PANIC,
1879 "Invalid amount of bytes (%d) for offset?!",
1880 ea_data.bytes);
1881 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001882 }
1883 offset += s;
H. Peter Anvin839eca22007-10-29 23:12:47 -07001884 }
H. Peter Anvin507ae032008-10-09 15:37:10 -07001885 break;
1886
1887 default:
1888 errfunc(ERR_PANIC, "internal instruction table corrupt"
H. Peter Anvin16a856c2009-03-01 00:22:16 -08001889 ": instruction code \\%o (0x%02X) given", c, c);
H. Peter Anvin507ae032008-10-09 15:37:10 -07001890 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001891 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001892 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001893}
1894
H. Peter Anvin0ec60e62007-07-07 01:59:52 +00001895static int32_t regflag(const operand * o)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001896{
1897 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1898 errfunc(ERR_PANIC, "invalid operand passed to regflag()");
1899 }
H. Peter Anvina4835d42008-05-20 14:21:29 -07001900 return nasm_reg_flags[o->basereg];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001901}
1902
H. Peter Anvin5b0e3ec2007-07-07 02:01:08 +00001903static int32_t regval(const operand * o)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001904{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001905 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1906 errfunc(ERR_PANIC, "invalid operand passed to regval()");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001907 }
H. Peter Anvina4835d42008-05-20 14:21:29 -07001908 return nasm_regvals[o->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001909}
1910
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001911static int op_rexflags(const operand * o, int mask)
1912{
1913 int32_t flags;
1914 int val;
1915
1916 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1917 errfunc(ERR_PANIC, "invalid operand passed to op_rexflags()");
1918 }
1919
H. Peter Anvina4835d42008-05-20 14:21:29 -07001920 flags = nasm_reg_flags[o->basereg];
1921 val = nasm_regvals[o->basereg];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001922
1923 return rexflags(val, flags, mask);
1924}
1925
1926static int rexflags(int val, int32_t flags, int mask)
1927{
1928 int rex = 0;
1929
1930 if (val >= 8)
1931 rex |= REX_B|REX_X|REX_R;
1932 if (flags & BITS64)
1933 rex |= REX_W;
1934 if (!(REG_HIGH & ~flags)) /* AH, CH, DH, BH */
1935 rex |= REX_H;
1936 else if (!(REG8 & ~flags) && val >= 4) /* SPL, BPL, SIL, DIL */
1937 rex |= REX_P;
1938
1939 return rex & mask;
1940}
1941
H. Peter Anvin3360d792007-09-11 04:16:57 +00001942static int matches(const struct itemplate *itemp, insn * instruction, int bits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001943{
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001944 int i, size[MAX_OPERANDS], asize, oprs, ret;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001945
1946 ret = 100;
1947
1948 /*
1949 * Check the opcode
1950 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001951 if (itemp->opcode != instruction->opcode)
1952 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001953
1954 /*
1955 * Count the operands
1956 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001957 if (itemp->operands != instruction->operands)
1958 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001959
1960 /*
1961 * Check that no spurious colons or TOs are present
1962 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001963 for (i = 0; i < itemp->operands; i++)
1964 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON | TO))
1965 return 0;
H. Peter Anvin70653092007-10-19 14:42:29 -07001966
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001967 /*
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001968 * Process size flags
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001969 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001970 if (itemp->flags & IF_ARMASK) {
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001971 memset(size, 0, sizeof size);
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001972
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001973 i = ((itemp->flags & IF_ARMASK) >> IF_ARSHFT) - 1;
1974
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001975 switch (itemp->flags & IF_SMASK) {
1976 case IF_SB:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001977 size[i] = BITS8;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001978 break;
1979 case IF_SW:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001980 size[i] = BITS16;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001981 break;
1982 case IF_SD:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001983 size[i] = BITS32;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001984 break;
1985 case IF_SQ:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001986 size[i] = BITS64;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001987 break;
H. Peter Anvin41c9f6f2007-09-18 13:01:32 -07001988 case IF_SO:
1989 size[i] = BITS128;
1990 break;
H. Peter Anvindfb91802008-05-20 11:43:53 -07001991 case IF_SY:
1992 size[i] = BITS256;
1993 break;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001994 case IF_SZ:
1995 switch (bits) {
1996 case 16:
1997 size[i] = BITS16;
1998 break;
1999 case 32:
2000 size[i] = BITS32;
2001 break;
2002 case 64:
2003 size[i] = BITS64;
2004 break;
2005 }
2006 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002007 default:
2008 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002009 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002010 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002011 asize = 0;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002012 switch (itemp->flags & IF_SMASK) {
2013 case IF_SB:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002014 asize = BITS8;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002015 break;
2016 case IF_SW:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002017 asize = BITS16;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002018 break;
2019 case IF_SD:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002020 asize = BITS32;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002021 break;
2022 case IF_SQ:
Keith Kaniosb7a89542007-04-12 02:40:54 +00002023 asize = BITS64;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002024 break;
H. Peter Anvin41c9f6f2007-09-18 13:01:32 -07002025 case IF_SO:
2026 asize = BITS128;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002027 break;
H. Peter Anvindfb91802008-05-20 11:43:53 -07002028 case IF_SY:
2029 asize = BITS256;
2030 break;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002031 case IF_SZ:
2032 switch (bits) {
2033 case 16:
2034 asize = BITS16;
2035 break;
2036 case 32:
2037 asize = BITS32;
2038 break;
2039 case 64:
2040 asize = BITS64;
2041 break;
2042 }
H. Peter Anvin41c9f6f2007-09-18 13:01:32 -07002043 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002044 default:
2045 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002046 }
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002047 for (i = 0; i < MAX_OPERANDS; i++)
2048 size[i] = asize;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002049 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002050
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002051 /*
2052 * Check that the operand flags all match up
2053 */
2054 for (i = 0; i < itemp->operands; i++) {
2055 int32_t type = instruction->oprs[i].type;
2056 if (!(type & SIZE_MASK))
2057 type |= size[i];
H. Peter Anvind85d2502008-05-04 17:53:31 -07002058
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002059 if (itemp->opd[i] & SAME_AS) {
2060 int j = itemp->opd[i] & ~SAME_AS;
2061 if (type != instruction->oprs[j].type ||
2062 instruction->oprs[i].basereg != instruction->oprs[j].basereg)
2063 return 0;
2064 } else if (itemp->opd[i] & ~type ||
2065 ((itemp->opd[i] & SIZE_MASK) &&
2066 ((itemp->opd[i] ^ type) & SIZE_MASK))) {
2067 if ((itemp->opd[i] & ~type & ~SIZE_MASK) ||
2068 (type & SIZE_MASK))
2069 return 0;
2070 else
2071 return 1;
2072 }
2073 }
2074
2075 /*
2076 * Check operand sizes
2077 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002078 if (itemp->flags & (IF_SM | IF_SM2)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002079 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
2080 asize = 0;
2081 for (i = 0; i < oprs; i++) {
2082 if ((asize = itemp->opd[i] & SIZE_MASK) != 0) {
2083 int j;
2084 for (j = 0; j < oprs; j++)
2085 size[j] = asize;
2086 break;
2087 }
2088 }
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002089 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002090 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002091 }
2092
Keith Kaniosb7a89542007-04-12 02:40:54 +00002093 for (i = 0; i < itemp->operands; i++) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002094 if (!(itemp->opd[i] & SIZE_MASK) &&
2095 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvine2c80182005-01-15 22:15:51 +00002096 return 2;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002097 }
2098
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002099 /*
2100 * Check template is okay at the set cpu level
2101 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002102 if (((itemp->flags & IF_PLEVEL) > cpu))
H. Peter Anvine2c80182005-01-15 22:15:51 +00002103 return 3;
H. Peter Anvin70653092007-10-19 14:42:29 -07002104
Keith Kaniosb7a89542007-04-12 02:40:54 +00002105 /*
H. Peter Anvin6cda4142008-12-29 20:52:28 -08002106 * Verify the appropriate long mode flag.
Keith Kaniosb7a89542007-04-12 02:40:54 +00002107 */
H. Peter Anvin6cda4142008-12-29 20:52:28 -08002108 if ((itemp->flags & (bits == 64 ? IF_NOLONG : IF_LONG)))
Keith Kaniosb7a89542007-04-12 02:40:54 +00002109 return 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002110
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002111 /*
2112 * Check if special handling needed for Jumps
2113 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002114 if ((uint8_t)(itemp->code[0]) >= 0370)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002115 return 99;
2116
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002117 return ret;
2118}
2119
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002120static ea *process_ea(operand * input, ea * output, int bits,
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07002121 int addrbits, int rfield, int32_t rflags)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002122{
H. Peter Anvin9945fee2009-02-26 14:48:03 -08002123 bool forw_ref = !!(input->opflags & OPFLAG_UNKNOWN);
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07002124
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002125 output->rip = false;
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00002126
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002127 /* REX flags for the rfield operand */
2128 output->rex |= rexflags(rfield, rflags, REX_R|REX_P|REX_W|REX_H);
2129
Keith Kaniosb7a89542007-04-12 02:40:54 +00002130 if (!(REGISTER & ~input->type)) { /* register direct */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002131 int i;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002132 int32_t f;
2133
2134 if (input->basereg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002135 || input->basereg >= REG_ENUM_LIMIT)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002136 return NULL;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002137 f = regflag(input);
H. Peter Anvina4835d42008-05-20 14:21:29 -07002138 i = nasm_regvals[input->basereg];
Keith Kaniosb7a89542007-04-12 02:40:54 +00002139
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002140 if (REG_EA & ~f)
2141 return NULL; /* Invalid EA register */
H. Peter Anvin70653092007-10-19 14:42:29 -07002142
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002143 output->rex |= op_rexflags(input, REX_B|REX_P|REX_W|REX_H);
2144
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002145 output->sib_present = false; /* no SIB necessary */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002146 output->bytes = 0; /* no offset necessary either */
2147 output->modrm = 0xC0 | ((rfield & 7) << 3) | (i & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002148 } else { /* it's a memory reference */
2149 if (input->basereg == -1
2150 && (input->indexreg == -1 || input->scale == 0)) {
2151 /* it's a pure offset */
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002152 if (bits == 64 && (~input->type & IP_REL)) {
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002153 int scale, index, base;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002154 output->sib_present = true;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002155 scale = 0;
2156 index = 4;
2157 base = 5;
2158 output->sib = (scale << 6) | (index << 3) | base;
2159 output->bytes = 4;
2160 output->modrm = 4 | ((rfield & 7) << 3);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002161 output->rip = false;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002162 } else {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002163 output->sib_present = false;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002164 output->bytes = (addrbits != 16 ? 4 : 2);
2165 output->modrm = (addrbits != 16 ? 5 : 6) | ((rfield & 7) << 3);
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002166 output->rip = bits == 64;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002167 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002168 } else { /* it's an indirection */
2169 int i = input->indexreg, b = input->basereg, s = input->scale;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002170 int32_t o = input->offset, seg = input->segment;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002171 int hb = input->hintbase, ht = input->hinttype;
2172 int t;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002173 int it, bt;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002174 int32_t ix, bx; /* register flags */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002175
H. Peter Anvine2c80182005-01-15 22:15:51 +00002176 if (s == 0)
2177 i = -1; /* make this easy, at least */
H. Peter Anvin70653092007-10-19 14:42:29 -07002178
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002179 if (i >= EXPR_REG_START && i < REG_ENUM_LIMIT) {
H. Peter Anvina4835d42008-05-20 14:21:29 -07002180 it = nasm_regvals[i];
2181 ix = nasm_reg_flags[i];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002182 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00002183 it = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002184 ix = 0;
2185 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002186
H. Peter Anvinb0c54622007-10-28 23:21:46 -07002187 if (b >= EXPR_REG_START && b < REG_ENUM_LIMIT) {
H. Peter Anvina4835d42008-05-20 14:21:29 -07002188 bt = nasm_regvals[b];
2189 bx = nasm_reg_flags[b];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002190 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00002191 bt = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002192 bx = 0;
2193 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002194
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002195 /* check for a 32/64-bit memory reference... */
2196 if ((ix|bx) & (BITS32|BITS64)) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00002197 /* it must be a 32/64-bit memory reference. Firstly we have
2198 * to check that all registers involved are type E/Rxx. */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002199 int32_t sok = BITS32|BITS64;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002200
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002201 if (it != -1) {
2202 if (!(REG64 & ~ix) || !(REG32 & ~ix))
2203 sok &= ix;
2204 else
2205 return NULL;
2206 }
2207
2208 if (bt != -1) {
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00002209 if (REG_GPR & ~bx)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002210 return NULL; /* Invalid register */
H. Peter Anvina57e8d42007-05-30 03:44:02 +00002211 if (~sok & bx & SIZE_MASK)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002212 return NULL; /* Invalid size */
H. Peter Anvinb0c54622007-10-28 23:21:46 -07002213 sok &= bx;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002214 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002215
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002216 /* While we're here, ensure the user didn't specify
2217 WORD or QWORD. */
2218 if (input->disp_size == 16 || input->disp_size == 64)
2219 return NULL;
2220
2221 if (addrbits == 16 ||
2222 (addrbits == 32 && !(sok & BITS32)) ||
2223 (addrbits == 64 && !(sok & BITS64)))
2224 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002225
Keith Kaniosb7a89542007-04-12 02:40:54 +00002226 /* now reorganize base/index */
2227 if (s == 1 && bt != it && bt != -1 && it != -1 &&
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002228 ((hb == b && ht == EAH_NOTBASE)
2229 || (hb == i && ht == EAH_MAKEBASE))) {
2230 /* swap if hints say so */
2231 t = bt, bt = it, it = t;
2232 t = bx, bx = ix, ix = t;
2233 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00002234 if (bt == it) /* convert EAX+2*EAX to 3*EAX */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002235 bt = -1, bx = 0, s++;
2236 if (bt == -1 && s == 1 && !(hb == it && ht == EAH_NOTBASE)) {
2237 /* make single reg base, unless hint */
2238 bt = it, bx = ix, it = -1, ix = 0;
2239 }
H. Peter Anvinf5843c62007-09-10 18:59:26 +00002240 if (((s == 2 && it != REG_NUM_ESP
H. Peter Anvine2c80182005-01-15 22:15:51 +00002241 && !(input->eaflags & EAF_TIMESTWO)) || s == 3
Keith Kaniosb7a89542007-04-12 02:40:54 +00002242 || s == 5 || s == 9) && bt == -1)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002243 bt = it, bx = ix, s--; /* convert 3*EAX to EAX+2*EAX */
Keith Kanios48af1772007-08-17 07:37:52 +00002244 if (it == -1 && (bt & 7) != REG_NUM_ESP
H. Peter Anvine2c80182005-01-15 22:15:51 +00002245 && (input->eaflags & EAF_TIMESTWO))
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002246 it = bt, ix = bx, bt = -1, bx = 0, s = 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002247 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
Keith Kanios48af1772007-08-17 07:37:52 +00002248 if (s == 1 && it == REG_NUM_ESP) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002249 /* swap ESP into base if scale is 1 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002250 t = it, it = bt, bt = t;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002251 t = ix, ix = bx, bx = t;
2252 }
Keith Kanios48af1772007-08-17 07:37:52 +00002253 if (it == REG_NUM_ESP
Keith Kaniosb7a89542007-04-12 02:40:54 +00002254 || (s != 1 && s != 2 && s != 4 && s != 8 && it != -1))
H. Peter Anvine2c80182005-01-15 22:15:51 +00002255 return NULL; /* wrong, for various reasons */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002256
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002257 output->rex |= rexflags(it, ix, REX_X);
2258 output->rex |= rexflags(bt, bx, REX_B);
Keith Kaniosb7a89542007-04-12 02:40:54 +00002259
Keith Kanios48af1772007-08-17 07:37:52 +00002260 if (it == -1 && (bt & 7) != REG_NUM_ESP) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002261 /* no SIB needed */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002262 int mod, rm;
H. Peter Anvin70653092007-10-19 14:42:29 -07002263
Keith Kaniosb7a89542007-04-12 02:40:54 +00002264 if (bt == -1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002265 rm = 5;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002266 mod = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002267 } else {
2268 rm = (bt & 7);
Keith Kanios48af1772007-08-17 07:37:52 +00002269 if (rm != REG_NUM_EBP && o == 0 &&
Keith Kaniosb7a89542007-04-12 02:40:54 +00002270 seg == NO_SEG && !forw_ref &&
2271 !(input->eaflags &
2272 (EAF_BYTEOFFS | EAF_WORDOFFS)))
2273 mod = 0;
2274 else if (input->eaflags & EAF_BYTEOFFS ||
2275 (o >= -128 && o <= 127 && seg == NO_SEG
2276 && !forw_ref
2277 && !(input->eaflags & EAF_WORDOFFS)))
2278 mod = 1;
2279 else
2280 mod = 2;
2281 }
H. Peter Anvinea838272002-04-30 20:51:53 +00002282
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002283 output->sib_present = false;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002284 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
2285 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002286 } else {
2287 /* we need a SIB */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002288 int mod, scale, index, base;
H. Peter Anvin70653092007-10-19 14:42:29 -07002289
Keith Kaniosb7a89542007-04-12 02:40:54 +00002290 if (it == -1)
2291 index = 4, s = 1;
2292 else
2293 index = (it & 7);
H. Peter Anvin70653092007-10-19 14:42:29 -07002294
H. Peter Anvine2c80182005-01-15 22:15:51 +00002295 switch (s) {
2296 case 1:
2297 scale = 0;
2298 break;
2299 case 2:
2300 scale = 1;
2301 break;
2302 case 4:
2303 scale = 2;
2304 break;
2305 case 8:
2306 scale = 3;
2307 break;
2308 default: /* then what the smeg is it? */
2309 return NULL; /* panic */
2310 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002311
Keith Kaniosb7a89542007-04-12 02:40:54 +00002312 if (bt == -1) {
2313 base = 5;
2314 mod = 0;
2315 } else {
2316 base = (bt & 7);
Keith Kanios48af1772007-08-17 07:37:52 +00002317 if (base != REG_NUM_EBP && o == 0 &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00002318 seg == NO_SEG && !forw_ref &&
2319 !(input->eaflags &
Keith Kaniosb7a89542007-04-12 02:40:54 +00002320 (EAF_BYTEOFFS | EAF_WORDOFFS)))
2321 mod = 0;
2322 else if (input->eaflags & EAF_BYTEOFFS ||
2323 (o >= -128 && o <= 127 && seg == NO_SEG
2324 && !forw_ref
2325 && !(input->eaflags & EAF_WORDOFFS)))
2326 mod = 1;
2327 else
2328 mod = 2;
2329 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002330
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002331 output->sib_present = true;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002332 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
2333 output->modrm = (mod << 6) | ((rfield & 7) << 3) | 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002334 output->sib = (scale << 6) | (index << 3) | base;
2335 }
2336 } else { /* it's 16-bit */
2337 int mod, rm;
H. Peter Anvin70653092007-10-19 14:42:29 -07002338
Keith Kaniosb7a89542007-04-12 02:40:54 +00002339 /* check for 64-bit long mode */
2340 if (addrbits == 64)
2341 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002342
H. Peter Anvine2c80182005-01-15 22:15:51 +00002343 /* check all registers are BX, BP, SI or DI */
2344 if ((b != -1 && b != R_BP && b != R_BX && b != R_SI
2345 && b != R_DI) || (i != -1 && i != R_BP && i != R_BX
2346 && i != R_SI && i != R_DI))
2347 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002348
Keith Kaniosb7a89542007-04-12 02:40:54 +00002349 /* ensure the user didn't specify DWORD/QWORD */
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002350 if (input->disp_size == 32 || input->disp_size == 64)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002351 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002352
H. Peter Anvine2c80182005-01-15 22:15:51 +00002353 if (s != 1 && i != -1)
2354 return NULL; /* no can do, in 16-bit EA */
2355 if (b == -1 && i != -1) {
2356 int tmp = b;
2357 b = i;
2358 i = tmp;
2359 } /* swap */
2360 if ((b == R_SI || b == R_DI) && i != -1) {
2361 int tmp = b;
2362 b = i;
2363 i = tmp;
2364 }
2365 /* have BX/BP as base, SI/DI index */
2366 if (b == i)
2367 return NULL; /* shouldn't ever happen, in theory */
2368 if (i != -1 && b != -1 &&
2369 (i == R_BP || i == R_BX || b == R_SI || b == R_DI))
2370 return NULL; /* invalid combinations */
2371 if (b == -1) /* pure offset: handled above */
2372 return NULL; /* so if it gets to here, panic! */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002373
H. Peter Anvine2c80182005-01-15 22:15:51 +00002374 rm = -1;
2375 if (i != -1)
2376 switch (i * 256 + b) {
2377 case R_SI * 256 + R_BX:
2378 rm = 0;
2379 break;
2380 case R_DI * 256 + R_BX:
2381 rm = 1;
2382 break;
2383 case R_SI * 256 + R_BP:
2384 rm = 2;
2385 break;
2386 case R_DI * 256 + R_BP:
2387 rm = 3;
2388 break;
2389 } else
2390 switch (b) {
2391 case R_SI:
2392 rm = 4;
2393 break;
2394 case R_DI:
2395 rm = 5;
2396 break;
2397 case R_BP:
2398 rm = 6;
2399 break;
2400 case R_BX:
2401 rm = 7;
2402 break;
2403 }
2404 if (rm == -1) /* can't happen, in theory */
2405 return NULL; /* so panic if it does */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002406
H. Peter Anvine2c80182005-01-15 22:15:51 +00002407 if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
2408 !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
2409 mod = 0;
2410 else if (input->eaflags & EAF_BYTEOFFS ||
2411 (o >= -128 && o <= 127 && seg == NO_SEG
2412 && !forw_ref
2413 && !(input->eaflags & EAF_WORDOFFS)))
2414 mod = 1;
2415 else
2416 mod = 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002417
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002418 output->sib_present = false; /* no SIB - it's 16-bit */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002419 output->bytes = mod; /* bytes of offset needed */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002420 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002421 }
2422 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002423 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002424
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002425 output->size = 1 + output->sib_present + output->bytes;
2426 return output;
2427}
2428
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002429static void add_asp(insn *ins, int addrbits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002430{
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002431 int j, valid;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002432 int defdisp;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002433
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002434 valid = (addrbits == 64) ? 64|32 : 32|16;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002435
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002436 switch (ins->prefixes[PPS_ASIZE]) {
2437 case P_A16:
2438 valid &= 16;
2439 break;
2440 case P_A32:
2441 valid &= 32;
2442 break;
2443 case P_A64:
2444 valid &= 64;
2445 break;
2446 case P_ASP:
2447 valid &= (addrbits == 32) ? 16 : 32;
2448 break;
2449 default:
2450 break;
2451 }
2452
2453 for (j = 0; j < ins->operands; j++) {
2454 if (!(MEMORY & ~ins->oprs[j].type)) {
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002455 int32_t i, b;
H. Peter Anvin70653092007-10-19 14:42:29 -07002456
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002457 /* Verify as Register */
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002458 if (ins->oprs[j].indexreg < EXPR_REG_START
2459 || ins->oprs[j].indexreg >= REG_ENUM_LIMIT)
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002460 i = 0;
2461 else
H. Peter Anvina4835d42008-05-20 14:21:29 -07002462 i = nasm_reg_flags[ins->oprs[j].indexreg];
H. Peter Anvin70653092007-10-19 14:42:29 -07002463
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002464 /* Verify as Register */
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002465 if (ins->oprs[j].basereg < EXPR_REG_START
2466 || ins->oprs[j].basereg >= REG_ENUM_LIMIT)
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002467 b = 0;
2468 else
H. Peter Anvina4835d42008-05-20 14:21:29 -07002469 b = nasm_reg_flags[ins->oprs[j].basereg];
H. Peter Anvin70653092007-10-19 14:42:29 -07002470
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002471 if (ins->oprs[j].scale == 0)
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002472 i = 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002473
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002474 if (!i && !b) {
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002475 int ds = ins->oprs[j].disp_size;
2476 if ((addrbits != 64 && ds > 8) ||
2477 (addrbits == 64 && ds == 16))
2478 valid &= ds;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002479 } else {
2480 if (!(REG16 & ~b))
2481 valid &= 16;
2482 if (!(REG32 & ~b))
2483 valid &= 32;
2484 if (!(REG64 & ~b))
2485 valid &= 64;
H. Peter Anvin70653092007-10-19 14:42:29 -07002486
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002487 if (!(REG16 & ~i))
2488 valid &= 16;
2489 if (!(REG32 & ~i))
2490 valid &= 32;
2491 if (!(REG64 & ~i))
2492 valid &= 64;
2493 }
2494 }
2495 }
2496
2497 if (valid & addrbits) {
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002498 ins->addr_size = addrbits;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002499 } else if (valid & ((addrbits == 32) ? 16 : 32)) {
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002500 /* Add an address size prefix */
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002501 enum prefixes pref = (addrbits == 32) ? P_A16 : P_A32;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002502 ins->prefixes[PPS_ASIZE] = pref;
2503 ins->addr_size = (addrbits == 32) ? 16 : 32;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002504 } else {
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002505 /* Impossible... */
2506 errfunc(ERR_NONFATAL, "impossible combination of address sizes");
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002507 ins->addr_size = addrbits; /* Error recovery */
2508 }
2509
2510 defdisp = ins->addr_size == 16 ? 16 : 32;
2511
2512 for (j = 0; j < ins->operands; j++) {
2513 if (!(MEM_OFFS & ~ins->oprs[j].type) &&
2514 (ins->oprs[j].disp_size ? ins->oprs[j].disp_size : defdisp)
2515 != ins->addr_size) {
2516 /* mem_offs sizes must match the address size; if not,
2517 strip the MEM_OFFS bit and match only EA instructions */
2518 ins->oprs[j].type &= ~(MEM_OFFS & ~MEMORY);
2519 }
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002520 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002521}