blob: 00ee78fbe96535b7eec707318aa7222044944a79 [file] [log] [blame]
H. Peter Anvin9e6747c2009-06-28 17:13:04 -07001/* ----------------------------------------------------------------------- *
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002 *
H. Peter Anvin9e6747c2009-06-28 17:13:04 -07003 * Copyright 1996-2009 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00006 *
H. Peter Anvin9e6747c2009-06-28 17:13:04 -07007 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
9 * conditions are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
Cyrill Gorcunov1de95002009-11-06 00:08:38 +030017 *
H. Peter Anvin9e6747c2009-06-28 17:13:04 -070018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 * ----------------------------------------------------------------------- */
33
34/*
35 * assemble.c code generation for the Netwide Assembler
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000036 *
37 * the actual codes (C syntax, i.e. octal):
38 * \0 - terminates the code. (Unless it's a literal of course.)
H. Peter Anvindcffe4b2008-10-10 22:10:31 -070039 * \1..\4 - that many literal bytes follow in the code stream
40 * \5 - add 4 to the primary operand number (b, low octdigit)
41 * \6 - add 4 to the secondary operand number (a, middle octdigit)
42 * \7 - add 4 to both the primary and the secondary operand number
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070043 * \10..\13 - a literal byte follows in the code stream, to be added
44 * to the register value of operand 0..3
45 * \14..\17 - a signed byte immediate operand, from operand 0..3
46 * \20..\23 - a byte immediate operand, from operand 0..3
47 * \24..\27 - an unsigned byte immediate operand, from operand 0..3
48 * \30..\33 - a word immediate operand, from operand 0..3
49 * \34..\37 - select between \3[0-3] and \4[0-3] depending on 16/32 bit
H. Peter Anvin3ba46772002-05-27 23:19:35 +000050 * assembly mode or the operand-size override on the operand
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070051 * \40..\43 - a long immediate operand, from operand 0..3
52 * \44..\47 - select between \3[0-3], \4[0-3] and \5[4-7]
H. Peter Anvinde4b89b2007-10-01 15:41:25 -070053 * depending on the address size of the instruction.
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070054 * \50..\53 - a byte relative operand, from operand 0..3
55 * \54..\57 - a qword immediate operand, from operand 0..3
56 * \60..\63 - a word relative operand, from operand 0..3
57 * \64..\67 - select between \6[0-3] and \7[0-3] depending on 16/32 bit
H. Peter Anvin17799b42002-05-21 03:31:21 +000058 * assembly mode or the operand-size override on the operand
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070059 * \70..\73 - a long relative operand, from operand 0..3
H. Peter Anvinc1377e92008-10-06 23:40:31 -070060 * \74..\77 - a word constant, from the _segment_ part of operand 0..3
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000061 * \1ab - a ModRM, calculated on EA in operand a, with the spare
62 * field the register value of operand b.
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070063 * \140..\143 - an immediate word or signed byte for operand 0..3
H. Peter Anvina30cc072007-11-18 21:55:26 -080064 * \144..\147 - or 2 (s-field) into opcode byte if operand 0..3
65 * is a signed byte rather than a word. Opcode byte follows.
H. Peter Anvinc1377e92008-10-06 23:40:31 -070066 * \150..\153 - an immediate dword or signed byte for operand 0..3
H. Peter Anvina30cc072007-11-18 21:55:26 -080067 * \154..\157 - or 2 (s-field) into opcode byte if operand 0..3
H. Peter Anvin32cd4c22008-04-04 13:34:53 -070068 * is a signed byte rather than a dword. Opcode byte follows.
H. Peter Anvin401c07e2007-09-17 16:55:04 -070069 * \160..\163 - this instruction uses DREX rather than REX, with the
70 * OC0 field set to 0, and the dest field taken from
71 * operand 0..3.
72 * \164..\167 - this instruction uses DREX rather than REX, with the
73 * OC0 field set to 1, and the dest field taken from
74 * operand 0..3.
H. Peter Anvin401c07e2007-09-17 16:55:04 -070075 * \171 - placement of DREX suffix in the absence of an EA
H. Peter Anvind85d2502008-05-04 17:53:31 -070076 * \172\ab - the register number from operand a in bits 7..4, with
H. Peter Anvin52dc3532008-05-20 19:29:04 -070077 * the 4-bit immediate from operand b in bits 3..0.
H. Peter Anvind58656f2008-05-06 20:11:14 -070078 * \173\xab - the register number from operand a in bits 7..4, with
H. Peter Anvin52dc3532008-05-20 19:29:04 -070079 * the value b in bits 3..0.
80 * \174\a - the register number from operand a in bits 7..4, and
81 * an arbitrary value in bits 3..0 (assembled as zero.)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000082 * \2ab - a ModRM, calculated on EA in operand a, with the spare
83 * field equal to digit b.
H. Peter Anvin32cd4c22008-04-04 13:34:53 -070084 * \250..\253 - same as \150..\153, except warn if the 64-bit operand
85 * is not equal to the truncated and sign-extended 32-bit
86 * operand; used for 32-bit immediates in 64-bit mode.
H. Peter Anvin588df782008-10-07 10:05:10 -070087 * \254..\257 - a signed 32-bit operand to be extended to 64 bits.
H. Peter Anvina04019c2009-05-03 21:42:34 -070088 * \260..\263 - this instruction uses VEX/XOP rather than REX, with the
H. Peter Anvind85d2502008-05-04 17:53:31 -070089 * V field taken from operand 0..3.
H. Peter Anvina04019c2009-05-03 21:42:34 -070090 * \270 - this instruction uses VEX/XOP rather than REX, with the
H. Peter Anvind85d2502008-05-04 17:53:31 -070091 * V field set to 1111b.
92 *
H. Peter Anvina04019c2009-05-03 21:42:34 -070093 * VEX/XOP prefixes are followed by the sequence:
94 * \tmm\wlp where mm is the M field; and wlp is:
H. Peter Anvinaaa088f2008-05-12 11:13:41 -070095 * 00 0ww lpp
H. Peter Anvinbd420c72008-05-22 11:24:35 -070096 * [w0] ww = 0 for W = 0
97 * [w1] ww = 1 for W = 1
98 * [wx] ww = 2 for W don't care (always assembled as 0)
99 * [ww] ww = 3 for W used as REX.W
100 *
H. Peter Anvina04019c2009-05-03 21:42:34 -0700101 * t = 0 for VEX (C4/C5), t = 1 for XOP (8F).
H. Peter Anvind85d2502008-05-04 17:53:31 -0700102 *
H. Peter Anvinc1377e92008-10-06 23:40:31 -0700103 * \274..\277 - a signed byte immediate operand, from operand 0..3,
104 * which is to be extended to the operand size.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000105 * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
106 * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
H. Peter Anvind28f07f2009-06-26 16:18:00 -0700107 * \312 - (disassembler only) invalid with non-default address size.
H. Peter Anvince2b3972007-05-30 22:21:11 +0000108 * \313 - indicates fixed 64-bit address size, 0x67 invalid.
H. Peter Anvin23440102007-11-12 21:02:33 -0800109 * \314 - (disassembler only) invalid with REX.B
110 * \315 - (disassembler only) invalid with REX.X
111 * \316 - (disassembler only) invalid with REX.R
112 * \317 - (disassembler only) invalid with REX.W
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000113 * \320 - indicates fixed 16-bit operand size, i.e. optional 0x66.
114 * \321 - indicates fixed 32-bit operand size, i.e. optional 0x66.
115 * \322 - indicates that this instruction is only valid when the
116 * operand size is the default (instruction to disassembler,
117 * generates no code in the assembler)
H. Peter Anvince2b3972007-05-30 22:21:11 +0000118 * \323 - indicates fixed 64-bit operand size, REX on extensions only.
Keith Kaniosb7a89542007-04-12 02:40:54 +0000119 * \324 - indicates 64-bit operand size requiring REX prefix.
H. Peter Anvin9472dab2009-06-24 21:38:29 -0700120 * \325 - instruction which always uses spl/bpl/sil/dil
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000121 * \330 - a literal byte follows in the code stream, to be added
122 * to the condition code value of the instruction.
Keith Kanios48af1772007-08-17 07:37:52 +0000123 * \331 - instruction not valid with REP prefix. Hint for
H. Peter Anvinef7468f2002-04-30 20:57:59 +0000124 * disassembler only; for SSE instructions.
H. Peter Anvincb9b6902007-09-12 21:58:51 -0700125 * \332 - REP prefix (0xF2 byte) used as opcode extension.
126 * \333 - REP prefix (0xF3 byte) used as opcode extension.
H. Peter Anvin9472dab2009-06-24 21:38:29 -0700127 * \334 - LOCK prefix used as REX.R (used in non-64-bit mode)
H. Peter Anvincb9b6902007-09-12 21:58:51 -0700128 * \335 - disassemble a rep (0xF3 byte) prefix as repe not rep.
H. Peter Anvin962e3052008-08-28 17:47:16 -0700129 * \336 - force a REP(E) prefix (0xF2) even if not specified.
130 * \337 - force a REPNE prefix (0xF3) even if not specified.
131 * \336-\337 are still listed as prefixes in the disassembler.
Keith Kaniosb7a89542007-04-12 02:40:54 +0000132 * \340 - reserve <operand 0> bytes of uninitialized storage.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000133 * Operand 0 had better be a segmentless constant.
H. Peter Anvinc2acf7b2009-02-21 18:22:56 -0800134 * \341 - this instruction needs a WAIT "prefix"
H. Peter Anvinff6e12d2008-10-08 21:17:32 -0700135 * \344,\345 - the PUSH/POP (respectively) codes for CS, DS, ES, SS
136 * (POP is never used for CS) depending on operand 0
137 * \346,\347 - the second byte of PUSH/POP codes for FS, GS, depending
138 * on operand 0
H. Peter Anvinfff5a472008-05-20 09:46:24 -0700139 * \360 - no SSE prefix (== \364\331)
140 * \361 - 66 SSE prefix (== \366\331)
141 * \362 - F2 SSE prefix (== \364\332)
142 * \363 - F3 SSE prefix (== \364\333)
H. Peter Anvin62cb6062007-09-11 22:44:03 +0000143 * \364 - operand-size prefix (0x66) not permitted
144 * \365 - address-size prefix (0x67) not permitted
145 * \366 - operand-size prefix (0x66) used as opcode extension
146 * \367 - address-size prefix (0x67) used as opcode extension
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000147 * \370,\371,\372 - match only if operand 0 meets byte jump criteria.
148 * 370 is used for Jcc, 371 is used for JMP.
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000149 * \373 - assemble 0x03 if bits==16, 0x05 if bits==32;
150 * used for conditional jump over longer jump
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000151 */
152
H. Peter Anvinfe501952007-10-02 21:53:51 -0700153#include "compiler.h"
154
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000155#include <stdio.h>
156#include <string.h>
Keith Kaniosb7a89542007-04-12 02:40:54 +0000157#include <inttypes.h>
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000158
159#include "nasm.h"
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000160#include "nasmlib.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000161#include "assemble.h"
162#include "insns.h"
H. Peter Anvina4835d42008-05-20 14:21:29 -0700163#include "tables.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000164
H. Peter Anvin65289e82009-07-25 17:25:11 -0700165enum match_result {
166 /*
167 * Matching errors. These should be sorted so that more specific
168 * errors come later in the sequence.
169 */
170 MERR_INVALOP,
171 MERR_OPSIZEMISSING,
172 MERR_OPSIZEMISMATCH,
173 MERR_BADCPU,
174 MERR_BADMODE,
175 /*
176 * Matching success; the conditional ones first
177 */
178 MOK_JUMP, /* Matching OK but needs jmp_match() */
179 MOK_GOOD /* Matching unconditionally OK */
180};
181
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000182typedef struct {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000183 int sib_present; /* is a SIB byte necessary? */
184 int bytes; /* # of bytes of offset needed */
185 int size; /* lazy - this is sib+bytes+1 */
186 uint8_t modrm, sib, rex, rip; /* the bytes themselves */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000187} ea;
188
Keith Kaniosb7a89542007-04-12 02:40:54 +0000189static uint32_t cpu; /* cpu level received from nasm.c */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000190static efunc errfunc;
191static struct ofmt *outfmt;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000192static ListGen *list;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000193
H. Peter Anvin3720f7b2008-05-12 11:00:50 -0700194static int64_t calcsize(int32_t, int64_t, int, insn *, const uint8_t *);
H. Peter Anvin833caea2008-10-04 19:02:30 -0700195static void gencode(int32_t segment, int64_t offset, int bits,
196 insn * ins, const struct itemplate *temp,
197 int64_t insn_end);
H. Peter Anvin23595f52009-07-25 17:44:25 -0700198static enum match_result find_match(const struct itemplate **tempp,
199 insn *instruction,
200 int32_t segment, int64_t offset, int bits);
H. Peter Anvin65289e82009-07-25 17:25:11 -0700201static enum match_result matches(const struct itemplate *, insn *, int bits);
H. Peter Anvinf8563f72009-10-13 12:28:14 -0700202static opflags_t regflag(const operand *);
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000203static int32_t regval(const operand *);
H. Peter Anvinf8563f72009-10-13 12:28:14 -0700204static int rexflags(int, opflags_t, int);
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000205static int op_rexflags(const operand *, int);
H. Peter Anvinf8563f72009-10-13 12:28:14 -0700206static ea *process_ea(operand *, ea *, int, int, int, opflags_t);
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700207static void add_asp(insn *, int);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000208
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700209static int has_prefix(insn * ins, enum prefix_pos pos, enum prefixes prefix)
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000210{
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700211 return ins->prefixes[pos] == prefix;
212}
213
214static void assert_no_prefix(insn * ins, enum prefix_pos pos)
215{
216 if (ins->prefixes[pos])
217 errfunc(ERR_NONFATAL, "invalid %s prefix",
218 prefix_name(ins->prefixes[pos]));
219}
220
221static const char *size_name(int size)
222{
223 switch (size) {
224 case 1:
225 return "byte";
226 case 2:
227 return "word";
228 case 4:
229 return "dword";
230 case 8:
231 return "qword";
232 case 10:
233 return "tword";
234 case 16:
235 return "oword";
H. Peter Anvindfb91802008-05-20 11:43:53 -0700236 case 32:
237 return "yword";
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700238 default:
239 return "???";
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000240 }
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700241}
242
Cyrill Gorcunov9ccabd22009-09-21 00:56:20 +0400243static void warn_overflow(int pass, int size)
244{
245 errfunc(ERR_WARNING | pass | ERR_WARN_NOV,
246 "%s data exceeds bounds", size_name(size));
247}
248
249static void warn_overflow_const(int64_t data, int size)
250{
251 if (overflow_general(data, size))
252 warn_overflow(ERR_PASS1, size);
253}
254
255static void warn_overflow_opd(const struct operand *o, int size)
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700256{
Victor van den Elzen0d268fb2010-01-24 21:24:57 +0100257 if (o->wrt == NO_SEG && o->segment == NO_SEG) {
Cyrill Gorcunov9ccabd22009-09-21 00:56:20 +0400258 if (overflow_general(o->offset, size))
259 warn_overflow(ERR_PASS2, size);
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700260 }
261}
Cyrill Gorcunov9ccabd22009-09-21 00:56:20 +0400262
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000263/*
264 * This routine wrappers the real output format's output routine,
265 * in order to pass a copy of the data off to the listing file
266 * generator at the same time.
267 */
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800268static void out(int64_t offset, int32_t segto, const void *data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800269 enum out_type type, uint64_t size,
270 int32_t segment, int32_t wrt)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000271{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000272 static int32_t lineno = 0; /* static!!! */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000273 static char *lnfname = NULL;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800274 uint8_t p[8];
H. Peter Anvineba20a72002-04-30 20:53:55 +0000275
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800276 if (type == OUT_ADDRESS && segment == NO_SEG && wrt == NO_SEG) {
277 /*
278 * This is a non-relocated address, and we're going to
279 * convert it into RAWDATA format.
280 */
281 uint8_t *q = p;
H. Peter Anvind1fb15c2007-11-13 09:37:59 -0800282
283 if (size > 8) {
284 errfunc(ERR_PANIC, "OUT_ADDRESS with size > 8");
285 return;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800286 }
H. Peter Anvind85d2502008-05-04 17:53:31 -0700287
H. Peter Anvind1fb15c2007-11-13 09:37:59 -0800288 WRITEADDR(q, *(int64_t *)data, size);
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800289 data = p;
290 type = OUT_RAWDATA;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000291 }
292
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800293 list->output(offset, data, type, size);
294
Frank Kotlerabebb082003-09-06 04:45:37 +0000295 /*
296 * this call to src_get determines when we call the
297 * debug-format-specific "linenum" function
298 * it updates lineno and lnfname to the current values
299 * returning 0 if "same as last time", -2 if lnfname
300 * changed, and the amount by which lineno changed,
301 * if it did. thus, these variables must be static
302 */
303
H. Peter Anvine2c80182005-01-15 22:15:51 +0000304 if (src_get(&lineno, &lnfname)) {
305 outfmt->current_dfmt->linenum(lnfname, lineno, segto);
H. Peter Anvince616072002-04-30 21:02:23 +0000306 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000307
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800308 outfmt->output(segto, data, type, size, segment, wrt);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000309}
310
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700311static bool jmp_match(int32_t segment, int64_t offset, int bits,
H. Peter Anvin3720f7b2008-05-12 11:00:50 -0700312 insn * ins, const uint8_t *code)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000313{
Charles Crayne5fbbc8c2007-11-07 19:03:46 -0800314 int64_t isize;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000315 uint8_t c = code[0];
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000316
Charles Craynef1aefd82008-09-30 16:11:32 -0700317 if ((c != 0370 && c != 0371) || (ins->oprs[0].type & STRICT))
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700318 return false;
319 if (!optimizing)
320 return false;
321 if (optimizing < 0 && c == 0371)
322 return false;
323
H. Peter Anvine2c80182005-01-15 22:15:51 +0000324 isize = calcsize(segment, offset, bits, ins, code);
Victor van den Elzenccafc3c2009-02-23 04:35:00 +0100325
Victor van den Elzen154e5922009-02-25 17:32:00 +0100326 if (ins->oprs[0].opflags & OPFLAG_UNKNOWN)
Victor van den Elzenccafc3c2009-02-23 04:35:00 +0100327 /* Be optimistic in pass 1 */
328 return true;
329
H. Peter Anvine2c80182005-01-15 22:15:51 +0000330 if (ins->oprs[0].segment != segment)
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700331 return false;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000332
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700333 isize = ins->oprs[0].offset - offset - isize; /* isize is delta */
334 return (isize >= -128 && isize <= 127); /* is it byte size? */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000335}
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000336
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800337int64_t assemble(int32_t segment, int64_t offset, int bits, uint32_t cp,
H. Peter Anvin65289e82009-07-25 17:25:11 -0700338 insn * instruction, struct ofmt *output, efunc error,
339 ListGen * listgen)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000340{
H. Peter Anvin3360d792007-09-11 04:16:57 +0000341 const struct itemplate *temp;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000342 int j;
H. Peter Anvin23595f52009-07-25 17:44:25 -0700343 enum match_result m;
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800344 int64_t insn_end;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000345 int32_t itimes;
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800346 int64_t start = offset;
Cyrill Gorcunovbafd8772009-10-31 20:02:14 +0300347 int64_t wsize; /* size for DB etc. */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000348
H. Peter Anvine2c80182005-01-15 22:15:51 +0000349 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000350 cpu = cp;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000351 outfmt = output; /* likewise */
352 list = listgen; /* and again */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000353
Cyrill Gorcunovbafd8772009-10-31 20:02:14 +0300354 wsize = idata_bytes(instruction->opcode);
355 if (wsize == -1)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000356 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000357
H. Peter Anvineba20a72002-04-30 20:53:55 +0000358 if (wsize) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000359 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000360 int32_t t = instruction->times;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000361 if (t < 0)
362 errfunc(ERR_PANIC,
363 "instruction->times < 0 (%ld) in assemble()", t);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000364
H. Peter Anvine2c80182005-01-15 22:15:51 +0000365 while (t--) { /* repeat TIMES times */
Cyrill Gorcunova92a3a52009-07-27 22:33:59 +0400366 list_for_each(e, instruction->eops) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000367 if (e->type == EOT_DB_NUMBER) {
H. Peter Anvin55ae1202010-05-06 15:25:43 -0700368 if (wsize > 8) {
H. Peter Anvin3be5d852008-05-20 14:49:32 -0700369 errfunc(ERR_NONFATAL,
370 "integer supplied to a DT, DO or DY"
Keith Kanios61ff53c2007-04-14 18:54:52 +0000371 " instruction");
H. Peter Anvin55ae1202010-05-06 15:25:43 -0700372 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000373 out(offset, segment, &e->offset,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800374 OUT_ADDRESS, wsize, e->segment, e->wrt);
H. Peter Anvin55ae1202010-05-06 15:25:43 -0700375 offset += wsize;
376 }
H. Peter Anvin518df302008-06-14 16:53:48 -0700377 } else if (e->type == EOT_DB_STRING ||
378 e->type == EOT_DB_STRING_FREE) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000379 int align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000380
H. Peter Anvine2c80182005-01-15 22:15:51 +0000381 out(offset, segment, e->stringval,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800382 OUT_RAWDATA, e->stringlen, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000383 align = e->stringlen % wsize;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000384
H. Peter Anvine2c80182005-01-15 22:15:51 +0000385 if (align) {
386 align = wsize - align;
H. Peter Anvin999868f2009-02-09 11:03:33 +0100387 out(offset, segment, zero_buffer,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800388 OUT_RAWDATA, align, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000389 }
390 offset += e->stringlen + align;
391 }
392 }
393 if (t > 0 && t == instruction->times - 1) {
394 /*
395 * Dummy call to list->output to give the offset to the
396 * listing module.
397 */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800398 list->output(offset, NULL, OUT_RAWDATA, 0);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000399 list->uplevel(LIST_TIMES);
400 }
401 }
402 if (instruction->times > 1)
403 list->downlevel(LIST_TIMES);
404 return offset - start;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000405 }
406
H. Peter Anvine2c80182005-01-15 22:15:51 +0000407 if (instruction->opcode == I_INCBIN) {
H. Peter Anvin518df302008-06-14 16:53:48 -0700408 const char *fname = instruction->eops->stringval;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000409 FILE *fp;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000410
H. Peter Anvin418ca702008-05-30 10:42:30 -0700411 fp = fopen(fname, "rb");
412 if (!fp) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000413 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
414 fname);
H. Peter Anvin418ca702008-05-30 10:42:30 -0700415 } else if (fseek(fp, 0L, SEEK_END) < 0) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000416 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
417 fname);
H. Peter Anvin418ca702008-05-30 10:42:30 -0700418 } else {
H. Peter Anvin518df302008-06-14 16:53:48 -0700419 static char buf[4096];
420 size_t t = instruction->times;
421 size_t base = 0;
422 size_t len;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000423
H. Peter Anvine2c80182005-01-15 22:15:51 +0000424 len = ftell(fp);
425 if (instruction->eops->next) {
426 base = instruction->eops->next->offset;
427 len -= base;
428 if (instruction->eops->next->next &&
H. Peter Anvin518df302008-06-14 16:53:48 -0700429 len > (size_t)instruction->eops->next->next->offset)
430 len = (size_t)instruction->eops->next->next->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000431 }
432 /*
433 * Dummy call to list->output to give the offset to the
434 * listing module.
435 */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800436 list->output(offset, NULL, OUT_RAWDATA, 0);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000437 list->uplevel(LIST_INCBIN);
438 while (t--) {
H. Peter Anvin518df302008-06-14 16:53:48 -0700439 size_t l;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000440
H. Peter Anvine2c80182005-01-15 22:15:51 +0000441 fseek(fp, base, SEEK_SET);
442 l = len;
443 while (l > 0) {
H. Peter Anvin4a5a6df2009-06-27 16:14:18 -0700444 int32_t m;
445 m = fread(buf, 1, l > sizeof(buf) ? sizeof(buf) : l, fp);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000446 if (!m) {
447 /*
448 * This shouldn't happen unless the file
449 * actually changes while we are reading
450 * it.
451 */
452 error(ERR_NONFATAL,
453 "`incbin': unexpected EOF while"
454 " reading file `%s'", fname);
455 t = 0; /* Try to exit cleanly */
456 break;
457 }
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800458 out(offset, segment, buf, OUT_RAWDATA, m,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000459 NO_SEG, NO_SEG);
460 l -= m;
461 }
462 }
463 list->downlevel(LIST_INCBIN);
464 if (instruction->times > 1) {
465 /*
466 * Dummy call to list->output to give the offset to the
467 * listing module.
468 */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800469 list->output(offset, NULL, OUT_RAWDATA, 0);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000470 list->uplevel(LIST_TIMES);
471 list->downlevel(LIST_TIMES);
472 }
473 fclose(fp);
474 return instruction->times * len;
475 }
476 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000477 }
478
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700479 /* Check to see if we need an address-size prefix */
480 add_asp(instruction, bits);
481
H. Peter Anvin23595f52009-07-25 17:44:25 -0700482 m = find_match(&temp, instruction, segment, offset, bits);
H. Peter Anvin70653092007-10-19 14:42:29 -0700483
H. Peter Anvin23595f52009-07-25 17:44:25 -0700484 if (m == MOK_GOOD) {
485 /* Matches! */
486 int64_t insn_size = calcsize(segment, offset, bits,
487 instruction, temp->code);
488 itimes = instruction->times;
489 if (insn_size < 0) /* shouldn't be, on pass two */
490 error(ERR_PANIC, "errors made it through from pass one");
491 else
492 while (itimes--) {
493 for (j = 0; j < MAXPREFIX; j++) {
494 uint8_t c = 0;
495 switch (instruction->prefixes[j]) {
496 case P_WAIT:
497 c = 0x9B;
498 break;
499 case P_LOCK:
500 c = 0xF0;
501 break;
502 case P_REPNE:
503 case P_REPNZ:
504 c = 0xF2;
505 break;
506 case P_REPE:
507 case P_REPZ:
508 case P_REP:
509 c = 0xF3;
510 break;
511 case R_CS:
512 if (bits == 64) {
513 error(ERR_WARNING | ERR_PASS2,
514 "cs segment base generated, but will be ignored in 64-bit mode");
515 }
516 c = 0x2E;
517 break;
518 case R_DS:
519 if (bits == 64) {
520 error(ERR_WARNING | ERR_PASS2,
521 "ds segment base generated, but will be ignored in 64-bit mode");
522 }
523 c = 0x3E;
524 break;
525 case R_ES:
526 if (bits == 64) {
527 error(ERR_WARNING | ERR_PASS2,
528 "es segment base generated, but will be ignored in 64-bit mode");
529 }
530 c = 0x26;
531 break;
532 case R_FS:
533 c = 0x64;
534 break;
535 case R_GS:
536 c = 0x65;
537 break;
538 case R_SS:
539 if (bits == 64) {
540 error(ERR_WARNING | ERR_PASS2,
541 "ss segment base generated, but will be ignored in 64-bit mode");
542 }
543 c = 0x36;
544 break;
545 case R_SEGR6:
546 case R_SEGR7:
547 error(ERR_NONFATAL,
548 "segr6 and segr7 cannot be used as prefixes");
549 break;
550 case P_A16:
551 if (bits == 64) {
552 error(ERR_NONFATAL,
553 "16-bit addressing is not supported "
554 "in 64-bit mode");
555 } else if (bits != 16)
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700556 c = 0x67;
H. Peter Anvin23595f52009-07-25 17:44:25 -0700557 break;
558 case P_A32:
559 if (bits != 32)
560 c = 0x67;
561 break;
562 case P_A64:
563 if (bits != 64) {
564 error(ERR_NONFATAL,
565 "64-bit addressing is only supported "
566 "in 64-bit mode");
567 }
568 break;
569 case P_ASP:
570 c = 0x67;
571 break;
572 case P_O16:
573 if (bits != 16)
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700574 c = 0x66;
H. Peter Anvin23595f52009-07-25 17:44:25 -0700575 break;
576 case P_O32:
577 if (bits == 16)
578 c = 0x66;
579 break;
580 case P_O64:
581 /* REX.W */
582 break;
583 case P_OSP:
584 c = 0x66;
585 break;
586 case P_none:
587 break;
588 default:
589 error(ERR_PANIC, "invalid instruction prefix");
590 }
591 if (c != 0) {
592 out(offset, segment, &c, OUT_RAWDATA, 1,
593 NO_SEG, NO_SEG);
594 offset++;
595 }
596 }
597 insn_end = offset + insn_size;
598 gencode(segment, offset, bits, instruction,
599 temp, insn_end);
600 offset += insn_size;
601 if (itimes > 0 && itimes == instruction->times - 1) {
602 /*
603 * Dummy call to list->output to give the offset to the
604 * listing module.
605 */
606 list->output(offset, NULL, OUT_RAWDATA, 0);
607 list->uplevel(LIST_TIMES);
608 }
609 }
610 if (instruction->times > 1)
611 list->downlevel(LIST_TIMES);
612 return offset - start;
613 } else {
614 /* No match */
615 switch (m) {
H. Peter Anvin65289e82009-07-25 17:25:11 -0700616 case MERR_OPSIZEMISSING:
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000617 error(ERR_NONFATAL, "operation size not specified");
618 break;
H. Peter Anvin65289e82009-07-25 17:25:11 -0700619 case MERR_OPSIZEMISMATCH:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000620 error(ERR_NONFATAL, "mismatch in operand sizes");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000621 break;
H. Peter Anvin65289e82009-07-25 17:25:11 -0700622 case MERR_BADCPU:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000623 error(ERR_NONFATAL, "no instruction for this cpu level");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000624 break;
H. Peter Anvin65289e82009-07-25 17:25:11 -0700625 case MERR_BADMODE:
H. Peter Anvin6cda4142008-12-29 20:52:28 -0800626 error(ERR_NONFATAL, "instruction not supported in %d-bit mode",
627 bits);
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000628 break;
629 default:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000630 error(ERR_NONFATAL,
631 "invalid combination of opcode and operands");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000632 break;
633 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000634 }
635 return 0;
636}
637
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800638int64_t insn_size(int32_t segment, int64_t offset, int bits, uint32_t cp,
H. Peter Anvin65289e82009-07-25 17:25:11 -0700639 insn * instruction, efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000640{
H. Peter Anvin3360d792007-09-11 04:16:57 +0000641 const struct itemplate *temp;
H. Peter Anvin23595f52009-07-25 17:44:25 -0700642 enum match_result m;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000643
H. Peter Anvine2c80182005-01-15 22:15:51 +0000644 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000645 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000646
Cyrill Gorcunov37575242009-08-16 12:00:01 +0400647 if (instruction->opcode == I_none)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000648 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000649
H. Peter Anvincfbe7c32007-09-18 17:49:09 -0700650 if (instruction->opcode == I_DB || instruction->opcode == I_DW ||
651 instruction->opcode == I_DD || instruction->opcode == I_DQ ||
H. Peter Anvindfb91802008-05-20 11:43:53 -0700652 instruction->opcode == I_DT || instruction->opcode == I_DO ||
653 instruction->opcode == I_DY) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000654 extop *e;
Cyrill Gorcunovbafd8772009-10-31 20:02:14 +0300655 int32_t isize, osize, wsize;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000656
H. Peter Anvine2c80182005-01-15 22:15:51 +0000657 isize = 0;
Cyrill Gorcunovbafd8772009-10-31 20:02:14 +0300658 wsize = idata_bytes(instruction->opcode);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000659
Cyrill Gorcunova92a3a52009-07-27 22:33:59 +0400660 list_for_each(e, instruction->eops) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000661 int32_t align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000662
H. Peter Anvine2c80182005-01-15 22:15:51 +0000663 osize = 0;
Cyrill Gorcunov9ccabd22009-09-21 00:56:20 +0400664 if (e->type == EOT_DB_NUMBER) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000665 osize = 1;
Cyrill Gorcunov9ccabd22009-09-21 00:56:20 +0400666 warn_overflow_const(e->offset, wsize);
667 } else if (e->type == EOT_DB_STRING ||
668 e->type == EOT_DB_STRING_FREE)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000669 osize = e->stringlen;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000670
H. Peter Anvine2c80182005-01-15 22:15:51 +0000671 align = (-osize) % wsize;
672 if (align < 0)
673 align += wsize;
674 isize += osize + align;
675 }
676 return isize * instruction->times;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000677 }
678
H. Peter Anvine2c80182005-01-15 22:15:51 +0000679 if (instruction->opcode == I_INCBIN) {
H. Peter Anvin518df302008-06-14 16:53:48 -0700680 const char *fname = instruction->eops->stringval;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000681 FILE *fp;
Cyrill Gorcunov6531d6d2009-12-05 14:04:55 +0300682 int64_t val = 0;
H. Peter Anvin518df302008-06-14 16:53:48 -0700683 size_t len;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000684
H. Peter Anvin418ca702008-05-30 10:42:30 -0700685 fp = fopen(fname, "rb");
686 if (!fp)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000687 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
688 fname);
689 else if (fseek(fp, 0L, SEEK_END) < 0)
690 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
691 fname);
692 else {
693 len = ftell(fp);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000694 if (instruction->eops->next) {
695 len -= instruction->eops->next->offset;
696 if (instruction->eops->next->next &&
H. Peter Anvin518df302008-06-14 16:53:48 -0700697 len > (size_t)instruction->eops->next->next->offset) {
698 len = (size_t)instruction->eops->next->next->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000699 }
700 }
Cyrill Gorcunov6531d6d2009-12-05 14:04:55 +0300701 val = instruction->times * len;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000702 }
Cyrill Gorcunov6531d6d2009-12-05 14:04:55 +0300703 if (fp)
704 fclose(fp);
705 return val;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000706 }
707
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700708 /* Check to see if we need an address-size prefix */
709 add_asp(instruction, bits);
710
H. Peter Anvin23595f52009-07-25 17:44:25 -0700711 m = find_match(&temp, instruction, segment, offset, bits);
712 if (m == MOK_GOOD) {
713 /* we've matched an instruction. */
714 int64_t isize;
715 const uint8_t *codes = temp->code;
716 int j;
Victor van den Elzen0d268fb2010-01-24 21:24:57 +0100717
H. Peter Anvin23595f52009-07-25 17:44:25 -0700718 isize = calcsize(segment, offset, bits, instruction, codes);
719 if (isize < 0)
720 return -1;
721 for (j = 0; j < MAXPREFIX; j++) {
722 switch (instruction->prefixes[j]) {
723 case P_A16:
724 if (bits != 16)
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700725 isize++;
H. Peter Anvin23595f52009-07-25 17:44:25 -0700726 break;
727 case P_A32:
728 if (bits != 32)
729 isize++;
730 break;
731 case P_O16:
732 if (bits != 16)
733 isize++;
734 break;
735 case P_O32:
736 if (bits == 16)
737 isize++;
738 break;
739 case P_A64:
740 case P_O64:
741 case P_none:
742 break;
743 default:
744 isize++;
745 break;
746 }
747 }
748 return isize * instruction->times;
749 } else {
750 return -1; /* didn't match any instruction */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000751 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000752}
753
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700754static bool possible_sbyte(operand *o)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000755{
H. Peter Anvinad6b8592008-10-07 09:56:38 -0700756 return o->wrt == NO_SEG && o->segment == NO_SEG &&
H. Peter Anvine8ab8912009-02-26 16:34:56 -0800757 !(o->opflags & OPFLAG_UNKNOWN) &&
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700758 optimizing >= 0 && !(o->type & STRICT);
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000759}
760
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700761/* check that opn[op] is a signed byte of size 16 or 32 */
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700762static bool is_sbyte16(operand *o)
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700763{
764 int16_t v;
765
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700766 if (!possible_sbyte(o))
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700767 return false;
768
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700769 v = o->offset;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700770 return v >= -128 && v <= 127;
771}
772
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700773static bool is_sbyte32(operand *o)
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700774{
775 int32_t v;
776
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700777 if (!possible_sbyte(o))
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700778 return false;
779
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700780 v = o->offset;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700781 return v >= -128 && v <= 127;
782}
783
H. Peter Anvin507ae032008-10-09 15:37:10 -0700784/* Common construct */
785#define case4(x) case (x): case (x)+1: case (x)+2: case (x)+3
786
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800787static int64_t calcsize(int32_t segment, int64_t offset, int bits,
H. Peter Anvin9f817132008-10-06 19:11:07 -0700788 insn * ins, const uint8_t *codes)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000789{
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800790 int64_t length = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000791 uint8_t c;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000792 int rex_mask = ~0;
H. Peter Anvindcffe4b2008-10-10 22:10:31 -0700793 int op1, op2;
H. Peter Anvin839eca22007-10-29 23:12:47 -0700794 struct operand *opx;
H. Peter Anvindcffe4b2008-10-10 22:10:31 -0700795 uint8_t opex = 0;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000796
H. Peter Anvine3917fc2007-11-01 14:53:32 -0700797 ins->rex = 0; /* Ensure REX is reset */
798
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700799 if (ins->prefixes[PPS_OSIZE] == P_O64)
800 ins->rex |= REX_W;
801
H. Peter Anvine2c80182005-01-15 22:15:51 +0000802 (void)segment; /* Don't warn that this parameter is unused */
803 (void)offset; /* Don't warn that this parameter is unused */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000804
H. Peter Anvin839eca22007-10-29 23:12:47 -0700805 while (*codes) {
806 c = *codes++;
H. Peter Anvindcffe4b2008-10-10 22:10:31 -0700807 op1 = (c & 3) + ((opex & 1) << 2);
808 op2 = ((c >> 3) & 3) + ((opex & 2) << 1);
809 opx = &ins->oprs[op1];
810 opex = 0; /* For the next iteration */
811
H. Peter Anvin839eca22007-10-29 23:12:47 -0700812 switch (c) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000813 case 01:
814 case 02:
815 case 03:
H. Peter Anvindcffe4b2008-10-10 22:10:31 -0700816 case 04:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000817 codes += c, length += c;
818 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700819
H. Peter Anvindcffe4b2008-10-10 22:10:31 -0700820 case 05:
821 case 06:
822 case 07:
823 opex = c;
824 break;
825
H. Peter Anvin507ae032008-10-09 15:37:10 -0700826 case4(010):
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000827 ins->rex |=
H. Peter Anvin839eca22007-10-29 23:12:47 -0700828 op_rexflags(opx, REX_B|REX_H|REX_P|REX_W);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000829 codes++, length++;
830 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700831
832 case4(014):
833 case4(020):
834 case4(024):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000835 length++;
836 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700837
838 case4(030):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000839 length += 2;
840 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700841
842 case4(034):
H. Peter Anvin839eca22007-10-29 23:12:47 -0700843 if (opx->type & (BITS16 | BITS32 | BITS64))
844 length += (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000845 else
846 length += (bits == 16) ? 2 : 4;
847 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700848
849 case4(040):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000850 length += 4;
851 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700852
853 case4(044):
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700854 length += ins->addr_size >> 3;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000855 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700856
857 case4(050):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000858 length++;
859 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700860
861 case4(054):
Keith Kaniosb7a89542007-04-12 02:40:54 +0000862 length += 8; /* MOV reg64/imm */
863 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700864
865 case4(060):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000866 length += 2;
867 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700868
869 case4(064):
H. Peter Anvin839eca22007-10-29 23:12:47 -0700870 if (opx->type & (BITS16 | BITS32 | BITS64))
871 length += (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000872 else
873 length += (bits == 16) ? 2 : 4;
874 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700875
876 case4(070):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000877 length += 4;
878 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700879
880 case4(074):
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700881 length += 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000882 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700883
884 case4(0140):
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700885 length += is_sbyte16(opx) ? 1 : 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000886 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700887
888 case4(0144):
H. Peter Anvina30cc072007-11-18 21:55:26 -0800889 codes++;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000890 length++;
891 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700892
893 case4(0150):
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700894 length += is_sbyte32(opx) ? 1 : 4;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700895 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700896
897 case4(0154):
H. Peter Anvina30cc072007-11-18 21:55:26 -0800898 codes++;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700899 length++;
900 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700901
902 case4(0160):
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700903 length++;
904 ins->rex |= REX_D;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700905 ins->drexdst = regval(opx);
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700906 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700907
908 case4(0164):
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700909 length++;
910 ins->rex |= REX_D|REX_OC;
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
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700914 case 0171:
915 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700916
H. Peter Anvind85d2502008-05-04 17:53:31 -0700917 case 0172:
H. Peter Anvind58656f2008-05-06 20:11:14 -0700918 case 0173:
H. Peter Anvin52dc3532008-05-20 19:29:04 -0700919 case 0174:
H. Peter Anvind85d2502008-05-04 17:53:31 -0700920 codes++;
921 length++;
922 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700923
924 case4(0250):
H. Peter Anvinad6b8592008-10-07 09:56:38 -0700925 length += is_sbyte32(opx) ? 1 : 4;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700926 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700927
928 case4(0254):
H. Peter Anvin588df782008-10-07 10:05:10 -0700929 length += 4;
930 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700931
932 case4(0260):
H. Peter Anvind85d2502008-05-04 17:53:31 -0700933 ins->rex |= REX_V;
934 ins->drexdst = regval(opx);
H. Peter Anvina04019c2009-05-03 21:42:34 -0700935 ins->vex_cm = *codes++;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700936 ins->vex_wlp = *codes++;
937 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700938
H. Peter Anvind85d2502008-05-04 17:53:31 -0700939 case 0270:
H. Peter Anvind85d2502008-05-04 17:53:31 -0700940 ins->rex |= REX_V;
941 ins->drexdst = 0;
H. Peter Anvina04019c2009-05-03 21:42:34 -0700942 ins->vex_cm = *codes++;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700943 ins->vex_wlp = *codes++;
944 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700945
946 case4(0274):
H. Peter Anvinc1377e92008-10-06 23:40:31 -0700947 length++;
948 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700949
950 case4(0300):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000951 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700952
H. Peter Anvine2c80182005-01-15 22:15:51 +0000953 case 0310:
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700954 if (bits == 64)
955 return -1;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700956 length += (bits != 16) && !has_prefix(ins, PPS_ASIZE, P_A16);
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 0311:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700960 length += (bits != 32) && !has_prefix(ins, PPS_ASIZE, P_A32);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000961 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700962
H. Peter Anvine2c80182005-01-15 22:15:51 +0000963 case 0312:
H. Peter Anvin70653092007-10-19 14:42:29 -0700964 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700965
Keith Kaniosb7a89542007-04-12 02:40:54 +0000966 case 0313:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700967 if (bits != 64 || has_prefix(ins, PPS_ASIZE, P_A16) ||
968 has_prefix(ins, PPS_ASIZE, P_A32))
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700969 return -1;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000970 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700971
972 case4(0314):
H. Peter Anvin23440102007-11-12 21:02:33 -0800973 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700974
H. Peter Anvine2c80182005-01-15 22:15:51 +0000975 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000976 length += (bits != 16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000977 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700978
H. Peter Anvine2c80182005-01-15 22:15:51 +0000979 case 0321:
980 length += (bits == 16);
981 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700982
H. Peter Anvine2c80182005-01-15 22:15:51 +0000983 case 0322:
984 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700985
Keith Kaniosb7a89542007-04-12 02:40:54 +0000986 case 0323:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000987 rex_mask &= ~REX_W;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000988 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700989
Keith Kaniosb7a89542007-04-12 02:40:54 +0000990 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000991 ins->rex |= REX_W;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000992 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700993
H. Peter Anvin9472dab2009-06-24 21:38:29 -0700994 case 0325:
995 ins->rex |= REX_NH;
996 break;
997
H. Peter Anvine2c80182005-01-15 22:15:51 +0000998 case 0330:
999 codes++, length++;
1000 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001001
H. Peter Anvine2c80182005-01-15 22:15:51 +00001002 case 0331:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001003 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001004
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001005 case 0332:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001006 case 0333:
1007 length++;
1008 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001009
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001010 case 0334:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001011 ins->rex |= REX_L;
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001012 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001013
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001014 case 0335:
1015 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001016
H. Peter Anvin962e3052008-08-28 17:47:16 -07001017 case 0336:
1018 if (!ins->prefixes[PPS_LREP])
1019 ins->prefixes[PPS_LREP] = P_REP;
1020 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001021
H. Peter Anvin962e3052008-08-28 17:47:16 -07001022 case 0337:
1023 if (!ins->prefixes[PPS_LREP])
1024 ins->prefixes[PPS_LREP] = P_REPNE;
1025 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001026
H. Peter Anvine2c80182005-01-15 22:15:51 +00001027 case 0340:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001028 if (ins->oprs[0].segment != NO_SEG)
1029 errfunc(ERR_NONFATAL, "attempt to reserve non-constant"
1030 " quantity of BSS space");
1031 else
H. Peter Anvin428fd672007-11-15 10:25:52 -08001032 length += ins->oprs[0].offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001033 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001034
H. Peter Anvinc2acf7b2009-02-21 18:22:56 -08001035 case 0341:
1036 if (!ins->prefixes[PPS_WAIT])
1037 ins->prefixes[PPS_WAIT] = P_WAIT;
1038 break;
1039
H. Peter Anvin507ae032008-10-09 15:37:10 -07001040 case4(0344):
H. Peter Anvinff6e12d2008-10-08 21:17:32 -07001041 length++;
1042 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001043
H. Peter Anvinfff5a472008-05-20 09:46:24 -07001044 case 0360:
1045 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001046
H. Peter Anvinfff5a472008-05-20 09:46:24 -07001047 case 0361:
1048 case 0362:
1049 case 0363:
1050 length++;
1051 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001052
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001053 case 0364:
1054 case 0365:
1055 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001056
Keith Kanios48af1772007-08-17 07:37:52 +00001057 case 0366:
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001058 case 0367:
1059 length++;
1060 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001061
H. Peter Anvine2c80182005-01-15 22:15:51 +00001062 case 0370:
1063 case 0371:
1064 case 0372:
1065 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001066
H. Peter Anvine2c80182005-01-15 22:15:51 +00001067 case 0373:
1068 length++;
1069 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001070
1071 case4(0100):
1072 case4(0110):
1073 case4(0120):
1074 case4(0130):
1075 case4(0200):
1076 case4(0204):
1077 case4(0210):
1078 case4(0214):
1079 case4(0220):
1080 case4(0224):
1081 case4(0230):
1082 case4(0234):
1083 {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001084 ea ea_data;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001085 int rfield;
H. Peter Anvinf8563f72009-10-13 12:28:14 -07001086 opflags_t rflags;
H. Peter Anvinae64c9d2008-10-25 00:41:00 -07001087 struct operand *opy = &ins->oprs[op2];
1088
Keith Kaniosb7a89542007-04-12 02:40:54 +00001089 ea_data.rex = 0; /* Ensure ea.REX is initially 0 */
H. Peter Anvin70653092007-10-19 14:42:29 -07001090
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001091 if (c <= 0177) {
H. Peter Anvinae64c9d2008-10-25 00:41:00 -07001092 /* pick rfield from operand b (opx) */
1093 rflags = regflag(opx);
1094 rfield = nasm_regvals[opx->basereg];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001095 } else {
1096 rflags = 0;
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001097 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001098 }
H. Peter Anvinae64c9d2008-10-25 00:41:00 -07001099 if (!process_ea(opy, &ea_data, bits,
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001100 ins->addr_size, rfield, rflags)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001101 errfunc(ERR_NONFATAL, "invalid effective address");
1102 return -1;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001103 } else {
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001104 ins->rex |= ea_data.rex;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001105 length += ea_data.size;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001106 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001107 }
H. Peter Anvin507ae032008-10-09 15:37:10 -07001108 break;
1109
1110 default:
1111 errfunc(ERR_PANIC, "internal instruction table corrupt"
H. Peter Anvin16a856c2009-03-01 00:22:16 -08001112 ": instruction code \\%o (0x%02X) given", c, c);
H. Peter Anvin507ae032008-10-09 15:37:10 -07001113 break;
1114 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001115 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001116
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001117 ins->rex &= rex_mask;
H. Peter Anvin70653092007-10-19 14:42:29 -07001118
H. Peter Anvin9472dab2009-06-24 21:38:29 -07001119 if (ins->rex & REX_NH) {
1120 if (ins->rex & REX_H) {
1121 errfunc(ERR_NONFATAL, "instruction cannot use high registers");
1122 return -1;
1123 }
1124 ins->rex &= ~REX_P; /* Don't force REX prefix due to high reg */
1125 }
1126
H. Peter Anvind85d2502008-05-04 17:53:31 -07001127 if (ins->rex & REX_V) {
1128 int bad32 = REX_R|REX_W|REX_X|REX_B;
1129
1130 if (ins->rex & REX_H) {
1131 errfunc(ERR_NONFATAL, "cannot use high register in vex instruction");
1132 return -1;
1133 }
1134 switch (ins->vex_wlp & 030) {
1135 case 000:
H. Peter Anvinbd420c72008-05-22 11:24:35 -07001136 case 020:
H. Peter Anvind85d2502008-05-04 17:53:31 -07001137 ins->rex &= ~REX_W;
1138 break;
1139 case 010:
1140 ins->rex |= REX_W;
1141 bad32 &= ~REX_W;
1142 break;
H. Peter Anvinbd420c72008-05-22 11:24:35 -07001143 case 030:
H. Peter Anvind85d2502008-05-04 17:53:31 -07001144 /* Follow REX_W */
1145 break;
1146 }
1147
1148 if (bits != 64 && ((ins->rex & bad32) || ins->drexdst > 7)) {
1149 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
1150 return -1;
1151 }
H. Peter Anvina04019c2009-05-03 21:42:34 -07001152 if (ins->vex_cm != 1 || (ins->rex & (REX_W|REX_R|REX_B)))
H. Peter Anvind85d2502008-05-04 17:53:31 -07001153 length += 3;
1154 else
1155 length += 2;
1156 } else if (ins->rex & REX_D) {
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001157 if (ins->rex & REX_H) {
1158 errfunc(ERR_NONFATAL, "cannot use high register in drex instruction");
1159 return -1;
1160 }
H. Peter Anvind85d2502008-05-04 17:53:31 -07001161 if (bits != 64 && ((ins->rex & (REX_R|REX_W|REX_X|REX_B)) ||
H. Peter Anvincf5180a2007-09-17 17:25:27 -07001162 ins->drexdst > 7)) {
1163 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
1164 return -1;
1165 }
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001166 length++;
1167 } else if (ins->rex & REX_REAL) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001168 if (ins->rex & REX_H) {
1169 errfunc(ERR_NONFATAL, "cannot use high register in rex instruction");
1170 return -1;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001171 } else if (bits == 64) {
1172 length++;
1173 } else if ((ins->rex & REX_L) &&
1174 !(ins->rex & (REX_P|REX_W|REX_X|REX_B)) &&
1175 cpu >= IF_X86_64) {
1176 /* LOCK-as-REX.R */
1177 assert_no_prefix(ins, PPS_LREP);
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001178 length++;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +00001179 } else {
H. Peter Anvincf5180a2007-09-17 17:25:27 -07001180 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
1181 return -1;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +00001182 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001183 }
1184
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001185 return length;
1186}
Keith Kaniosb7a89542007-04-12 02:40:54 +00001187
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001188#define EMIT_REX() \
H. Peter Anvind85d2502008-05-04 17:53:31 -07001189 if (!(ins->rex & (REX_D|REX_V)) && (ins->rex & REX_REAL) && (bits == 64)) { \
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001190 ins->rex = (ins->rex & REX_REAL)|REX_P; \
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001191 out(offset, segment, &ins->rex, OUT_RAWDATA, 1, NO_SEG, NO_SEG); \
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001192 ins->rex = 0; \
1193 offset += 1; \
1194 }
1195
Charles Crayne1f8bc4c2007-11-06 18:27:23 -08001196static void gencode(int32_t segment, int64_t offset, int bits,
H. Peter Anvin833caea2008-10-04 19:02:30 -07001197 insn * ins, const struct itemplate *temp,
1198 int64_t insn_end)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001199{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001200 static char condval[] = { /* conditional opcodes */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001201 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
1202 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
1203 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001204 };
Keith Kaniosb7a89542007-04-12 02:40:54 +00001205 uint8_t c;
1206 uint8_t bytes[4];
Charles Crayne1f8bc4c2007-11-06 18:27:23 -08001207 int64_t size;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001208 int64_t data;
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001209 int op1, op2;
H. Peter Anvin839eca22007-10-29 23:12:47 -07001210 struct operand *opx;
H. Peter Anvin833caea2008-10-04 19:02:30 -07001211 const uint8_t *codes = temp->code;
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001212 uint8_t opex = 0;
H. Peter Anvin70653092007-10-19 14:42:29 -07001213
H. Peter Anvin839eca22007-10-29 23:12:47 -07001214 while (*codes) {
1215 c = *codes++;
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001216 op1 = (c & 3) + ((opex & 1) << 2);
1217 op2 = ((c >> 3) & 3) + ((opex & 2) << 1);
1218 opx = &ins->oprs[op1];
1219 opex = 0; /* For the next iteration */
1220
H. Peter Anvin839eca22007-10-29 23:12:47 -07001221 switch (c) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001222 case 01:
1223 case 02:
1224 case 03:
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001225 case 04:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001226 EMIT_REX();
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001227 out(offset, segment, codes, OUT_RAWDATA, c, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001228 codes += c;
1229 offset += c;
1230 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001231
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001232 case 05:
1233 case 06:
1234 case 07:
1235 opex = c;
1236 break;
1237
H. Peter Anvin507ae032008-10-09 15:37:10 -07001238 case4(010):
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001239 EMIT_REX();
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001240 bytes[0] = *codes++ + (regval(opx) & 7);
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001241 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001242 offset += 1;
1243 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001244
H. Peter Anvin507ae032008-10-09 15:37:10 -07001245 case4(014):
H. Peter Anvin6c80ab62008-10-04 18:50:47 -07001246 /* The test for BITS8 and SBYTE here is intended to avoid
1247 warning on optimizer actions due to SBYTE, while still
1248 warn on explicit BYTE directives. Also warn, obviously,
1249 if the optimizer isn't enabled. */
1250 if (((opx->type & BITS8) ||
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001251 !(opx->type & temp->opd[op1] & BYTENESS)) &&
H. Peter Anvin6c80ab62008-10-04 18:50:47 -07001252 (opx->offset < -128 || opx->offset > 127)) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001253 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
H. Peter Anvin72c64372008-01-08 22:13:48 -08001254 "signed byte value exceeds bounds");
H. Peter Anvin6c80ab62008-10-04 18:50:47 -07001255 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001256 if (opx->segment != NO_SEG) {
1257 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001258 out(offset, segment, &data, OUT_ADDRESS, 1,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001259 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001260 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001261 bytes[0] = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001262 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001263 NO_SEG);
1264 }
1265 offset += 1;
1266 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001267
H. Peter Anvin507ae032008-10-09 15:37:10 -07001268 case4(020):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001269 if (opx->offset < -256 || opx->offset > 255) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001270 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
H. Peter Anvin72c64372008-01-08 22:13:48 -08001271 "byte value exceeds bounds");
H. Peter Anvine2c80182005-01-15 22:15:51 +00001272 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001273 if (opx->segment != NO_SEG) {
1274 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001275 out(offset, segment, &data, OUT_ADDRESS, 1,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001276 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001277 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001278 bytes[0] = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001279 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001280 NO_SEG);
1281 }
1282 offset += 1;
1283 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001284
H. Peter Anvin507ae032008-10-09 15:37:10 -07001285 case4(024):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001286 if (opx->offset < 0 || opx->offset > 255)
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001287 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
H. Peter Anvin72c64372008-01-08 22:13:48 -08001288 "unsigned byte value exceeds bounds");
H. Peter Anvin839eca22007-10-29 23:12:47 -07001289 if (opx->segment != NO_SEG) {
1290 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001291 out(offset, segment, &data, OUT_ADDRESS, 1,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001292 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001293 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001294 bytes[0] = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001295 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001296 NO_SEG);
1297 }
1298 offset += 1;
1299 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001300
H. Peter Anvin507ae032008-10-09 15:37:10 -07001301 case4(030):
Cyrill Gorcunov9ccabd22009-09-21 00:56:20 +04001302 warn_overflow_opd(opx, 2);
H. Peter Anvin839eca22007-10-29 23:12:47 -07001303 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001304 out(offset, segment, &data, OUT_ADDRESS, 2,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001305 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001306 offset += 2;
1307 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001308
H. Peter Anvin507ae032008-10-09 15:37:10 -07001309 case4(034):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001310 if (opx->type & (BITS16 | BITS32))
1311 size = (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001312 else
1313 size = (bits == 16) ? 2 : 4;
Cyrill Gorcunov9ccabd22009-09-21 00:56:20 +04001314 warn_overflow_opd(opx, size);
H. Peter Anvin839eca22007-10-29 23:12:47 -07001315 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001316 out(offset, segment, &data, OUT_ADDRESS, size,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001317 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001318 offset += size;
1319 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001320
H. Peter Anvin507ae032008-10-09 15:37:10 -07001321 case4(040):
Cyrill Gorcunov9ccabd22009-09-21 00:56:20 +04001322 warn_overflow_opd(opx, 4);
H. Peter Anvin839eca22007-10-29 23:12:47 -07001323 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001324 out(offset, segment, &data, OUT_ADDRESS, 4,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001325 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001326 offset += 4;
1327 break;
H. Peter Anvin3ba46772002-05-27 23:19:35 +00001328
H. Peter Anvin507ae032008-10-09 15:37:10 -07001329 case4(044):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001330 data = opx->offset;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001331 size = ins->addr_size >> 3;
Cyrill Gorcunov9ccabd22009-09-21 00:56:20 +04001332 warn_overflow_opd(opx, size);
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001333 out(offset, segment, &data, OUT_ADDRESS, size,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001334 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001335 offset += size;
1336 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001337
H. Peter Anvin507ae032008-10-09 15:37:10 -07001338 case4(050):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001339 if (opx->segment != segment)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001340 errfunc(ERR_NONFATAL,
1341 "short relative jump outside segment");
H. Peter Anvin839eca22007-10-29 23:12:47 -07001342 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001343 if (data > 127 || data < -128)
1344 errfunc(ERR_NONFATAL, "short jump is out of range");
1345 bytes[0] = data;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001346 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001347 offset += 1;
1348 break;
H. Peter Anvin70653092007-10-19 14:42:29 -07001349
H. Peter Anvin507ae032008-10-09 15:37:10 -07001350 case4(054):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001351 data = (int64_t)opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001352 out(offset, segment, &data, OUT_ADDRESS, 8,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001353 opx->segment, opx->wrt);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001354 offset += 8;
1355 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001356
H. Peter Anvin507ae032008-10-09 15:37:10 -07001357 case4(060):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001358 if (opx->segment != segment) {
1359 data = opx->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001360 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001361 OUT_REL2ADR, insn_end - offset,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001362 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001363 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001364 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001365 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001366 OUT_ADDRESS, 2, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001367 }
1368 offset += 2;
1369 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001370
H. Peter Anvin507ae032008-10-09 15:37:10 -07001371 case4(064):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001372 if (opx->type & (BITS16 | BITS32 | BITS64))
1373 size = (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001374 else
1375 size = (bits == 16) ? 2 : 4;
H. Peter Anvin839eca22007-10-29 23:12:47 -07001376 if (opx->segment != segment) {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001377 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001378 out(offset, segment, &data,
1379 size == 2 ? OUT_REL2ADR : OUT_REL4ADR,
1380 insn_end - offset, opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001381 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001382 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001383 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001384 OUT_ADDRESS, size, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001385 }
1386 offset += size;
1387 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001388
H. Peter Anvin507ae032008-10-09 15:37:10 -07001389 case4(070):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001390 if (opx->segment != segment) {
1391 data = opx->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001392 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001393 OUT_REL4ADR, insn_end - offset,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001394 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001395 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001396 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001397 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001398 OUT_ADDRESS, 4, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001399 }
1400 offset += 4;
1401 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001402
H. Peter Anvin507ae032008-10-09 15:37:10 -07001403 case4(074):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001404 if (opx->segment == NO_SEG)
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001405 errfunc(ERR_NONFATAL, "value referenced by FAR is not"
1406 " relocatable");
H. Peter Anvindfb91802008-05-20 11:43:53 -07001407 data = 0;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001408 out(offset, segment, &data, OUT_ADDRESS, 2,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001409 outfmt->segbase(1 + opx->segment),
1410 opx->wrt);
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001411 offset += 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001412 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001413
H. Peter Anvin507ae032008-10-09 15:37:10 -07001414 case4(0140):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001415 data = opx->offset;
Cyrill Gorcunov9ccabd22009-09-21 00:56:20 +04001416 warn_overflow_opd(opx, 2);
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001417 if (is_sbyte16(opx)) {
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001418 bytes[0] = data;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001419 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001420 NO_SEG);
1421 offset++;
1422 } else {
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001423 out(offset, segment, &data, OUT_ADDRESS, 2,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001424 opx->segment, opx->wrt);
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001425 offset += 2;
1426 }
1427 break;
1428
H. Peter Anvin507ae032008-10-09 15:37:10 -07001429 case4(0144):
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001430 EMIT_REX();
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001431 bytes[0] = *codes++;
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001432 if (is_sbyte16(opx))
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001433 bytes[0] |= 2; /* s-bit */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001434 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001435 offset++;
1436 break;
1437
H. Peter Anvin507ae032008-10-09 15:37:10 -07001438 case4(0150):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001439 data = opx->offset;
Cyrill Gorcunov9ccabd22009-09-21 00:56:20 +04001440 warn_overflow_opd(opx, 4);
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001441 if (is_sbyte32(opx)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001442 bytes[0] = data;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001443 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001444 NO_SEG);
1445 offset++;
1446 } else {
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001447 out(offset, segment, &data, OUT_ADDRESS, 4,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001448 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001449 offset += 4;
1450 }
1451 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001452
H. Peter Anvin507ae032008-10-09 15:37:10 -07001453 case4(0154):
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001454 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001455 bytes[0] = *codes++;
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001456 if (is_sbyte32(opx))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001457 bytes[0] |= 2; /* s-bit */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001458 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001459 offset++;
1460 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001461
H. Peter Anvin507ae032008-10-09 15:37:10 -07001462 case4(0160):
1463 case4(0164):
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001464 break;
1465
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001466 case 0171:
1467 bytes[0] =
1468 (ins->drexdst << 4) |
1469 (ins->rex & REX_OC ? 0x08 : 0) |
1470 (ins->rex & (REX_R|REX_X|REX_B));
1471 ins->rex = 0;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001472 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001473 offset++;
1474 break;
1475
H. Peter Anvind85d2502008-05-04 17:53:31 -07001476 case 0172:
1477 c = *codes++;
1478 opx = &ins->oprs[c >> 3];
H. Peter Anvina4835d42008-05-20 14:21:29 -07001479 bytes[0] = nasm_regvals[opx->basereg] << 4;
H. Peter Anvind85d2502008-05-04 17:53:31 -07001480 opx = &ins->oprs[c & 7];
1481 if (opx->segment != NO_SEG || opx->wrt != NO_SEG) {
1482 errfunc(ERR_NONFATAL,
1483 "non-absolute expression not permitted as argument %d",
1484 c & 7);
1485 } else {
1486 if (opx->offset & ~15) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001487 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
H. Peter Anvind85d2502008-05-04 17:53:31 -07001488 "four-bit argument exceeds bounds");
1489 }
1490 bytes[0] |= opx->offset & 15;
1491 }
1492 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1493 offset++;
1494 break;
1495
H. Peter Anvind58656f2008-05-06 20:11:14 -07001496 case 0173:
1497 c = *codes++;
1498 opx = &ins->oprs[c >> 4];
H. Peter Anvina4835d42008-05-20 14:21:29 -07001499 bytes[0] = nasm_regvals[opx->basereg] << 4;
H. Peter Anvind58656f2008-05-06 20:11:14 -07001500 bytes[0] |= c & 15;
1501 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1502 offset++;
1503 break;
1504
H. Peter Anvin52dc3532008-05-20 19:29:04 -07001505 case 0174:
1506 c = *codes++;
1507 opx = &ins->oprs[c];
1508 bytes[0] = nasm_regvals[opx->basereg] << 4;
1509 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1510 offset++;
1511 break;
1512
H. Peter Anvin507ae032008-10-09 15:37:10 -07001513 case4(0250):
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001514 data = opx->offset;
H. Peter Anvinad6b8592008-10-07 09:56:38 -07001515 if (opx->wrt == NO_SEG && opx->segment == NO_SEG &&
1516 (int32_t)data != (int64_t)data) {
1517 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
1518 "signed dword immediate exceeds bounds");
1519 }
1520 if (is_sbyte32(opx)) {
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001521 bytes[0] = data;
1522 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
1523 NO_SEG);
1524 offset++;
1525 } else {
1526 out(offset, segment, &data, OUT_ADDRESS, 4,
1527 opx->segment, opx->wrt);
1528 offset += 4;
1529 }
1530 break;
1531
H. Peter Anvin507ae032008-10-09 15:37:10 -07001532 case4(0254):
H. Peter Anvin588df782008-10-07 10:05:10 -07001533 data = opx->offset;
1534 if (opx->wrt == NO_SEG && opx->segment == NO_SEG &&
1535 (int32_t)data != (int64_t)data) {
1536 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
1537 "signed dword immediate exceeds bounds");
1538 }
1539 out(offset, segment, &data, OUT_ADDRESS, 4,
1540 opx->segment, opx->wrt);
1541 offset += 4;
1542 break;
1543
H. Peter Anvin507ae032008-10-09 15:37:10 -07001544 case4(0260):
H. Peter Anvind85d2502008-05-04 17:53:31 -07001545 case 0270:
1546 codes += 2;
H. Peter Anvina04019c2009-05-03 21:42:34 -07001547 if (ins->vex_cm != 1 || (ins->rex & (REX_W|REX_X|REX_B))) {
1548 bytes[0] = (ins->vex_cm >> 6) ? 0x8f : 0xc4;
1549 bytes[1] = (ins->vex_cm & 31) | ((~ins->rex & 7) << 5);
H. Peter Anvind85d2502008-05-04 17:53:31 -07001550 bytes[2] = ((ins->rex & REX_W) << (7-3)) |
H. Peter Anvin4d2c38c2008-05-04 23:15:13 -07001551 ((~ins->drexdst & 15)<< 3) | (ins->vex_wlp & 07);
H. Peter Anvind85d2502008-05-04 17:53:31 -07001552 out(offset, segment, &bytes, OUT_RAWDATA, 3, NO_SEG, NO_SEG);
1553 offset += 3;
1554 } else {
1555 bytes[0] = 0xc5;
H. Peter Anvin4d2c38c2008-05-04 23:15:13 -07001556 bytes[1] = ((~ins->rex & REX_R) << (7-2)) |
1557 ((~ins->drexdst & 15) << 3) | (ins->vex_wlp & 07);
H. Peter Anvind85d2502008-05-04 17:53:31 -07001558 out(offset, segment, &bytes, OUT_RAWDATA, 2, NO_SEG, NO_SEG);
1559 offset += 2;
1560 }
1561 break;
1562
H. Peter Anvin507ae032008-10-09 15:37:10 -07001563 case4(0274):
H. Peter Anvinc1377e92008-10-06 23:40:31 -07001564 {
1565 uint64_t uv, um;
1566 int s;
1567
1568 if (ins->rex & REX_W)
1569 s = 64;
1570 else if (ins->prefixes[PPS_OSIZE] == P_O16)
1571 s = 16;
1572 else if (ins->prefixes[PPS_OSIZE] == P_O32)
1573 s = 32;
1574 else
1575 s = bits;
1576
1577 um = (uint64_t)2 << (s-1);
1578 uv = opx->offset;
1579
1580 if (uv > 127 && uv < (uint64_t)-128 &&
1581 (uv < um-128 || uv > um-1)) {
1582 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
1583 "signed byte value exceeds bounds");
1584 }
1585 if (opx->segment != NO_SEG) {
H. Peter Anvin779ed8b2008-10-16 13:01:43 -07001586 data = uv;
H. Peter Anvinc1377e92008-10-06 23:40:31 -07001587 out(offset, segment, &data, OUT_ADDRESS, 1,
1588 opx->segment, opx->wrt);
1589 } else {
H. Peter Anvin779ed8b2008-10-16 13:01:43 -07001590 bytes[0] = uv;
H. Peter Anvinc1377e92008-10-06 23:40:31 -07001591 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
1592 NO_SEG);
1593 }
1594 offset += 1;
1595 break;
1596 }
1597
H. Peter Anvin507ae032008-10-09 15:37:10 -07001598 case4(0300):
H. Peter Anvine2c80182005-01-15 22:15:51 +00001599 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001600
H. Peter Anvine2c80182005-01-15 22:15:51 +00001601 case 0310:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001602 if (bits == 32 && !has_prefix(ins, PPS_ASIZE, P_A16)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001603 *bytes = 0x67;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001604 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001605 offset += 1;
1606 } else
1607 offset += 0;
1608 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001609
H. Peter Anvine2c80182005-01-15 22:15:51 +00001610 case 0311:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001611 if (bits != 32 && !has_prefix(ins, PPS_ASIZE, P_A32)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001612 *bytes = 0x67;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001613 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001614 offset += 1;
1615 } else
1616 offset += 0;
1617 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001618
H. Peter Anvine2c80182005-01-15 22:15:51 +00001619 case 0312:
1620 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001621
Keith Kaniosb7a89542007-04-12 02:40:54 +00001622 case 0313:
1623 ins->rex = 0;
1624 break;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07001625
H. Peter Anvin507ae032008-10-09 15:37:10 -07001626 case4(0314):
H. Peter Anvin23440102007-11-12 21:02:33 -08001627 break;
1628
H. Peter Anvine2c80182005-01-15 22:15:51 +00001629 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001630 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001631 *bytes = 0x66;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001632 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001633 offset += 1;
1634 } else
1635 offset += 0;
1636 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001637
H. Peter Anvine2c80182005-01-15 22:15:51 +00001638 case 0321:
1639 if (bits == 16) {
1640 *bytes = 0x66;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001641 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001642 offset += 1;
1643 } else
1644 offset += 0;
1645 break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001646
H. Peter Anvine2c80182005-01-15 22:15:51 +00001647 case 0322:
H. Peter Anvin70653092007-10-19 14:42:29 -07001648 case 0323:
1649 break;
1650
Keith Kaniosb7a89542007-04-12 02:40:54 +00001651 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001652 ins->rex |= REX_W;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001653 break;
H. Peter Anvin70653092007-10-19 14:42:29 -07001654
H. Peter Anvin9472dab2009-06-24 21:38:29 -07001655 case 0325:
1656 break;
1657
H. Peter Anvine2c80182005-01-15 22:15:51 +00001658 case 0330:
1659 *bytes = *codes++ ^ condval[ins->condition];
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001660 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001661 offset += 1;
1662 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001663
H. Peter Anvine2c80182005-01-15 22:15:51 +00001664 case 0331:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001665 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001666
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001667 case 0332:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001668 case 0333:
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001669 *bytes = c - 0332 + 0xF2;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001670 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001671 offset += 1;
1672 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001673
Keith Kanios48af1772007-08-17 07:37:52 +00001674 case 0334:
1675 if (ins->rex & REX_R) {
1676 *bytes = 0xF0;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001677 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
Keith Kanios48af1772007-08-17 07:37:52 +00001678 offset += 1;
1679 }
1680 ins->rex &= ~(REX_L|REX_R);
1681 break;
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001682
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001683 case 0335:
1684 break;
1685
H. Peter Anvin962e3052008-08-28 17:47:16 -07001686 case 0336:
1687 case 0337:
1688 break;
1689
H. Peter Anvine2c80182005-01-15 22:15:51 +00001690 case 0340:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001691 if (ins->oprs[0].segment != NO_SEG)
1692 errfunc(ERR_PANIC, "non-constant BSS size in pass two");
1693 else {
H. Peter Anvin428fd672007-11-15 10:25:52 -08001694 int64_t size = ins->oprs[0].offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001695 if (size > 0)
1696 out(offset, segment, NULL,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001697 OUT_RESERVE, size, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001698 offset += size;
1699 }
1700 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001701
H. Peter Anvinc2acf7b2009-02-21 18:22:56 -08001702 case 0341:
1703 break;
1704
H. Peter Anvinff6e12d2008-10-08 21:17:32 -07001705 case 0344:
1706 case 0345:
1707 bytes[0] = c & 1;
1708 switch (ins->oprs[0].basereg) {
1709 case R_CS:
1710 bytes[0] += 0x0E;
1711 break;
1712 case R_DS:
1713 bytes[0] += 0x1E;
1714 break;
1715 case R_ES:
1716 bytes[0] += 0x06;
1717 break;
1718 case R_SS:
1719 bytes[0] += 0x16;
1720 break;
1721 default:
1722 errfunc(ERR_PANIC,
1723 "bizarre 8086 segment register received");
1724 }
1725 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1726 offset++;
1727 break;
1728
1729 case 0346:
1730 case 0347:
1731 bytes[0] = c & 1;
1732 switch (ins->oprs[0].basereg) {
1733 case R_FS:
1734 bytes[0] += 0xA0;
1735 break;
1736 case R_GS:
1737 bytes[0] += 0xA8;
1738 break;
1739 default:
1740 errfunc(ERR_PANIC,
1741 "bizarre 386 segment register received");
1742 }
1743 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1744 offset++;
1745 break;
1746
H. Peter Anvinfff5a472008-05-20 09:46:24 -07001747 case 0360:
1748 break;
1749
1750 case 0361:
1751 bytes[0] = 0x66;
1752 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1753 offset += 1;
1754 break;
1755
1756 case 0362:
1757 case 0363:
1758 bytes[0] = c - 0362 + 0xf2;
1759 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1760 offset += 1;
1761 break;
1762
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001763 case 0364:
1764 case 0365:
1765 break;
1766
Keith Kanios48af1772007-08-17 07:37:52 +00001767 case 0366:
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001768 case 0367:
1769 *bytes = c - 0366 + 0x66;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001770 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
Keith Kanios48af1772007-08-17 07:37:52 +00001771 offset += 1;
1772 break;
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001773
H. Peter Anvine2c80182005-01-15 22:15:51 +00001774 case 0370:
1775 case 0371:
1776 case 0372:
1777 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001778
H. Peter Anvine2c80182005-01-15 22:15:51 +00001779 case 0373:
1780 *bytes = bits == 16 ? 3 : 5;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001781 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001782 offset += 1;
1783 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001784
H. Peter Anvin507ae032008-10-09 15:37:10 -07001785 case4(0100):
1786 case4(0110):
1787 case4(0120):
1788 case4(0130):
1789 case4(0200):
1790 case4(0204):
1791 case4(0210):
1792 case4(0214):
1793 case4(0220):
1794 case4(0224):
1795 case4(0230):
1796 case4(0234):
1797 {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001798 ea ea_data;
1799 int rfield;
H. Peter Anvinf8563f72009-10-13 12:28:14 -07001800 opflags_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001801 uint8_t *p;
1802 int32_t s;
H. Peter Anvin9f817132008-10-06 19:11:07 -07001803 enum out_type type;
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001804 struct operand *opy = &ins->oprs[op2];
H. Peter Anvin70653092007-10-19 14:42:29 -07001805
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001806 if (c <= 0177) {
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001807 /* pick rfield from operand b (opx) */
1808 rflags = regflag(opx);
1809 rfield = nasm_regvals[opx->basereg];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001810 } else {
1811 /* rfield is constant */
1812 rflags = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001813 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001814 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001815
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001816 if (!process_ea(opy, &ea_data, bits, ins->addr_size,
1817 rfield, rflags)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001818 errfunc(ERR_NONFATAL, "invalid effective address");
1819 }
H. Peter Anvin70653092007-10-19 14:42:29 -07001820
Charles Crayne7e975552007-11-03 22:06:13 -07001821
H. Peter Anvine2c80182005-01-15 22:15:51 +00001822 p = bytes;
1823 *p++ = ea_data.modrm;
1824 if (ea_data.sib_present)
1825 *p++ = ea_data.sib;
1826
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001827 /* DREX suffixes come between the SIB and the displacement */
1828 if (ins->rex & REX_D) {
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001829 *p++ = (ins->drexdst << 4) |
1830 (ins->rex & REX_OC ? 0x08 : 0) |
1831 (ins->rex & (REX_R|REX_X|REX_B));
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001832 ins->rex = 0;
1833 }
1834
H. Peter Anvine2c80182005-01-15 22:15:51 +00001835 s = p - bytes;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001836 out(offset, segment, bytes, OUT_RAWDATA, s, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001837
Victor van den Elzencf9332c2008-10-01 12:18:28 +02001838 /*
1839 * Make sure the address gets the right offset in case
1840 * the line breaks in the .lst file (BR 1197827)
1841 */
1842 offset += s;
1843 s = 0;
1844
H. Peter Anvine2c80182005-01-15 22:15:51 +00001845 switch (ea_data.bytes) {
1846 case 0:
1847 break;
1848 case 1:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001849 case 2:
1850 case 4:
Victor van den Elzen352fe062008-12-10 13:04:58 +01001851 case 8:
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001852 data = opy->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001853 s += ea_data.bytes;
H. Peter Anvin9f817132008-10-06 19:11:07 -07001854 if (ea_data.rip) {
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001855 if (opy->segment == segment) {
H. Peter Anvine286c7e2008-10-22 11:15:00 -07001856 data -= insn_end;
Victor van den Elzen0d268fb2010-01-24 21:24:57 +01001857 if (overflow_signed(data, ea_data.bytes))
1858 warn_overflow(ERR_PASS2, ea_data.bytes);
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001859 out(offset, segment, &data, OUT_ADDRESS,
1860 ea_data.bytes, NO_SEG, NO_SEG);
H. Peter Anvine286c7e2008-10-22 11:15:00 -07001861 } else {
Victor van den Elzen0d268fb2010-01-24 21:24:57 +01001862 /* overflow check in output/linker? */
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001863 out(offset, segment, &data, OUT_REL4ADR,
1864 insn_end - offset, opy->segment, opy->wrt);
H. Peter Anvine286c7e2008-10-22 11:15:00 -07001865 }
H. Peter Anvin9f817132008-10-06 19:11:07 -07001866 } else {
Victor van den Elzen0d268fb2010-01-24 21:24:57 +01001867 if (overflow_general(opy->offset, ins->addr_size >> 3) ||
1868 signed_bits(opy->offset, ins->addr_size) !=
1869 signed_bits(opy->offset, ea_data.bytes * 8))
1870 warn_overflow(ERR_PASS2, ea_data.bytes);
1871
H. Peter Anvin9f817132008-10-06 19:11:07 -07001872 type = OUT_ADDRESS;
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001873 out(offset, segment, &data, OUT_ADDRESS,
1874 ea_data.bytes, opy->segment, opy->wrt);
H. Peter Anvin9f817132008-10-06 19:11:07 -07001875 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001876 break;
Victor van den Elzen352fe062008-12-10 13:04:58 +01001877 default:
1878 /* Impossible! */
1879 errfunc(ERR_PANIC,
1880 "Invalid amount of bytes (%d) for offset?!",
1881 ea_data.bytes);
1882 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001883 }
1884 offset += s;
H. Peter Anvin839eca22007-10-29 23:12:47 -07001885 }
H. Peter Anvin507ae032008-10-09 15:37:10 -07001886 break;
1887
1888 default:
1889 errfunc(ERR_PANIC, "internal instruction table corrupt"
H. Peter Anvin16a856c2009-03-01 00:22:16 -08001890 ": instruction code \\%o (0x%02X) given", c, c);
H. Peter Anvin507ae032008-10-09 15:37:10 -07001891 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001892 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001893 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001894}
1895
H. Peter Anvinf8563f72009-10-13 12:28:14 -07001896static opflags_t regflag(const operand * o)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001897{
1898 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1899 errfunc(ERR_PANIC, "invalid operand passed to regflag()");
1900 }
H. Peter Anvina4835d42008-05-20 14:21:29 -07001901 return nasm_reg_flags[o->basereg];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001902}
1903
H. Peter Anvin5b0e3ec2007-07-07 02:01:08 +00001904static int32_t regval(const operand * o)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001905{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001906 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1907 errfunc(ERR_PANIC, "invalid operand passed to regval()");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001908 }
H. Peter Anvina4835d42008-05-20 14:21:29 -07001909 return nasm_regvals[o->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001910}
1911
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001912static int op_rexflags(const operand * o, int mask)
1913{
H. Peter Anvinf8563f72009-10-13 12:28:14 -07001914 opflags_t flags;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001915 int val;
1916
1917 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1918 errfunc(ERR_PANIC, "invalid operand passed to op_rexflags()");
1919 }
1920
H. Peter Anvina4835d42008-05-20 14:21:29 -07001921 flags = nasm_reg_flags[o->basereg];
1922 val = nasm_regvals[o->basereg];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001923
1924 return rexflags(val, flags, mask);
1925}
1926
H. Peter Anvinf8563f72009-10-13 12:28:14 -07001927static int rexflags(int val, opflags_t flags, int mask)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001928{
1929 int rex = 0;
1930
1931 if (val >= 8)
1932 rex |= REX_B|REX_X|REX_R;
1933 if (flags & BITS64)
1934 rex |= REX_W;
1935 if (!(REG_HIGH & ~flags)) /* AH, CH, DH, BH */
1936 rex |= REX_H;
1937 else if (!(REG8 & ~flags) && val >= 4) /* SPL, BPL, SIL, DIL */
1938 rex |= REX_P;
1939
1940 return rex & mask;
1941}
1942
H. Peter Anvin23595f52009-07-25 17:44:25 -07001943static enum match_result find_match(const struct itemplate **tempp,
1944 insn *instruction,
1945 int32_t segment, int64_t offset, int bits)
1946{
1947 const struct itemplate *temp;
1948 enum match_result m, merr;
H. Peter Anvina7643f42009-10-13 12:32:20 -07001949 opflags_t xsizeflags[MAX_OPERANDS];
H. Peter Anvina81655b2009-07-25 18:15:28 -07001950 bool opsizemissing = false;
1951 int i;
1952
1953 for (i = 0; i < instruction->operands; i++)
1954 xsizeflags[i] = instruction->oprs[i].type & SIZE_MASK;
H. Peter Anvin23595f52009-07-25 17:44:25 -07001955
1956 merr = MERR_INVALOP;
1957
1958 for (temp = nasm_instructions[instruction->opcode];
1959 temp->opcode != I_none; temp++) {
1960 m = matches(temp, instruction, bits);
1961 if (m == MOK_JUMP) {
1962 if (jmp_match(segment, offset, bits, instruction, temp->code))
1963 m = MOK_GOOD;
1964 else
1965 m = MERR_INVALOP;
H. Peter Anvina81655b2009-07-25 18:15:28 -07001966 } else if (m == MERR_OPSIZEMISSING &&
1967 (temp->flags & IF_SMASK) != IF_SX) {
1968 /*
1969 * Missing operand size and a candidate for fuzzy matching...
1970 */
H. Peter Anvinff5d6562009-10-05 14:08:05 -07001971 for (i = 0; i < temp->operands; i++) {
1972 if ((temp->opd[i] & SAME_AS) == 0)
1973 xsizeflags[i] |= temp->opd[i] & SIZE_MASK;
1974 }
H. Peter Anvina81655b2009-07-25 18:15:28 -07001975 opsizemissing = true;
1976 }
1977 if (m > merr)
1978 merr = m;
1979 if (merr == MOK_GOOD)
1980 goto done;
1981 }
1982
1983 /* No match, but see if we can get a fuzzy operand size match... */
1984 if (!opsizemissing)
1985 goto done;
1986
1987 for (i = 0; i < instruction->operands; i++) {
H. Peter Anvinff5d6562009-10-05 14:08:05 -07001988 /*
1989 * We ignore extrinsic operand sizes on registers, so we should
1990 * never try to fuzzy-match on them. This also resolves the case
1991 * when we have e.g. "xmmrm128" in two different positions.
1992 */
Cyrill Gorcunov8a6345c2009-10-13 19:05:31 +04001993 if (is_class(REGISTER, instruction->oprs[i].type))
H. Peter Anvinff5d6562009-10-05 14:08:05 -07001994 continue;
1995
H. Peter Anvina81655b2009-07-25 18:15:28 -07001996 /* This tests if xsizeflags[i] has more than one bit set */
1997 if ((xsizeflags[i] & (xsizeflags[i]-1)))
1998 goto done; /* No luck */
1999
2000 instruction->oprs[i].type |= xsizeflags[i]; /* Set the size */
2001 }
2002
2003 /* Try matching again... */
2004 for (temp = nasm_instructions[instruction->opcode];
2005 temp->opcode != I_none; temp++) {
2006 m = matches(temp, instruction, bits);
2007 if (m == MOK_JUMP) {
2008 if (jmp_match(segment, offset, bits, instruction, temp->code))
2009 m = MOK_GOOD;
2010 else
2011 m = MERR_INVALOP;
H. Peter Anvin23595f52009-07-25 17:44:25 -07002012 }
2013 if (m > merr)
2014 merr = m;
2015 if (merr == MOK_GOOD)
H. Peter Anvina81655b2009-07-25 18:15:28 -07002016 goto done;
H. Peter Anvin23595f52009-07-25 17:44:25 -07002017 }
2018
H. Peter Anvina81655b2009-07-25 18:15:28 -07002019done:
H. Peter Anvin23595f52009-07-25 17:44:25 -07002020 *tempp = temp;
2021 return merr;
2022}
2023
H. Peter Anvin65289e82009-07-25 17:25:11 -07002024static enum match_result matches(const struct itemplate *itemp,
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002025 insn *instruction, int bits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002026{
H. Peter Anvin60926242009-07-26 16:25:38 -07002027 int i, size[MAX_OPERANDS], asize, oprs;
H. Peter Anvin3fb86f22009-07-25 19:12:10 -07002028 bool opsizemissing = false;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002029
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002030 /*
2031 * Check the opcode
2032 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002033 if (itemp->opcode != instruction->opcode)
H. Peter Anvin65289e82009-07-25 17:25:11 -07002034 return MERR_INVALOP;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002035
2036 /*
2037 * Count the operands
2038 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002039 if (itemp->operands != instruction->operands)
H. Peter Anvin65289e82009-07-25 17:25:11 -07002040 return MERR_INVALOP;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002041
2042 /*
2043 * Check that no spurious colons or TOs are present
2044 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002045 for (i = 0; i < itemp->operands; i++)
2046 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON | TO))
H. Peter Anvin65289e82009-07-25 17:25:11 -07002047 return MERR_INVALOP;
H. Peter Anvin70653092007-10-19 14:42:29 -07002048
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002049 /*
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002050 * Process size flags
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002051 */
H. Peter Anvin60926242009-07-26 16:25:38 -07002052 switch (itemp->flags & IF_SMASK) {
2053 case IF_SB:
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002054 asize = BITS8;
2055 break;
H. Peter Anvin60926242009-07-26 16:25:38 -07002056 case IF_SW:
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002057 asize = BITS16;
2058 break;
H. Peter Anvin60926242009-07-26 16:25:38 -07002059 case IF_SD:
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002060 asize = BITS32;
2061 break;
H. Peter Anvin60926242009-07-26 16:25:38 -07002062 case IF_SQ:
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002063 asize = BITS64;
2064 break;
H. Peter Anvin60926242009-07-26 16:25:38 -07002065 case IF_SO:
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002066 asize = BITS128;
2067 break;
H. Peter Anvin60926242009-07-26 16:25:38 -07002068 case IF_SY:
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002069 asize = BITS256;
2070 break;
H. Peter Anvin60926242009-07-26 16:25:38 -07002071 case IF_SZ:
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002072 switch (bits) {
2073 case 16:
2074 asize = BITS16;
2075 break;
2076 case 32:
2077 asize = BITS32;
2078 break;
2079 case 64:
2080 asize = BITS64;
2081 break;
2082 default:
2083 asize = 0;
2084 break;
2085 }
2086 break;
H. Peter Anvin60926242009-07-26 16:25:38 -07002087 default:
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002088 asize = 0;
2089 break;
H. Peter Anvin60926242009-07-26 16:25:38 -07002090 }
2091
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002092 if (itemp->flags & IF_ARMASK) {
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002093 /* S- flags only apply to a specific operand */
2094 i = ((itemp->flags & IF_ARMASK) >> IF_ARSHFT) - 1;
2095 memset(size, 0, sizeof size);
2096 size[i] = asize;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002097 } else {
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002098 /* S- flags apply to all operands */
2099 for (i = 0; i < MAX_OPERANDS; i++)
2100 size[i] = asize;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002101 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002102
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002103 /*
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002104 * Check that the operand flags all match up,
2105 * it's a bit tricky so lets be verbose:
2106 *
2107 * 1) Find out the size of operand. If instruction
2108 * doesn't have one specified -- we're trying to
2109 * guess it either from template (IF_S* flag) or
2110 * from code bits.
2111 *
2112 * 2) If template operand (i) has SAME_AS flag [used for registers only]
2113 * (ie the same operand as was specified somewhere in template, and
2114 * this referred operand index is being achieved via ~SAME_AS)
2115 * we are to be sure that both registers (in template and instruction)
2116 * do exactly match.
2117 *
2118 * 3) If template operand do not match the instruction OR
2119 * template has an operand size specified AND this size differ
2120 * from which instruction has (perhaps we got it from code bits)
2121 * we are:
2122 * a) Check that only size of instruction and operand is differ
2123 * other characteristics do match
2124 * b) Perhaps it's a register specified in instruction so
2125 * for such a case we just mark that operand as "size
2126 * missing" and this will turn on fuzzy operand size
2127 * logic facility (handled by a caller)
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002128 */
2129 for (i = 0; i < itemp->operands; i++) {
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002130 opflags_t type = instruction->oprs[i].type;
2131 if (!(type & SIZE_MASK))
2132 type |= size[i];
H. Peter Anvind85d2502008-05-04 17:53:31 -07002133
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002134 if (itemp->opd[i] & SAME_AS) {
2135 int j = itemp->opd[i] & ~SAME_AS;
2136 if (type != instruction->oprs[j].type ||
2137 instruction->oprs[i].basereg != instruction->oprs[j].basereg)
2138 return MERR_INVALOP;
2139 } else if (itemp->opd[i] & ~type ||
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002140 ((itemp->opd[i] & SIZE_MASK) &&
2141 ((itemp->opd[i] ^ type) & SIZE_MASK))) {
H. Peter Anvinff5d6562009-10-05 14:08:05 -07002142 if ((itemp->opd[i] & ~type & ~SIZE_MASK) || (type & SIZE_MASK)) {
H. Peter Anvin65289e82009-07-25 17:25:11 -07002143 return MERR_INVALOP;
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002144 } else if (!is_class(REGISTER, type)) {
2145 /*
2146 * Note: we don't honor extrinsic operand sizes for registers,
2147 * so "missing operand size" for a register should be
2148 * considered a wildcard match rather than an error.
2149 */
2150 opsizemissing = true;
2151 }
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002152 }
2153 }
2154
H. Peter Anvin3fb86f22009-07-25 19:12:10 -07002155 if (opsizemissing)
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002156 return MERR_OPSIZEMISSING;
H. Peter Anvin3fb86f22009-07-25 19:12:10 -07002157
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002158 /*
2159 * Check operand sizes
2160 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002161 if (itemp->flags & (IF_SM | IF_SM2)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002162 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002163 for (i = 0; i < oprs; i++) {
Cyrill Gorcunovbc31bee2009-11-01 23:16:01 +03002164 asize = itemp->opd[i] & SIZE_MASK;
2165 if (asize) {
2166 for (i = 0; i < oprs; i++)
2167 size[i] = asize;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002168 break;
2169 }
2170 }
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002171 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002172 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002173 }
2174
Keith Kaniosb7a89542007-04-12 02:40:54 +00002175 for (i = 0; i < itemp->operands; i++) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002176 if (!(itemp->opd[i] & SIZE_MASK) &&
2177 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvin65289e82009-07-25 17:25:11 -07002178 return MERR_OPSIZEMISMATCH;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002179 }
2180
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002181 /*
2182 * Check template is okay at the set cpu level
2183 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002184 if (((itemp->flags & IF_PLEVEL) > cpu))
H. Peter Anvin65289e82009-07-25 17:25:11 -07002185 return MERR_BADCPU;
H. Peter Anvin70653092007-10-19 14:42:29 -07002186
Keith Kaniosb7a89542007-04-12 02:40:54 +00002187 /*
H. Peter Anvin6cda4142008-12-29 20:52:28 -08002188 * Verify the appropriate long mode flag.
Keith Kaniosb7a89542007-04-12 02:40:54 +00002189 */
H. Peter Anvin6cda4142008-12-29 20:52:28 -08002190 if ((itemp->flags & (bits == 64 ? IF_NOLONG : IF_LONG)))
H. Peter Anvin65289e82009-07-25 17:25:11 -07002191 return MERR_BADMODE;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002192
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002193 /*
2194 * Check if special handling needed for Jumps
2195 */
H. Peter Anvin60926242009-07-26 16:25:38 -07002196 if ((itemp->code[0] & 0374) == 0370)
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002197 return MOK_JUMP;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002198
H. Peter Anvin60926242009-07-26 16:25:38 -07002199 return MOK_GOOD;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002200}
2201
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002202static ea *process_ea(operand * input, ea * output, int bits,
H. Peter Anvinf8563f72009-10-13 12:28:14 -07002203 int addrbits, int rfield, opflags_t rflags)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002204{
H. Peter Anvin9945fee2009-02-26 14:48:03 -08002205 bool forw_ref = !!(input->opflags & OPFLAG_UNKNOWN);
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07002206
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002207 output->rip = false;
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00002208
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002209 /* REX flags for the rfield operand */
2210 output->rex |= rexflags(rfield, rflags, REX_R|REX_P|REX_W|REX_H);
2211
Cyrill Gorcunov8a6345c2009-10-13 19:05:31 +04002212 if (is_class(REGISTER, input->type)) { /* register direct */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002213 int i;
H. Peter Anvinf8563f72009-10-13 12:28:14 -07002214 opflags_t f;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002215
2216 if (input->basereg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002217 || input->basereg >= REG_ENUM_LIMIT)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002218 return NULL;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002219 f = regflag(input);
H. Peter Anvina4835d42008-05-20 14:21:29 -07002220 i = nasm_regvals[input->basereg];
Keith Kaniosb7a89542007-04-12 02:40:54 +00002221
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002222 if (REG_EA & ~f)
2223 return NULL; /* Invalid EA register */
H. Peter Anvin70653092007-10-19 14:42:29 -07002224
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002225 output->rex |= op_rexflags(input, REX_B|REX_P|REX_W|REX_H);
2226
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002227 output->sib_present = false; /* no SIB necessary */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002228 output->bytes = 0; /* no offset necessary either */
2229 output->modrm = 0xC0 | ((rfield & 7) << 3) | (i & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002230 } else { /* it's a memory reference */
2231 if (input->basereg == -1
2232 && (input->indexreg == -1 || input->scale == 0)) {
2233 /* it's a pure offset */
Victor van den Elzen0d268fb2010-01-24 21:24:57 +01002234
2235 if (bits == 64 && ((input->type & IP_REL) == IP_REL) &&
2236 input->segment == NO_SEG) {
2237 nasm_error(ERR_WARNING | ERR_PASS1, "absolute address can not be RIP-relative");
2238 input->type &= ~IP_REL;
2239 input->type |= MEMORY;
2240 }
2241
2242 if (input->eaflags & EAF_BYTEOFFS ||
2243 (input->eaflags & EAF_WORDOFFS &&
2244 input->disp_size != (addrbits != 16 ? 32 : 16))) {
2245 nasm_error(ERR_WARNING | ERR_PASS1, "displacement size ignored on absolute address");
2246 }
2247
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002248 if (bits == 64 && (~input->type & IP_REL)) {
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002249 int scale, index, base;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002250 output->sib_present = true;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002251 scale = 0;
2252 index = 4;
2253 base = 5;
2254 output->sib = (scale << 6) | (index << 3) | base;
2255 output->bytes = 4;
2256 output->modrm = 4 | ((rfield & 7) << 3);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002257 output->rip = false;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002258 } else {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002259 output->sib_present = false;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002260 output->bytes = (addrbits != 16 ? 4 : 2);
2261 output->modrm = (addrbits != 16 ? 5 : 6) | ((rfield & 7) << 3);
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002262 output->rip = bits == 64;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002263 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002264 } else { /* it's an indirection */
2265 int i = input->indexreg, b = input->basereg, s = input->scale;
Victor van den Elzen0d268fb2010-01-24 21:24:57 +01002266 int32_t seg = input->segment;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002267 int hb = input->hintbase, ht = input->hinttype;
H. Peter Anvinf8563f72009-10-13 12:28:14 -07002268 int t, it, bt; /* register numbers */
2269 opflags_t x, ix, bx; /* register flags */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002270
H. Peter Anvine2c80182005-01-15 22:15:51 +00002271 if (s == 0)
2272 i = -1; /* make this easy, at least */
H. Peter Anvin70653092007-10-19 14:42:29 -07002273
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002274 if (i >= EXPR_REG_START && i < REG_ENUM_LIMIT) {
H. Peter Anvina4835d42008-05-20 14:21:29 -07002275 it = nasm_regvals[i];
2276 ix = nasm_reg_flags[i];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002277 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00002278 it = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002279 ix = 0;
2280 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002281
H. Peter Anvinb0c54622007-10-28 23:21:46 -07002282 if (b >= EXPR_REG_START && b < REG_ENUM_LIMIT) {
H. Peter Anvina4835d42008-05-20 14:21:29 -07002283 bt = nasm_regvals[b];
2284 bx = nasm_reg_flags[b];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002285 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00002286 bt = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002287 bx = 0;
2288 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002289
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002290 /* check for a 32/64-bit memory reference... */
2291 if ((ix|bx) & (BITS32|BITS64)) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00002292 /* it must be a 32/64-bit memory reference. Firstly we have
2293 * to check that all registers involved are type E/Rxx. */
Victor van den Elzen0d268fb2010-01-24 21:24:57 +01002294 int32_t sok = BITS32|BITS64, o = input->offset;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002295
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002296 if (it != -1) {
2297 if (!(REG64 & ~ix) || !(REG32 & ~ix))
2298 sok &= ix;
2299 else
2300 return NULL;
2301 }
2302
2303 if (bt != -1) {
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00002304 if (REG_GPR & ~bx)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002305 return NULL; /* Invalid register */
H. Peter Anvina57e8d42007-05-30 03:44:02 +00002306 if (~sok & bx & SIZE_MASK)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002307 return NULL; /* Invalid size */
H. Peter Anvinb0c54622007-10-28 23:21:46 -07002308 sok &= bx;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002309 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002310
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002311 /* While we're here, ensure the user didn't specify
2312 WORD or QWORD. */
2313 if (input->disp_size == 16 || input->disp_size == 64)
2314 return NULL;
2315
2316 if (addrbits == 16 ||
2317 (addrbits == 32 && !(sok & BITS32)) ||
2318 (addrbits == 64 && !(sok & BITS64)))
2319 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002320
Keith Kaniosb7a89542007-04-12 02:40:54 +00002321 /* now reorganize base/index */
2322 if (s == 1 && bt != it && bt != -1 && it != -1 &&
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002323 ((hb == b && ht == EAH_NOTBASE)
2324 || (hb == i && ht == EAH_MAKEBASE))) {
2325 /* swap if hints say so */
2326 t = bt, bt = it, it = t;
H. Peter Anvinf8563f72009-10-13 12:28:14 -07002327 x = bx, bx = ix, ix = x;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002328 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00002329 if (bt == it) /* convert EAX+2*EAX to 3*EAX */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002330 bt = -1, bx = 0, s++;
2331 if (bt == -1 && s == 1 && !(hb == it && ht == EAH_NOTBASE)) {
2332 /* make single reg base, unless hint */
2333 bt = it, bx = ix, it = -1, ix = 0;
2334 }
H. Peter Anvinf5843c62007-09-10 18:59:26 +00002335 if (((s == 2 && it != REG_NUM_ESP
H. Peter Anvine2c80182005-01-15 22:15:51 +00002336 && !(input->eaflags & EAF_TIMESTWO)) || s == 3
Keith Kaniosb7a89542007-04-12 02:40:54 +00002337 || s == 5 || s == 9) && bt == -1)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002338 bt = it, bx = ix, s--; /* convert 3*EAX to EAX+2*EAX */
Keith Kanios48af1772007-08-17 07:37:52 +00002339 if (it == -1 && (bt & 7) != REG_NUM_ESP
H. Peter Anvine2c80182005-01-15 22:15:51 +00002340 && (input->eaflags & EAF_TIMESTWO))
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002341 it = bt, ix = bx, bt = -1, bx = 0, s = 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002342 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
Keith Kanios48af1772007-08-17 07:37:52 +00002343 if (s == 1 && it == REG_NUM_ESP) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002344 /* swap ESP into base if scale is 1 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002345 t = it, it = bt, bt = t;
H. Peter Anvinf8563f72009-10-13 12:28:14 -07002346 x = ix, ix = bx, bx = x;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002347 }
Keith Kanios48af1772007-08-17 07:37:52 +00002348 if (it == REG_NUM_ESP
Keith Kaniosb7a89542007-04-12 02:40:54 +00002349 || (s != 1 && s != 2 && s != 4 && s != 8 && it != -1))
H. Peter Anvine2c80182005-01-15 22:15:51 +00002350 return NULL; /* wrong, for various reasons */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002351
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002352 output->rex |= rexflags(it, ix, REX_X);
2353 output->rex |= rexflags(bt, bx, REX_B);
Keith Kaniosb7a89542007-04-12 02:40:54 +00002354
Keith Kanios48af1772007-08-17 07:37:52 +00002355 if (it == -1 && (bt & 7) != REG_NUM_ESP) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002356 /* no SIB needed */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002357 int mod, rm;
H. Peter Anvin70653092007-10-19 14:42:29 -07002358
Keith Kaniosb7a89542007-04-12 02:40:54 +00002359 if (bt == -1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002360 rm = 5;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002361 mod = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002362 } else {
2363 rm = (bt & 7);
Keith Kanios48af1772007-08-17 07:37:52 +00002364 if (rm != REG_NUM_EBP && o == 0 &&
Keith Kaniosb7a89542007-04-12 02:40:54 +00002365 seg == NO_SEG && !forw_ref &&
2366 !(input->eaflags &
2367 (EAF_BYTEOFFS | EAF_WORDOFFS)))
2368 mod = 0;
2369 else if (input->eaflags & EAF_BYTEOFFS ||
2370 (o >= -128 && o <= 127 && seg == NO_SEG
2371 && !forw_ref
2372 && !(input->eaflags & EAF_WORDOFFS)))
2373 mod = 1;
2374 else
2375 mod = 2;
2376 }
H. Peter Anvinea838272002-04-30 20:51:53 +00002377
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002378 output->sib_present = false;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002379 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
2380 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002381 } else {
2382 /* we need a SIB */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002383 int mod, scale, index, base;
H. Peter Anvin70653092007-10-19 14:42:29 -07002384
Keith Kaniosb7a89542007-04-12 02:40:54 +00002385 if (it == -1)
2386 index = 4, s = 1;
2387 else
2388 index = (it & 7);
H. Peter Anvin70653092007-10-19 14:42:29 -07002389
H. Peter Anvine2c80182005-01-15 22:15:51 +00002390 switch (s) {
2391 case 1:
2392 scale = 0;
2393 break;
2394 case 2:
2395 scale = 1;
2396 break;
2397 case 4:
2398 scale = 2;
2399 break;
2400 case 8:
2401 scale = 3;
2402 break;
2403 default: /* then what the smeg is it? */
2404 return NULL; /* panic */
2405 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002406
Keith Kaniosb7a89542007-04-12 02:40:54 +00002407 if (bt == -1) {
2408 base = 5;
2409 mod = 0;
2410 } else {
2411 base = (bt & 7);
Keith Kanios48af1772007-08-17 07:37:52 +00002412 if (base != REG_NUM_EBP && o == 0 &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00002413 seg == NO_SEG && !forw_ref &&
2414 !(input->eaflags &
Keith Kaniosb7a89542007-04-12 02:40:54 +00002415 (EAF_BYTEOFFS | EAF_WORDOFFS)))
2416 mod = 0;
2417 else if (input->eaflags & EAF_BYTEOFFS ||
2418 (o >= -128 && o <= 127 && seg == NO_SEG
2419 && !forw_ref
2420 && !(input->eaflags & EAF_WORDOFFS)))
2421 mod = 1;
2422 else
2423 mod = 2;
2424 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002425
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002426 output->sib_present = true;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002427 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
2428 output->modrm = (mod << 6) | ((rfield & 7) << 3) | 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002429 output->sib = (scale << 6) | (index << 3) | base;
2430 }
2431 } else { /* it's 16-bit */
2432 int mod, rm;
Victor van den Elzen0d268fb2010-01-24 21:24:57 +01002433 int16_t o = input->offset;
H. Peter Anvin70653092007-10-19 14:42:29 -07002434
Keith Kaniosb7a89542007-04-12 02:40:54 +00002435 /* check for 64-bit long mode */
2436 if (addrbits == 64)
2437 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002438
H. Peter Anvine2c80182005-01-15 22:15:51 +00002439 /* check all registers are BX, BP, SI or DI */
2440 if ((b != -1 && b != R_BP && b != R_BX && b != R_SI
2441 && b != R_DI) || (i != -1 && i != R_BP && i != R_BX
2442 && i != R_SI && i != R_DI))
2443 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002444
Keith Kaniosb7a89542007-04-12 02:40:54 +00002445 /* ensure the user didn't specify DWORD/QWORD */
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002446 if (input->disp_size == 32 || input->disp_size == 64)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002447 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002448
H. Peter Anvine2c80182005-01-15 22:15:51 +00002449 if (s != 1 && i != -1)
2450 return NULL; /* no can do, in 16-bit EA */
2451 if (b == -1 && i != -1) {
2452 int tmp = b;
2453 b = i;
2454 i = tmp;
2455 } /* swap */
2456 if ((b == R_SI || b == R_DI) && i != -1) {
2457 int tmp = b;
2458 b = i;
2459 i = tmp;
2460 }
2461 /* have BX/BP as base, SI/DI index */
2462 if (b == i)
2463 return NULL; /* shouldn't ever happen, in theory */
2464 if (i != -1 && b != -1 &&
2465 (i == R_BP || i == R_BX || b == R_SI || b == R_DI))
2466 return NULL; /* invalid combinations */
2467 if (b == -1) /* pure offset: handled above */
2468 return NULL; /* so if it gets to here, panic! */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002469
H. Peter Anvine2c80182005-01-15 22:15:51 +00002470 rm = -1;
2471 if (i != -1)
2472 switch (i * 256 + b) {
2473 case R_SI * 256 + R_BX:
2474 rm = 0;
2475 break;
2476 case R_DI * 256 + R_BX:
2477 rm = 1;
2478 break;
2479 case R_SI * 256 + R_BP:
2480 rm = 2;
2481 break;
2482 case R_DI * 256 + R_BP:
2483 rm = 3;
2484 break;
2485 } else
2486 switch (b) {
2487 case R_SI:
2488 rm = 4;
2489 break;
2490 case R_DI:
2491 rm = 5;
2492 break;
2493 case R_BP:
2494 rm = 6;
2495 break;
2496 case R_BX:
2497 rm = 7;
2498 break;
2499 }
2500 if (rm == -1) /* can't happen, in theory */
2501 return NULL; /* so panic if it does */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002502
H. Peter Anvine2c80182005-01-15 22:15:51 +00002503 if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
2504 !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
2505 mod = 0;
2506 else if (input->eaflags & EAF_BYTEOFFS ||
2507 (o >= -128 && o <= 127 && seg == NO_SEG
2508 && !forw_ref
2509 && !(input->eaflags & EAF_WORDOFFS)))
2510 mod = 1;
2511 else
2512 mod = 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002513
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002514 output->sib_present = false; /* no SIB - it's 16-bit */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002515 output->bytes = mod; /* bytes of offset needed */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002516 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002517 }
2518 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002519 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002520
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002521 output->size = 1 + output->sib_present + output->bytes;
2522 return output;
2523}
2524
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002525static void add_asp(insn *ins, int addrbits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002526{
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002527 int j, valid;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002528 int defdisp;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002529
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002530 valid = (addrbits == 64) ? 64|32 : 32|16;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002531
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002532 switch (ins->prefixes[PPS_ASIZE]) {
2533 case P_A16:
2534 valid &= 16;
2535 break;
2536 case P_A32:
2537 valid &= 32;
2538 break;
2539 case P_A64:
2540 valid &= 64;
2541 break;
2542 case P_ASP:
2543 valid &= (addrbits == 32) ? 16 : 32;
2544 break;
2545 default:
2546 break;
2547 }
2548
2549 for (j = 0; j < ins->operands; j++) {
Cyrill Gorcunove4f526b2009-10-18 12:41:14 +04002550 if (is_class(MEMORY, ins->oprs[j].type)) {
H. Peter Anvinf8563f72009-10-13 12:28:14 -07002551 opflags_t i, b;
H. Peter Anvin70653092007-10-19 14:42:29 -07002552
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002553 /* Verify as Register */
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002554 if (ins->oprs[j].indexreg < EXPR_REG_START
2555 || ins->oprs[j].indexreg >= REG_ENUM_LIMIT)
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002556 i = 0;
2557 else
H. Peter Anvina4835d42008-05-20 14:21:29 -07002558 i = nasm_reg_flags[ins->oprs[j].indexreg];
H. Peter Anvin70653092007-10-19 14:42:29 -07002559
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002560 /* Verify as Register */
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002561 if (ins->oprs[j].basereg < EXPR_REG_START
2562 || ins->oprs[j].basereg >= REG_ENUM_LIMIT)
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002563 b = 0;
2564 else
H. Peter Anvina4835d42008-05-20 14:21:29 -07002565 b = nasm_reg_flags[ins->oprs[j].basereg];
H. Peter Anvin70653092007-10-19 14:42:29 -07002566
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002567 if (ins->oprs[j].scale == 0)
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002568 i = 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002569
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002570 if (!i && !b) {
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002571 int ds = ins->oprs[j].disp_size;
2572 if ((addrbits != 64 && ds > 8) ||
2573 (addrbits == 64 && ds == 16))
2574 valid &= ds;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002575 } else {
2576 if (!(REG16 & ~b))
2577 valid &= 16;
2578 if (!(REG32 & ~b))
2579 valid &= 32;
2580 if (!(REG64 & ~b))
2581 valid &= 64;
H. Peter Anvin70653092007-10-19 14:42:29 -07002582
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002583 if (!(REG16 & ~i))
2584 valid &= 16;
2585 if (!(REG32 & ~i))
2586 valid &= 32;
2587 if (!(REG64 & ~i))
2588 valid &= 64;
2589 }
2590 }
2591 }
2592
2593 if (valid & addrbits) {
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002594 ins->addr_size = addrbits;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002595 } else if (valid & ((addrbits == 32) ? 16 : 32)) {
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002596 /* Add an address size prefix */
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002597 enum prefixes pref = (addrbits == 32) ? P_A16 : P_A32;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002598 ins->prefixes[PPS_ASIZE] = pref;
2599 ins->addr_size = (addrbits == 32) ? 16 : 32;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002600 } else {
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002601 /* Impossible... */
2602 errfunc(ERR_NONFATAL, "impossible combination of address sizes");
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002603 ins->addr_size = addrbits; /* Error recovery */
2604 }
2605
2606 defdisp = ins->addr_size == 16 ? 16 : 32;
2607
2608 for (j = 0; j < ins->operands; j++) {
2609 if (!(MEM_OFFS & ~ins->oprs[j].type) &&
2610 (ins->oprs[j].disp_size ? ins->oprs[j].disp_size : defdisp)
2611 != ins->addr_size) {
2612 /* mem_offs sizes must match the address size; if not,
2613 strip the MEM_OFFS bit and match only EA instructions */
2614 ins->oprs[j].type &= ~(MEM_OFFS & ~MEMORY);
2615 }
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002616 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002617}