blob: 66acb843f1948931f1985891cc2b22bcdb6cc50a [file] [log] [blame]
H. Peter Anvin9e6747c2009-06-28 17:13:04 -07001/* ----------------------------------------------------------------------- *
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002 *
H. Peter Anvin4ecd5d72012-02-24 21:51:46 -08003 * Copyright 1996-2012 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.)
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +040039 * \1..\4 - that many literal bytes follow in the code stream
H. Peter Anvindcffe4b2008-10-10 22:10:31 -070040 * \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]
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +040053 * 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
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +040065 * 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
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +040068 * is a signed byte rather than a dword. Opcode byte follows.
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +040069 * \172\ab - the register number from operand a in bits 7..4, with
H. Peter Anvin52dc3532008-05-20 19:29:04 -070070 * the 4-bit immediate from operand b in bits 3..0.
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +040071 * \173\xab - the register number from operand a in bits 7..4, with
72 * the value b in bits 3..0.
H. Peter Anvincffe61e2011-07-07 17:21:24 -070073 * \174..\177 - the register number from operand 0..3 in bits 7..4, and
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +040074 * an arbitrary value in bits 3..0 (assembled as zero.)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000075 * \2ab - a ModRM, calculated on EA in operand a, with the spare
76 * field equal to digit b.
H. Peter Anvin32cd4c22008-04-04 13:34:53 -070077 * \250..\253 - same as \150..\153, except warn if the 64-bit operand
78 * is not equal to the truncated and sign-extended 32-bit
79 * operand; used for 32-bit immediates in 64-bit mode.
H. Peter Anvin588df782008-10-07 10:05:10 -070080 * \254..\257 - a signed 32-bit operand to be extended to 64 bits.
H. Peter Anvina04019c2009-05-03 21:42:34 -070081 * \260..\263 - this instruction uses VEX/XOP rather than REX, with the
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +040082 * V field taken from operand 0..3.
83 * \270 - this instruction uses VEX/XOP rather than REX, with the
84 * V field set to 1111b.
H. Peter Anvind85d2502008-05-04 17:53:31 -070085 *
H. Peter Anvina04019c2009-05-03 21:42:34 -070086 * VEX/XOP prefixes are followed by the sequence:
87 * \tmm\wlp where mm is the M field; and wlp is:
H. Peter Anvin421059c2010-08-16 14:56:33 -070088 * 00 wwl lpp
89 * [l0] ll = 0 for L = 0 (.128, .lz)
90 * [l1] ll = 1 for L = 1 (.256)
91 * [lig] ll = 2 for L don't care (always assembled as 0)
92 *
H. Peter Anvin978c2172010-08-16 13:48:43 -070093 * [w0] ww = 0 for W = 0
94 * [w1 ] ww = 1 for W = 1
95 * [wig] ww = 2 for W don't care (always assembled as 0)
96 * [ww] ww = 3 for W used as REX.W
H. Peter Anvinbd420c72008-05-22 11:24:35 -070097 *
H. Peter Anvina04019c2009-05-03 21:42:34 -070098 * t = 0 for VEX (C4/C5), t = 1 for XOP (8F).
H. Peter Anvind85d2502008-05-04 17:53:31 -070099 *
H. Peter Anvin574784d2012-02-25 22:33:46 -0800100 * \271 - instruction takes XRELEASE (F3) with or without lock
101 * \272 - instruction takes XACQUIRE/XRELEASE with or without lock
102 * \273 - instruction takes XACQUIRE/XRELEASE with lock only
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.
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400120 * \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 Anvin755f5212012-02-25 11:41:34 -0800129 * \336 - force a REP(E) prefix (0xF3) even if not specified.
130 * \337 - force a REPNE prefix (0xF2) even if not specified.
H. Peter Anvin962e3052008-08-28 17:47:16 -0700131 * \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.
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400134 * \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
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400139 * \360 - no SSE prefix (== \364\331)
H. Peter Anvinfff5a472008-05-20 09:46:24 -0700140 * \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 Anvin755f5212012-02-25 11:41:34 -0800147 * \370,\371 - match only if operand 0 meets byte jump criteria.
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400148 * 370 is used for Jcc, 371 is used for JMP.
149 * \373 - assemble 0x03 if bits==16, 0x05 if bits==32;
150 * used for conditional jump over longer jump
H. Peter Anvin3089f7e2011-06-22 18:19:28 -0700151 * \374 - this instruction takes an XMM VSIB memory EA
152 * \375 - this instruction takes an YMM VSIB memory EA
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000153 */
154
H. Peter Anvinfe501952007-10-02 21:53:51 -0700155#include "compiler.h"
156
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000157#include <stdio.h>
158#include <string.h>
Keith Kaniosb7a89542007-04-12 02:40:54 +0000159#include <inttypes.h>
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000160
161#include "nasm.h"
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000162#include "nasmlib.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000163#include "assemble.h"
164#include "insns.h"
H. Peter Anvina4835d42008-05-20 14:21:29 -0700165#include "tables.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000166
H. Peter Anvin65289e82009-07-25 17:25:11 -0700167enum match_result {
168 /*
169 * Matching errors. These should be sorted so that more specific
170 * errors come later in the sequence.
171 */
172 MERR_INVALOP,
173 MERR_OPSIZEMISSING,
174 MERR_OPSIZEMISMATCH,
175 MERR_BADCPU,
176 MERR_BADMODE,
H. Peter Anvinfb3f4e62012-02-25 22:22:07 -0800177 MERR_BADHLE,
H. Peter Anvin65289e82009-07-25 17:25:11 -0700178 /*
179 * Matching success; the conditional ones first
180 */
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400181 MOK_JUMP, /* Matching OK but needs jmp_match() */
182 MOK_GOOD /* Matching unconditionally OK */
H. Peter Anvin65289e82009-07-25 17:25:11 -0700183};
184
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000185typedef struct {
H. Peter Anvin3089f7e2011-06-22 18:19:28 -0700186 enum ea_type type; /* what kind of EA is this? */
187 int sib_present; /* is a SIB byte necessary? */
188 int bytes; /* # of bytes of offset needed */
189 int size; /* lazy - this is sib+bytes+1 */
190 uint8_t modrm, sib, rex, rip; /* the bytes themselves */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000191} ea;
192
Cyrill Gorcunov10734c72011-08-29 00:07:17 +0400193#define GEN_SIB(scale, index, base) \
194 (((scale) << 6) | ((index) << 3) | ((base)))
195
196#define GEN_MODRM(mod, reg, rm) \
197 (((mod) << 6) | (((reg) & 7) << 3) | ((rm) & 7))
198
Keith Kaniosb7a89542007-04-12 02:40:54 +0000199static uint32_t cpu; /* cpu level received from nasm.c */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000200static efunc errfunc;
201static struct ofmt *outfmt;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000202static ListGen *list;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000203
H. Peter Anvin8cc8a1d2012-02-25 11:11:42 -0800204static int64_t calcsize(int32_t, int64_t, int, insn *,
205 const struct itemplate *);
H. Peter Anvin833caea2008-10-04 19:02:30 -0700206static void gencode(int32_t segment, int64_t offset, int bits,
207 insn * ins, const struct itemplate *temp,
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400208 int64_t insn_end);
H. Peter Anvin23595f52009-07-25 17:44:25 -0700209static enum match_result find_match(const struct itemplate **tempp,
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400210 insn *instruction,
211 int32_t segment, int64_t offset, int bits);
H. Peter Anvin65289e82009-07-25 17:25:11 -0700212static enum match_result matches(const struct itemplate *, insn *, int bits);
H. Peter Anvinf8563f72009-10-13 12:28:14 -0700213static opflags_t regflag(const operand *);
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000214static int32_t regval(const operand *);
H. Peter Anvinf8563f72009-10-13 12:28:14 -0700215static int rexflags(int, opflags_t, int);
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000216static int op_rexflags(const operand *, int);
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700217static void add_asp(insn *, int);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000218
H. Peter Anvin3089f7e2011-06-22 18:19:28 -0700219static enum ea_type process_ea(operand *, ea *, int, int, int, opflags_t);
220
Cyrill Gorcunov18914e62011-11-12 11:41:51 +0400221static int has_prefix(insn * ins, enum prefix_pos pos, int prefix)
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000222{
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700223 return ins->prefixes[pos] == prefix;
224}
225
226static void assert_no_prefix(insn * ins, enum prefix_pos pos)
227{
228 if (ins->prefixes[pos])
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400229 errfunc(ERR_NONFATAL, "invalid %s prefix",
230 prefix_name(ins->prefixes[pos]));
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700231}
232
233static const char *size_name(int size)
234{
235 switch (size) {
236 case 1:
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400237 return "byte";
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700238 case 2:
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400239 return "word";
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700240 case 4:
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400241 return "dword";
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700242 case 8:
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400243 return "qword";
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700244 case 10:
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400245 return "tword";
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700246 case 16:
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400247 return "oword";
H. Peter Anvindfb91802008-05-20 11:43:53 -0700248 case 32:
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400249 return "yword";
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700250 default:
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400251 return "???";
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000252 }
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700253}
254
Cyrill Gorcunov9ccabd22009-09-21 00:56:20 +0400255static void warn_overflow(int pass, int size)
256{
257 errfunc(ERR_WARNING | pass | ERR_WARN_NOV,
258 "%s data exceeds bounds", size_name(size));
259}
260
261static void warn_overflow_const(int64_t data, int size)
262{
263 if (overflow_general(data, size))
264 warn_overflow(ERR_PASS1, size);
265}
266
267static void warn_overflow_opd(const struct operand *o, int size)
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700268{
Victor van den Elzen0d268fb2010-01-24 21:24:57 +0100269 if (o->wrt == NO_SEG && o->segment == NO_SEG) {
Cyrill Gorcunov9ccabd22009-09-21 00:56:20 +0400270 if (overflow_general(o->offset, size))
271 warn_overflow(ERR_PASS2, size);
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700272 }
273}
Cyrill Gorcunov9ccabd22009-09-21 00:56:20 +0400274
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000275/*
276 * This routine wrappers the real output format's output routine,
277 * in order to pass a copy of the data off to the listing file
278 * generator at the same time.
279 */
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800280static void out(int64_t offset, int32_t segto, const void *data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800281 enum out_type type, uint64_t size,
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400282 int32_t segment, int32_t wrt)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000283{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000284 static int32_t lineno = 0; /* static!!! */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000285 static char *lnfname = NULL;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800286 uint8_t p[8];
H. Peter Anvineba20a72002-04-30 20:53:55 +0000287
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800288 if (type == OUT_ADDRESS && segment == NO_SEG && wrt == NO_SEG) {
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400289 /*
290 * This is a non-relocated address, and we're going to
291 * convert it into RAWDATA format.
292 */
293 uint8_t *q = p;
H. Peter Anvind1fb15c2007-11-13 09:37:59 -0800294
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400295 if (size > 8) {
296 errfunc(ERR_PANIC, "OUT_ADDRESS with size > 8");
297 return;
298 }
H. Peter Anvind85d2502008-05-04 17:53:31 -0700299
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400300 WRITEADDR(q, *(int64_t *)data, size);
301 data = p;
302 type = OUT_RAWDATA;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000303 }
304
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800305 list->output(offset, data, type, size);
306
Frank Kotlerabebb082003-09-06 04:45:37 +0000307 /*
308 * this call to src_get determines when we call the
309 * debug-format-specific "linenum" function
310 * it updates lineno and lnfname to the current values
311 * returning 0 if "same as last time", -2 if lnfname
312 * changed, and the amount by which lineno changed,
313 * if it did. thus, these variables must be static
314 */
315
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400316 if (src_get(&lineno, &lnfname))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000317 outfmt->current_dfmt->linenum(lnfname, lineno, segto);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000318
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800319 outfmt->output(segto, data, type, size, segment, wrt);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000320}
321
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700322static bool jmp_match(int32_t segment, int64_t offset, int bits,
H. Peter Anvin8cc8a1d2012-02-25 11:11:42 -0800323 insn * ins, const struct itemplate *temp)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000324{
Charles Crayne5fbbc8c2007-11-07 19:03:46 -0800325 int64_t isize;
H. Peter Anvin8cc8a1d2012-02-25 11:11:42 -0800326 const uint8_t *code = temp->code;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000327 uint8_t c = code[0];
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000328
H. Peter Anvin755f5212012-02-25 11:41:34 -0800329 if (((c & ~1) != 0370) || (ins->oprs[0].type & STRICT))
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700330 return false;
331 if (!optimizing)
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400332 return false;
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700333 if (optimizing < 0 && c == 0371)
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400334 return false;
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700335
H. Peter Anvin8cc8a1d2012-02-25 11:11:42 -0800336 isize = calcsize(segment, offset, bits, ins, temp);
Victor van den Elzenccafc3c2009-02-23 04:35:00 +0100337
Victor van den Elzen154e5922009-02-25 17:32:00 +0100338 if (ins->oprs[0].opflags & OPFLAG_UNKNOWN)
Victor van den Elzenccafc3c2009-02-23 04:35:00 +0100339 /* Be optimistic in pass 1 */
340 return true;
341
H. Peter Anvine2c80182005-01-15 22:15:51 +0000342 if (ins->oprs[0].segment != segment)
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700343 return false;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000344
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700345 isize = ins->oprs[0].offset - offset - isize; /* isize is delta */
346 return (isize >= -128 && isize <= 127); /* is it byte size? */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000347}
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000348
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800349int64_t assemble(int32_t segment, int64_t offset, int bits, uint32_t cp,
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400350 insn * instruction, struct ofmt *output, efunc error,
351 ListGen * listgen)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000352{
H. Peter Anvin3360d792007-09-11 04:16:57 +0000353 const struct itemplate *temp;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000354 int j;
H. Peter Anvin23595f52009-07-25 17:44:25 -0700355 enum match_result m;
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800356 int64_t insn_end;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000357 int32_t itimes;
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800358 int64_t start = offset;
Cyrill Gorcunovbafd8772009-10-31 20:02:14 +0300359 int64_t wsize; /* size for DB etc. */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000360
H. Peter Anvine2c80182005-01-15 22:15:51 +0000361 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000362 cpu = cp;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000363 outfmt = output; /* likewise */
364 list = listgen; /* and again */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000365
Cyrill Gorcunovbafd8772009-10-31 20:02:14 +0300366 wsize = idata_bytes(instruction->opcode);
367 if (wsize == -1)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000368 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000369
H. Peter Anvineba20a72002-04-30 20:53:55 +0000370 if (wsize) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000371 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000372 int32_t t = instruction->times;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000373 if (t < 0)
374 errfunc(ERR_PANIC,
375 "instruction->times < 0 (%ld) in assemble()", t);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000376
H. Peter Anvine2c80182005-01-15 22:15:51 +0000377 while (t--) { /* repeat TIMES times */
Cyrill Gorcunova92a3a52009-07-27 22:33:59 +0400378 list_for_each(e, instruction->eops) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000379 if (e->type == EOT_DB_NUMBER) {
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400380 if (wsize > 8) {
H. Peter Anvin3be5d852008-05-20 14:49:32 -0700381 errfunc(ERR_NONFATAL,
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400382 "integer supplied to a DT, DO or DY"
Keith Kanios61ff53c2007-04-14 18:54:52 +0000383 " instruction");
H. Peter Anvin55ae1202010-05-06 15:25:43 -0700384 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000385 out(offset, segment, &e->offset,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800386 OUT_ADDRESS, wsize, e->segment, e->wrt);
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400387 offset += wsize;
388 }
H. Peter Anvin518df302008-06-14 16:53:48 -0700389 } else if (e->type == EOT_DB_STRING ||
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400390 e->type == EOT_DB_STRING_FREE) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000391 int align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000392
H. Peter Anvine2c80182005-01-15 22:15:51 +0000393 out(offset, segment, e->stringval,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800394 OUT_RAWDATA, e->stringlen, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000395 align = e->stringlen % wsize;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000396
H. Peter Anvine2c80182005-01-15 22:15:51 +0000397 if (align) {
398 align = wsize - align;
H. Peter Anvin999868f2009-02-09 11:03:33 +0100399 out(offset, segment, zero_buffer,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800400 OUT_RAWDATA, align, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000401 }
402 offset += e->stringlen + align;
403 }
404 }
405 if (t > 0 && t == instruction->times - 1) {
406 /*
407 * Dummy call to list->output to give the offset to the
408 * listing module.
409 */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800410 list->output(offset, NULL, OUT_RAWDATA, 0);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000411 list->uplevel(LIST_TIMES);
412 }
413 }
414 if (instruction->times > 1)
415 list->downlevel(LIST_TIMES);
416 return offset - start;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000417 }
418
H. Peter Anvine2c80182005-01-15 22:15:51 +0000419 if (instruction->opcode == I_INCBIN) {
H. Peter Anvin518df302008-06-14 16:53:48 -0700420 const char *fname = instruction->eops->stringval;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000421 FILE *fp;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000422
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400423 fp = fopen(fname, "rb");
424 if (!fp) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000425 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
426 fname);
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400427 } else if (fseek(fp, 0L, SEEK_END) < 0) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000428 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
429 fname);
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400430 } else {
H. Peter Anvin518df302008-06-14 16:53:48 -0700431 static char buf[4096];
432 size_t t = instruction->times;
433 size_t base = 0;
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400434 size_t len;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000435
H. Peter Anvine2c80182005-01-15 22:15:51 +0000436 len = ftell(fp);
437 if (instruction->eops->next) {
438 base = instruction->eops->next->offset;
439 len -= base;
440 if (instruction->eops->next->next &&
H. Peter Anvin518df302008-06-14 16:53:48 -0700441 len > (size_t)instruction->eops->next->next->offset)
442 len = (size_t)instruction->eops->next->next->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000443 }
444 /*
445 * Dummy call to list->output to give the offset to the
446 * listing module.
447 */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800448 list->output(offset, NULL, OUT_RAWDATA, 0);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000449 list->uplevel(LIST_INCBIN);
450 while (t--) {
H. Peter Anvin518df302008-06-14 16:53:48 -0700451 size_t l;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000452
H. Peter Anvine2c80182005-01-15 22:15:51 +0000453 fseek(fp, base, SEEK_SET);
454 l = len;
455 while (l > 0) {
H. Peter Anvin4a5a6df2009-06-27 16:14:18 -0700456 int32_t m;
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400457 m = fread(buf, 1, l > sizeof(buf) ? sizeof(buf) : l, fp);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000458 if (!m) {
459 /*
460 * This shouldn't happen unless the file
461 * actually changes while we are reading
462 * it.
463 */
464 error(ERR_NONFATAL,
465 "`incbin': unexpected EOF while"
466 " reading file `%s'", fname);
467 t = 0; /* Try to exit cleanly */
468 break;
469 }
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800470 out(offset, segment, buf, OUT_RAWDATA, m,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000471 NO_SEG, NO_SEG);
472 l -= m;
473 }
474 }
475 list->downlevel(LIST_INCBIN);
476 if (instruction->times > 1) {
477 /*
478 * Dummy call to list->output to give the offset to the
479 * listing module.
480 */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800481 list->output(offset, NULL, OUT_RAWDATA, 0);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000482 list->uplevel(LIST_TIMES);
483 list->downlevel(LIST_TIMES);
484 }
485 fclose(fp);
486 return instruction->times * len;
487 }
488 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000489 }
490
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700491 /* Check to see if we need an address-size prefix */
492 add_asp(instruction, bits);
493
H. Peter Anvin23595f52009-07-25 17:44:25 -0700494 m = find_match(&temp, instruction, segment, offset, bits);
H. Peter Anvin70653092007-10-19 14:42:29 -0700495
H. Peter Anvin23595f52009-07-25 17:44:25 -0700496 if (m == MOK_GOOD) {
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400497 /* Matches! */
H. Peter Anvin8cc8a1d2012-02-25 11:11:42 -0800498 int64_t insn_size = calcsize(segment, offset, bits, instruction, temp);
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400499 itimes = instruction->times;
500 if (insn_size < 0) /* shouldn't be, on pass two */
501 error(ERR_PANIC, "errors made it through from pass one");
502 else
503 while (itimes--) {
504 for (j = 0; j < MAXPREFIX; j++) {
505 uint8_t c = 0;
506 switch (instruction->prefixes[j]) {
507 case P_WAIT:
508 c = 0x9B;
509 break;
510 case P_LOCK:
511 c = 0xF0;
512 break;
513 case P_REPNE:
514 case P_REPNZ:
H. Peter Anvin4ecd5d72012-02-24 21:51:46 -0800515 case P_XACQUIRE:
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400516 c = 0xF2;
517 break;
518 case P_REPE:
519 case P_REPZ:
520 case P_REP:
H. Peter Anvin4ecd5d72012-02-24 21:51:46 -0800521 case P_XRELEASE:
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400522 c = 0xF3;
523 break;
524 case R_CS:
525 if (bits == 64) {
526 error(ERR_WARNING | ERR_PASS2,
527 "cs segment base generated, but will be ignored in 64-bit mode");
528 }
529 c = 0x2E;
530 break;
531 case R_DS:
532 if (bits == 64) {
533 error(ERR_WARNING | ERR_PASS2,
534 "ds segment base generated, but will be ignored in 64-bit mode");
535 }
536 c = 0x3E;
537 break;
538 case R_ES:
539 if (bits == 64) {
540 error(ERR_WARNING | ERR_PASS2,
541 "es segment base generated, but will be ignored in 64-bit mode");
542 }
543 c = 0x26;
544 break;
545 case R_FS:
546 c = 0x64;
547 break;
548 case R_GS:
549 c = 0x65;
550 break;
551 case R_SS:
552 if (bits == 64) {
553 error(ERR_WARNING | ERR_PASS2,
554 "ss segment base generated, but will be ignored in 64-bit mode");
555 }
556 c = 0x36;
557 break;
558 case R_SEGR6:
559 case R_SEGR7:
560 error(ERR_NONFATAL,
561 "segr6 and segr7 cannot be used as prefixes");
562 break;
563 case P_A16:
564 if (bits == 64) {
565 error(ERR_NONFATAL,
566 "16-bit addressing is not supported "
567 "in 64-bit mode");
568 } else if (bits != 16)
569 c = 0x67;
570 break;
571 case P_A32:
572 if (bits != 32)
573 c = 0x67;
574 break;
575 case P_A64:
576 if (bits != 64) {
577 error(ERR_NONFATAL,
578 "64-bit addressing is only supported "
579 "in 64-bit mode");
580 }
581 break;
582 case P_ASP:
583 c = 0x67;
584 break;
585 case P_O16:
586 if (bits != 16)
587 c = 0x66;
588 break;
589 case P_O32:
590 if (bits == 16)
591 c = 0x66;
592 break;
593 case P_O64:
594 /* REX.W */
595 break;
596 case P_OSP:
597 c = 0x66;
598 break;
599 case P_none:
600 break;
601 default:
602 error(ERR_PANIC, "invalid instruction prefix");
603 }
604 if (c != 0) {
605 out(offset, segment, &c, OUT_RAWDATA, 1,
606 NO_SEG, NO_SEG);
607 offset++;
608 }
609 }
610 insn_end = offset + insn_size;
611 gencode(segment, offset, bits, instruction,
612 temp, insn_end);
613 offset += insn_size;
614 if (itimes > 0 && itimes == instruction->times - 1) {
615 /*
616 * Dummy call to list->output to give the offset to the
617 * listing module.
618 */
619 list->output(offset, NULL, OUT_RAWDATA, 0);
620 list->uplevel(LIST_TIMES);
621 }
622 }
623 if (instruction->times > 1)
624 list->downlevel(LIST_TIMES);
625 return offset - start;
H. Peter Anvin23595f52009-07-25 17:44:25 -0700626 } else {
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400627 /* No match */
628 switch (m) {
629 case MERR_OPSIZEMISSING:
630 error(ERR_NONFATAL, "operation size not specified");
631 break;
632 case MERR_OPSIZEMISMATCH:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000633 error(ERR_NONFATAL, "mismatch in operand sizes");
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400634 break;
635 case MERR_BADCPU:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000636 error(ERR_NONFATAL, "no instruction for this cpu level");
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400637 break;
638 case MERR_BADMODE:
H. Peter Anvin6cda4142008-12-29 20:52:28 -0800639 error(ERR_NONFATAL, "instruction not supported in %d-bit mode",
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400640 bits);
641 break;
642 default:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000643 error(ERR_NONFATAL,
644 "invalid combination of opcode and operands");
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400645 break;
646 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000647 }
648 return 0;
649}
650
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800651int64_t insn_size(int32_t segment, int64_t offset, int bits, uint32_t cp,
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400652 insn * instruction, efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000653{
H. Peter Anvin3360d792007-09-11 04:16:57 +0000654 const struct itemplate *temp;
H. Peter Anvin23595f52009-07-25 17:44:25 -0700655 enum match_result m;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000656
H. Peter Anvine2c80182005-01-15 22:15:51 +0000657 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000658 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000659
Cyrill Gorcunov37575242009-08-16 12:00:01 +0400660 if (instruction->opcode == I_none)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000661 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000662
H. Peter Anvincfbe7c32007-09-18 17:49:09 -0700663 if (instruction->opcode == I_DB || instruction->opcode == I_DW ||
664 instruction->opcode == I_DD || instruction->opcode == I_DQ ||
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400665 instruction->opcode == I_DT || instruction->opcode == I_DO ||
666 instruction->opcode == I_DY) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000667 extop *e;
Cyrill Gorcunovbafd8772009-10-31 20:02:14 +0300668 int32_t isize, osize, wsize;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000669
H. Peter Anvine2c80182005-01-15 22:15:51 +0000670 isize = 0;
Cyrill Gorcunovbafd8772009-10-31 20:02:14 +0300671 wsize = idata_bytes(instruction->opcode);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000672
Cyrill Gorcunova92a3a52009-07-27 22:33:59 +0400673 list_for_each(e, instruction->eops) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000674 int32_t align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000675
H. Peter Anvine2c80182005-01-15 22:15:51 +0000676 osize = 0;
Cyrill Gorcunov9ccabd22009-09-21 00:56:20 +0400677 if (e->type == EOT_DB_NUMBER) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000678 osize = 1;
Cyrill Gorcunov9ccabd22009-09-21 00:56:20 +0400679 warn_overflow_const(e->offset, wsize);
680 } else if (e->type == EOT_DB_STRING ||
681 e->type == EOT_DB_STRING_FREE)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000682 osize = e->stringlen;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000683
H. Peter Anvine2c80182005-01-15 22:15:51 +0000684 align = (-osize) % wsize;
685 if (align < 0)
686 align += wsize;
687 isize += osize + align;
688 }
689 return isize * instruction->times;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000690 }
691
H. Peter Anvine2c80182005-01-15 22:15:51 +0000692 if (instruction->opcode == I_INCBIN) {
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400693 const char *fname = instruction->eops->stringval;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000694 FILE *fp;
Cyrill Gorcunov6531d6d2009-12-05 14:04:55 +0300695 int64_t val = 0;
H. Peter Anvin518df302008-06-14 16:53:48 -0700696 size_t len;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000697
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400698 fp = fopen(fname, "rb");
699 if (!fp)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000700 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
701 fname);
702 else if (fseek(fp, 0L, SEEK_END) < 0)
703 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
704 fname);
705 else {
706 len = ftell(fp);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000707 if (instruction->eops->next) {
708 len -= instruction->eops->next->offset;
709 if (instruction->eops->next->next &&
H. Peter Anvin518df302008-06-14 16:53:48 -0700710 len > (size_t)instruction->eops->next->next->offset) {
711 len = (size_t)instruction->eops->next->next->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000712 }
713 }
Cyrill Gorcunov6531d6d2009-12-05 14:04:55 +0300714 val = instruction->times * len;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000715 }
Cyrill Gorcunov6531d6d2009-12-05 14:04:55 +0300716 if (fp)
717 fclose(fp);
718 return val;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000719 }
720
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700721 /* Check to see if we need an address-size prefix */
722 add_asp(instruction, bits);
723
H. Peter Anvin23595f52009-07-25 17:44:25 -0700724 m = find_match(&temp, instruction, segment, offset, bits);
725 if (m == MOK_GOOD) {
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400726 /* we've matched an instruction. */
727 int64_t isize;
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400728 int j;
Victor van den Elzen0d268fb2010-01-24 21:24:57 +0100729
H. Peter Anvin8cc8a1d2012-02-25 11:11:42 -0800730 isize = calcsize(segment, offset, bits, instruction, temp);
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400731 if (isize < 0)
732 return -1;
733 for (j = 0; j < MAXPREFIX; j++) {
734 switch (instruction->prefixes[j]) {
735 case P_A16:
736 if (bits != 16)
737 isize++;
738 break;
739 case P_A32:
740 if (bits != 32)
741 isize++;
742 break;
743 case P_O16:
744 if (bits != 16)
745 isize++;
746 break;
747 case P_O32:
748 if (bits == 16)
749 isize++;
750 break;
751 case P_A64:
752 case P_O64:
753 case P_none:
754 break;
755 default:
756 isize++;
757 break;
758 }
759 }
760 return isize * instruction->times;
H. Peter Anvin23595f52009-07-25 17:44:25 -0700761 } else {
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400762 return -1; /* didn't match any instruction */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000763 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000764}
765
H. Peter Anvinab5bd052010-07-25 12:43:30 -0700766static bool possible_sbyte(operand *o)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000767{
H. Peter Anvinad6b8592008-10-07 09:56:38 -0700768 return o->wrt == NO_SEG && o->segment == NO_SEG &&
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400769 !(o->opflags & OPFLAG_UNKNOWN) &&
770 optimizing >= 0 && !(o->type & STRICT);
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000771}
772
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700773/* check that opn[op] is a signed byte of size 16 or 32 */
H. Peter Anvinab5bd052010-07-25 12:43:30 -0700774static bool is_sbyte16(operand *o)
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700775{
776 int16_t v;
777
H. Peter Anvinab5bd052010-07-25 12:43:30 -0700778 if (!possible_sbyte(o))
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400779 return false;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700780
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700781 v = o->offset;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700782 return v >= -128 && v <= 127;
783}
784
H. Peter Anvinab5bd052010-07-25 12:43:30 -0700785static bool is_sbyte32(operand *o)
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700786{
787 int32_t v;
788
H. Peter Anvinab5bd052010-07-25 12:43:30 -0700789 if (!possible_sbyte(o))
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400790 return false;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700791
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700792 v = o->offset;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700793 return v >= -128 && v <= 127;
794}
795
H. Peter Anvin4ecd5d72012-02-24 21:51:46 -0800796static void bad_hle_warn(const insn * ins, uint8_t hleok)
797{
798 enum prefixes rep_pfx = ins->prefixes[PPS_REP];
H. Peter Anvin8cc8a1d2012-02-25 11:11:42 -0800799 enum whatwarn { w_none, w_lock, w_inval } ww;
H. Peter Anvin4ecd5d72012-02-24 21:51:46 -0800800 static const enum whatwarn warn[2][4] =
801 {
802 { w_inval, w_inval, w_none, w_lock }, /* XACQUIRE */
803 { w_inval, w_none, w_none, w_lock }, /* XRELEASE */
804 };
805 unsigned int n;
806
807 n = (unsigned int)rep_pfx - P_XACQUIRE;
808 if (n > 1)
809 return; /* Not XACQUIRE/XRELEASE */
810
H. Peter Anvin8cc8a1d2012-02-25 11:11:42 -0800811 ww = warn[n][hleok];
812 if (!is_class(MEMORY, ins->oprs[0].type))
813 ww = w_inval; /* HLE requires operand 0 to be memory */
814
815 switch (ww) {
H. Peter Anvin4ecd5d72012-02-24 21:51:46 -0800816 case w_none:
817 break;
818
819 case w_lock:
820 if (ins->prefixes[PPS_LOCK] != P_LOCK) {
H. Peter Anvin5a24fdd2012-02-25 15:10:04 -0800821 errfunc(ERR_WARNING | ERR_WARN_HLE | ERR_PASS2,
H. Peter Anvin4ecd5d72012-02-24 21:51:46 -0800822 "%s with this instruction requires lock",
823 prefix_name(rep_pfx));
824 }
825 break;
826
827 case w_inval:
H. Peter Anvin5a24fdd2012-02-25 15:10:04 -0800828 errfunc(ERR_WARNING | ERR_WARN_HLE | ERR_PASS2,
H. Peter Anvin4ecd5d72012-02-24 21:51:46 -0800829 "%s invalid with this instruction",
830 prefix_name(rep_pfx));
831 break;
832 }
833}
834
H. Peter Anvin507ae032008-10-09 15:37:10 -0700835/* Common construct */
836#define case4(x) case (x): case (x)+1: case (x)+2: case (x)+3
837
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800838static int64_t calcsize(int32_t segment, int64_t offset, int bits,
H. Peter Anvin8cc8a1d2012-02-25 11:11:42 -0800839 insn * ins, const struct itemplate *temp)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000840{
H. Peter Anvin8cc8a1d2012-02-25 11:11:42 -0800841 const uint8_t *codes = temp->code;
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800842 int64_t length = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000843 uint8_t c;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000844 int rex_mask = ~0;
H. Peter Anvindcffe4b2008-10-10 22:10:31 -0700845 int op1, op2;
H. Peter Anvin839eca22007-10-29 23:12:47 -0700846 struct operand *opx;
H. Peter Anvindcffe4b2008-10-10 22:10:31 -0700847 uint8_t opex = 0;
H. Peter Anvin3089f7e2011-06-22 18:19:28 -0700848 enum ea_type eat;
H. Peter Anvin4ecd5d72012-02-24 21:51:46 -0800849 uint8_t hleok = 0;
H. Peter Anvin8cc8a1d2012-02-25 11:11:42 -0800850 bool lockcheck = true;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000851
H. Peter Anvine3917fc2007-11-01 14:53:32 -0700852 ins->rex = 0; /* Ensure REX is reset */
H. Peter Anvin3089f7e2011-06-22 18:19:28 -0700853 eat = EA_SCALAR; /* Expect a scalar EA */
H. Peter Anvine3917fc2007-11-01 14:53:32 -0700854
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700855 if (ins->prefixes[PPS_OSIZE] == P_O64)
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400856 ins->rex |= REX_W;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700857
H. Peter Anvine2c80182005-01-15 22:15:51 +0000858 (void)segment; /* Don't warn that this parameter is unused */
859 (void)offset; /* Don't warn that this parameter is unused */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000860
H. Peter Anvin839eca22007-10-29 23:12:47 -0700861 while (*codes) {
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400862 c = *codes++;
863 op1 = (c & 3) + ((opex & 1) << 2);
864 op2 = ((c >> 3) & 3) + ((opex & 2) << 1);
865 opx = &ins->oprs[op1];
866 opex = 0; /* For the next iteration */
H. Peter Anvindcffe4b2008-10-10 22:10:31 -0700867
H. Peter Anvin839eca22007-10-29 23:12:47 -0700868 switch (c) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000869 case 01:
870 case 02:
871 case 03:
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400872 case 04:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000873 codes += c, length += c;
874 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700875
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400876 case 05:
877 case 06:
878 case 07:
879 opex = c;
880 break;
H. Peter Anvindcffe4b2008-10-10 22:10:31 -0700881
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400882 case4(010):
883 ins->rex |=
884 op_rexflags(opx, REX_B|REX_H|REX_P|REX_W);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000885 codes++, length++;
886 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700887
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400888 case4(014):
889 case4(020):
890 case4(024):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000891 length++;
892 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700893
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400894 case4(030):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000895 length += 2;
896 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700897
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400898 case4(034):
H. Peter Anvin839eca22007-10-29 23:12:47 -0700899 if (opx->type & (BITS16 | BITS32 | BITS64))
900 length += (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000901 else
902 length += (bits == 16) ? 2 : 4;
903 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700904
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400905 case4(040):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000906 length += 4;
907 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700908
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400909 case4(044):
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700910 length += ins->addr_size >> 3;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000911 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700912
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400913 case4(050):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000914 length++;
915 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700916
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400917 case4(054):
Keith Kaniosb7a89542007-04-12 02:40:54 +0000918 length += 8; /* MOV reg64/imm */
919 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700920
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400921 case4(060):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000922 length += 2;
923 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700924
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400925 case4(064):
H. Peter Anvin839eca22007-10-29 23:12:47 -0700926 if (opx->type & (BITS16 | BITS32 | BITS64))
927 length += (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000928 else
929 length += (bits == 16) ? 2 : 4;
930 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700931
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400932 case4(070):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000933 length += 4;
934 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700935
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400936 case4(074):
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700937 length += 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000938 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700939
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400940 case4(0140):
H. Peter Anvinab5bd052010-07-25 12:43:30 -0700941 length += is_sbyte16(opx) ? 1 : 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000942 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700943
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400944 case4(0144):
H. Peter Anvina30cc072007-11-18 21:55:26 -0800945 codes++;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000946 length++;
947 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700948
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400949 case4(0150):
H. Peter Anvinab5bd052010-07-25 12:43:30 -0700950 length += is_sbyte32(opx) ? 1 : 4;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700951 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700952
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400953 case4(0154):
H. Peter Anvina30cc072007-11-18 21:55:26 -0800954 codes++;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700955 length++;
956 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700957
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400958 case 0172:
959 case 0173:
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400960 codes++;
H. Peter Anvinc1377e92008-10-06 23:40:31 -0700961 length++;
962 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700963
H. Peter Anvincffe61e2011-07-07 17:21:24 -0700964 case4(0174):
965 length++;
966 break;
967
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400968 case4(0250):
969 length += is_sbyte32(opx) ? 1 : 4;
970 break;
971
972 case4(0254):
973 length += 4;
974 break;
975
976 case4(0260):
977 ins->rex |= REX_V;
H. Peter Anvinfc561202011-07-07 16:58:22 -0700978 ins->vexreg = regval(opx);
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400979 ins->vex_cm = *codes++;
980 ins->vex_wlp = *codes++;
981 break;
982
983 case 0270:
984 ins->rex |= REX_V;
H. Peter Anvinfc561202011-07-07 16:58:22 -0700985 ins->vexreg = 0;
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400986 ins->vex_cm = *codes++;
987 ins->vex_wlp = *codes++;
988 break;
989
H. Peter Anvin574784d2012-02-25 22:33:46 -0800990 case 0271:
991 case 0272:
992 case 0273:
993 hleok = c & 3;
994 break;
995
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +0400996 case4(0274):
997 length++;
998 break;
999
1000 case4(0300):
H. Peter Anvine2c80182005-01-15 22:15:51 +00001001 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001002
H. Peter Anvine2c80182005-01-15 22:15:51 +00001003 case 0310:
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001004 if (bits == 64)
1005 return -1;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001006 length += (bits != 16) && !has_prefix(ins, PPS_ASIZE, P_A16);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001007 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001008
H. Peter Anvine2c80182005-01-15 22:15:51 +00001009 case 0311:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001010 length += (bits != 32) && !has_prefix(ins, PPS_ASIZE, P_A32);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001011 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001012
H. Peter Anvine2c80182005-01-15 22:15:51 +00001013 case 0312:
H. Peter Anvin70653092007-10-19 14:42:29 -07001014 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001015
Keith Kaniosb7a89542007-04-12 02:40:54 +00001016 case 0313:
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001017 if (bits != 64 || has_prefix(ins, PPS_ASIZE, P_A16) ||
1018 has_prefix(ins, PPS_ASIZE, P_A32))
1019 return -1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001020 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001021
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001022 case4(0314):
1023 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001024
H. Peter Anvine2c80182005-01-15 22:15:51 +00001025 case 0320:
Victor van den Elzen6dfbddb2010-12-29 17:13:38 +00001026 {
1027 enum prefixes pfx = ins->prefixes[PPS_OSIZE];
1028 if (pfx == P_O16)
1029 break;
1030 if (pfx != P_none)
1031 errfunc(ERR_WARNING | ERR_PASS2, "invalid operand size prefix");
1032 else
1033 ins->prefixes[PPS_OSIZE] = P_O16;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001034 break;
Victor van den Elzen6dfbddb2010-12-29 17:13:38 +00001035 }
H. Peter Anvin507ae032008-10-09 15:37:10 -07001036
H. Peter Anvine2c80182005-01-15 22:15:51 +00001037 case 0321:
Victor van den Elzen6dfbddb2010-12-29 17:13:38 +00001038 {
1039 enum prefixes pfx = ins->prefixes[PPS_OSIZE];
1040 if (pfx == P_O32)
1041 break;
1042 if (pfx != P_none)
1043 errfunc(ERR_WARNING | ERR_PASS2, "invalid operand size prefix");
1044 else
1045 ins->prefixes[PPS_OSIZE] = P_O32;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001046 break;
Victor van den Elzen6dfbddb2010-12-29 17:13:38 +00001047 }
H. Peter Anvin507ae032008-10-09 15:37:10 -07001048
H. Peter Anvine2c80182005-01-15 22:15:51 +00001049 case 0322:
1050 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001051
Keith Kaniosb7a89542007-04-12 02:40:54 +00001052 case 0323:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001053 rex_mask &= ~REX_W;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001054 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001055
Keith Kaniosb7a89542007-04-12 02:40:54 +00001056 case 0324:
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001057 ins->rex |= REX_W;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +00001058 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001059
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001060 case 0325:
1061 ins->rex |= REX_NH;
1062 break;
H. Peter Anvin9472dab2009-06-24 21:38:29 -07001063
H. Peter Anvine2c80182005-01-15 22:15:51 +00001064 case 0330:
1065 codes++, length++;
1066 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001067
H. Peter Anvine2c80182005-01-15 22:15:51 +00001068 case 0331:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001069 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001070
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001071 case 0332:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001072 case 0333:
1073 length++;
1074 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001075
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001076 case 0334:
1077 ins->rex |= REX_L;
1078 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001079
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001080 case 0335:
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001081 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001082
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001083 case 0336:
H. Peter Anvin10da41e2012-02-24 20:57:04 -08001084 if (!ins->prefixes[PPS_REP])
1085 ins->prefixes[PPS_REP] = P_REP;
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001086 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001087
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001088 case 0337:
H. Peter Anvin10da41e2012-02-24 20:57:04 -08001089 if (!ins->prefixes[PPS_REP])
1090 ins->prefixes[PPS_REP] = P_REPNE;
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001091 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001092
H. Peter Anvine2c80182005-01-15 22:15:51 +00001093 case 0340:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001094 if (ins->oprs[0].segment != NO_SEG)
1095 errfunc(ERR_NONFATAL, "attempt to reserve non-constant"
1096 " quantity of BSS space");
1097 else
H. Peter Anvin428fd672007-11-15 10:25:52 -08001098 length += ins->oprs[0].offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001099 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001100
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001101 case 0341:
1102 if (!ins->prefixes[PPS_WAIT])
1103 ins->prefixes[PPS_WAIT] = P_WAIT;
1104 break;
H. Peter Anvinc2acf7b2009-02-21 18:22:56 -08001105
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001106 case4(0344):
H. Peter Anvinff6e12d2008-10-08 21:17:32 -07001107 length++;
1108 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001109
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001110 case 0360:
1111 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001112
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001113 case 0361:
1114 case 0362:
1115 case 0363:
1116 length++;
1117 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001118
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001119 case 0364:
1120 case 0365:
1121 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001122
Keith Kanios48af1772007-08-17 07:37:52 +00001123 case 0366:
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001124 case 0367:
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001125 length++;
1126 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001127
H. Peter Anvine2c80182005-01-15 22:15:51 +00001128 case 0370:
1129 case 0371:
1130 case 0372:
1131 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001132
H. Peter Anvine2c80182005-01-15 22:15:51 +00001133 case 0373:
1134 length++;
1135 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001136
H. Peter Anvin3089f7e2011-06-22 18:19:28 -07001137 case 0374:
1138 eat = EA_XMMVSIB;
1139 break;
1140
1141 case 0375:
1142 eat = EA_YMMVSIB;
1143 break;
1144
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001145 case4(0100):
1146 case4(0110):
1147 case4(0120):
1148 case4(0130):
1149 case4(0200):
1150 case4(0204):
1151 case4(0210):
1152 case4(0214):
1153 case4(0220):
1154 case4(0224):
1155 case4(0230):
1156 case4(0234):
1157 {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001158 ea ea_data;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001159 int rfield;
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001160 opflags_t rflags;
1161 struct operand *opy = &ins->oprs[op2];
H. Peter Anvinae64c9d2008-10-25 00:41:00 -07001162
Keith Kaniosb7a89542007-04-12 02:40:54 +00001163 ea_data.rex = 0; /* Ensure ea.REX is initially 0 */
H. Peter Anvin70653092007-10-19 14:42:29 -07001164
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001165 if (c <= 0177) {
1166 /* pick rfield from operand b (opx) */
1167 rflags = regflag(opx);
1168 rfield = nasm_regvals[opx->basereg];
1169 } else {
1170 rflags = 0;
1171 rfield = c & 7;
1172 }
H. Peter Anvin3089f7e2011-06-22 18:19:28 -07001173 if (process_ea(opy, &ea_data, bits,ins->addr_size,
1174 rfield, rflags) != eat) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001175 errfunc(ERR_NONFATAL, "invalid effective address");
1176 return -1;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001177 } else {
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001178 ins->rex |= ea_data.rex;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001179 length += ea_data.size;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001180 }
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001181 }
1182 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001183
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001184 default:
1185 errfunc(ERR_PANIC, "internal instruction table corrupt"
1186 ": instruction code \\%o (0x%02X) given", c, c);
1187 break;
1188 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001189 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001190
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001191 ins->rex &= rex_mask;
H. Peter Anvin70653092007-10-19 14:42:29 -07001192
H. Peter Anvin9472dab2009-06-24 21:38:29 -07001193 if (ins->rex & REX_NH) {
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001194 if (ins->rex & REX_H) {
1195 errfunc(ERR_NONFATAL, "instruction cannot use high registers");
1196 return -1;
1197 }
1198 ins->rex &= ~REX_P; /* Don't force REX prefix due to high reg */
H. Peter Anvin9472dab2009-06-24 21:38:29 -07001199 }
1200
H. Peter Anvind85d2502008-05-04 17:53:31 -07001201 if (ins->rex & REX_V) {
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001202 int bad32 = REX_R|REX_W|REX_X|REX_B;
H. Peter Anvind85d2502008-05-04 17:53:31 -07001203
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001204 if (ins->rex & REX_H) {
1205 errfunc(ERR_NONFATAL, "cannot use high register in vex instruction");
1206 return -1;
1207 }
H. Peter Anvin421059c2010-08-16 14:56:33 -07001208 switch (ins->vex_wlp & 060) {
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001209 case 000:
H. Peter Anvin229fa6c2010-08-16 15:21:48 -07001210 case 040:
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001211 ins->rex &= ~REX_W;
1212 break;
H. Peter Anvin229fa6c2010-08-16 15:21:48 -07001213 case 020:
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001214 ins->rex |= REX_W;
1215 bad32 &= ~REX_W;
1216 break;
H. Peter Anvin421059c2010-08-16 14:56:33 -07001217 case 060:
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001218 /* Follow REX_W */
1219 break;
1220 }
H. Peter Anvind85d2502008-05-04 17:53:31 -07001221
H. Peter Anvinfc561202011-07-07 16:58:22 -07001222 if (bits != 64 && ((ins->rex & bad32) || ins->vexreg > 7)) {
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001223 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
1224 return -1;
1225 }
H. Peter Anvin3cb0e8c2010-11-16 09:36:58 -08001226 if (ins->vex_cm != 1 || (ins->rex & (REX_W|REX_X|REX_B)))
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001227 length += 3;
1228 else
1229 length += 2;
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001230 } else if (ins->rex & REX_REAL) {
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001231 if (ins->rex & REX_H) {
1232 errfunc(ERR_NONFATAL, "cannot use high register in rex instruction");
1233 return -1;
1234 } else if (bits == 64) {
1235 length++;
1236 } else if ((ins->rex & REX_L) &&
1237 !(ins->rex & (REX_P|REX_W|REX_X|REX_B)) &&
1238 cpu >= IF_X86_64) {
1239 /* LOCK-as-REX.R */
H. Peter Anvin10da41e2012-02-24 20:57:04 -08001240 assert_no_prefix(ins, PPS_LOCK);
H. Peter Anvin8cc8a1d2012-02-25 11:11:42 -08001241 lockcheck = false; /* Already errored, no need for warning */
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001242 length++;
1243 } else {
1244 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
1245 return -1;
1246 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001247 }
H. Peter Anvin8cc8a1d2012-02-25 11:11:42 -08001248
1249 if (has_prefix(ins, PPS_LOCK, P_LOCK) && lockcheck &&
1250 (!(temp->flags & IF_LOCK) || !is_class(MEMORY, ins->oprs[0].type))) {
H. Peter Anvin5a24fdd2012-02-25 15:10:04 -08001251 errfunc(ERR_WARNING | ERR_WARN_LOCK | ERR_PASS2 ,
H. Peter Anvin8cc8a1d2012-02-25 11:11:42 -08001252 "instruction is not lockable");
1253 }
1254
H. Peter Anvin4ecd5d72012-02-24 21:51:46 -08001255 bad_hle_warn(ins, hleok);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001256
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001257 return length;
1258}
Keith Kaniosb7a89542007-04-12 02:40:54 +00001259
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001260#define EMIT_REX() \
H. Peter Anvinfc561202011-07-07 16:58:22 -07001261 if (!(ins->rex & REX_V) && (ins->rex & REX_REAL) && (bits == 64)) { \
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001262 ins->rex = (ins->rex & REX_REAL)|REX_P; \
1263 out(offset, segment, &ins->rex, OUT_RAWDATA, 1, NO_SEG, NO_SEG); \
1264 ins->rex = 0; \
1265 offset += 1; \
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001266 }
1267
Charles Crayne1f8bc4c2007-11-06 18:27:23 -08001268static void gencode(int32_t segment, int64_t offset, int bits,
H. Peter Anvin833caea2008-10-04 19:02:30 -07001269 insn * ins, const struct itemplate *temp,
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001270 int64_t insn_end)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001271{
H. Peter Anvin3089f7e2011-06-22 18:19:28 -07001272 static const char condval[] = { /* conditional opcodes */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001273 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
1274 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
1275 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001276 };
Keith Kaniosb7a89542007-04-12 02:40:54 +00001277 uint8_t c;
1278 uint8_t bytes[4];
Charles Crayne1f8bc4c2007-11-06 18:27:23 -08001279 int64_t size;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001280 int64_t data;
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001281 int op1, op2;
H. Peter Anvin839eca22007-10-29 23:12:47 -07001282 struct operand *opx;
H. Peter Anvin833caea2008-10-04 19:02:30 -07001283 const uint8_t *codes = temp->code;
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001284 uint8_t opex = 0;
H. Peter Anvin3089f7e2011-06-22 18:19:28 -07001285 enum ea_type eat = EA_SCALAR;
H. Peter Anvin70653092007-10-19 14:42:29 -07001286
H. Peter Anvin839eca22007-10-29 23:12:47 -07001287 while (*codes) {
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001288 c = *codes++;
1289 op1 = (c & 3) + ((opex & 1) << 2);
1290 op2 = ((c >> 3) & 3) + ((opex & 2) << 1);
1291 opx = &ins->oprs[op1];
1292 opex = 0; /* For the next iteration */
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001293
H. Peter Anvin839eca22007-10-29 23:12:47 -07001294 switch (c) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001295 case 01:
1296 case 02:
1297 case 03:
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001298 case 04:
1299 EMIT_REX();
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001300 out(offset, segment, codes, OUT_RAWDATA, c, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001301 codes += c;
1302 offset += c;
1303 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001304
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001305 case 05:
1306 case 06:
1307 case 07:
1308 opex = c;
1309 break;
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001310
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001311 case4(010):
1312 EMIT_REX();
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001313 bytes[0] = *codes++ + (regval(opx) & 7);
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001314 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001315 offset += 1;
1316 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001317
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001318 case4(014):
1319 /*
1320 * The test for BITS8 and SBYTE here is intended to avoid
1321 * warning on optimizer actions due to SBYTE, while still
1322 * warn on explicit BYTE directives. Also warn, obviously,
1323 * if the optimizer isn't enabled.
1324 */
H. Peter Anvin6c80ab62008-10-04 18:50:47 -07001325 if (((opx->type & BITS8) ||
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001326 !(opx->type & temp->opd[op1] & BYTENESS)) &&
1327 (opx->offset < -128 || opx->offset > 127)) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001328 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001329 "signed byte value exceeds bounds");
1330 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001331 if (opx->segment != NO_SEG) {
1332 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001333 out(offset, segment, &data, OUT_ADDRESS, 1,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001334 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001335 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001336 bytes[0] = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001337 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001338 NO_SEG);
1339 }
1340 offset += 1;
1341 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001342
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001343 case4(020):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001344 if (opx->offset < -256 || opx->offset > 255) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001345 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001346 "byte value exceeds bounds");
H. Peter Anvine2c80182005-01-15 22:15:51 +00001347 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001348 if (opx->segment != NO_SEG) {
1349 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001350 out(offset, segment, &data, OUT_ADDRESS, 1,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001351 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001352 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001353 bytes[0] = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001354 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001355 NO_SEG);
1356 }
1357 offset += 1;
1358 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001359
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001360 case4(024):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001361 if (opx->offset < 0 || opx->offset > 255)
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001362 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001363 "unsigned byte value exceeds bounds");
H. Peter Anvin839eca22007-10-29 23:12:47 -07001364 if (opx->segment != NO_SEG) {
1365 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001366 out(offset, segment, &data, OUT_ADDRESS, 1,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001367 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001368 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001369 bytes[0] = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001370 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001371 NO_SEG);
1372 }
1373 offset += 1;
1374 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001375
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001376 case4(030):
Cyrill Gorcunov9ccabd22009-09-21 00:56:20 +04001377 warn_overflow_opd(opx, 2);
H. Peter Anvin839eca22007-10-29 23:12:47 -07001378 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001379 out(offset, segment, &data, OUT_ADDRESS, 2,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001380 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001381 offset += 2;
1382 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001383
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001384 case4(034):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001385 if (opx->type & (BITS16 | BITS32))
1386 size = (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001387 else
1388 size = (bits == 16) ? 2 : 4;
Cyrill Gorcunov9ccabd22009-09-21 00:56:20 +04001389 warn_overflow_opd(opx, size);
H. Peter Anvin839eca22007-10-29 23:12:47 -07001390 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001391 out(offset, segment, &data, OUT_ADDRESS, size,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001392 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001393 offset += size;
1394 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001395
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001396 case4(040):
Cyrill Gorcunov9ccabd22009-09-21 00:56:20 +04001397 warn_overflow_opd(opx, 4);
H. Peter Anvin839eca22007-10-29 23:12:47 -07001398 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001399 out(offset, segment, &data, OUT_ADDRESS, 4,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001400 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001401 offset += 4;
1402 break;
H. Peter Anvin3ba46772002-05-27 23:19:35 +00001403
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001404 case4(044):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001405 data = opx->offset;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001406 size = ins->addr_size >> 3;
Cyrill Gorcunov9ccabd22009-09-21 00:56:20 +04001407 warn_overflow_opd(opx, size);
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001408 out(offset, segment, &data, OUT_ADDRESS, size,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001409 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001410 offset += size;
1411 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001412
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001413 case4(050):
H. Peter Anvinfea84d72010-05-06 15:32:20 -07001414 if (opx->segment != segment) {
1415 data = opx->offset;
1416 out(offset, segment, &data,
1417 OUT_REL1ADR, insn_end - offset,
1418 opx->segment, opx->wrt);
1419 } else {
1420 data = opx->offset - insn_end;
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001421 if (data > 127 || data < -128)
1422 errfunc(ERR_NONFATAL, "short jump is out of range");
H. Peter Anvinfea84d72010-05-06 15:32:20 -07001423 out(offset, segment, &data,
1424 OUT_ADDRESS, 1, NO_SEG, NO_SEG);
1425 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001426 offset += 1;
1427 break;
H. Peter Anvin70653092007-10-19 14:42:29 -07001428
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001429 case4(054):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001430 data = (int64_t)opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001431 out(offset, segment, &data, OUT_ADDRESS, 8,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001432 opx->segment, opx->wrt);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001433 offset += 8;
1434 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001435
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001436 case4(060):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001437 if (opx->segment != segment) {
1438 data = opx->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001439 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001440 OUT_REL2ADR, insn_end - offset,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001441 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001442 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001443 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001444 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001445 OUT_ADDRESS, 2, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001446 }
1447 offset += 2;
1448 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001449
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001450 case4(064):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001451 if (opx->type & (BITS16 | BITS32 | BITS64))
1452 size = (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001453 else
1454 size = (bits == 16) ? 2 : 4;
H. Peter Anvin839eca22007-10-29 23:12:47 -07001455 if (opx->segment != segment) {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001456 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001457 out(offset, segment, &data,
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001458 size == 2 ? OUT_REL2ADR : OUT_REL4ADR,
1459 insn_end - offset, opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001460 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001461 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001462 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001463 OUT_ADDRESS, size, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001464 }
1465 offset += size;
1466 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001467
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001468 case4(070):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001469 if (opx->segment != segment) {
1470 data = opx->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001471 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001472 OUT_REL4ADR, insn_end - offset,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001473 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001474 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001475 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001476 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001477 OUT_ADDRESS, 4, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001478 }
1479 offset += 4;
1480 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001481
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001482 case4(074):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001483 if (opx->segment == NO_SEG)
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001484 errfunc(ERR_NONFATAL, "value referenced by FAR is not"
1485 " relocatable");
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001486 data = 0;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001487 out(offset, segment, &data, OUT_ADDRESS, 2,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001488 outfmt->segbase(1 + opx->segment),
1489 opx->wrt);
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001490 offset += 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001491 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001492
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001493 case4(0140):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001494 data = opx->offset;
Cyrill Gorcunov9ccabd22009-09-21 00:56:20 +04001495 warn_overflow_opd(opx, 2);
H. Peter Anvinab5bd052010-07-25 12:43:30 -07001496 if (is_sbyte16(opx)) {
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001497 bytes[0] = data;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001498 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001499 NO_SEG);
1500 offset++;
1501 } else {
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001502 out(offset, segment, &data, OUT_ADDRESS, 2,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001503 opx->segment, opx->wrt);
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001504 offset += 2;
1505 }
1506 break;
1507
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001508 case4(0144):
1509 EMIT_REX();
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001510 bytes[0] = *codes++;
H. Peter Anvinab5bd052010-07-25 12:43:30 -07001511 if (is_sbyte16(opx))
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001512 bytes[0] |= 2; /* s-bit */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001513 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001514 offset++;
1515 break;
1516
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001517 case4(0150):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001518 data = opx->offset;
Cyrill Gorcunov9ccabd22009-09-21 00:56:20 +04001519 warn_overflow_opd(opx, 4);
H. Peter Anvinab5bd052010-07-25 12:43:30 -07001520 if (is_sbyte32(opx)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001521 bytes[0] = data;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001522 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001523 NO_SEG);
1524 offset++;
1525 } else {
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001526 out(offset, segment, &data, OUT_ADDRESS, 4,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001527 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001528 offset += 4;
1529 }
1530 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001531
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001532 case4(0154):
1533 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001534 bytes[0] = *codes++;
H. Peter Anvinab5bd052010-07-25 12:43:30 -07001535 if (is_sbyte32(opx))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001536 bytes[0] |= 2; /* s-bit */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001537 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001538 offset++;
1539 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001540
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001541 case 0172:
1542 c = *codes++;
1543 opx = &ins->oprs[c >> 3];
1544 bytes[0] = nasm_regvals[opx->basereg] << 4;
1545 opx = &ins->oprs[c & 7];
1546 if (opx->segment != NO_SEG || opx->wrt != NO_SEG) {
1547 errfunc(ERR_NONFATAL,
1548 "non-absolute expression not permitted as argument %d",
1549 c & 7);
1550 } else {
1551 if (opx->offset & ~15) {
1552 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
1553 "four-bit argument exceeds bounds");
1554 }
1555 bytes[0] |= opx->offset & 15;
1556 }
1557 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1558 offset++;
1559 break;
H. Peter Anvind85d2502008-05-04 17:53:31 -07001560
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001561 case 0173:
1562 c = *codes++;
1563 opx = &ins->oprs[c >> 4];
1564 bytes[0] = nasm_regvals[opx->basereg] << 4;
1565 bytes[0] |= c & 15;
1566 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1567 offset++;
1568 break;
H. Peter Anvind58656f2008-05-06 20:11:14 -07001569
H. Peter Anvincffe61e2011-07-07 17:21:24 -07001570 case4(0174):
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001571 bytes[0] = nasm_regvals[opx->basereg] << 4;
1572 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1573 offset++;
1574 break;
H. Peter Anvin52dc3532008-05-20 19:29:04 -07001575
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001576 case4(0250):
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001577 data = opx->offset;
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001578 if (opx->wrt == NO_SEG && opx->segment == NO_SEG &&
1579 (int32_t)data != (int64_t)data) {
1580 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
1581 "signed dword immediate exceeds bounds");
1582 }
H. Peter Anvinab5bd052010-07-25 12:43:30 -07001583 if (is_sbyte32(opx)) {
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001584 bytes[0] = data;
1585 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
1586 NO_SEG);
1587 offset++;
1588 } else {
1589 out(offset, segment, &data, OUT_ADDRESS, 4,
1590 opx->segment, opx->wrt);
1591 offset += 4;
1592 }
1593 break;
1594
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001595 case4(0254):
H. Peter Anvin588df782008-10-07 10:05:10 -07001596 data = opx->offset;
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001597 if (opx->wrt == NO_SEG && opx->segment == NO_SEG &&
1598 (int32_t)data != (int64_t)data) {
1599 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
1600 "signed dword immediate exceeds bounds");
1601 }
1602 out(offset, segment, &data, OUT_ADDRESS, 4,
1603 opx->segment, opx->wrt);
1604 offset += 4;
H. Peter Anvin588df782008-10-07 10:05:10 -07001605 break;
1606
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001607 case4(0260):
1608 case 0270:
1609 codes += 2;
1610 if (ins->vex_cm != 1 || (ins->rex & (REX_W|REX_X|REX_B))) {
1611 bytes[0] = (ins->vex_cm >> 6) ? 0x8f : 0xc4;
1612 bytes[1] = (ins->vex_cm & 31) | ((~ins->rex & 7) << 5);
1613 bytes[2] = ((ins->rex & REX_W) << (7-3)) |
H. Peter Anvinfc561202011-07-07 16:58:22 -07001614 ((~ins->vexreg & 15)<< 3) | (ins->vex_wlp & 07);
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001615 out(offset, segment, &bytes, OUT_RAWDATA, 3, NO_SEG, NO_SEG);
1616 offset += 3;
1617 } else {
1618 bytes[0] = 0xc5;
1619 bytes[1] = ((~ins->rex & REX_R) << (7-2)) |
H. Peter Anvinfc561202011-07-07 16:58:22 -07001620 ((~ins->vexreg & 15) << 3) | (ins->vex_wlp & 07);
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001621 out(offset, segment, &bytes, OUT_RAWDATA, 2, NO_SEG, NO_SEG);
1622 offset += 2;
1623 }
1624 break;
H. Peter Anvind85d2502008-05-04 17:53:31 -07001625
H. Peter Anvinfb3f4e62012-02-25 22:22:07 -08001626 case 0265:
1627 case 0266:
1628 case 0267:
H. Peter Anvin8ea22002012-02-25 10:24:24 -08001629 break;
1630
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001631 case4(0274):
1632 {
1633 uint64_t uv, um;
1634 int s;
H. Peter Anvinc1377e92008-10-06 23:40:31 -07001635
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001636 if (ins->rex & REX_W)
1637 s = 64;
1638 else if (ins->prefixes[PPS_OSIZE] == P_O16)
1639 s = 16;
1640 else if (ins->prefixes[PPS_OSIZE] == P_O32)
1641 s = 32;
1642 else
1643 s = bits;
H. Peter Anvinc1377e92008-10-06 23:40:31 -07001644
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001645 um = (uint64_t)2 << (s-1);
1646 uv = opx->offset;
H. Peter Anvinc1377e92008-10-06 23:40:31 -07001647
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001648 if (uv > 127 && uv < (uint64_t)-128 &&
1649 (uv < um-128 || uv > um-1)) {
H. Peter Anvinc1377e92008-10-06 23:40:31 -07001650 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001651 "signed byte value exceeds bounds");
1652 }
H. Peter Anvinc1377e92008-10-06 23:40:31 -07001653 if (opx->segment != NO_SEG) {
H. Peter Anvin779ed8b2008-10-16 13:01:43 -07001654 data = uv;
H. Peter Anvinc1377e92008-10-06 23:40:31 -07001655 out(offset, segment, &data, OUT_ADDRESS, 1,
1656 opx->segment, opx->wrt);
1657 } else {
H. Peter Anvin779ed8b2008-10-16 13:01:43 -07001658 bytes[0] = uv;
H. Peter Anvinc1377e92008-10-06 23:40:31 -07001659 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
1660 NO_SEG);
1661 }
1662 offset += 1;
1663 break;
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001664 }
H. Peter Anvinc1377e92008-10-06 23:40:31 -07001665
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001666 case4(0300):
H. Peter Anvine2c80182005-01-15 22:15:51 +00001667 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001668
H. Peter Anvine2c80182005-01-15 22:15:51 +00001669 case 0310:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001670 if (bits == 32 && !has_prefix(ins, PPS_ASIZE, P_A16)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001671 *bytes = 0x67;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001672 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001673 offset += 1;
1674 } else
1675 offset += 0;
1676 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001677
H. Peter Anvine2c80182005-01-15 22:15:51 +00001678 case 0311:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001679 if (bits != 32 && !has_prefix(ins, PPS_ASIZE, P_A32)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001680 *bytes = 0x67;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001681 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001682 offset += 1;
1683 } else
1684 offset += 0;
1685 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001686
H. Peter Anvine2c80182005-01-15 22:15:51 +00001687 case 0312:
1688 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001689
Keith Kaniosb7a89542007-04-12 02:40:54 +00001690 case 0313:
1691 ins->rex = 0;
1692 break;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07001693
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001694 case4(0314):
1695 break;
H. Peter Anvin23440102007-11-12 21:02:33 -08001696
H. Peter Anvine2c80182005-01-15 22:15:51 +00001697 case 0320:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001698 case 0321:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001699 break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001700
H. Peter Anvine2c80182005-01-15 22:15:51 +00001701 case 0322:
H. Peter Anvin70653092007-10-19 14:42:29 -07001702 case 0323:
1703 break;
1704
Keith Kaniosb7a89542007-04-12 02:40:54 +00001705 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001706 ins->rex |= REX_W;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001707 break;
H. Peter Anvin70653092007-10-19 14:42:29 -07001708
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001709 case 0325:
1710 break;
H. Peter Anvin9472dab2009-06-24 21:38:29 -07001711
H. Peter Anvine2c80182005-01-15 22:15:51 +00001712 case 0330:
1713 *bytes = *codes++ ^ condval[ins->condition];
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001714 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001715 offset += 1;
1716 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001717
H. Peter Anvine2c80182005-01-15 22:15:51 +00001718 case 0331:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001719 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001720
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001721 case 0332:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001722 case 0333:
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001723 *bytes = c - 0332 + 0xF2;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001724 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001725 offset += 1;
1726 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001727
Keith Kanios48af1772007-08-17 07:37:52 +00001728 case 0334:
1729 if (ins->rex & REX_R) {
1730 *bytes = 0xF0;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001731 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
Keith Kanios48af1772007-08-17 07:37:52 +00001732 offset += 1;
1733 }
1734 ins->rex &= ~(REX_L|REX_R);
1735 break;
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001736
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001737 case 0335:
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001738 break;
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001739
H. Peter Anvin962e3052008-08-28 17:47:16 -07001740 case 0336:
1741 case 0337:
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001742 break;
H. Peter Anvin962e3052008-08-28 17:47:16 -07001743
H. Peter Anvine2c80182005-01-15 22:15:51 +00001744 case 0340:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001745 if (ins->oprs[0].segment != NO_SEG)
1746 errfunc(ERR_PANIC, "non-constant BSS size in pass two");
1747 else {
H. Peter Anvin428fd672007-11-15 10:25:52 -08001748 int64_t size = ins->oprs[0].offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001749 if (size > 0)
1750 out(offset, segment, NULL,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001751 OUT_RESERVE, size, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001752 offset += size;
1753 }
1754 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001755
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001756 case 0341:
1757 break;
H. Peter Anvinc2acf7b2009-02-21 18:22:56 -08001758
H. Peter Anvinff6e12d2008-10-08 21:17:32 -07001759 case 0344:
1760 case 0345:
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001761 bytes[0] = c & 1;
H. Peter Anvinff6e12d2008-10-08 21:17:32 -07001762 switch (ins->oprs[0].basereg) {
1763 case R_CS:
1764 bytes[0] += 0x0E;
1765 break;
1766 case R_DS:
1767 bytes[0] += 0x1E;
1768 break;
1769 case R_ES:
1770 bytes[0] += 0x06;
1771 break;
1772 case R_SS:
1773 bytes[0] += 0x16;
1774 break;
1775 default:
1776 errfunc(ERR_PANIC,
1777 "bizarre 8086 segment register received");
1778 }
1779 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1780 offset++;
1781 break;
1782
1783 case 0346:
1784 case 0347:
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001785 bytes[0] = c & 1;
H. Peter Anvinff6e12d2008-10-08 21:17:32 -07001786 switch (ins->oprs[0].basereg) {
1787 case R_FS:
1788 bytes[0] += 0xA0;
1789 break;
1790 case R_GS:
1791 bytes[0] += 0xA8;
1792 break;
1793 default:
1794 errfunc(ERR_PANIC,
1795 "bizarre 386 segment register received");
1796 }
1797 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1798 offset++;
1799 break;
1800
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001801 case 0360:
1802 break;
H. Peter Anvinfff5a472008-05-20 09:46:24 -07001803
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001804 case 0361:
1805 bytes[0] = 0x66;
H. Peter Anvinfff5a472008-05-20 09:46:24 -07001806 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1807 offset += 1;
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001808 break;
H. Peter Anvinfff5a472008-05-20 09:46:24 -07001809
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001810 case 0362:
1811 case 0363:
1812 bytes[0] = c - 0362 + 0xf2;
H. Peter Anvinfff5a472008-05-20 09:46:24 -07001813 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1814 offset += 1;
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001815 break;
H. Peter Anvinfff5a472008-05-20 09:46:24 -07001816
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001817 case 0364:
1818 case 0365:
1819 break;
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001820
Keith Kanios48af1772007-08-17 07:37:52 +00001821 case 0366:
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001822 case 0367:
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001823 *bytes = c - 0366 + 0x66;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001824 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
Keith Kanios48af1772007-08-17 07:37:52 +00001825 offset += 1;
1826 break;
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001827
H. Peter Anvine2c80182005-01-15 22:15:51 +00001828 case 0370:
1829 case 0371:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001830 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001831
H. Peter Anvine2c80182005-01-15 22:15:51 +00001832 case 0373:
1833 *bytes = bits == 16 ? 3 : 5;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001834 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001835 offset += 1;
1836 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001837
H. Peter Anvin3089f7e2011-06-22 18:19:28 -07001838 case 0374:
1839 eat = EA_XMMVSIB;
1840 break;
1841
1842 case 0375:
1843 eat = EA_YMMVSIB;
1844 break;
1845
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001846 case4(0100):
1847 case4(0110):
1848 case4(0120):
1849 case4(0130):
1850 case4(0200):
1851 case4(0204):
1852 case4(0210):
1853 case4(0214):
1854 case4(0220):
1855 case4(0224):
1856 case4(0230):
1857 case4(0234):
1858 {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001859 ea ea_data;
1860 int rfield;
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001861 opflags_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001862 uint8_t *p;
1863 int32_t s;
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001864 struct operand *opy = &ins->oprs[op2];
H. Peter Anvin70653092007-10-19 14:42:29 -07001865
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001866 if (c <= 0177) {
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001867 /* pick rfield from operand b (opx) */
1868 rflags = regflag(opx);
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001869 rfield = nasm_regvals[opx->basereg];
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001870 } else {
1871 /* rfield is constant */
1872 rflags = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001873 rfield = c & 7;
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001874 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001875
H. Peter Anvin3089f7e2011-06-22 18:19:28 -07001876 if (process_ea(opy, &ea_data, bits, ins->addr_size,
Cyrill Gorcunovcdb8cd72011-08-28 16:33:39 +04001877 rfield, rflags) != eat)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001878 errfunc(ERR_NONFATAL, "invalid effective address");
Charles Crayne7e975552007-11-03 22:06:13 -07001879
H. Peter Anvine2c80182005-01-15 22:15:51 +00001880 p = bytes;
1881 *p++ = ea_data.modrm;
1882 if (ea_data.sib_present)
1883 *p++ = ea_data.sib;
1884
1885 s = p - bytes;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001886 out(offset, segment, bytes, OUT_RAWDATA, s, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001887
Victor van den Elzencf9332c2008-10-01 12:18:28 +02001888 /*
1889 * Make sure the address gets the right offset in case
1890 * the line breaks in the .lst file (BR 1197827)
1891 */
1892 offset += s;
1893 s = 0;
1894
H. Peter Anvine2c80182005-01-15 22:15:51 +00001895 switch (ea_data.bytes) {
1896 case 0:
1897 break;
1898 case 1:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001899 case 2:
1900 case 4:
Victor van den Elzen352fe062008-12-10 13:04:58 +01001901 case 8:
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001902 data = opy->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001903 s += ea_data.bytes;
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001904 if (ea_data.rip) {
1905 if (opy->segment == segment) {
1906 data -= insn_end;
Victor van den Elzen0d268fb2010-01-24 21:24:57 +01001907 if (overflow_signed(data, ea_data.bytes))
1908 warn_overflow(ERR_PASS2, ea_data.bytes);
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001909 out(offset, segment, &data, OUT_ADDRESS,
1910 ea_data.bytes, NO_SEG, NO_SEG);
1911 } else {
Victor van den Elzen0d268fb2010-01-24 21:24:57 +01001912 /* overflow check in output/linker? */
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001913 out(offset, segment, &data, OUT_REL4ADR,
1914 insn_end - offset, opy->segment, opy->wrt);
1915 }
1916 } else {
Victor van den Elzen0d268fb2010-01-24 21:24:57 +01001917 if (overflow_general(opy->offset, ins->addr_size >> 3) ||
1918 signed_bits(opy->offset, ins->addr_size) !=
1919 signed_bits(opy->offset, ea_data.bytes * 8))
1920 warn_overflow(ERR_PASS2, ea_data.bytes);
1921
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001922 out(offset, segment, &data, OUT_ADDRESS,
1923 ea_data.bytes, opy->segment, opy->wrt);
1924 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001925 break;
Victor van den Elzen352fe062008-12-10 13:04:58 +01001926 default:
1927 /* Impossible! */
1928 errfunc(ERR_PANIC,
1929 "Invalid amount of bytes (%d) for offset?!",
1930 ea_data.bytes);
1931 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001932 }
1933 offset += s;
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001934 }
1935 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001936
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001937 default:
1938 errfunc(ERR_PANIC, "internal instruction table corrupt"
1939 ": instruction code \\%o (0x%02X) given", c, c);
1940 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001941 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001942 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001943}
1944
H. Peter Anvinf8563f72009-10-13 12:28:14 -07001945static opflags_t regflag(const operand * o)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001946{
Cyrill Gorcunov2124b7b2010-07-25 01:16:33 +04001947 if (!is_register(o->basereg))
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001948 errfunc(ERR_PANIC, "invalid operand passed to regflag()");
H. Peter Anvina4835d42008-05-20 14:21:29 -07001949 return nasm_reg_flags[o->basereg];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001950}
1951
H. Peter Anvin5b0e3ec2007-07-07 02:01:08 +00001952static int32_t regval(const operand * o)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001953{
Cyrill Gorcunov2124b7b2010-07-25 01:16:33 +04001954 if (!is_register(o->basereg))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001955 errfunc(ERR_PANIC, "invalid operand passed to regval()");
H. Peter Anvina4835d42008-05-20 14:21:29 -07001956 return nasm_regvals[o->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001957}
1958
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001959static int op_rexflags(const operand * o, int mask)
1960{
H. Peter Anvinf8563f72009-10-13 12:28:14 -07001961 opflags_t flags;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001962 int val;
1963
Cyrill Gorcunov2124b7b2010-07-25 01:16:33 +04001964 if (!is_register(o->basereg))
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001965 errfunc(ERR_PANIC, "invalid operand passed to op_rexflags()");
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001966
H. Peter Anvina4835d42008-05-20 14:21:29 -07001967 flags = nasm_reg_flags[o->basereg];
1968 val = nasm_regvals[o->basereg];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001969
1970 return rexflags(val, flags, mask);
1971}
1972
H. Peter Anvinf8563f72009-10-13 12:28:14 -07001973static int rexflags(int val, opflags_t flags, int mask)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001974{
1975 int rex = 0;
1976
1977 if (val >= 8)
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001978 rex |= REX_B|REX_X|REX_R;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001979 if (flags & BITS64)
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001980 rex |= REX_W;
1981 if (!(REG_HIGH & ~flags)) /* AH, CH, DH, BH */
1982 rex |= REX_H;
1983 else if (!(REG8 & ~flags) && val >= 4) /* SPL, BPL, SIL, DIL */
1984 rex |= REX_P;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001985
1986 return rex & mask;
1987}
1988
H. Peter Anvin23595f52009-07-25 17:44:25 -07001989static enum match_result find_match(const struct itemplate **tempp,
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04001990 insn *instruction,
1991 int32_t segment, int64_t offset, int bits)
H. Peter Anvin23595f52009-07-25 17:44:25 -07001992{
1993 const struct itemplate *temp;
1994 enum match_result m, merr;
H. Peter Anvina7643f42009-10-13 12:32:20 -07001995 opflags_t xsizeflags[MAX_OPERANDS];
H. Peter Anvina81655b2009-07-25 18:15:28 -07001996 bool opsizemissing = false;
1997 int i;
1998
1999 for (i = 0; i < instruction->operands; i++)
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002000 xsizeflags[i] = instruction->oprs[i].type & SIZE_MASK;
H. Peter Anvin23595f52009-07-25 17:44:25 -07002001
2002 merr = MERR_INVALOP;
2003
2004 for (temp = nasm_instructions[instruction->opcode];
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002005 temp->opcode != I_none; temp++) {
2006 m = matches(temp, instruction, bits);
2007 if (m == MOK_JUMP) {
H. Peter Anvin8cc8a1d2012-02-25 11:11:42 -08002008 if (jmp_match(segment, offset, bits, instruction, temp))
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002009 m = MOK_GOOD;
2010 else
2011 m = MERR_INVALOP;
2012 } else if (m == MERR_OPSIZEMISSING &&
2013 (temp->flags & IF_SMASK) != IF_SX) {
2014 /*
2015 * Missing operand size and a candidate for fuzzy matching...
2016 */
2017 for (i = 0; i < temp->operands; i++) {
2018 if ((temp->opd[i] & SAME_AS) == 0)
2019 xsizeflags[i] |= temp->opd[i] & SIZE_MASK;
2020 }
2021 opsizemissing = true;
2022 }
2023 if (m > merr)
2024 merr = m;
2025 if (merr == MOK_GOOD)
2026 goto done;
H. Peter Anvina81655b2009-07-25 18:15:28 -07002027 }
2028
2029 /* No match, but see if we can get a fuzzy operand size match... */
2030 if (!opsizemissing)
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002031 goto done;
H. Peter Anvina81655b2009-07-25 18:15:28 -07002032
2033 for (i = 0; i < instruction->operands; i++) {
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002034 /*
2035 * We ignore extrinsic operand sizes on registers, so we should
2036 * never try to fuzzy-match on them. This also resolves the case
2037 * when we have e.g. "xmmrm128" in two different positions.
2038 */
2039 if (is_class(REGISTER, instruction->oprs[i].type))
2040 continue;
H. Peter Anvinff5d6562009-10-05 14:08:05 -07002041
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002042 /* This tests if xsizeflags[i] has more than one bit set */
2043 if ((xsizeflags[i] & (xsizeflags[i]-1)))
2044 goto done; /* No luck */
H. Peter Anvina81655b2009-07-25 18:15:28 -07002045
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002046 instruction->oprs[i].type |= xsizeflags[i]; /* Set the size */
H. Peter Anvina81655b2009-07-25 18:15:28 -07002047 }
2048
2049 /* Try matching again... */
2050 for (temp = nasm_instructions[instruction->opcode];
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002051 temp->opcode != I_none; temp++) {
2052 m = matches(temp, instruction, bits);
2053 if (m == MOK_JUMP) {
H. Peter Anvin8cc8a1d2012-02-25 11:11:42 -08002054 if (jmp_match(segment, offset, bits, instruction, temp))
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002055 m = MOK_GOOD;
2056 else
2057 m = MERR_INVALOP;
2058 }
2059 if (m > merr)
2060 merr = m;
2061 if (merr == MOK_GOOD)
2062 goto done;
H. Peter Anvin23595f52009-07-25 17:44:25 -07002063 }
2064
H. Peter Anvina81655b2009-07-25 18:15:28 -07002065done:
H. Peter Anvin23595f52009-07-25 17:44:25 -07002066 *tempp = temp;
2067 return merr;
2068}
2069
H. Peter Anvin65289e82009-07-25 17:25:11 -07002070static enum match_result matches(const struct itemplate *itemp,
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002071 insn *instruction, int bits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002072{
H. Peter Anvin60926242009-07-26 16:25:38 -07002073 int i, size[MAX_OPERANDS], asize, oprs;
H. Peter Anvin3fb86f22009-07-25 19:12:10 -07002074 bool opsizemissing = false;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002075
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002076 /*
2077 * Check the opcode
2078 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002079 if (itemp->opcode != instruction->opcode)
H. Peter Anvin65289e82009-07-25 17:25:11 -07002080 return MERR_INVALOP;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002081
2082 /*
2083 * Count the operands
2084 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002085 if (itemp->operands != instruction->operands)
H. Peter Anvin65289e82009-07-25 17:25:11 -07002086 return MERR_INVALOP;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002087
2088 /*
H. Peter Anvin47fb7bc2010-08-24 13:53:22 -07002089 * Is it legal?
2090 */
2091 if (!(optimizing > 0) && (itemp->flags & IF_OPT))
2092 return MERR_INVALOP;
2093
2094 /*
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002095 * Check that no spurious colons or TOs are present
2096 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002097 for (i = 0; i < itemp->operands; i++)
2098 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON | TO))
H. Peter Anvin65289e82009-07-25 17:25:11 -07002099 return MERR_INVALOP;
H. Peter Anvin70653092007-10-19 14:42:29 -07002100
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002101 /*
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002102 * Process size flags
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002103 */
H. Peter Anvin60926242009-07-26 16:25:38 -07002104 switch (itemp->flags & IF_SMASK) {
2105 case IF_SB:
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002106 asize = BITS8;
2107 break;
H. Peter Anvin60926242009-07-26 16:25:38 -07002108 case IF_SW:
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002109 asize = BITS16;
2110 break;
H. Peter Anvin60926242009-07-26 16:25:38 -07002111 case IF_SD:
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002112 asize = BITS32;
2113 break;
H. Peter Anvin60926242009-07-26 16:25:38 -07002114 case IF_SQ:
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002115 asize = BITS64;
2116 break;
H. Peter Anvin60926242009-07-26 16:25:38 -07002117 case IF_SO:
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002118 asize = BITS128;
2119 break;
H. Peter Anvin60926242009-07-26 16:25:38 -07002120 case IF_SY:
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002121 asize = BITS256;
2122 break;
H. Peter Anvin60926242009-07-26 16:25:38 -07002123 case IF_SZ:
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002124 switch (bits) {
2125 case 16:
2126 asize = BITS16;
2127 break;
2128 case 32:
2129 asize = BITS32;
2130 break;
2131 case 64:
2132 asize = BITS64;
2133 break;
2134 default:
2135 asize = 0;
2136 break;
2137 }
2138 break;
H. Peter Anvin60926242009-07-26 16:25:38 -07002139 default:
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002140 asize = 0;
2141 break;
H. Peter Anvin60926242009-07-26 16:25:38 -07002142 }
2143
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002144 if (itemp->flags & IF_ARMASK) {
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002145 /* S- flags only apply to a specific operand */
2146 i = ((itemp->flags & IF_ARMASK) >> IF_ARSHFT) - 1;
2147 memset(size, 0, sizeof size);
2148 size[i] = asize;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002149 } else {
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002150 /* S- flags apply to all operands */
2151 for (i = 0; i < MAX_OPERANDS; i++)
2152 size[i] = asize;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002153 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002154
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002155 /*
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002156 * Check that the operand flags all match up,
2157 * it's a bit tricky so lets be verbose:
2158 *
2159 * 1) Find out the size of operand. If instruction
2160 * doesn't have one specified -- we're trying to
2161 * guess it either from template (IF_S* flag) or
2162 * from code bits.
2163 *
2164 * 2) If template operand (i) has SAME_AS flag [used for registers only]
2165 * (ie the same operand as was specified somewhere in template, and
2166 * this referred operand index is being achieved via ~SAME_AS)
2167 * we are to be sure that both registers (in template and instruction)
2168 * do exactly match.
2169 *
2170 * 3) If template operand do not match the instruction OR
2171 * template has an operand size specified AND this size differ
2172 * from which instruction has (perhaps we got it from code bits)
2173 * we are:
2174 * a) Check that only size of instruction and operand is differ
2175 * other characteristics do match
2176 * b) Perhaps it's a register specified in instruction so
2177 * for such a case we just mark that operand as "size
2178 * missing" and this will turn on fuzzy operand size
2179 * logic facility (handled by a caller)
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002180 */
2181 for (i = 0; i < itemp->operands; i++) {
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002182 opflags_t type = instruction->oprs[i].type;
2183 if (!(type & SIZE_MASK))
2184 type |= size[i];
H. Peter Anvind85d2502008-05-04 17:53:31 -07002185
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002186 if (itemp->opd[i] & SAME_AS) {
2187 int j = itemp->opd[i] & ~SAME_AS;
2188 if (type != instruction->oprs[j].type ||
2189 instruction->oprs[i].basereg != instruction->oprs[j].basereg)
2190 return MERR_INVALOP;
2191 } else if (itemp->opd[i] & ~type ||
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002192 ((itemp->opd[i] & SIZE_MASK) &&
2193 ((itemp->opd[i] ^ type) & SIZE_MASK))) {
H. Peter Anvinff5d6562009-10-05 14:08:05 -07002194 if ((itemp->opd[i] & ~type & ~SIZE_MASK) || (type & SIZE_MASK)) {
H. Peter Anvin65289e82009-07-25 17:25:11 -07002195 return MERR_INVALOP;
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002196 } else if (!is_class(REGISTER, type)) {
2197 /*
2198 * Note: we don't honor extrinsic operand sizes for registers,
2199 * so "missing operand size" for a register should be
2200 * considered a wildcard match rather than an error.
2201 */
2202 opsizemissing = true;
2203 }
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002204 }
2205 }
2206
H. Peter Anvin3fb86f22009-07-25 19:12:10 -07002207 if (opsizemissing)
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002208 return MERR_OPSIZEMISSING;
H. Peter Anvin3fb86f22009-07-25 19:12:10 -07002209
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002210 /*
2211 * Check operand sizes
2212 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002213 if (itemp->flags & (IF_SM | IF_SM2)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002214 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002215 for (i = 0; i < oprs; i++) {
Cyrill Gorcunovbc31bee2009-11-01 23:16:01 +03002216 asize = itemp->opd[i] & SIZE_MASK;
2217 if (asize) {
2218 for (i = 0; i < oprs; i++)
2219 size[i] = asize;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002220 break;
2221 }
2222 }
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002223 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002224 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002225 }
2226
Keith Kaniosb7a89542007-04-12 02:40:54 +00002227 for (i = 0; i < itemp->operands; i++) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002228 if (!(itemp->opd[i] & SIZE_MASK) &&
2229 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvin65289e82009-07-25 17:25:11 -07002230 return MERR_OPSIZEMISMATCH;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002231 }
2232
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002233 /*
2234 * Check template is okay at the set cpu level
2235 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002236 if (((itemp->flags & IF_PLEVEL) > cpu))
H. Peter Anvin65289e82009-07-25 17:25:11 -07002237 return MERR_BADCPU;
H. Peter Anvin70653092007-10-19 14:42:29 -07002238
Keith Kaniosb7a89542007-04-12 02:40:54 +00002239 /*
H. Peter Anvin6cda4142008-12-29 20:52:28 -08002240 * Verify the appropriate long mode flag.
Keith Kaniosb7a89542007-04-12 02:40:54 +00002241 */
H. Peter Anvin6cda4142008-12-29 20:52:28 -08002242 if ((itemp->flags & (bits == 64 ? IF_NOLONG : IF_LONG)))
H. Peter Anvin65289e82009-07-25 17:25:11 -07002243 return MERR_BADMODE;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002244
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002245 /*
H. Peter Anvinfb3f4e62012-02-25 22:22:07 -08002246 * If we have a HLE prefix, look for the NOHLE flag
2247 */
2248 if ((itemp->flags & IF_NOHLE) &&
2249 (has_prefix(instruction, PPS_REP, P_XACQUIRE) ||
2250 has_prefix(instruction, PPS_REP, P_XRELEASE)))
2251 return MERR_BADHLE;
2252
2253 /*
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002254 * Check if special handling needed for Jumps
2255 */
H. Peter Anvin755f5212012-02-25 11:41:34 -08002256 if ((itemp->code[0] & ~1) == 0370)
Cyrill Gorcunov1de95002009-11-06 00:08:38 +03002257 return MOK_JUMP;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002258
H. Peter Anvin60926242009-07-26 16:25:38 -07002259 return MOK_GOOD;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002260}
2261
Cyrill Gorcunov10734c72011-08-29 00:07:17 +04002262static enum ea_type process_ea(operand *input, ea *output, int bits,
H. Peter Anvin3089f7e2011-06-22 18:19:28 -07002263 int addrbits, int rfield, opflags_t rflags)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002264{
H. Peter Anvinab5bd052010-07-25 12:43:30 -07002265 bool forw_ref = !!(input->opflags & OPFLAG_UNKNOWN);
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07002266
Cyrill Gorcunov10734c72011-08-29 00:07:17 +04002267 output->type = EA_SCALAR;
2268 output->rip = false;
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00002269
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002270 /* REX flags for the rfield operand */
Cyrill Gorcunov10734c72011-08-29 00:07:17 +04002271 output->rex |= rexflags(rfield, rflags, REX_R | REX_P | REX_W | REX_H);
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002272
Cyrill Gorcunov10734c72011-08-29 00:07:17 +04002273 if (is_class(REGISTER, input->type)) {
2274 /*
2275 * It's a direct register.
2276 */
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002277 opflags_t f;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002278
Cyrill Gorcunov2124b7b2010-07-25 01:16:33 +04002279 if (!is_register(input->basereg))
H. Peter Anvin3089f7e2011-06-22 18:19:28 -07002280 goto err;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002281
Cyrill Gorcunov10734c72011-08-29 00:07:17 +04002282 f = regflag(input);
2283
2284 if (!is_class(REG_EA, f))
H. Peter Anvin3089f7e2011-06-22 18:19:28 -07002285 goto err;
H. Peter Anvin70653092007-10-19 14:42:29 -07002286
Cyrill Gorcunov10734c72011-08-29 00:07:17 +04002287 output->rex |= op_rexflags(input, REX_B | REX_P | REX_W | REX_H);
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002288 output->sib_present = false; /* no SIB necessary */
Cyrill Gorcunov10734c72011-08-29 00:07:17 +04002289 output->bytes = 0; /* no offset necessary either */
2290 output->modrm = GEN_MODRM(3, rfield, nasm_regvals[input->basereg]);
2291 } else {
2292 /*
2293 * It's a memory reference.
2294 */
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002295 if (input->basereg == -1 &&
2296 (input->indexreg == -1 || input->scale == 0)) {
Cyrill Gorcunov10734c72011-08-29 00:07:17 +04002297 /*
2298 * It's a pure offset.
2299 */
Victor van den Elzen0d268fb2010-01-24 21:24:57 +01002300 if (bits == 64 && ((input->type & IP_REL) == IP_REL) &&
2301 input->segment == NO_SEG) {
2302 nasm_error(ERR_WARNING | ERR_PASS1, "absolute address can not be RIP-relative");
2303 input->type &= ~IP_REL;
2304 input->type |= MEMORY;
2305 }
2306
2307 if (input->eaflags & EAF_BYTEOFFS ||
2308 (input->eaflags & EAF_WORDOFFS &&
2309 input->disp_size != (addrbits != 16 ? 32 : 16))) {
2310 nasm_error(ERR_WARNING | ERR_PASS1, "displacement size ignored on absolute address");
2311 }
2312
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002313 if (bits == 64 && (~input->type & IP_REL)) {
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002314 output->sib_present = true;
Cyrill Gorcunov10734c72011-08-29 00:07:17 +04002315 output->sib = GEN_SIB(0, 4, 5);
2316 output->bytes = 4;
2317 output->modrm = GEN_MODRM(0, rfield, 4);
2318 output->rip = false;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002319 } else {
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002320 output->sib_present = false;
Cyrill Gorcunov10734c72011-08-29 00:07:17 +04002321 output->bytes = (addrbits != 16 ? 4 : 2);
2322 output->modrm = GEN_MODRM(0, rfield, (addrbits != 16 ? 5 : 6));
2323 output->rip = bits == 64;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002324 }
Cyrill Gorcunov10734c72011-08-29 00:07:17 +04002325 } else {
2326 /*
2327 * It's an indirection.
2328 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002329 int i = input->indexreg, b = input->basereg, s = input->scale;
H. Peter Anvinab5bd052010-07-25 12:43:30 -07002330 int32_t seg = input->segment;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002331 int hb = input->hintbase, ht = input->hinttype;
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002332 int t, it, bt; /* register numbers */
2333 opflags_t x, ix, bx; /* register flags */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002334
H. Peter Anvine2c80182005-01-15 22:15:51 +00002335 if (s == 0)
2336 i = -1; /* make this easy, at least */
H. Peter Anvin70653092007-10-19 14:42:29 -07002337
Cyrill Gorcunov2124b7b2010-07-25 01:16:33 +04002338 if (is_register(i)) {
H. Peter Anvina4835d42008-05-20 14:21:29 -07002339 it = nasm_regvals[i];
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002340 ix = nasm_reg_flags[i];
2341 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00002342 it = -1;
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002343 ix = 0;
2344 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002345
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002346 if (is_register(b)) {
H. Peter Anvina4835d42008-05-20 14:21:29 -07002347 bt = nasm_regvals[b];
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002348 bx = nasm_reg_flags[b];
2349 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00002350 bt = -1;
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002351 bx = 0;
2352 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002353
H. Peter Anvin3089f7e2011-06-22 18:19:28 -07002354 /* if either one are a vector register... */
2355 if ((ix|bx) & (XMMREG|YMMREG) & ~REG_EA) {
2356 int32_t sok = BITS32 | BITS64;
2357 int32_t o = input->offset;
2358 int mod, scale, index, base;
2359
H. Peter Anvin3089f7e2011-06-22 18:19:28 -07002360 /*
2361 * For a vector SIB, one has to be a vector and the other,
2362 * if present, a GPR. The vector must be the index operand.
2363 */
2364 if (it == -1 || (bx & (XMMREG|YMMREG) & ~REG_EA)) {
2365 if (s == 0)
2366 s = 1;
2367 else if (s != 1)
2368 goto err;
2369
2370 t = bt, bt = it, it = t;
2371 x = bx, bx = ix, ix = x;
2372 }
2373
2374 if (bt != -1) {
2375 if (REG_GPR & ~bx)
2376 goto err;
2377 if (!(REG64 & ~bx) || !(REG32 & ~bx))
2378 sok &= bx;
2379 else
2380 goto err;
2381 }
2382
2383 /*
2384 * While we're here, ensure the user didn't specify
2385 * WORD or QWORD
2386 */
2387 if (input->disp_size == 16 || input->disp_size == 64)
2388 goto err;
2389
2390 if (addrbits == 16 ||
2391 (addrbits == 32 && !(sok & BITS32)) ||
2392 (addrbits == 64 && !(sok & BITS64)))
2393 goto err;
2394
2395 output->type = (ix & YMMREG & ~REG_EA)
2396 ? EA_YMMVSIB : EA_XMMVSIB;
2397
2398 output->rex |= rexflags(it, ix, REX_X);
2399 output->rex |= rexflags(bt, bx, REX_B);
2400
2401 index = it & 7; /* it is known to be != -1 */
2402
2403 switch (s) {
2404 case 1:
2405 scale = 0;
2406 break;
2407 case 2:
2408 scale = 1;
2409 break;
2410 case 4:
2411 scale = 2;
2412 break;
2413 case 8:
2414 scale = 3;
2415 break;
2416 default: /* then what the smeg is it? */
2417 goto err; /* panic */
2418 }
2419
2420 if (bt == -1) {
2421 base = 5;
2422 mod = 0;
2423 } else {
2424 base = (bt & 7);
2425 if (base != REG_NUM_EBP && o == 0 &&
2426 seg == NO_SEG && !forw_ref &&
2427 !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
2428 mod = 0;
2429 else if (input->eaflags & EAF_BYTEOFFS ||
2430 (o >= -128 && o <= 127 &&
2431 seg == NO_SEG && !forw_ref &&
2432 !(input->eaflags & EAF_WORDOFFS)))
2433 mod = 1;
2434 else
2435 mod = 2;
2436 }
2437
2438 output->sib_present = true;
Cyrill Gorcunov10734c72011-08-29 00:07:17 +04002439 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
2440 output->modrm = GEN_MODRM(mod, rfield, 4);
2441 output->sib = GEN_SIB(scale, index, base);
H. Peter Anvin3089f7e2011-06-22 18:19:28 -07002442 } else if ((ix|bx) & (BITS32|BITS64)) {
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002443 /*
2444 * it must be a 32/64-bit memory reference. Firstly we have
2445 * to check that all registers involved are type E/Rxx.
2446 */
H. Peter Anvin3089f7e2011-06-22 18:19:28 -07002447 int32_t sok = BITS32 | BITS64;
2448 int32_t o = input->offset;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002449
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002450 if (it != -1) {
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002451 if (!(REG64 & ~ix) || !(REG32 & ~ix))
2452 sok &= ix;
2453 else
H. Peter Anvin3089f7e2011-06-22 18:19:28 -07002454 goto err;
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002455 }
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002456
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002457 if (bt != -1) {
2458 if (REG_GPR & ~bx)
H. Peter Anvin3089f7e2011-06-22 18:19:28 -07002459 goto err; /* Invalid register */
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002460 if (~sok & bx & SIZE_MASK)
H. Peter Anvin3089f7e2011-06-22 18:19:28 -07002461 goto err; /* Invalid size */
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002462 sok &= bx;
2463 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002464
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002465 /*
2466 * While we're here, ensure the user didn't specify
2467 * WORD or QWORD
2468 */
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002469 if (input->disp_size == 16 || input->disp_size == 64)
H. Peter Anvin3089f7e2011-06-22 18:19:28 -07002470 goto err;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002471
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002472 if (addrbits == 16 ||
2473 (addrbits == 32 && !(sok & BITS32)) ||
2474 (addrbits == 64 && !(sok & BITS64)))
H. Peter Anvin3089f7e2011-06-22 18:19:28 -07002475 goto err;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002476
Keith Kaniosb7a89542007-04-12 02:40:54 +00002477 /* now reorganize base/index */
2478 if (s == 1 && bt != it && bt != -1 && it != -1 &&
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002479 ((hb == b && ht == EAH_NOTBASE) ||
2480 (hb == i && ht == EAH_MAKEBASE))) {
2481 /* swap if hints say so */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002482 t = bt, bt = it, it = t;
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002483 x = bx, bx = ix, ix = x;
2484 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00002485 if (bt == it) /* convert EAX+2*EAX to 3*EAX */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002486 bt = -1, bx = 0, s++;
2487 if (bt == -1 && s == 1 && !(hb == it && ht == EAH_NOTBASE)) {
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002488 /* make single reg base, unless hint */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002489 bt = it, bx = ix, it = -1, ix = 0;
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002490 }
2491 if (((s == 2 && it != REG_NUM_ESP && !(input->eaflags & EAF_TIMESTWO)) ||
2492 s == 3 || s == 5 || s == 9) && bt == -1)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002493 bt = it, bx = ix, s--; /* convert 3*EAX to EAX+2*EAX */
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002494 if (it == -1 && (bt & 7) != REG_NUM_ESP &&
2495 (input->eaflags & EAF_TIMESTWO))
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002496 it = bt, ix = bx, bt = -1, bx = 0, s = 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002497 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
Keith Kanios48af1772007-08-17 07:37:52 +00002498 if (s == 1 && it == REG_NUM_ESP) {
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002499 /* swap ESP into base if scale is 1 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002500 t = it, it = bt, bt = t;
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002501 x = ix, ix = bx, bx = x;
2502 }
2503 if (it == REG_NUM_ESP ||
2504 (s != 1 && s != 2 && s != 4 && s != 8 && it != -1))
H. Peter Anvin3089f7e2011-06-22 18:19:28 -07002505 goto err; /* wrong, for various reasons */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002506
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002507 output->rex |= rexflags(it, ix, REX_X);
2508 output->rex |= rexflags(bt, bx, REX_B);
Keith Kaniosb7a89542007-04-12 02:40:54 +00002509
Keith Kanios48af1772007-08-17 07:37:52 +00002510 if (it == -1 && (bt & 7) != REG_NUM_ESP) {
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002511 /* no SIB needed */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002512 int mod, rm;
H. Peter Anvin70653092007-10-19 14:42:29 -07002513
Keith Kaniosb7a89542007-04-12 02:40:54 +00002514 if (bt == -1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002515 rm = 5;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002516 mod = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002517 } else {
2518 rm = (bt & 7);
H. Peter Anvinab5bd052010-07-25 12:43:30 -07002519 if (rm != REG_NUM_EBP && o == 0 &&
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002520 seg == NO_SEG && !forw_ref &&
2521 !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
Keith Kaniosb7a89542007-04-12 02:40:54 +00002522 mod = 0;
H. Peter Anvinab5bd052010-07-25 12:43:30 -07002523 else if (input->eaflags & EAF_BYTEOFFS ||
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002524 (o >= -128 && o <= 127 &&
2525 seg == NO_SEG && !forw_ref &&
2526 !(input->eaflags & EAF_WORDOFFS)))
Keith Kaniosb7a89542007-04-12 02:40:54 +00002527 mod = 1;
2528 else
2529 mod = 2;
2530 }
H. Peter Anvinea838272002-04-30 20:51:53 +00002531
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002532 output->sib_present = false;
Cyrill Gorcunov10734c72011-08-29 00:07:17 +04002533 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
2534 output->modrm = GEN_MODRM(mod, rfield, rm);
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002535 } else {
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002536 /* we need a SIB */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002537 int mod, scale, index, base;
H. Peter Anvin70653092007-10-19 14:42:29 -07002538
Keith Kaniosb7a89542007-04-12 02:40:54 +00002539 if (it == -1)
2540 index = 4, s = 1;
2541 else
2542 index = (it & 7);
H. Peter Anvin70653092007-10-19 14:42:29 -07002543
H. Peter Anvine2c80182005-01-15 22:15:51 +00002544 switch (s) {
2545 case 1:
2546 scale = 0;
2547 break;
2548 case 2:
2549 scale = 1;
2550 break;
2551 case 4:
2552 scale = 2;
2553 break;
2554 case 8:
2555 scale = 3;
2556 break;
2557 default: /* then what the smeg is it? */
H. Peter Anvin3089f7e2011-06-22 18:19:28 -07002558 goto err; /* panic */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002559 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002560
Keith Kaniosb7a89542007-04-12 02:40:54 +00002561 if (bt == -1) {
2562 base = 5;
2563 mod = 0;
2564 } else {
2565 base = (bt & 7);
H. Peter Anvinab5bd052010-07-25 12:43:30 -07002566 if (base != REG_NUM_EBP && o == 0 &&
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002567 seg == NO_SEG && !forw_ref &&
2568 !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
Keith Kaniosb7a89542007-04-12 02:40:54 +00002569 mod = 0;
H. Peter Anvinab5bd052010-07-25 12:43:30 -07002570 else if (input->eaflags & EAF_BYTEOFFS ||
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002571 (o >= -128 && o <= 127 &&
2572 seg == NO_SEG && !forw_ref &&
2573 !(input->eaflags & EAF_WORDOFFS)))
Keith Kaniosb7a89542007-04-12 02:40:54 +00002574 mod = 1;
2575 else
2576 mod = 2;
2577 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002578
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002579 output->sib_present = true;
Cyrill Gorcunov10734c72011-08-29 00:07:17 +04002580 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
2581 output->modrm = GEN_MODRM(mod, rfield, 4);
2582 output->sib = GEN_SIB(scale, index, base);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002583 }
2584 } else { /* it's 16-bit */
2585 int mod, rm;
H. Peter Anvinab5bd052010-07-25 12:43:30 -07002586 int16_t o = input->offset;
H. Peter Anvin70653092007-10-19 14:42:29 -07002587
Keith Kaniosb7a89542007-04-12 02:40:54 +00002588 /* check for 64-bit long mode */
2589 if (addrbits == 64)
H. Peter Anvin3089f7e2011-06-22 18:19:28 -07002590 goto err;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002591
H. Peter Anvine2c80182005-01-15 22:15:51 +00002592 /* check all registers are BX, BP, SI or DI */
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002593 if ((b != -1 && b != R_BP && b != R_BX && b != R_SI && b != R_DI) ||
2594 (i != -1 && i != R_BP && i != R_BX && i != R_SI && i != R_DI))
H. Peter Anvin3089f7e2011-06-22 18:19:28 -07002595 goto err;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002596
Keith Kaniosb7a89542007-04-12 02:40:54 +00002597 /* ensure the user didn't specify DWORD/QWORD */
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002598 if (input->disp_size == 32 || input->disp_size == 64)
H. Peter Anvin3089f7e2011-06-22 18:19:28 -07002599 goto err;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002600
H. Peter Anvine2c80182005-01-15 22:15:51 +00002601 if (s != 1 && i != -1)
H. Peter Anvin3089f7e2011-06-22 18:19:28 -07002602 goto err; /* no can do, in 16-bit EA */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002603 if (b == -1 && i != -1) {
2604 int tmp = b;
2605 b = i;
2606 i = tmp;
2607 } /* swap */
2608 if ((b == R_SI || b == R_DI) && i != -1) {
2609 int tmp = b;
2610 b = i;
2611 i = tmp;
2612 }
2613 /* have BX/BP as base, SI/DI index */
2614 if (b == i)
H. Peter Anvin3089f7e2011-06-22 18:19:28 -07002615 goto err; /* shouldn't ever happen, in theory */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002616 if (i != -1 && b != -1 &&
2617 (i == R_BP || i == R_BX || b == R_SI || b == R_DI))
H. Peter Anvin3089f7e2011-06-22 18:19:28 -07002618 goto err; /* invalid combinations */
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002619 if (b == -1) /* pure offset: handled above */
H. Peter Anvin3089f7e2011-06-22 18:19:28 -07002620 goto err; /* so if it gets to here, panic! */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002621
H. Peter Anvine2c80182005-01-15 22:15:51 +00002622 rm = -1;
2623 if (i != -1)
2624 switch (i * 256 + b) {
2625 case R_SI * 256 + R_BX:
2626 rm = 0;
2627 break;
2628 case R_DI * 256 + R_BX:
2629 rm = 1;
2630 break;
2631 case R_SI * 256 + R_BP:
2632 rm = 2;
2633 break;
2634 case R_DI * 256 + R_BP:
2635 rm = 3;
2636 break;
2637 } else
2638 switch (b) {
2639 case R_SI:
2640 rm = 4;
2641 break;
2642 case R_DI:
2643 rm = 5;
2644 break;
2645 case R_BP:
2646 rm = 6;
2647 break;
2648 case R_BX:
2649 rm = 7;
2650 break;
2651 }
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002652 if (rm == -1) /* can't happen, in theory */
H. Peter Anvin3089f7e2011-06-22 18:19:28 -07002653 goto err; /* so panic if it does */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002654
H. Peter Anvinab5bd052010-07-25 12:43:30 -07002655 if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
2656 !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
H. Peter Anvine2c80182005-01-15 22:15:51 +00002657 mod = 0;
H. Peter Anvinab5bd052010-07-25 12:43:30 -07002658 else if (input->eaflags & EAF_BYTEOFFS ||
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002659 (o >= -128 && o <= 127 && seg == NO_SEG &&
2660 !forw_ref && !(input->eaflags & EAF_WORDOFFS)))
H. Peter Anvine2c80182005-01-15 22:15:51 +00002661 mod = 1;
2662 else
2663 mod = 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002664
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002665 output->sib_present = false; /* no SIB - it's 16-bit */
Cyrill Gorcunov10734c72011-08-29 00:07:17 +04002666 output->bytes = mod; /* bytes of offset needed */
2667 output->modrm = GEN_MODRM(mod, rfield, rm);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002668 }
2669 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002670 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002671
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002672 output->size = 1 + output->sib_present + output->bytes;
H. Peter Anvin3089f7e2011-06-22 18:19:28 -07002673 return output->type;
2674
2675err:
2676 return output->type = EA_INVALID;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002677}
2678
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002679static void add_asp(insn *ins, int addrbits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002680{
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002681 int j, valid;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002682 int defdisp;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002683
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002684 valid = (addrbits == 64) ? 64|32 : 32|16;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002685
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002686 switch (ins->prefixes[PPS_ASIZE]) {
2687 case P_A16:
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002688 valid &= 16;
2689 break;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002690 case P_A32:
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002691 valid &= 32;
2692 break;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002693 case P_A64:
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002694 valid &= 64;
2695 break;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002696 case P_ASP:
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002697 valid &= (addrbits == 32) ? 16 : 32;
2698 break;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002699 default:
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002700 break;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002701 }
2702
2703 for (j = 0; j < ins->operands; j++) {
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002704 if (is_class(MEMORY, ins->oprs[j].type)) {
2705 opflags_t i, b;
H. Peter Anvin70653092007-10-19 14:42:29 -07002706
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002707 /* Verify as Register */
Cyrill Gorcunov2124b7b2010-07-25 01:16:33 +04002708 if (!is_register(ins->oprs[j].indexreg))
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002709 i = 0;
2710 else
2711 i = nasm_reg_flags[ins->oprs[j].indexreg];
H. Peter Anvin70653092007-10-19 14:42:29 -07002712
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002713 /* Verify as Register */
Cyrill Gorcunov2124b7b2010-07-25 01:16:33 +04002714 if (!is_register(ins->oprs[j].basereg))
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002715 b = 0;
2716 else
2717 b = nasm_reg_flags[ins->oprs[j].basereg];
H. Peter Anvin70653092007-10-19 14:42:29 -07002718
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002719 if (ins->oprs[j].scale == 0)
2720 i = 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002721
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002722 if (!i && !b) {
2723 int ds = ins->oprs[j].disp_size;
2724 if ((addrbits != 64 && ds > 8) ||
2725 (addrbits == 64 && ds == 16))
2726 valid &= ds;
2727 } else {
2728 if (!(REG16 & ~b))
2729 valid &= 16;
2730 if (!(REG32 & ~b))
2731 valid &= 32;
2732 if (!(REG64 & ~b))
2733 valid &= 64;
H. Peter Anvin70653092007-10-19 14:42:29 -07002734
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002735 if (!(REG16 & ~i))
2736 valid &= 16;
2737 if (!(REG32 & ~i))
2738 valid &= 32;
2739 if (!(REG64 & ~i))
2740 valid &= 64;
2741 }
2742 }
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002743 }
2744
2745 if (valid & addrbits) {
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002746 ins->addr_size = addrbits;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002747 } else if (valid & ((addrbits == 32) ? 16 : 32)) {
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002748 /* Add an address size prefix */
Cyrill Gorcunovd6851d42011-09-25 18:01:45 +04002749 ins->prefixes[PPS_ASIZE] = (addrbits == 32) ? P_A16 : P_A32;;
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002750 ins->addr_size = (addrbits == 32) ? 16 : 32;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002751 } else {
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002752 /* Impossible... */
2753 errfunc(ERR_NONFATAL, "impossible combination of address sizes");
2754 ins->addr_size = addrbits; /* Error recovery */
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002755 }
2756
2757 defdisp = ins->addr_size == 16 ? 16 : 32;
2758
2759 for (j = 0; j < ins->operands; j++) {
Cyrill Gorcunovd6f31242010-07-26 23:14:40 +04002760 if (!(MEM_OFFS & ~ins->oprs[j].type) &&
2761 (ins->oprs[j].disp_size ? ins->oprs[j].disp_size : defdisp) != ins->addr_size) {
2762 /*
2763 * mem_offs sizes must match the address size; if not,
2764 * strip the MEM_OFFS bit and match only EA instructions
2765 */
2766 ins->oprs[j].type &= ~(MEM_OFFS & ~MEMORY);
2767 }
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002768 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002769}