blob: 222ebfaaee2cd0e1af00cf2b0c09f24dc6afa54f [file] [log] [blame]
H. Peter Anvin9e6747c2009-06-28 17:13:04 -07001/* ----------------------------------------------------------------------- *
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002 *
H. Peter Anvinfea84d72010-05-06 15:32:20 -07003 * Copyright 1996-2010 The NASM Authors - All Rights Reserved
H. Peter Anvin9e6747c2009-06-28 17:13:04 -07004 * 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 Anvinab5bd052010-07-25 12:43:30 -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 Anvinab5bd052010-07-25 12:43:30 -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 Anvinab5bd052010-07-25 12:43:30 -0700762static bool is_sbyte16(operand *o)
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700763{
764 int16_t v;
765
H. Peter Anvinab5bd052010-07-25 12:43:30 -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 Anvinab5bd052010-07-25 12:43:30 -0700773static bool is_sbyte32(operand *o)
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700774{
775 int32_t v;
776
H. Peter Anvinab5bd052010-07-25 12:43:30 -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 Anvinab5bd052010-07-25 12:43:30 -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 Anvinab5bd052010-07-25 12:43:30 -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 Anvinab5bd052010-07-25 12:43:30 -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 Anvinfea84d72010-05-06 15:32:20 -07001339 if (opx->segment != segment) {
1340 data = opx->offset;
1341 out(offset, segment, &data,
1342 OUT_REL1ADR, insn_end - offset,
1343 opx->segment, opx->wrt);
1344 } else {
1345 data = opx->offset - insn_end;
1346 if (data > 127 || data < -128)
1347 errfunc(ERR_NONFATAL, "short jump is out of range");
1348 out(offset, segment, &data,
1349 OUT_ADDRESS, 1, NO_SEG, NO_SEG);
1350 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001351 offset += 1;
1352 break;
H. Peter Anvin70653092007-10-19 14:42:29 -07001353
H. Peter Anvin507ae032008-10-09 15:37:10 -07001354 case4(054):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001355 data = (int64_t)opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001356 out(offset, segment, &data, OUT_ADDRESS, 8,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001357 opx->segment, opx->wrt);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001358 offset += 8;
1359 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001360
H. Peter Anvin507ae032008-10-09 15:37:10 -07001361 case4(060):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001362 if (opx->segment != segment) {
1363 data = opx->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001364 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001365 OUT_REL2ADR, insn_end - offset,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001366 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001367 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001368 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001369 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001370 OUT_ADDRESS, 2, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001371 }
1372 offset += 2;
1373 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001374
H. Peter Anvin507ae032008-10-09 15:37:10 -07001375 case4(064):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001376 if (opx->type & (BITS16 | BITS32 | BITS64))
1377 size = (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001378 else
1379 size = (bits == 16) ? 2 : 4;
H. Peter Anvin839eca22007-10-29 23:12:47 -07001380 if (opx->segment != segment) {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001381 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001382 out(offset, segment, &data,
1383 size == 2 ? OUT_REL2ADR : OUT_REL4ADR,
1384 insn_end - offset, opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001385 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001386 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001387 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001388 OUT_ADDRESS, size, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001389 }
1390 offset += size;
1391 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001392
H. Peter Anvin507ae032008-10-09 15:37:10 -07001393 case4(070):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001394 if (opx->segment != segment) {
1395 data = opx->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001396 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001397 OUT_REL4ADR, insn_end - offset,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001398 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001399 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001400 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001401 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001402 OUT_ADDRESS, 4, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001403 }
1404 offset += 4;
1405 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001406
H. Peter Anvin507ae032008-10-09 15:37:10 -07001407 case4(074):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001408 if (opx->segment == NO_SEG)
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001409 errfunc(ERR_NONFATAL, "value referenced by FAR is not"
1410 " relocatable");
H. Peter Anvindfb91802008-05-20 11:43:53 -07001411 data = 0;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001412 out(offset, segment, &data, OUT_ADDRESS, 2,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001413 outfmt->segbase(1 + opx->segment),
1414 opx->wrt);
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001415 offset += 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001416 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001417
H. Peter Anvin507ae032008-10-09 15:37:10 -07001418 case4(0140):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001419 data = opx->offset;
Cyrill Gorcunov9ccabd22009-09-21 00:56:20 +04001420 warn_overflow_opd(opx, 2);
H. Peter Anvinab5bd052010-07-25 12:43:30 -07001421 if (is_sbyte16(opx)) {
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001422 bytes[0] = data;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001423 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001424 NO_SEG);
1425 offset++;
1426 } else {
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001427 out(offset, segment, &data, OUT_ADDRESS, 2,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001428 opx->segment, opx->wrt);
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001429 offset += 2;
1430 }
1431 break;
1432
H. Peter Anvin507ae032008-10-09 15:37:10 -07001433 case4(0144):
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001434 EMIT_REX();
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001435 bytes[0] = *codes++;
H. Peter Anvinab5bd052010-07-25 12:43:30 -07001436 if (is_sbyte16(opx))
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001437 bytes[0] |= 2; /* s-bit */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001438 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001439 offset++;
1440 break;
1441
H. Peter Anvin507ae032008-10-09 15:37:10 -07001442 case4(0150):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001443 data = opx->offset;
Cyrill Gorcunov9ccabd22009-09-21 00:56:20 +04001444 warn_overflow_opd(opx, 4);
H. Peter Anvinab5bd052010-07-25 12:43:30 -07001445 if (is_sbyte32(opx)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001446 bytes[0] = data;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001447 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001448 NO_SEG);
1449 offset++;
1450 } else {
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001451 out(offset, segment, &data, OUT_ADDRESS, 4,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001452 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001453 offset += 4;
1454 }
1455 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001456
H. Peter Anvin507ae032008-10-09 15:37:10 -07001457 case4(0154):
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001458 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001459 bytes[0] = *codes++;
H. Peter Anvinab5bd052010-07-25 12:43:30 -07001460 if (is_sbyte32(opx))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001461 bytes[0] |= 2; /* s-bit */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001462 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001463 offset++;
1464 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001465
H. Peter Anvin507ae032008-10-09 15:37:10 -07001466 case4(0160):
1467 case4(0164):
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001468 break;
1469
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001470 case 0171:
1471 bytes[0] =
1472 (ins->drexdst << 4) |
1473 (ins->rex & REX_OC ? 0x08 : 0) |
1474 (ins->rex & (REX_R|REX_X|REX_B));
1475 ins->rex = 0;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001476 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001477 offset++;
1478 break;
1479
H. Peter Anvind85d2502008-05-04 17:53:31 -07001480 case 0172:
1481 c = *codes++;
1482 opx = &ins->oprs[c >> 3];
H. Peter Anvina4835d42008-05-20 14:21:29 -07001483 bytes[0] = nasm_regvals[opx->basereg] << 4;
H. Peter Anvind85d2502008-05-04 17:53:31 -07001484 opx = &ins->oprs[c & 7];
1485 if (opx->segment != NO_SEG || opx->wrt != NO_SEG) {
1486 errfunc(ERR_NONFATAL,
1487 "non-absolute expression not permitted as argument %d",
1488 c & 7);
1489 } else {
1490 if (opx->offset & ~15) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001491 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
H. Peter Anvind85d2502008-05-04 17:53:31 -07001492 "four-bit argument exceeds bounds");
1493 }
1494 bytes[0] |= opx->offset & 15;
1495 }
1496 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1497 offset++;
1498 break;
1499
H. Peter Anvind58656f2008-05-06 20:11:14 -07001500 case 0173:
1501 c = *codes++;
1502 opx = &ins->oprs[c >> 4];
H. Peter Anvina4835d42008-05-20 14:21:29 -07001503 bytes[0] = nasm_regvals[opx->basereg] << 4;
H. Peter Anvind58656f2008-05-06 20:11:14 -07001504 bytes[0] |= c & 15;
1505 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1506 offset++;
1507 break;
1508
H. Peter Anvin52dc3532008-05-20 19:29:04 -07001509 case 0174:
1510 c = *codes++;
1511 opx = &ins->oprs[c];
1512 bytes[0] = nasm_regvals[opx->basereg] << 4;
1513 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1514 offset++;
1515 break;
1516
H. Peter Anvin507ae032008-10-09 15:37:10 -07001517 case4(0250):
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001518 data = opx->offset;
H. Peter Anvinad6b8592008-10-07 09:56:38 -07001519 if (opx->wrt == NO_SEG && opx->segment == NO_SEG &&
1520 (int32_t)data != (int64_t)data) {
1521 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
1522 "signed dword immediate exceeds bounds");
1523 }
H. Peter Anvinab5bd052010-07-25 12:43:30 -07001524 if (is_sbyte32(opx)) {
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001525 bytes[0] = data;
1526 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
1527 NO_SEG);
1528 offset++;
1529 } else {
1530 out(offset, segment, &data, OUT_ADDRESS, 4,
1531 opx->segment, opx->wrt);
1532 offset += 4;
1533 }
1534 break;
1535
H. Peter Anvin507ae032008-10-09 15:37:10 -07001536 case4(0254):
H. Peter Anvin588df782008-10-07 10:05:10 -07001537 data = opx->offset;
1538 if (opx->wrt == NO_SEG && opx->segment == NO_SEG &&
1539 (int32_t)data != (int64_t)data) {
1540 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
1541 "signed dword immediate exceeds bounds");
1542 }
1543 out(offset, segment, &data, OUT_ADDRESS, 4,
1544 opx->segment, opx->wrt);
1545 offset += 4;
1546 break;
1547
H. Peter Anvin507ae032008-10-09 15:37:10 -07001548 case4(0260):
H. Peter Anvind85d2502008-05-04 17:53:31 -07001549 case 0270:
1550 codes += 2;
H. Peter Anvina04019c2009-05-03 21:42:34 -07001551 if (ins->vex_cm != 1 || (ins->rex & (REX_W|REX_X|REX_B))) {
1552 bytes[0] = (ins->vex_cm >> 6) ? 0x8f : 0xc4;
1553 bytes[1] = (ins->vex_cm & 31) | ((~ins->rex & 7) << 5);
H. Peter Anvind85d2502008-05-04 17:53:31 -07001554 bytes[2] = ((ins->rex & REX_W) << (7-3)) |
H. Peter Anvin4d2c38c2008-05-04 23:15:13 -07001555 ((~ins->drexdst & 15)<< 3) | (ins->vex_wlp & 07);
H. Peter Anvind85d2502008-05-04 17:53:31 -07001556 out(offset, segment, &bytes, OUT_RAWDATA, 3, NO_SEG, NO_SEG);
1557 offset += 3;
1558 } else {
1559 bytes[0] = 0xc5;
H. Peter Anvin4d2c38c2008-05-04 23:15:13 -07001560 bytes[1] = ((~ins->rex & REX_R) << (7-2)) |
1561 ((~ins->drexdst & 15) << 3) | (ins->vex_wlp & 07);
H. Peter Anvind85d2502008-05-04 17:53:31 -07001562 out(offset, segment, &bytes, OUT_RAWDATA, 2, NO_SEG, NO_SEG);
1563 offset += 2;
1564 }
1565 break;
1566
H. Peter Anvin507ae032008-10-09 15:37:10 -07001567 case4(0274):
H. Peter Anvinc1377e92008-10-06 23:40:31 -07001568 {
1569 uint64_t uv, um;
1570 int s;
1571
1572 if (ins->rex & REX_W)
1573 s = 64;
1574 else if (ins->prefixes[PPS_OSIZE] == P_O16)
1575 s = 16;
1576 else if (ins->prefixes[PPS_OSIZE] == P_O32)
1577 s = 32;
1578 else
1579 s = bits;
1580
1581 um = (uint64_t)2 << (s-1);
1582 uv = opx->offset;
1583
1584 if (uv > 127 && uv < (uint64_t)-128 &&
1585 (uv < um-128 || uv > um-1)) {
1586 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
1587 "signed byte value exceeds bounds");
1588 }
1589 if (opx->segment != NO_SEG) {
H. Peter Anvin779ed8b2008-10-16 13:01:43 -07001590 data = uv;
H. Peter Anvinc1377e92008-10-06 23:40:31 -07001591 out(offset, segment, &data, OUT_ADDRESS, 1,
1592 opx->segment, opx->wrt);
1593 } else {
H. Peter Anvin779ed8b2008-10-16 13:01:43 -07001594 bytes[0] = uv;
H. Peter Anvinc1377e92008-10-06 23:40:31 -07001595 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
1596 NO_SEG);
1597 }
1598 offset += 1;
1599 break;
1600 }
1601
H. Peter Anvin507ae032008-10-09 15:37:10 -07001602 case4(0300):
H. Peter Anvine2c80182005-01-15 22:15:51 +00001603 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001604
H. Peter Anvine2c80182005-01-15 22:15:51 +00001605 case 0310:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001606 if (bits == 32 && !has_prefix(ins, PPS_ASIZE, P_A16)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001607 *bytes = 0x67;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001608 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001609 offset += 1;
1610 } else
1611 offset += 0;
1612 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001613
H. Peter Anvine2c80182005-01-15 22:15:51 +00001614 case 0311:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001615 if (bits != 32 && !has_prefix(ins, PPS_ASIZE, P_A32)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001616 *bytes = 0x67;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001617 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001618 offset += 1;
1619 } else
1620 offset += 0;
1621 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001622
H. Peter Anvine2c80182005-01-15 22:15:51 +00001623 case 0312:
1624 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001625
Keith Kaniosb7a89542007-04-12 02:40:54 +00001626 case 0313:
1627 ins->rex = 0;
1628 break;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07001629
H. Peter Anvin507ae032008-10-09 15:37:10 -07001630 case4(0314):
H. Peter Anvin23440102007-11-12 21:02:33 -08001631 break;
1632
H. Peter Anvine2c80182005-01-15 22:15:51 +00001633 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001634 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001635 *bytes = 0x66;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001636 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001637 offset += 1;
1638 } else
1639 offset += 0;
1640 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001641
H. Peter Anvine2c80182005-01-15 22:15:51 +00001642 case 0321:
1643 if (bits == 16) {
1644 *bytes = 0x66;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001645 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001646 offset += 1;
1647 } else
1648 offset += 0;
1649 break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001650
H. Peter Anvine2c80182005-01-15 22:15:51 +00001651 case 0322:
H. Peter Anvin70653092007-10-19 14:42:29 -07001652 case 0323:
1653 break;
1654
Keith Kaniosb7a89542007-04-12 02:40:54 +00001655 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001656 ins->rex |= REX_W;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001657 break;
H. Peter Anvin70653092007-10-19 14:42:29 -07001658
H. Peter Anvin9472dab2009-06-24 21:38:29 -07001659 case 0325:
1660 break;
1661
H. Peter Anvine2c80182005-01-15 22:15:51 +00001662 case 0330:
1663 *bytes = *codes++ ^ condval[ins->condition];
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001664 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001665 offset += 1;
1666 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001667
H. Peter Anvine2c80182005-01-15 22:15:51 +00001668 case 0331:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001669 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001670
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001671 case 0332:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001672 case 0333:
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001673 *bytes = c - 0332 + 0xF2;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001674 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001675 offset += 1;
1676 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001677
Keith Kanios48af1772007-08-17 07:37:52 +00001678 case 0334:
1679 if (ins->rex & REX_R) {
1680 *bytes = 0xF0;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001681 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
Keith Kanios48af1772007-08-17 07:37:52 +00001682 offset += 1;
1683 }
1684 ins->rex &= ~(REX_L|REX_R);
1685 break;
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001686
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001687 case 0335:
1688 break;
1689
H. Peter Anvin962e3052008-08-28 17:47:16 -07001690 case 0336:
1691 case 0337:
1692 break;
1693
H. Peter Anvine2c80182005-01-15 22:15:51 +00001694 case 0340:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001695 if (ins->oprs[0].segment != NO_SEG)
1696 errfunc(ERR_PANIC, "non-constant BSS size in pass two");
1697 else {
H. Peter Anvin428fd672007-11-15 10:25:52 -08001698 int64_t size = ins->oprs[0].offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001699 if (size > 0)
1700 out(offset, segment, NULL,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001701 OUT_RESERVE, size, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001702 offset += size;
1703 }
1704 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001705
H. Peter Anvinc2acf7b2009-02-21 18:22:56 -08001706 case 0341:
1707 break;
1708
H. Peter Anvinff6e12d2008-10-08 21:17:32 -07001709 case 0344:
1710 case 0345:
1711 bytes[0] = c & 1;
1712 switch (ins->oprs[0].basereg) {
1713 case R_CS:
1714 bytes[0] += 0x0E;
1715 break;
1716 case R_DS:
1717 bytes[0] += 0x1E;
1718 break;
1719 case R_ES:
1720 bytes[0] += 0x06;
1721 break;
1722 case R_SS:
1723 bytes[0] += 0x16;
1724 break;
1725 default:
1726 errfunc(ERR_PANIC,
1727 "bizarre 8086 segment register received");
1728 }
1729 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1730 offset++;
1731 break;
1732
1733 case 0346:
1734 case 0347:
1735 bytes[0] = c & 1;
1736 switch (ins->oprs[0].basereg) {
1737 case R_FS:
1738 bytes[0] += 0xA0;
1739 break;
1740 case R_GS:
1741 bytes[0] += 0xA8;
1742 break;
1743 default:
1744 errfunc(ERR_PANIC,
1745 "bizarre 386 segment register received");
1746 }
1747 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1748 offset++;
1749 break;
1750
H. Peter Anvinfff5a472008-05-20 09:46:24 -07001751 case 0360:
1752 break;
1753
1754 case 0361:
1755 bytes[0] = 0x66;
1756 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1757 offset += 1;
1758 break;
1759
1760 case 0362:
1761 case 0363:
1762 bytes[0] = c - 0362 + 0xf2;
1763 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1764 offset += 1;
1765 break;
1766
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001767 case 0364:
1768 case 0365:
1769 break;
1770
Keith Kanios48af1772007-08-17 07:37:52 +00001771 case 0366:
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001772 case 0367:
1773 *bytes = c - 0366 + 0x66;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001774 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
Keith Kanios48af1772007-08-17 07:37:52 +00001775 offset += 1;
1776 break;
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001777
H. Peter Anvine2c80182005-01-15 22:15:51 +00001778 case 0370:
1779 case 0371:
1780 case 0372:
1781 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001782
H. Peter Anvine2c80182005-01-15 22:15:51 +00001783 case 0373:
1784 *bytes = bits == 16 ? 3 : 5;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001785 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001786 offset += 1;
1787 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001788
H. Peter Anvin507ae032008-10-09 15:37:10 -07001789 case4(0100):
1790 case4(0110):
1791 case4(0120):
1792 case4(0130):
1793 case4(0200):
1794 case4(0204):
1795 case4(0210):
1796 case4(0214):
1797 case4(0220):
1798 case4(0224):
1799 case4(0230):
1800 case4(0234):
1801 {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001802 ea ea_data;
1803 int rfield;
H. Peter Anvinf8563f72009-10-13 12:28:14 -07001804 opflags_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001805 uint8_t *p;
1806 int32_t s;
H. Peter Anvin9f817132008-10-06 19:11:07 -07001807 enum out_type type;
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001808 struct operand *opy = &ins->oprs[op2];
H. Peter Anvin70653092007-10-19 14:42:29 -07001809
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001810 if (c <= 0177) {
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001811 /* pick rfield from operand b (opx) */
1812 rflags = regflag(opx);
1813 rfield = nasm_regvals[opx->basereg];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001814 } else {
1815 /* rfield is constant */
1816 rflags = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001817 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001818 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001819
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001820 if (!process_ea(opy, &ea_data, bits, ins->addr_size,
1821 rfield, rflags)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001822 errfunc(ERR_NONFATAL, "invalid effective address");
1823 }
H. Peter Anvin70653092007-10-19 14:42:29 -07001824
Charles Crayne7e975552007-11-03 22:06:13 -07001825
H. Peter Anvine2c80182005-01-15 22:15:51 +00001826 p = bytes;
1827 *p++ = ea_data.modrm;
1828 if (ea_data.sib_present)
1829 *p++ = ea_data.sib;
1830
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001831 /* DREX suffixes come between the SIB and the displacement */
1832 if (ins->rex & REX_D) {
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001833 *p++ = (ins->drexdst << 4) |
1834 (ins->rex & REX_OC ? 0x08 : 0) |
1835 (ins->rex & (REX_R|REX_X|REX_B));
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001836 ins->rex = 0;
1837 }
1838
H. Peter Anvine2c80182005-01-15 22:15:51 +00001839 s = p - bytes;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001840 out(offset, segment, bytes, OUT_RAWDATA, s, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001841
Victor van den Elzencf9332c2008-10-01 12:18:28 +02001842 /*
1843 * Make sure the address gets the right offset in case
1844 * the line breaks in the .lst file (BR 1197827)
1845 */
1846 offset += s;
1847 s = 0;
1848
H. Peter Anvine2c80182005-01-15 22:15:51 +00001849 switch (ea_data.bytes) {
1850 case 0:
1851 break;
1852 case 1:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001853 case 2:
1854 case 4:
Victor van den Elzen352fe062008-12-10 13:04:58 +01001855 case 8:
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001856 data = opy->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001857 s += ea_data.bytes;
H. Peter Anvin9f817132008-10-06 19:11:07 -07001858 if (ea_data.rip) {
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001859 if (opy->segment == segment) {
H. Peter Anvine286c7e2008-10-22 11:15:00 -07001860 data -= insn_end;
Victor van den Elzen0d268fb2010-01-24 21:24:57 +01001861 if (overflow_signed(data, ea_data.bytes))
1862 warn_overflow(ERR_PASS2, ea_data.bytes);
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001863 out(offset, segment, &data, OUT_ADDRESS,
1864 ea_data.bytes, NO_SEG, NO_SEG);
H. Peter Anvine286c7e2008-10-22 11:15:00 -07001865 } else {
Victor van den Elzen0d268fb2010-01-24 21:24:57 +01001866 /* overflow check in output/linker? */
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001867 out(offset, segment, &data, OUT_REL4ADR,
1868 insn_end - offset, opy->segment, opy->wrt);
H. Peter Anvine286c7e2008-10-22 11:15:00 -07001869 }
H. Peter Anvin9f817132008-10-06 19:11:07 -07001870 } else {
Victor van den Elzen0d268fb2010-01-24 21:24:57 +01001871 if (overflow_general(opy->offset, ins->addr_size >> 3) ||
1872 signed_bits(opy->offset, ins->addr_size) !=
1873 signed_bits(opy->offset, ea_data.bytes * 8))
1874 warn_overflow(ERR_PASS2, ea_data.bytes);
1875
H. Peter Anvin9f817132008-10-06 19:11:07 -07001876 type = OUT_ADDRESS;
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001877 out(offset, segment, &data, OUT_ADDRESS,
1878 ea_data.bytes, opy->segment, opy->wrt);
H. Peter Anvin9f817132008-10-06 19:11:07 -07001879 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001880 break;
Victor van den Elzen352fe062008-12-10 13:04:58 +01001881 default:
1882 /* Impossible! */
1883 errfunc(ERR_PANIC,
1884 "Invalid amount of bytes (%d) for offset?!",
1885 ea_data.bytes);
1886 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001887 }
1888 offset += s;
H. Peter Anvin839eca22007-10-29 23:12:47 -07001889 }
H. Peter Anvin507ae032008-10-09 15:37:10 -07001890 break;
1891
1892 default:
1893 errfunc(ERR_PANIC, "internal instruction table corrupt"
H. Peter Anvin16a856c2009-03-01 00:22:16 -08001894 ": instruction code \\%o (0x%02X) given", c, c);
H. Peter Anvin507ae032008-10-09 15:37:10 -07001895 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001896 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001897 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001898}
1899
H. Peter Anvinf8563f72009-10-13 12:28:14 -07001900static opflags_t regflag(const operand * o)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001901{
Cyrill Gorcunov2124b7b2010-07-25 01:16:33 +04001902 if (!is_register(o->basereg))
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001903 errfunc(ERR_PANIC, "invalid operand passed to regflag()");
H. Peter Anvina4835d42008-05-20 14:21:29 -07001904 return nasm_reg_flags[o->basereg];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001905}
1906
H. Peter Anvin5b0e3ec2007-07-07 02:01:08 +00001907static int32_t regval(const operand * o)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001908{
Cyrill Gorcunov2124b7b2010-07-25 01:16:33 +04001909 if (!is_register(o->basereg))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001910 errfunc(ERR_PANIC, "invalid operand passed to regval()");
H. Peter Anvina4835d42008-05-20 14:21:29 -07001911 return nasm_regvals[o->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001912}
1913
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001914static int op_rexflags(const operand * o, int mask)
1915{
H. Peter Anvinf8563f72009-10-13 12:28:14 -07001916 opflags_t flags;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001917 int val;
1918
Cyrill Gorcunov2124b7b2010-07-25 01:16:33 +04001919 if (!is_register(o->basereg))
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001920 errfunc(ERR_PANIC, "invalid operand passed to op_rexflags()");
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001921
H. Peter Anvina4835d42008-05-20 14:21:29 -07001922 flags = nasm_reg_flags[o->basereg];
1923 val = nasm_regvals[o->basereg];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001924
1925 return rexflags(val, flags, mask);
1926}
1927
H. Peter Anvinf8563f72009-10-13 12:28:14 -07001928static int rexflags(int val, opflags_t flags, int mask)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001929{
1930 int rex = 0;
1931
1932 if (val >= 8)
1933 rex |= REX_B|REX_X|REX_R;
1934 if (flags & BITS64)
1935 rex |= REX_W;
1936 if (!(REG_HIGH & ~flags)) /* AH, CH, DH, BH */
1937 rex |= REX_H;
1938 else if (!(REG8 & ~flags) && val >= 4) /* SPL, BPL, SIL, DIL */
1939 rex |= REX_P;
1940
1941 return rex & mask;
1942}
1943
H. Peter Anvin23595f52009-07-25 17:44:25 -07001944static enum match_result find_match(const struct itemplate **tempp,
1945 insn *instruction,
1946 int32_t segment, int64_t offset, int bits)
1947{
1948 const struct itemplate *temp;
1949 enum match_result m, merr;
H. Peter Anvina7643f42009-10-13 12:32:20 -07001950 opflags_t xsizeflags[MAX_OPERANDS];
H. Peter Anvina81655b2009-07-25 18:15:28 -07001951 bool opsizemissing = false;
1952 int i;
1953
1954 for (i = 0; i < instruction->operands; i++)
1955 xsizeflags[i] = instruction->oprs[i].type & SIZE_MASK;
H. Peter Anvin23595f52009-07-25 17:44:25 -07001956
1957 merr = MERR_INVALOP;
1958
1959 for (temp = nasm_instructions[instruction->opcode];
1960 temp->opcode != I_none; temp++) {
1961 m = matches(temp, instruction, bits);
1962 if (m == MOK_JUMP) {
1963 if (jmp_match(segment, offset, bits, instruction, temp->code))
1964 m = MOK_GOOD;
1965 else
1966 m = MERR_INVALOP;
H. Peter Anvina81655b2009-07-25 18:15:28 -07001967 } else if (m == MERR_OPSIZEMISSING &&
1968 (temp->flags & IF_SMASK) != IF_SX) {
1969 /*
1970 * Missing operand size and a candidate for fuzzy matching...
1971 */
H. Peter Anvinff5d6562009-10-05 14:08:05 -07001972 for (i = 0; i < temp->operands; i++) {
1973 if ((temp->opd[i] & SAME_AS) == 0)
1974 xsizeflags[i] |= temp->opd[i] & SIZE_MASK;
1975 }
H. Peter Anvina81655b2009-07-25 18:15:28 -07001976 opsizemissing = true;
1977 }
1978 if (m > merr)
1979 merr = m;
1980 if (merr == MOK_GOOD)
1981 goto done;
1982 }
1983
1984 /* No match, but see if we can get a fuzzy operand size match... */
1985 if (!opsizemissing)
1986 goto done;
1987
1988 for (i = 0; i < instruction->operands; i++) {
H. Peter Anvinff5d6562009-10-05 14:08:05 -07001989 /*
1990 * We ignore extrinsic operand sizes on registers, so we should
1991 * never try to fuzzy-match on them. This also resolves the case
1992 * when we have e.g. "xmmrm128" in two different positions.
1993 */
Cyrill Gorcunov8a6345c2009-10-13 19:05:31 +04001994 if (is_class(REGISTER, instruction->oprs[i].type))
H. Peter Anvinff5d6562009-10-05 14:08:05 -07001995 continue;
1996
H. Peter Anvina81655b2009-07-25 18:15:28 -07001997 /* This tests if xsizeflags[i] has more than one bit set */
1998 if ((xsizeflags[i] & (xsizeflags[i]-1)))
1999 goto done; /* No luck */
2000
2001 instruction->oprs[i].type |= xsizeflags[i]; /* Set the size */
2002 }
2003
2004 /* Try matching again... */
2005 for (temp = nasm_instructions[instruction->opcode];
2006 temp->opcode != I_none; temp++) {
2007 m = matches(temp, instruction, bits);
2008 if (m == MOK_JUMP) {
2009 if (jmp_match(segment, offset, bits, instruction, temp->code))
2010 m = MOK_GOOD;
2011 else
2012 m = MERR_INVALOP;
H. Peter Anvin23595f52009-07-25 17:44:25 -07002013 }
2014 if (m > merr)
2015 merr = m;
2016 if (merr == MOK_GOOD)
H. Peter Anvina81655b2009-07-25 18:15:28 -07002017 goto done;
H. Peter Anvin23595f52009-07-25 17:44:25 -07002018 }
2019
H. Peter Anvina81655b2009-07-25 18:15:28 -07002020done:
H. Peter Anvin23595f52009-07-25 17:44:25 -07002021 *tempp = temp;
2022 return merr;
2023}
2024
H. Peter Anvin65289e82009-07-25 17:25:11 -07002025static enum match_result matches(const struct itemplate *itemp,
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002026 insn *instruction, int bits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002027{
H. Peter Anvin60926242009-07-26 16:25:38 -07002028 int i, size[MAX_OPERANDS], asize, oprs;
H. Peter Anvin3fb86f22009-07-25 19:12:10 -07002029 bool opsizemissing = false;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002030
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002031 /*
2032 * Check the opcode
2033 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002034 if (itemp->opcode != instruction->opcode)
H. Peter Anvin65289e82009-07-25 17:25:11 -07002035 return MERR_INVALOP;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002036
2037 /*
2038 * Count the operands
2039 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002040 if (itemp->operands != instruction->operands)
H. Peter Anvin65289e82009-07-25 17:25:11 -07002041 return MERR_INVALOP;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002042
2043 /*
2044 * Check that no spurious colons or TOs are present
2045 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002046 for (i = 0; i < itemp->operands; i++)
2047 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON | TO))
H. Peter Anvin65289e82009-07-25 17:25:11 -07002048 return MERR_INVALOP;
H. Peter Anvin70653092007-10-19 14:42:29 -07002049
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002050 /*
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002051 * Process size flags
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002052 */
H. Peter Anvin60926242009-07-26 16:25:38 -07002053 switch (itemp->flags & IF_SMASK) {
2054 case IF_SB:
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002055 asize = BITS8;
2056 break;
H. Peter Anvin60926242009-07-26 16:25:38 -07002057 case IF_SW:
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002058 asize = BITS16;
2059 break;
H. Peter Anvin60926242009-07-26 16:25:38 -07002060 case IF_SD:
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002061 asize = BITS32;
2062 break;
H. Peter Anvin60926242009-07-26 16:25:38 -07002063 case IF_SQ:
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002064 asize = BITS64;
2065 break;
H. Peter Anvin60926242009-07-26 16:25:38 -07002066 case IF_SO:
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002067 asize = BITS128;
2068 break;
H. Peter Anvin60926242009-07-26 16:25:38 -07002069 case IF_SY:
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002070 asize = BITS256;
2071 break;
H. Peter Anvin60926242009-07-26 16:25:38 -07002072 case IF_SZ:
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002073 switch (bits) {
2074 case 16:
2075 asize = BITS16;
2076 break;
2077 case 32:
2078 asize = BITS32;
2079 break;
2080 case 64:
2081 asize = BITS64;
2082 break;
2083 default:
2084 asize = 0;
2085 break;
2086 }
2087 break;
H. Peter Anvin60926242009-07-26 16:25:38 -07002088 default:
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002089 asize = 0;
2090 break;
H. Peter Anvin60926242009-07-26 16:25:38 -07002091 }
2092
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002093 if (itemp->flags & IF_ARMASK) {
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002094 /* S- flags only apply to a specific operand */
2095 i = ((itemp->flags & IF_ARMASK) >> IF_ARSHFT) - 1;
2096 memset(size, 0, sizeof size);
2097 size[i] = asize;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002098 } else {
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002099 /* S- flags apply to all operands */
2100 for (i = 0; i < MAX_OPERANDS; i++)
2101 size[i] = asize;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002102 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002103
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002104 /*
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002105 * Check that the operand flags all match up,
2106 * it's a bit tricky so lets be verbose:
2107 *
2108 * 1) Find out the size of operand. If instruction
2109 * doesn't have one specified -- we're trying to
2110 * guess it either from template (IF_S* flag) or
2111 * from code bits.
2112 *
2113 * 2) If template operand (i) has SAME_AS flag [used for registers only]
2114 * (ie the same operand as was specified somewhere in template, and
2115 * this referred operand index is being achieved via ~SAME_AS)
2116 * we are to be sure that both registers (in template and instruction)
2117 * do exactly match.
2118 *
2119 * 3) If template operand do not match the instruction OR
2120 * template has an operand size specified AND this size differ
2121 * from which instruction has (perhaps we got it from code bits)
2122 * we are:
2123 * a) Check that only size of instruction and operand is differ
2124 * other characteristics do match
2125 * b) Perhaps it's a register specified in instruction so
2126 * for such a case we just mark that operand as "size
2127 * missing" and this will turn on fuzzy operand size
2128 * logic facility (handled by a caller)
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002129 */
2130 for (i = 0; i < itemp->operands; i++) {
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002131 opflags_t type = instruction->oprs[i].type;
2132 if (!(type & SIZE_MASK))
2133 type |= size[i];
H. Peter Anvind85d2502008-05-04 17:53:31 -07002134
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002135 if (itemp->opd[i] & SAME_AS) {
2136 int j = itemp->opd[i] & ~SAME_AS;
2137 if (type != instruction->oprs[j].type ||
2138 instruction->oprs[i].basereg != instruction->oprs[j].basereg)
2139 return MERR_INVALOP;
2140 } else if (itemp->opd[i] & ~type ||
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002141 ((itemp->opd[i] & SIZE_MASK) &&
2142 ((itemp->opd[i] ^ type) & SIZE_MASK))) {
H. Peter Anvinff5d6562009-10-05 14:08:05 -07002143 if ((itemp->opd[i] & ~type & ~SIZE_MASK) || (type & SIZE_MASK)) {
H. Peter Anvin65289e82009-07-25 17:25:11 -07002144 return MERR_INVALOP;
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002145 } else if (!is_class(REGISTER, type)) {
2146 /*
2147 * Note: we don't honor extrinsic operand sizes for registers,
2148 * so "missing operand size" for a register should be
2149 * considered a wildcard match rather than an error.
2150 */
2151 opsizemissing = true;
2152 }
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002153 }
2154 }
2155
H. Peter Anvin3fb86f22009-07-25 19:12:10 -07002156 if (opsizemissing)
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002157 return MERR_OPSIZEMISSING;
H. Peter Anvin3fb86f22009-07-25 19:12:10 -07002158
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002159 /*
2160 * Check operand sizes
2161 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002162 if (itemp->flags & (IF_SM | IF_SM2)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002163 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002164 for (i = 0; i < oprs; i++) {
Cyrill Gorcunovbc31bee2009-11-01 23:16:01 +03002165 asize = itemp->opd[i] & SIZE_MASK;
2166 if (asize) {
2167 for (i = 0; i < oprs; i++)
2168 size[i] = asize;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002169 break;
2170 }
2171 }
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002172 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002173 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002174 }
2175
Keith Kaniosb7a89542007-04-12 02:40:54 +00002176 for (i = 0; i < itemp->operands; i++) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002177 if (!(itemp->opd[i] & SIZE_MASK) &&
2178 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvin65289e82009-07-25 17:25:11 -07002179 return MERR_OPSIZEMISMATCH;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002180 }
2181
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002182 /*
2183 * Check template is okay at the set cpu level
2184 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002185 if (((itemp->flags & IF_PLEVEL) > cpu))
H. Peter Anvin65289e82009-07-25 17:25:11 -07002186 return MERR_BADCPU;
H. Peter Anvin70653092007-10-19 14:42:29 -07002187
Keith Kaniosb7a89542007-04-12 02:40:54 +00002188 /*
H. Peter Anvin6cda4142008-12-29 20:52:28 -08002189 * Verify the appropriate long mode flag.
Keith Kaniosb7a89542007-04-12 02:40:54 +00002190 */
H. Peter Anvin6cda4142008-12-29 20:52:28 -08002191 if ((itemp->flags & (bits == 64 ? IF_NOLONG : IF_LONG)))
H. Peter Anvin65289e82009-07-25 17:25:11 -07002192 return MERR_BADMODE;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002193
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002194 /*
2195 * Check if special handling needed for Jumps
2196 */
H. Peter Anvin60926242009-07-26 16:25:38 -07002197 if ((itemp->code[0] & 0374) == 0370)
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002198 return MOK_JUMP;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002199
H. Peter Anvin60926242009-07-26 16:25:38 -07002200 return MOK_GOOD;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002201}
2202
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002203static ea *process_ea(operand * input, ea * output, int bits,
H. Peter Anvinf8563f72009-10-13 12:28:14 -07002204 int addrbits, int rfield, opflags_t rflags)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002205{
H. Peter Anvinab5bd052010-07-25 12:43:30 -07002206 bool forw_ref = !!(input->opflags & OPFLAG_UNKNOWN);
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07002207
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002208 output->rip = false;
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00002209
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002210 /* REX flags for the rfield operand */
2211 output->rex |= rexflags(rfield, rflags, REX_R|REX_P|REX_W|REX_H);
2212
Cyrill Gorcunov8a6345c2009-10-13 19:05:31 +04002213 if (is_class(REGISTER, input->type)) { /* register direct */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002214 int i;
H. Peter Anvinf8563f72009-10-13 12:28:14 -07002215 opflags_t f;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002216
Cyrill Gorcunov2124b7b2010-07-25 01:16:33 +04002217 if (!is_register(input->basereg))
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;
H. Peter Anvinab5bd052010-07-25 12:43:30 -07002266 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
Cyrill Gorcunov2124b7b2010-07-25 01:16:33 +04002274 if (is_register(i)) {
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
Cyrill Gorcunov2124b7b2010-07-25 01:16:33 +04002282 if (is_register(b)) {
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. */
H. Peter Anvinab5bd052010-07-25 12:43:30 -07002294 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);
H. Peter Anvinab5bd052010-07-25 12:43:30 -07002364 if (rm != REG_NUM_EBP && o == 0 &&
2365 seg == NO_SEG && !forw_ref &&
2366 !(input->eaflags &
2367 (EAF_BYTEOFFS | EAF_WORDOFFS)))
Keith Kaniosb7a89542007-04-12 02:40:54 +00002368 mod = 0;
H. Peter Anvinab5bd052010-07-25 12:43:30 -07002369 else if (input->eaflags & EAF_BYTEOFFS ||
2370 (o >= -128 && o <= 127 && seg == NO_SEG
2371 && !forw_ref
2372 && !(input->eaflags & EAF_WORDOFFS)))
Keith Kaniosb7a89542007-04-12 02:40:54 +00002373 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);
H. Peter Anvinab5bd052010-07-25 12:43:30 -07002412 if (base != REG_NUM_EBP && o == 0 &&
2413 seg == NO_SEG && !forw_ref &&
2414 !(input->eaflags &
2415 (EAF_BYTEOFFS | EAF_WORDOFFS)))
Keith Kaniosb7a89542007-04-12 02:40:54 +00002416 mod = 0;
H. Peter Anvinab5bd052010-07-25 12:43:30 -07002417 else if (input->eaflags & EAF_BYTEOFFS ||
2418 (o >= -128 && o <= 127 && seg == NO_SEG
2419 && !forw_ref
2420 && !(input->eaflags & EAF_WORDOFFS)))
Keith Kaniosb7a89542007-04-12 02:40:54 +00002421 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;
H. Peter Anvinab5bd052010-07-25 12:43:30 -07002433 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 Anvinab5bd052010-07-25 12:43:30 -07002503 if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
2504 !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
H. Peter Anvine2c80182005-01-15 22:15:51 +00002505 mod = 0;
H. Peter Anvinab5bd052010-07-25 12:43:30 -07002506 else if (input->eaflags & EAF_BYTEOFFS ||
2507 (o >= -128 && o <= 127 && seg == NO_SEG
2508 && !forw_ref
2509 && !(input->eaflags & EAF_WORDOFFS)))
H. Peter Anvine2c80182005-01-15 22:15:51 +00002510 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 */
Cyrill Gorcunov2124b7b2010-07-25 01:16:33 +04002554 if (!is_register(ins->oprs[j].indexreg))
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002555 i = 0;
2556 else
H. Peter Anvina4835d42008-05-20 14:21:29 -07002557 i = nasm_reg_flags[ins->oprs[j].indexreg];
H. Peter Anvin70653092007-10-19 14:42:29 -07002558
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002559 /* Verify as Register */
Cyrill Gorcunov2124b7b2010-07-25 01:16:33 +04002560 if (!is_register(ins->oprs[j].basereg))
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002561 b = 0;
2562 else
H. Peter Anvina4835d42008-05-20 14:21:29 -07002563 b = nasm_reg_flags[ins->oprs[j].basereg];
H. Peter Anvin70653092007-10-19 14:42:29 -07002564
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002565 if (ins->oprs[j].scale == 0)
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002566 i = 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002567
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002568 if (!i && !b) {
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002569 int ds = ins->oprs[j].disp_size;
2570 if ((addrbits != 64 && ds > 8) ||
2571 (addrbits == 64 && ds == 16))
2572 valid &= ds;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002573 } else {
2574 if (!(REG16 & ~b))
2575 valid &= 16;
2576 if (!(REG32 & ~b))
2577 valid &= 32;
2578 if (!(REG64 & ~b))
2579 valid &= 64;
H. Peter Anvin70653092007-10-19 14:42:29 -07002580
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002581 if (!(REG16 & ~i))
2582 valid &= 16;
2583 if (!(REG32 & ~i))
2584 valid &= 32;
2585 if (!(REG64 & ~i))
2586 valid &= 64;
2587 }
2588 }
2589 }
2590
2591 if (valid & addrbits) {
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002592 ins->addr_size = addrbits;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002593 } else if (valid & ((addrbits == 32) ? 16 : 32)) {
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002594 /* Add an address size prefix */
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002595 enum prefixes pref = (addrbits == 32) ? P_A16 : P_A32;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002596 ins->prefixes[PPS_ASIZE] = pref;
2597 ins->addr_size = (addrbits == 32) ? 16 : 32;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002598 } else {
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002599 /* Impossible... */
2600 errfunc(ERR_NONFATAL, "impossible combination of address sizes");
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002601 ins->addr_size = addrbits; /* Error recovery */
2602 }
2603
2604 defdisp = ins->addr_size == 16 ? 16 : 32;
2605
2606 for (j = 0; j < ins->operands; j++) {
2607 if (!(MEM_OFFS & ~ins->oprs[j].type) &&
2608 (ins->oprs[j].disp_size ? ins->oprs[j].disp_size : defdisp)
2609 != ins->addr_size) {
2610 /* mem_offs sizes must match the address size; if not,
2611 strip the MEM_OFFS bit and match only EA instructions */
2612 ins->oprs[j].type &= ~(MEM_OFFS & ~MEMORY);
2613 }
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002614 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002615}