blob: aafbee806964275ee2c208b629cdf62b1f3d8991 [file] [log] [blame]
H. Peter Anvin9e6747c2009-06-28 17:13:04 -07001/* ----------------------------------------------------------------------- *
2 *
3 * Copyright 1996-2009 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00006 *
H. Peter Anvin9e6747c2009-06-28 17:13:04 -07007 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
9 * conditions are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 * ----------------------------------------------------------------------- */
33
34/*
35 * assemble.c code generation for the Netwide Assembler
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000036 *
37 * the actual codes (C syntax, i.e. octal):
38 * \0 - terminates the code. (Unless it's a literal of course.)
H. Peter Anvindcffe4b2008-10-10 22:10:31 -070039 * \1..\4 - that many literal bytes follow in the code stream
40 * \5 - add 4 to the primary operand number (b, low octdigit)
41 * \6 - add 4 to the secondary operand number (a, middle octdigit)
42 * \7 - add 4 to both the primary and the secondary operand number
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070043 * \10..\13 - a literal byte follows in the code stream, to be added
44 * to the register value of operand 0..3
45 * \14..\17 - a signed byte immediate operand, from operand 0..3
46 * \20..\23 - a byte immediate operand, from operand 0..3
47 * \24..\27 - an unsigned byte immediate operand, from operand 0..3
48 * \30..\33 - a word immediate operand, from operand 0..3
49 * \34..\37 - select between \3[0-3] and \4[0-3] depending on 16/32 bit
H. Peter Anvin3ba46772002-05-27 23:19:35 +000050 * assembly mode or the operand-size override on the operand
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070051 * \40..\43 - a long immediate operand, from operand 0..3
52 * \44..\47 - select between \3[0-3], \4[0-3] and \5[4-7]
H. Peter Anvinde4b89b2007-10-01 15:41:25 -070053 * depending on the address size of the instruction.
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070054 * \50..\53 - a byte relative operand, from operand 0..3
55 * \54..\57 - a qword immediate operand, from operand 0..3
56 * \60..\63 - a word relative operand, from operand 0..3
57 * \64..\67 - select between \6[0-3] and \7[0-3] depending on 16/32 bit
H. Peter Anvin17799b42002-05-21 03:31:21 +000058 * assembly mode or the operand-size override on the operand
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070059 * \70..\73 - a long relative operand, from operand 0..3
H. Peter Anvinc1377e92008-10-06 23:40:31 -070060 * \74..\77 - a word constant, from the _segment_ part of operand 0..3
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000061 * \1ab - a ModRM, calculated on EA in operand a, with the spare
62 * field the register value of operand b.
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070063 * \140..\143 - an immediate word or signed byte for operand 0..3
H. Peter Anvina30cc072007-11-18 21:55:26 -080064 * \144..\147 - or 2 (s-field) into opcode byte if operand 0..3
65 * is a signed byte rather than a word. Opcode byte follows.
H. Peter Anvinc1377e92008-10-06 23:40:31 -070066 * \150..\153 - an immediate dword or signed byte for operand 0..3
H. Peter Anvina30cc072007-11-18 21:55:26 -080067 * \154..\157 - or 2 (s-field) into opcode byte if operand 0..3
H. Peter Anvin32cd4c22008-04-04 13:34:53 -070068 * is a signed byte rather than a dword. Opcode byte follows.
H. Peter Anvin401c07e2007-09-17 16:55:04 -070069 * \160..\163 - this instruction uses DREX rather than REX, with the
70 * OC0 field set to 0, and the dest field taken from
71 * operand 0..3.
72 * \164..\167 - this instruction uses DREX rather than REX, with the
73 * OC0 field set to 1, and the dest field taken from
74 * operand 0..3.
H. Peter Anvin401c07e2007-09-17 16:55:04 -070075 * \171 - placement of DREX suffix in the absence of an EA
H. Peter Anvind85d2502008-05-04 17:53:31 -070076 * \172\ab - the register number from operand a in bits 7..4, with
H. Peter Anvin52dc3532008-05-20 19:29:04 -070077 * the 4-bit immediate from operand b in bits 3..0.
H. Peter Anvind58656f2008-05-06 20:11:14 -070078 * \173\xab - the register number from operand a in bits 7..4, with
H. Peter Anvin52dc3532008-05-20 19:29:04 -070079 * the value b in bits 3..0.
80 * \174\a - the register number from operand a in bits 7..4, and
81 * an arbitrary value in bits 3..0 (assembled as zero.)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000082 * \2ab - a ModRM, calculated on EA in operand a, with the spare
83 * field equal to digit b.
H. Peter Anvin32cd4c22008-04-04 13:34:53 -070084 * \250..\253 - same as \150..\153, except warn if the 64-bit operand
85 * is not equal to the truncated and sign-extended 32-bit
86 * operand; used for 32-bit immediates in 64-bit mode.
H. Peter Anvin588df782008-10-07 10:05:10 -070087 * \254..\257 - a signed 32-bit operand to be extended to 64 bits.
H. Peter Anvina04019c2009-05-03 21:42:34 -070088 * \260..\263 - this instruction uses VEX/XOP rather than REX, with the
H. Peter Anvind85d2502008-05-04 17:53:31 -070089 * V field taken from operand 0..3.
H. Peter Anvina04019c2009-05-03 21:42:34 -070090 * \270 - this instruction uses VEX/XOP rather than REX, with the
H. Peter Anvind85d2502008-05-04 17:53:31 -070091 * V field set to 1111b.
92 *
H. Peter Anvina04019c2009-05-03 21:42:34 -070093 * VEX/XOP prefixes are followed by the sequence:
94 * \tmm\wlp where mm is the M field; and wlp is:
H. Peter Anvinaaa088f2008-05-12 11:13:41 -070095 * 00 0ww lpp
H. Peter Anvinbd420c72008-05-22 11:24:35 -070096 * [w0] ww = 0 for W = 0
97 * [w1] ww = 1 for W = 1
98 * [wx] ww = 2 for W don't care (always assembled as 0)
99 * [ww] ww = 3 for W used as REX.W
100 *
H. Peter Anvina04019c2009-05-03 21:42:34 -0700101 * t = 0 for VEX (C4/C5), t = 1 for XOP (8F).
H. Peter Anvind85d2502008-05-04 17:53:31 -0700102 *
H. Peter Anvinc1377e92008-10-06 23:40:31 -0700103 * \274..\277 - a signed byte immediate operand, from operand 0..3,
104 * which is to be extended to the operand size.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000105 * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
106 * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
H. Peter Anvind28f07f2009-06-26 16:18:00 -0700107 * \312 - (disassembler only) invalid with non-default address size.
H. Peter Anvince2b3972007-05-30 22:21:11 +0000108 * \313 - indicates fixed 64-bit address size, 0x67 invalid.
H. Peter Anvin23440102007-11-12 21:02:33 -0800109 * \314 - (disassembler only) invalid with REX.B
110 * \315 - (disassembler only) invalid with REX.X
111 * \316 - (disassembler only) invalid with REX.R
112 * \317 - (disassembler only) invalid with REX.W
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000113 * \320 - indicates fixed 16-bit operand size, i.e. optional 0x66.
114 * \321 - indicates fixed 32-bit operand size, i.e. optional 0x66.
115 * \322 - indicates that this instruction is only valid when the
116 * operand size is the default (instruction to disassembler,
117 * generates no code in the assembler)
H. Peter Anvince2b3972007-05-30 22:21:11 +0000118 * \323 - indicates fixed 64-bit operand size, REX on extensions only.
Keith Kaniosb7a89542007-04-12 02:40:54 +0000119 * \324 - indicates 64-bit operand size requiring REX prefix.
H. Peter Anvin9472dab2009-06-24 21:38:29 -0700120 * \325 - instruction which always uses spl/bpl/sil/dil
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000121 * \330 - a literal byte follows in the code stream, to be added
122 * to the condition code value of the instruction.
Keith Kanios48af1772007-08-17 07:37:52 +0000123 * \331 - instruction not valid with REP prefix. Hint for
H. Peter Anvinef7468f2002-04-30 20:57:59 +0000124 * disassembler only; for SSE instructions.
H. Peter Anvincb9b6902007-09-12 21:58:51 -0700125 * \332 - REP prefix (0xF2 byte) used as opcode extension.
126 * \333 - REP prefix (0xF3 byte) used as opcode extension.
H. Peter Anvin9472dab2009-06-24 21:38:29 -0700127 * \334 - LOCK prefix used as REX.R (used in non-64-bit mode)
H. Peter Anvincb9b6902007-09-12 21:58:51 -0700128 * \335 - disassemble a rep (0xF3 byte) prefix as repe not rep.
H. Peter Anvin962e3052008-08-28 17:47:16 -0700129 * \336 - force a REP(E) prefix (0xF2) even if not specified.
130 * \337 - force a REPNE prefix (0xF3) even if not specified.
131 * \336-\337 are still listed as prefixes in the disassembler.
Keith Kaniosb7a89542007-04-12 02:40:54 +0000132 * \340 - reserve <operand 0> bytes of uninitialized storage.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000133 * Operand 0 had better be a segmentless constant.
H. Peter Anvinc2acf7b2009-02-21 18:22:56 -0800134 * \341 - this instruction needs a WAIT "prefix"
H. Peter Anvinff6e12d2008-10-08 21:17:32 -0700135 * \344,\345 - the PUSH/POP (respectively) codes for CS, DS, ES, SS
136 * (POP is never used for CS) depending on operand 0
137 * \346,\347 - the second byte of PUSH/POP codes for FS, GS, depending
138 * on operand 0
H. Peter Anvinfff5a472008-05-20 09:46:24 -0700139 * \360 - no SSE prefix (== \364\331)
140 * \361 - 66 SSE prefix (== \366\331)
141 * \362 - F2 SSE prefix (== \364\332)
142 * \363 - F3 SSE prefix (== \364\333)
H. Peter Anvin62cb6062007-09-11 22:44:03 +0000143 * \364 - operand-size prefix (0x66) not permitted
144 * \365 - address-size prefix (0x67) not permitted
145 * \366 - operand-size prefix (0x66) used as opcode extension
146 * \367 - address-size prefix (0x67) used as opcode extension
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000147 * \370,\371,\372 - match only if operand 0 meets byte jump criteria.
148 * 370 is used for Jcc, 371 is used for JMP.
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000149 * \373 - assemble 0x03 if bits==16, 0x05 if bits==32;
150 * used for conditional jump over longer jump
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000151 */
152
H. Peter Anvinfe501952007-10-02 21:53:51 -0700153#include "compiler.h"
154
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000155#include <stdio.h>
156#include <string.h>
Keith Kaniosb7a89542007-04-12 02:40:54 +0000157#include <inttypes.h>
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000158
159#include "nasm.h"
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000160#include "nasmlib.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000161#include "assemble.h"
162#include "insns.h"
H. Peter Anvina4835d42008-05-20 14:21:29 -0700163#include "tables.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000164
H. Peter Anvin65289e82009-07-25 17:25:11 -0700165enum match_result {
166 /*
167 * Matching errors. These should be sorted so that more specific
168 * errors come later in the sequence.
169 */
170 MERR_INVALOP,
171 MERR_OPSIZEMISSING,
172 MERR_OPSIZEMISMATCH,
173 MERR_BADCPU,
174 MERR_BADMODE,
175 /*
176 * Matching success; the conditional ones first
177 */
178 MOK_JUMP, /* Matching OK but needs jmp_match() */
179 MOK_GOOD /* Matching unconditionally OK */
180};
181
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000182typedef struct {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000183 int sib_present; /* is a SIB byte necessary? */
184 int bytes; /* # of bytes of offset needed */
185 int size; /* lazy - this is sib+bytes+1 */
186 uint8_t modrm, sib, rex, rip; /* the bytes themselves */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000187} ea;
188
Keith Kaniosb7a89542007-04-12 02:40:54 +0000189static uint32_t cpu; /* cpu level received from nasm.c */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000190static efunc errfunc;
191static struct ofmt *outfmt;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000192static ListGen *list;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000193
H. Peter Anvin3720f7b2008-05-12 11:00:50 -0700194static int64_t calcsize(int32_t, int64_t, int, insn *, const uint8_t *);
H. Peter Anvin833caea2008-10-04 19:02:30 -0700195static void gencode(int32_t segment, int64_t offset, int bits,
196 insn * ins, const struct itemplate *temp,
197 int64_t insn_end);
H. Peter Anvin65289e82009-07-25 17:25:11 -0700198static enum match_result matches(const struct itemplate *, insn *, int bits);
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000199static int32_t regflag(const operand *);
200static int32_t regval(const operand *);
201static int rexflags(int, int32_t, int);
202static int op_rexflags(const operand *, int);
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700203static ea *process_ea(operand *, ea *, int, int, int, int32_t);
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700204static void add_asp(insn *, int);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000205
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700206static int has_prefix(insn * ins, enum prefix_pos pos, enum prefixes prefix)
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000207{
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700208 return ins->prefixes[pos] == prefix;
209}
210
211static void assert_no_prefix(insn * ins, enum prefix_pos pos)
212{
213 if (ins->prefixes[pos])
214 errfunc(ERR_NONFATAL, "invalid %s prefix",
215 prefix_name(ins->prefixes[pos]));
216}
217
218static const char *size_name(int size)
219{
220 switch (size) {
221 case 1:
222 return "byte";
223 case 2:
224 return "word";
225 case 4:
226 return "dword";
227 case 8:
228 return "qword";
229 case 10:
230 return "tword";
231 case 16:
232 return "oword";
H. Peter Anvindfb91802008-05-20 11:43:53 -0700233 case 32:
234 return "yword";
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700235 default:
236 return "???";
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000237 }
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700238}
239
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700240static void warn_overflow(int size, const struct operand *o)
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700241{
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700242 if (size < 8 && o->wrt == NO_SEG && o->segment == NO_SEG) {
Charles Craynedd462c82007-11-04 15:28:30 -0800243 int64_t lim = ((int64_t)1 << (size*8))-1;
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700244 int64_t data = o->offset;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000245
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700246 if (data < ~lim || data > lim)
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700247 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700248 "%s data exceeds bounds", size_name(size));
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700249 }
250}
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000251/*
252 * This routine wrappers the real output format's output routine,
253 * in order to pass a copy of the data off to the listing file
254 * generator at the same time.
255 */
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800256static void out(int64_t offset, int32_t segto, const void *data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800257 enum out_type type, uint64_t size,
258 int32_t segment, int32_t wrt)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000259{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000260 static int32_t lineno = 0; /* static!!! */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000261 static char *lnfname = NULL;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800262 uint8_t p[8];
H. Peter Anvineba20a72002-04-30 20:53:55 +0000263
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800264 if (type == OUT_ADDRESS && segment == NO_SEG && wrt == NO_SEG) {
265 /*
266 * This is a non-relocated address, and we're going to
267 * convert it into RAWDATA format.
268 */
269 uint8_t *q = p;
H. Peter Anvind1fb15c2007-11-13 09:37:59 -0800270
271 if (size > 8) {
272 errfunc(ERR_PANIC, "OUT_ADDRESS with size > 8");
273 return;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800274 }
H. Peter Anvind85d2502008-05-04 17:53:31 -0700275
H. Peter Anvind1fb15c2007-11-13 09:37:59 -0800276 WRITEADDR(q, *(int64_t *)data, size);
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800277 data = p;
278 type = OUT_RAWDATA;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000279 }
280
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800281 list->output(offset, data, type, size);
282
Frank Kotlerabebb082003-09-06 04:45:37 +0000283 /*
284 * this call to src_get determines when we call the
285 * debug-format-specific "linenum" function
286 * it updates lineno and lnfname to the current values
287 * returning 0 if "same as last time", -2 if lnfname
288 * changed, and the amount by which lineno changed,
289 * if it did. thus, these variables must be static
290 */
291
H. Peter Anvine2c80182005-01-15 22:15:51 +0000292 if (src_get(&lineno, &lnfname)) {
293 outfmt->current_dfmt->linenum(lnfname, lineno, segto);
H. Peter Anvince616072002-04-30 21:02:23 +0000294 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000295
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800296 outfmt->output(segto, data, type, size, segment, wrt);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000297}
298
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700299static bool jmp_match(int32_t segment, int64_t offset, int bits,
H. Peter Anvin3720f7b2008-05-12 11:00:50 -0700300 insn * ins, const uint8_t *code)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000301{
Charles Crayne5fbbc8c2007-11-07 19:03:46 -0800302 int64_t isize;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000303 uint8_t c = code[0];
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000304
Charles Craynef1aefd82008-09-30 16:11:32 -0700305 if ((c != 0370 && c != 0371) || (ins->oprs[0].type & STRICT))
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700306 return false;
307 if (!optimizing)
308 return false;
309 if (optimizing < 0 && c == 0371)
310 return false;
311
H. Peter Anvine2c80182005-01-15 22:15:51 +0000312 isize = calcsize(segment, offset, bits, ins, code);
Victor van den Elzenccafc3c2009-02-23 04:35:00 +0100313
Victor van den Elzen154e5922009-02-25 17:32:00 +0100314 if (ins->oprs[0].opflags & OPFLAG_UNKNOWN)
Victor van den Elzenccafc3c2009-02-23 04:35:00 +0100315 /* Be optimistic in pass 1 */
316 return true;
317
H. Peter Anvine2c80182005-01-15 22:15:51 +0000318 if (ins->oprs[0].segment != segment)
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700319 return false;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000320
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700321 isize = ins->oprs[0].offset - offset - isize; /* isize is delta */
322 return (isize >= -128 && isize <= 127); /* is it byte size? */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000323}
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000324
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800325int64_t assemble(int32_t segment, int64_t offset, int bits, uint32_t cp,
H. Peter Anvin65289e82009-07-25 17:25:11 -0700326 insn * instruction, struct ofmt *output, efunc error,
327 ListGen * listgen)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000328{
H. Peter Anvin3360d792007-09-11 04:16:57 +0000329 const struct itemplate *temp;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000330 int j;
H. Peter Anvin65289e82009-07-25 17:25:11 -0700331 enum match_result size_prob;
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800332 int64_t insn_end;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000333 int32_t itimes;
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800334 int64_t start = offset;
335 int64_t wsize = 0; /* size for DB etc. */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000336
H. Peter Anvine2c80182005-01-15 22:15:51 +0000337 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000338 cpu = cp;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000339 outfmt = output; /* likewise */
340 list = listgen; /* and again */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000341
H. Peter Anvine2c80182005-01-15 22:15:51 +0000342 switch (instruction->opcode) {
343 case -1:
344 return 0;
345 case I_DB:
346 wsize = 1;
347 break;
348 case I_DW:
349 wsize = 2;
350 break;
351 case I_DD:
352 wsize = 4;
353 break;
354 case I_DQ:
355 wsize = 8;
356 break;
357 case I_DT:
358 wsize = 10;
359 break;
H. Peter Anvincfbe7c32007-09-18 17:49:09 -0700360 case I_DO:
361 wsize = 16;
362 break;
H. Peter Anvindfb91802008-05-20 11:43:53 -0700363 case I_DY:
364 wsize = 32;
365 break;
H. Peter Anvin16b0a332007-09-12 20:27:41 -0700366 default:
367 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000368 }
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 */
378 for (e = instruction->eops; e; e = e->next) {
379 if (e->type == EOT_DB_NUMBER) {
380 if (wsize == 1) {
381 if (e->segment != NO_SEG)
382 errfunc(ERR_NONFATAL,
383 "one-byte relocation attempted");
384 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000385 uint8_t out_byte = e->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000386 out(offset, segment, &out_byte,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800387 OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000388 }
Keith Kanios61ff53c2007-04-14 18:54:52 +0000389 } else if (wsize > 8) {
H. Peter Anvin3be5d852008-05-20 14:49:32 -0700390 errfunc(ERR_NONFATAL,
391 "integer supplied to a DT, DO or DY"
Keith Kanios61ff53c2007-04-14 18:54:52 +0000392 " instruction");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000393 } else
394 out(offset, segment, &e->offset,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800395 OUT_ADDRESS, wsize, e->segment, e->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000396 offset += wsize;
H. Peter Anvin518df302008-06-14 16:53:48 -0700397 } else if (e->type == EOT_DB_STRING ||
398 e->type == EOT_DB_STRING_FREE) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000399 int align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000400
H. Peter Anvine2c80182005-01-15 22:15:51 +0000401 out(offset, segment, e->stringval,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800402 OUT_RAWDATA, e->stringlen, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000403 align = e->stringlen % wsize;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000404
H. Peter Anvine2c80182005-01-15 22:15:51 +0000405 if (align) {
406 align = wsize - align;
H. Peter Anvin999868f2009-02-09 11:03:33 +0100407 out(offset, segment, zero_buffer,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800408 OUT_RAWDATA, align, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000409 }
410 offset += e->stringlen + align;
411 }
412 }
413 if (t > 0 && t == instruction->times - 1) {
414 /*
415 * Dummy call to list->output to give the offset to the
416 * listing module.
417 */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800418 list->output(offset, NULL, OUT_RAWDATA, 0);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000419 list->uplevel(LIST_TIMES);
420 }
421 }
422 if (instruction->times > 1)
423 list->downlevel(LIST_TIMES);
424 return offset - start;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000425 }
426
H. Peter Anvine2c80182005-01-15 22:15:51 +0000427 if (instruction->opcode == I_INCBIN) {
H. Peter Anvin518df302008-06-14 16:53:48 -0700428 const char *fname = instruction->eops->stringval;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000429 FILE *fp;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000430
H. Peter Anvin418ca702008-05-30 10:42:30 -0700431 fp = fopen(fname, "rb");
432 if (!fp) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000433 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
434 fname);
H. Peter Anvin418ca702008-05-30 10:42:30 -0700435 } else if (fseek(fp, 0L, SEEK_END) < 0) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000436 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
437 fname);
H. Peter Anvin418ca702008-05-30 10:42:30 -0700438 } else {
H. Peter Anvin518df302008-06-14 16:53:48 -0700439 static char buf[4096];
440 size_t t = instruction->times;
441 size_t base = 0;
442 size_t len;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000443
H. Peter Anvine2c80182005-01-15 22:15:51 +0000444 len = ftell(fp);
445 if (instruction->eops->next) {
446 base = instruction->eops->next->offset;
447 len -= base;
448 if (instruction->eops->next->next &&
H. Peter Anvin518df302008-06-14 16:53:48 -0700449 len > (size_t)instruction->eops->next->next->offset)
450 len = (size_t)instruction->eops->next->next->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000451 }
452 /*
453 * Dummy call to list->output to give the offset to the
454 * listing module.
455 */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800456 list->output(offset, NULL, OUT_RAWDATA, 0);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000457 list->uplevel(LIST_INCBIN);
458 while (t--) {
H. Peter Anvin518df302008-06-14 16:53:48 -0700459 size_t l;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000460
H. Peter Anvine2c80182005-01-15 22:15:51 +0000461 fseek(fp, base, SEEK_SET);
462 l = len;
463 while (l > 0) {
H. Peter Anvin4a5a6df2009-06-27 16:14:18 -0700464 int32_t m;
465 m = fread(buf, 1, l > sizeof(buf) ? sizeof(buf) : l, fp);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000466 if (!m) {
467 /*
468 * This shouldn't happen unless the file
469 * actually changes while we are reading
470 * it.
471 */
472 error(ERR_NONFATAL,
473 "`incbin': unexpected EOF while"
474 " reading file `%s'", fname);
475 t = 0; /* Try to exit cleanly */
476 break;
477 }
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800478 out(offset, segment, buf, OUT_RAWDATA, m,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000479 NO_SEG, NO_SEG);
480 l -= m;
481 }
482 }
483 list->downlevel(LIST_INCBIN);
484 if (instruction->times > 1) {
485 /*
486 * Dummy call to list->output to give the offset to the
487 * listing module.
488 */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800489 list->output(offset, NULL, OUT_RAWDATA, 0);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000490 list->uplevel(LIST_TIMES);
491 list->downlevel(LIST_TIMES);
492 }
493 fclose(fp);
494 return instruction->times * len;
495 }
496 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000497 }
498
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700499 /* Check to see if we need an address-size prefix */
500 add_asp(instruction, bits);
501
H. Peter Anvin65289e82009-07-25 17:25:11 -0700502 size_prob = MERR_INVALOP;
H. Peter Anvin70653092007-10-19 14:42:29 -0700503
H. Peter Anvin65289e82009-07-25 17:25:11 -0700504 for (temp = nasm_instructions[instruction->opcode];
505 temp->opcode != -1; temp++){
506 enum match_result m = matches(temp, instruction, bits);
507 if (m == MOK_GOOD ||
508 (m == MOK_JUMP && jmp_match(segment, offset, bits,
509 instruction, temp->code))) {
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700510 /* Matches! */
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800511 int64_t insn_size = calcsize(segment, offset, bits,
H. Peter Anvin65289e82009-07-25 17:25:11 -0700512 instruction, temp->code);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000513 itimes = instruction->times;
514 if (insn_size < 0) /* shouldn't be, on pass two */
515 error(ERR_PANIC, "errors made it through from pass one");
516 else
517 while (itimes--) {
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700518 for (j = 0; j < MAXPREFIX; j++) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000519 uint8_t c = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000520 switch (instruction->prefixes[j]) {
H. Peter Anvinc2acf7b2009-02-21 18:22:56 -0800521 case P_WAIT:
522 c = 0x9B;
523 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000524 case P_LOCK:
525 c = 0xF0;
526 break;
527 case P_REPNE:
528 case P_REPNZ:
529 c = 0xF2;
530 break;
531 case P_REPE:
532 case P_REPZ:
533 case P_REP:
534 c = 0xF3;
535 break;
536 case R_CS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000537 if (bits == 64) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700538 error(ERR_WARNING | ERR_PASS2,
Charles Crayne1b851dc2007-11-05 21:49:49 -0800539 "cs segment base generated, but will be ignored in 64-bit mode");
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000540 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000541 c = 0x2E;
542 break;
543 case R_DS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000544 if (bits == 64) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700545 error(ERR_WARNING | ERR_PASS2,
Charles Crayne1b851dc2007-11-05 21:49:49 -0800546 "ds segment base generated, but will be ignored in 64-bit mode");
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000547 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000548 c = 0x3E;
549 break;
550 case R_ES:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000551 if (bits == 64) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700552 error(ERR_WARNING | ERR_PASS2,
Charles Crayne1b851dc2007-11-05 21:49:49 -0800553 "es segment base generated, but will be ignored in 64-bit mode");
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000554 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000555 c = 0x26;
556 break;
557 case R_FS:
558 c = 0x64;
559 break;
560 case R_GS:
561 c = 0x65;
562 break;
563 case R_SS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000564 if (bits == 64) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700565 error(ERR_WARNING | ERR_PASS2,
Charles Crayne1b851dc2007-11-05 21:49:49 -0800566 "ss segment base generated, but will be ignored in 64-bit mode");
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000567 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000568 c = 0x36;
569 break;
570 case R_SEGR6:
571 case R_SEGR7:
572 error(ERR_NONFATAL,
573 "segr6 and segr7 cannot be used as prefixes");
574 break;
575 case P_A16:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000576 if (bits == 64) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000577 error(ERR_NONFATAL,
578 "16-bit addressing is not supported "
579 "in 64-bit mode");
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700580 } else if (bits != 16)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000581 c = 0x67;
582 break;
583 case P_A32:
584 if (bits != 32)
585 c = 0x67;
586 break;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700587 case P_A64:
588 if (bits != 64) {
589 error(ERR_NONFATAL,
590 "64-bit addressing is only supported "
591 "in 64-bit mode");
592 }
593 break;
594 case P_ASP:
595 c = 0x67;
596 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000597 case P_O16:
598 if (bits != 16)
599 c = 0x66;
600 break;
601 case P_O32:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000602 if (bits == 16)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000603 c = 0x66;
604 break;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700605 case P_O64:
606 /* REX.W */
607 break;
608 case P_OSP:
609 c = 0x66;
610 break;
611 case P_none:
612 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000613 default:
614 error(ERR_PANIC, "invalid instruction prefix");
615 }
616 if (c != 0) {
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800617 out(offset, segment, &c, OUT_RAWDATA, 1,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000618 NO_SEG, NO_SEG);
619 offset++;
620 }
H. Peter Anvin70653092007-10-19 14:42:29 -0700621 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000622 insn_end = offset + insn_size;
H. Peter Anvin833caea2008-10-04 19:02:30 -0700623 gencode(segment, offset, bits, instruction,
624 temp, insn_end);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000625 offset += insn_size;
626 if (itimes > 0 && itimes == instruction->times - 1) {
627 /*
628 * Dummy call to list->output to give the offset to the
629 * listing module.
630 */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800631 list->output(offset, NULL, OUT_RAWDATA, 0);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000632 list->uplevel(LIST_TIMES);
633 }
634 }
635 if (instruction->times > 1)
636 list->downlevel(LIST_TIMES);
637 return offset - start;
638 } else if (m > 0 && m > size_prob) {
639 size_prob = m;
640 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000641 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000642
H. Peter Anvine2c80182005-01-15 22:15:51 +0000643 if (temp->opcode == -1) { /* didn't match any instruction */
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000644 switch (size_prob) {
H. Peter Anvin65289e82009-07-25 17:25:11 -0700645 case MERR_OPSIZEMISSING:
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000646 error(ERR_NONFATAL, "operation size not specified");
647 break;
H. Peter Anvin65289e82009-07-25 17:25:11 -0700648 case MERR_OPSIZEMISMATCH:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000649 error(ERR_NONFATAL, "mismatch in operand sizes");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000650 break;
H. Peter Anvin65289e82009-07-25 17:25:11 -0700651 case MERR_BADCPU:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000652 error(ERR_NONFATAL, "no instruction for this cpu level");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000653 break;
H. Peter Anvin65289e82009-07-25 17:25:11 -0700654 case MERR_BADMODE:
H. Peter Anvin6cda4142008-12-29 20:52:28 -0800655 error(ERR_NONFATAL, "instruction not supported in %d-bit mode",
656 bits);
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000657 break;
658 default:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000659 error(ERR_NONFATAL,
660 "invalid combination of opcode and operands");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000661 break;
662 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000663 }
664 return 0;
665}
666
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800667int64_t insn_size(int32_t segment, int64_t offset, int bits, uint32_t cp,
H. Peter Anvin65289e82009-07-25 17:25:11 -0700668 insn * instruction, efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000669{
H. Peter Anvin3360d792007-09-11 04:16:57 +0000670 const struct itemplate *temp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000671
H. Peter Anvine2c80182005-01-15 22:15:51 +0000672 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000673 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000674
675 if (instruction->opcode == -1)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000676 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000677
H. Peter Anvincfbe7c32007-09-18 17:49:09 -0700678 if (instruction->opcode == I_DB || instruction->opcode == I_DW ||
679 instruction->opcode == I_DD || instruction->opcode == I_DQ ||
H. Peter Anvindfb91802008-05-20 11:43:53 -0700680 instruction->opcode == I_DT || instruction->opcode == I_DO ||
681 instruction->opcode == I_DY) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000682 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000683 int32_t isize, osize, wsize = 0; /* placate gcc */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000684
H. Peter Anvine2c80182005-01-15 22:15:51 +0000685 isize = 0;
686 switch (instruction->opcode) {
687 case I_DB:
688 wsize = 1;
689 break;
690 case I_DW:
691 wsize = 2;
692 break;
693 case I_DD:
694 wsize = 4;
695 break;
696 case I_DQ:
697 wsize = 8;
698 break;
699 case I_DT:
700 wsize = 10;
701 break;
H. Peter Anvincfbe7c32007-09-18 17:49:09 -0700702 case I_DO:
703 wsize = 16;
704 break;
H. Peter Anvindfb91802008-05-20 11:43:53 -0700705 case I_DY:
706 wsize = 32;
707 break;
H. Peter Anvin16b0a332007-09-12 20:27:41 -0700708 default:
709 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000710 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000711
H. Peter Anvine2c80182005-01-15 22:15:51 +0000712 for (e = instruction->eops; e; e = e->next) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000713 int32_t align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000714
H. Peter Anvine2c80182005-01-15 22:15:51 +0000715 osize = 0;
716 if (e->type == EOT_DB_NUMBER)
717 osize = 1;
H. Peter Anvin518df302008-06-14 16:53:48 -0700718 else if (e->type == EOT_DB_STRING ||
719 e->type == EOT_DB_STRING_FREE)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000720 osize = e->stringlen;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000721
H. Peter Anvine2c80182005-01-15 22:15:51 +0000722 align = (-osize) % wsize;
723 if (align < 0)
724 align += wsize;
725 isize += osize + align;
726 }
727 return isize * instruction->times;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000728 }
729
H. Peter Anvine2c80182005-01-15 22:15:51 +0000730 if (instruction->opcode == I_INCBIN) {
H. Peter Anvin518df302008-06-14 16:53:48 -0700731 const char *fname = instruction->eops->stringval;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000732 FILE *fp;
H. Peter Anvin518df302008-06-14 16:53:48 -0700733 size_t len;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000734
H. Peter Anvin418ca702008-05-30 10:42:30 -0700735 fp = fopen(fname, "rb");
736 if (!fp)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000737 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
738 fname);
739 else if (fseek(fp, 0L, SEEK_END) < 0)
740 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
741 fname);
742 else {
743 len = ftell(fp);
744 fclose(fp);
745 if (instruction->eops->next) {
746 len -= instruction->eops->next->offset;
747 if (instruction->eops->next->next &&
H. Peter Anvin518df302008-06-14 16:53:48 -0700748 len > (size_t)instruction->eops->next->next->offset) {
749 len = (size_t)instruction->eops->next->next->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000750 }
751 }
752 return instruction->times * len;
753 }
754 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000755 }
756
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700757 /* Check to see if we need an address-size prefix */
758 add_asp(instruction, bits);
759
H. Peter Anvin65289e82009-07-25 17:25:11 -0700760 for (temp = nasm_instructions[instruction->opcode];
761 temp->opcode != -1; temp++) {
762 enum match_result m = matches(temp, instruction, bits);
763 if (m == MOK_GOOD ||
764 (m == MOK_JUMP && jmp_match(segment, offset, bits,
765 instruction, temp->code))) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000766 /* we've matched an instruction. */
Charles Crayne5fbbc8c2007-11-07 19:03:46 -0800767 int64_t isize;
H. Peter Anvin3720f7b2008-05-12 11:00:50 -0700768 const uint8_t *codes = temp->code;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000769 int j;
770
771 isize = calcsize(segment, offset, bits, instruction, codes);
772 if (isize < 0)
773 return -1;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700774 for (j = 0; j < MAXPREFIX; j++) {
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700775 switch (instruction->prefixes[j]) {
776 case P_A16:
777 if (bits != 16)
778 isize++;
779 break;
780 case P_A32:
781 if (bits != 32)
782 isize++;
783 break;
784 case P_O16:
785 if (bits != 16)
786 isize++;
787 break;
788 case P_O32:
789 if (bits == 16)
790 isize++;
791 break;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700792 case P_A64:
793 case P_O64:
794 case P_none:
795 break;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700796 default:
797 isize++;
798 break;
799 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000800 }
801 return isize * instruction->times;
802 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000803 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000804 return -1; /* didn't match any instruction */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000805}
806
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700807static bool possible_sbyte(operand *o)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000808{
H. Peter Anvinad6b8592008-10-07 09:56:38 -0700809 return o->wrt == NO_SEG && o->segment == NO_SEG &&
H. Peter Anvine8ab8912009-02-26 16:34:56 -0800810 !(o->opflags & OPFLAG_UNKNOWN) &&
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700811 optimizing >= 0 && !(o->type & STRICT);
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000812}
813
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700814/* check that opn[op] is a signed byte of size 16 or 32 */
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700815static bool is_sbyte16(operand *o)
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700816{
817 int16_t v;
818
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700819 if (!possible_sbyte(o))
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700820 return false;
821
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700822 v = o->offset;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700823 return v >= -128 && v <= 127;
824}
825
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700826static bool is_sbyte32(operand *o)
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700827{
828 int32_t v;
829
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700830 if (!possible_sbyte(o))
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700831 return false;
832
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700833 v = o->offset;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700834 return v >= -128 && v <= 127;
835}
836
H. Peter Anvin507ae032008-10-09 15:37:10 -0700837/* Common construct */
838#define case4(x) case (x): case (x)+1: case (x)+2: case (x)+3
839
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800840static int64_t calcsize(int32_t segment, int64_t offset, int bits,
H. Peter Anvin9f817132008-10-06 19:11:07 -0700841 insn * ins, const uint8_t *codes)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000842{
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800843 int64_t length = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000844 uint8_t c;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000845 int rex_mask = ~0;
H. Peter Anvindcffe4b2008-10-10 22:10:31 -0700846 int op1, op2;
H. Peter Anvin839eca22007-10-29 23:12:47 -0700847 struct operand *opx;
H. Peter Anvindcffe4b2008-10-10 22:10:31 -0700848 uint8_t opex = 0;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000849
H. Peter Anvine3917fc2007-11-01 14:53:32 -0700850 ins->rex = 0; /* Ensure REX is reset */
851
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700852 if (ins->prefixes[PPS_OSIZE] == P_O64)
853 ins->rex |= REX_W;
854
H. Peter Anvine2c80182005-01-15 22:15:51 +0000855 (void)segment; /* Don't warn that this parameter is unused */
856 (void)offset; /* Don't warn that this parameter is unused */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000857
H. Peter Anvin839eca22007-10-29 23:12:47 -0700858 while (*codes) {
859 c = *codes++;
H. Peter Anvindcffe4b2008-10-10 22:10:31 -0700860 op1 = (c & 3) + ((opex & 1) << 2);
861 op2 = ((c >> 3) & 3) + ((opex & 2) << 1);
862 opx = &ins->oprs[op1];
863 opex = 0; /* For the next iteration */
864
H. Peter Anvin839eca22007-10-29 23:12:47 -0700865 switch (c) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000866 case 01:
867 case 02:
868 case 03:
H. Peter Anvindcffe4b2008-10-10 22:10:31 -0700869 case 04:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000870 codes += c, length += c;
871 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700872
H. Peter Anvindcffe4b2008-10-10 22:10:31 -0700873 case 05:
874 case 06:
875 case 07:
876 opex = c;
877 break;
878
H. Peter Anvin507ae032008-10-09 15:37:10 -0700879 case4(010):
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000880 ins->rex |=
H. Peter Anvin839eca22007-10-29 23:12:47 -0700881 op_rexflags(opx, REX_B|REX_H|REX_P|REX_W);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000882 codes++, length++;
883 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700884
885 case4(014):
886 case4(020):
887 case4(024):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000888 length++;
889 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700890
891 case4(030):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000892 length += 2;
893 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700894
895 case4(034):
H. Peter Anvin839eca22007-10-29 23:12:47 -0700896 if (opx->type & (BITS16 | BITS32 | BITS64))
897 length += (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000898 else
899 length += (bits == 16) ? 2 : 4;
900 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700901
902 case4(040):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000903 length += 4;
904 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700905
906 case4(044):
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700907 length += ins->addr_size >> 3;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000908 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700909
910 case4(050):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000911 length++;
912 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700913
914 case4(054):
Keith Kaniosb7a89542007-04-12 02:40:54 +0000915 length += 8; /* MOV reg64/imm */
916 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700917
918 case4(060):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000919 length += 2;
920 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700921
922 case4(064):
H. Peter Anvin839eca22007-10-29 23:12:47 -0700923 if (opx->type & (BITS16 | BITS32 | BITS64))
924 length += (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000925 else
926 length += (bits == 16) ? 2 : 4;
927 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700928
929 case4(070):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000930 length += 4;
931 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700932
933 case4(074):
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700934 length += 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000935 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700936
937 case4(0140):
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700938 length += is_sbyte16(opx) ? 1 : 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000939 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700940
941 case4(0144):
H. Peter Anvina30cc072007-11-18 21:55:26 -0800942 codes++;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000943 length++;
944 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700945
946 case4(0150):
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700947 length += is_sbyte32(opx) ? 1 : 4;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700948 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700949
950 case4(0154):
H. Peter Anvina30cc072007-11-18 21:55:26 -0800951 codes++;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700952 length++;
953 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700954
955 case4(0160):
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700956 length++;
957 ins->rex |= REX_D;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700958 ins->drexdst = regval(opx);
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700959 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700960
961 case4(0164):
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700962 length++;
963 ins->rex |= REX_D|REX_OC;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700964 ins->drexdst = regval(opx);
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700965 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700966
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700967 case 0171:
968 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700969
H. Peter Anvind85d2502008-05-04 17:53:31 -0700970 case 0172:
H. Peter Anvind58656f2008-05-06 20:11:14 -0700971 case 0173:
H. Peter Anvin52dc3532008-05-20 19:29:04 -0700972 case 0174:
H. Peter Anvind85d2502008-05-04 17:53:31 -0700973 codes++;
974 length++;
975 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700976
977 case4(0250):
H. Peter Anvinad6b8592008-10-07 09:56:38 -0700978 length += is_sbyte32(opx) ? 1 : 4;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700979 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700980
981 case4(0254):
H. Peter Anvin588df782008-10-07 10:05:10 -0700982 length += 4;
983 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700984
985 case4(0260):
H. Peter Anvind85d2502008-05-04 17:53:31 -0700986 ins->rex |= REX_V;
987 ins->drexdst = regval(opx);
H. Peter Anvina04019c2009-05-03 21:42:34 -0700988 ins->vex_cm = *codes++;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700989 ins->vex_wlp = *codes++;
990 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700991
H. Peter Anvind85d2502008-05-04 17:53:31 -0700992 case 0270:
H. Peter Anvind85d2502008-05-04 17:53:31 -0700993 ins->rex |= REX_V;
994 ins->drexdst = 0;
H. Peter Anvina04019c2009-05-03 21:42:34 -0700995 ins->vex_cm = *codes++;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700996 ins->vex_wlp = *codes++;
997 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700998
999 case4(0274):
H. Peter Anvinc1377e92008-10-06 23:40:31 -07001000 length++;
1001 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001002
1003 case4(0300):
H. Peter Anvine2c80182005-01-15 22:15:51 +00001004 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001005
H. Peter Anvine2c80182005-01-15 22:15:51 +00001006 case 0310:
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07001007 if (bits == 64)
1008 return -1;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001009 length += (bits != 16) && !has_prefix(ins, PPS_ASIZE, P_A16);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001010 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001011
H. Peter Anvine2c80182005-01-15 22:15:51 +00001012 case 0311:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001013 length += (bits != 32) && !has_prefix(ins, PPS_ASIZE, P_A32);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001014 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001015
H. Peter Anvine2c80182005-01-15 22:15:51 +00001016 case 0312:
H. Peter Anvin70653092007-10-19 14:42:29 -07001017 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001018
Keith Kaniosb7a89542007-04-12 02:40:54 +00001019 case 0313:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001020 if (bits != 64 || has_prefix(ins, PPS_ASIZE, P_A16) ||
1021 has_prefix(ins, PPS_ASIZE, P_A32))
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07001022 return -1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001023 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001024
1025 case4(0314):
H. Peter Anvin23440102007-11-12 21:02:33 -08001026 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001027
H. Peter Anvine2c80182005-01-15 22:15:51 +00001028 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001029 length += (bits != 16);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001030 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001031
H. Peter Anvine2c80182005-01-15 22:15:51 +00001032 case 0321:
1033 length += (bits == 16);
1034 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001035
H. Peter Anvine2c80182005-01-15 22:15:51 +00001036 case 0322:
1037 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001038
Keith Kaniosb7a89542007-04-12 02:40:54 +00001039 case 0323:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001040 rex_mask &= ~REX_W;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001041 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001042
Keith Kaniosb7a89542007-04-12 02:40:54 +00001043 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001044 ins->rex |= REX_W;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +00001045 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001046
H. Peter Anvin9472dab2009-06-24 21:38:29 -07001047 case 0325:
1048 ins->rex |= REX_NH;
1049 break;
1050
H. Peter Anvine2c80182005-01-15 22:15:51 +00001051 case 0330:
1052 codes++, length++;
1053 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001054
H. Peter Anvine2c80182005-01-15 22:15:51 +00001055 case 0331:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001056 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001057
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001058 case 0332:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001059 case 0333:
1060 length++;
1061 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001062
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001063 case 0334:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001064 ins->rex |= REX_L;
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001065 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001066
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001067 case 0335:
1068 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001069
H. Peter Anvin962e3052008-08-28 17:47:16 -07001070 case 0336:
1071 if (!ins->prefixes[PPS_LREP])
1072 ins->prefixes[PPS_LREP] = P_REP;
1073 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001074
H. Peter Anvin962e3052008-08-28 17:47:16 -07001075 case 0337:
1076 if (!ins->prefixes[PPS_LREP])
1077 ins->prefixes[PPS_LREP] = P_REPNE;
1078 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001079
H. Peter Anvine2c80182005-01-15 22:15:51 +00001080 case 0340:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001081 if (ins->oprs[0].segment != NO_SEG)
1082 errfunc(ERR_NONFATAL, "attempt to reserve non-constant"
1083 " quantity of BSS space");
1084 else
H. Peter Anvin428fd672007-11-15 10:25:52 -08001085 length += ins->oprs[0].offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001086 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001087
H. Peter Anvinc2acf7b2009-02-21 18:22:56 -08001088 case 0341:
1089 if (!ins->prefixes[PPS_WAIT])
1090 ins->prefixes[PPS_WAIT] = P_WAIT;
1091 break;
1092
H. Peter Anvin507ae032008-10-09 15:37:10 -07001093 case4(0344):
H. Peter Anvinff6e12d2008-10-08 21:17:32 -07001094 length++;
1095 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001096
H. Peter Anvinfff5a472008-05-20 09:46:24 -07001097 case 0360:
1098 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001099
H. Peter Anvinfff5a472008-05-20 09:46:24 -07001100 case 0361:
1101 case 0362:
1102 case 0363:
1103 length++;
1104 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001105
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001106 case 0364:
1107 case 0365:
1108 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001109
Keith Kanios48af1772007-08-17 07:37:52 +00001110 case 0366:
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001111 case 0367:
1112 length++;
1113 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001114
H. Peter Anvine2c80182005-01-15 22:15:51 +00001115 case 0370:
1116 case 0371:
1117 case 0372:
1118 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001119
H. Peter Anvine2c80182005-01-15 22:15:51 +00001120 case 0373:
1121 length++;
1122 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001123
1124 case4(0100):
1125 case4(0110):
1126 case4(0120):
1127 case4(0130):
1128 case4(0200):
1129 case4(0204):
1130 case4(0210):
1131 case4(0214):
1132 case4(0220):
1133 case4(0224):
1134 case4(0230):
1135 case4(0234):
1136 {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001137 ea ea_data;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001138 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001139 int32_t rflags;
H. Peter Anvinae64c9d2008-10-25 00:41:00 -07001140 struct operand *opy = &ins->oprs[op2];
1141
Keith Kaniosb7a89542007-04-12 02:40:54 +00001142 ea_data.rex = 0; /* Ensure ea.REX is initially 0 */
H. Peter Anvin70653092007-10-19 14:42:29 -07001143
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001144 if (c <= 0177) {
H. Peter Anvinae64c9d2008-10-25 00:41:00 -07001145 /* pick rfield from operand b (opx) */
1146 rflags = regflag(opx);
1147 rfield = nasm_regvals[opx->basereg];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001148 } else {
1149 rflags = 0;
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001150 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001151 }
H. Peter Anvinae64c9d2008-10-25 00:41:00 -07001152 if (!process_ea(opy, &ea_data, bits,
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001153 ins->addr_size, rfield, rflags)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001154 errfunc(ERR_NONFATAL, "invalid effective address");
1155 return -1;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001156 } else {
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001157 ins->rex |= ea_data.rex;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001158 length += ea_data.size;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001159 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001160 }
H. Peter Anvin507ae032008-10-09 15:37:10 -07001161 break;
1162
1163 default:
1164 errfunc(ERR_PANIC, "internal instruction table corrupt"
H. Peter Anvin16a856c2009-03-01 00:22:16 -08001165 ": instruction code \\%o (0x%02X) given", c, c);
H. Peter Anvin507ae032008-10-09 15:37:10 -07001166 break;
1167 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001168 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001169
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001170 ins->rex &= rex_mask;
H. Peter Anvin70653092007-10-19 14:42:29 -07001171
H. Peter Anvin9472dab2009-06-24 21:38:29 -07001172 if (ins->rex & REX_NH) {
1173 if (ins->rex & REX_H) {
1174 errfunc(ERR_NONFATAL, "instruction cannot use high registers");
1175 return -1;
1176 }
1177 ins->rex &= ~REX_P; /* Don't force REX prefix due to high reg */
1178 }
1179
H. Peter Anvind85d2502008-05-04 17:53:31 -07001180 if (ins->rex & REX_V) {
1181 int bad32 = REX_R|REX_W|REX_X|REX_B;
1182
1183 if (ins->rex & REX_H) {
1184 errfunc(ERR_NONFATAL, "cannot use high register in vex instruction");
1185 return -1;
1186 }
1187 switch (ins->vex_wlp & 030) {
1188 case 000:
H. Peter Anvinbd420c72008-05-22 11:24:35 -07001189 case 020:
H. Peter Anvind85d2502008-05-04 17:53:31 -07001190 ins->rex &= ~REX_W;
1191 break;
1192 case 010:
1193 ins->rex |= REX_W;
1194 bad32 &= ~REX_W;
1195 break;
H. Peter Anvinbd420c72008-05-22 11:24:35 -07001196 case 030:
H. Peter Anvind85d2502008-05-04 17:53:31 -07001197 /* Follow REX_W */
1198 break;
1199 }
1200
1201 if (bits != 64 && ((ins->rex & bad32) || ins->drexdst > 7)) {
1202 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
1203 return -1;
1204 }
H. Peter Anvina04019c2009-05-03 21:42:34 -07001205 if (ins->vex_cm != 1 || (ins->rex & (REX_W|REX_R|REX_B)))
H. Peter Anvind85d2502008-05-04 17:53:31 -07001206 length += 3;
1207 else
1208 length += 2;
1209 } else if (ins->rex & REX_D) {
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001210 if (ins->rex & REX_H) {
1211 errfunc(ERR_NONFATAL, "cannot use high register in drex instruction");
1212 return -1;
1213 }
H. Peter Anvind85d2502008-05-04 17:53:31 -07001214 if (bits != 64 && ((ins->rex & (REX_R|REX_W|REX_X|REX_B)) ||
H. Peter Anvincf5180a2007-09-17 17:25:27 -07001215 ins->drexdst > 7)) {
1216 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
1217 return -1;
1218 }
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001219 length++;
1220 } else if (ins->rex & REX_REAL) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001221 if (ins->rex & REX_H) {
1222 errfunc(ERR_NONFATAL, "cannot use high register in rex instruction");
1223 return -1;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001224 } else if (bits == 64) {
1225 length++;
1226 } else if ((ins->rex & REX_L) &&
1227 !(ins->rex & (REX_P|REX_W|REX_X|REX_B)) &&
1228 cpu >= IF_X86_64) {
1229 /* LOCK-as-REX.R */
1230 assert_no_prefix(ins, PPS_LREP);
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001231 length++;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +00001232 } else {
H. Peter Anvincf5180a2007-09-17 17:25:27 -07001233 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
1234 return -1;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +00001235 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001236 }
1237
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001238 return length;
1239}
Keith Kaniosb7a89542007-04-12 02:40:54 +00001240
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001241#define EMIT_REX() \
H. Peter Anvind85d2502008-05-04 17:53:31 -07001242 if (!(ins->rex & (REX_D|REX_V)) && (ins->rex & REX_REAL) && (bits == 64)) { \
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001243 ins->rex = (ins->rex & REX_REAL)|REX_P; \
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001244 out(offset, segment, &ins->rex, OUT_RAWDATA, 1, NO_SEG, NO_SEG); \
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001245 ins->rex = 0; \
1246 offset += 1; \
1247 }
1248
Charles Crayne1f8bc4c2007-11-06 18:27:23 -08001249static void gencode(int32_t segment, int64_t offset, int bits,
H. Peter Anvin833caea2008-10-04 19:02:30 -07001250 insn * ins, const struct itemplate *temp,
1251 int64_t insn_end)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001252{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001253 static char condval[] = { /* conditional opcodes */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001254 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
1255 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
1256 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001257 };
Keith Kaniosb7a89542007-04-12 02:40:54 +00001258 uint8_t c;
1259 uint8_t bytes[4];
Charles Crayne1f8bc4c2007-11-06 18:27:23 -08001260 int64_t size;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001261 int64_t data;
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001262 int op1, op2;
H. Peter Anvin839eca22007-10-29 23:12:47 -07001263 struct operand *opx;
H. Peter Anvin833caea2008-10-04 19:02:30 -07001264 const uint8_t *codes = temp->code;
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001265 uint8_t opex = 0;
H. Peter Anvin70653092007-10-19 14:42:29 -07001266
H. Peter Anvin839eca22007-10-29 23:12:47 -07001267 while (*codes) {
1268 c = *codes++;
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001269 op1 = (c & 3) + ((opex & 1) << 2);
1270 op2 = ((c >> 3) & 3) + ((opex & 2) << 1);
1271 opx = &ins->oprs[op1];
1272 opex = 0; /* For the next iteration */
1273
H. Peter Anvin839eca22007-10-29 23:12:47 -07001274 switch (c) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001275 case 01:
1276 case 02:
1277 case 03:
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001278 case 04:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001279 EMIT_REX();
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001280 out(offset, segment, codes, OUT_RAWDATA, c, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001281 codes += c;
1282 offset += c;
1283 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001284
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001285 case 05:
1286 case 06:
1287 case 07:
1288 opex = c;
1289 break;
1290
H. Peter Anvin507ae032008-10-09 15:37:10 -07001291 case4(010):
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001292 EMIT_REX();
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001293 bytes[0] = *codes++ + (regval(opx) & 7);
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001294 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001295 offset += 1;
1296 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001297
H. Peter Anvin507ae032008-10-09 15:37:10 -07001298 case4(014):
H. Peter Anvin6c80ab62008-10-04 18:50:47 -07001299 /* The test for BITS8 and SBYTE here is intended to avoid
1300 warning on optimizer actions due to SBYTE, while still
1301 warn on explicit BYTE directives. Also warn, obviously,
1302 if the optimizer isn't enabled. */
1303 if (((opx->type & BITS8) ||
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001304 !(opx->type & temp->opd[op1] & BYTENESS)) &&
H. Peter Anvin6c80ab62008-10-04 18:50:47 -07001305 (opx->offset < -128 || opx->offset > 127)) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001306 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
H. Peter Anvin72c64372008-01-08 22:13:48 -08001307 "signed byte value exceeds bounds");
H. Peter Anvin6c80ab62008-10-04 18:50:47 -07001308 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001309 if (opx->segment != NO_SEG) {
1310 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001311 out(offset, segment, &data, OUT_ADDRESS, 1,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001312 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001313 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001314 bytes[0] = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001315 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001316 NO_SEG);
1317 }
1318 offset += 1;
1319 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001320
H. Peter Anvin507ae032008-10-09 15:37:10 -07001321 case4(020):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001322 if (opx->offset < -256 || opx->offset > 255) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001323 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
H. Peter Anvin72c64372008-01-08 22:13:48 -08001324 "byte value exceeds bounds");
H. Peter Anvine2c80182005-01-15 22:15:51 +00001325 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001326 if (opx->segment != NO_SEG) {
1327 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001328 out(offset, segment, &data, OUT_ADDRESS, 1,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001329 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001330 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001331 bytes[0] = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001332 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001333 NO_SEG);
1334 }
1335 offset += 1;
1336 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001337
H. Peter Anvin507ae032008-10-09 15:37:10 -07001338 case4(024):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001339 if (opx->offset < 0 || opx->offset > 255)
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001340 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
H. Peter Anvin72c64372008-01-08 22:13:48 -08001341 "unsigned byte value exceeds bounds");
H. Peter Anvin839eca22007-10-29 23:12:47 -07001342 if (opx->segment != NO_SEG) {
1343 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001344 out(offset, segment, &data, OUT_ADDRESS, 1,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001345 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001346 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001347 bytes[0] = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001348 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001349 NO_SEG);
1350 }
1351 offset += 1;
1352 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001353
H. Peter Anvin507ae032008-10-09 15:37:10 -07001354 case4(030):
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001355 warn_overflow(2, opx);
H. Peter Anvin839eca22007-10-29 23:12:47 -07001356 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001357 out(offset, segment, &data, OUT_ADDRESS, 2,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001358 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001359 offset += 2;
1360 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001361
H. Peter Anvin507ae032008-10-09 15:37:10 -07001362 case4(034):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001363 if (opx->type & (BITS16 | BITS32))
1364 size = (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001365 else
1366 size = (bits == 16) ? 2 : 4;
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001367 warn_overflow(size, opx);
H. Peter Anvin839eca22007-10-29 23:12:47 -07001368 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001369 out(offset, segment, &data, OUT_ADDRESS, size,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001370 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001371 offset += size;
1372 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001373
H. Peter Anvin507ae032008-10-09 15:37:10 -07001374 case4(040):
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001375 warn_overflow(4, opx);
H. Peter Anvin839eca22007-10-29 23:12:47 -07001376 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001377 out(offset, segment, &data, OUT_ADDRESS, 4,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001378 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001379 offset += 4;
1380 break;
H. Peter Anvin3ba46772002-05-27 23:19:35 +00001381
H. Peter Anvin507ae032008-10-09 15:37:10 -07001382 case4(044):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001383 data = opx->offset;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001384 size = ins->addr_size >> 3;
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001385 warn_overflow(size, opx);
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001386 out(offset, segment, &data, OUT_ADDRESS, size,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001387 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001388 offset += size;
1389 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001390
H. Peter Anvin507ae032008-10-09 15:37:10 -07001391 case4(050):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001392 if (opx->segment != segment)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001393 errfunc(ERR_NONFATAL,
1394 "short relative jump outside segment");
H. Peter Anvin839eca22007-10-29 23:12:47 -07001395 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001396 if (data > 127 || data < -128)
1397 errfunc(ERR_NONFATAL, "short jump is out of range");
1398 bytes[0] = data;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001399 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001400 offset += 1;
1401 break;
H. Peter Anvin70653092007-10-19 14:42:29 -07001402
H. Peter Anvin507ae032008-10-09 15:37:10 -07001403 case4(054):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001404 data = (int64_t)opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001405 out(offset, segment, &data, OUT_ADDRESS, 8,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001406 opx->segment, opx->wrt);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001407 offset += 8;
1408 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001409
H. Peter Anvin507ae032008-10-09 15:37:10 -07001410 case4(060):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001411 if (opx->segment != segment) {
1412 data = opx->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001413 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001414 OUT_REL2ADR, insn_end - offset,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001415 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001416 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001417 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001418 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001419 OUT_ADDRESS, 2, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001420 }
1421 offset += 2;
1422 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001423
H. Peter Anvin507ae032008-10-09 15:37:10 -07001424 case4(064):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001425 if (opx->type & (BITS16 | BITS32 | BITS64))
1426 size = (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001427 else
1428 size = (bits == 16) ? 2 : 4;
H. Peter Anvin839eca22007-10-29 23:12:47 -07001429 if (opx->segment != segment) {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001430 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001431 out(offset, segment, &data,
1432 size == 2 ? OUT_REL2ADR : OUT_REL4ADR,
1433 insn_end - offset, opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001434 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001435 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001436 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001437 OUT_ADDRESS, size, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001438 }
1439 offset += size;
1440 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001441
H. Peter Anvin507ae032008-10-09 15:37:10 -07001442 case4(070):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001443 if (opx->segment != segment) {
1444 data = opx->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001445 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001446 OUT_REL4ADR, insn_end - offset,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001447 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001448 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001449 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001450 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001451 OUT_ADDRESS, 4, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001452 }
1453 offset += 4;
1454 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001455
H. Peter Anvin507ae032008-10-09 15:37:10 -07001456 case4(074):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001457 if (opx->segment == NO_SEG)
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001458 errfunc(ERR_NONFATAL, "value referenced by FAR is not"
1459 " relocatable");
H. Peter Anvindfb91802008-05-20 11:43:53 -07001460 data = 0;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001461 out(offset, segment, &data, OUT_ADDRESS, 2,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001462 outfmt->segbase(1 + opx->segment),
1463 opx->wrt);
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001464 offset += 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001465 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001466
H. Peter Anvin507ae032008-10-09 15:37:10 -07001467 case4(0140):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001468 data = opx->offset;
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001469 warn_overflow(2, opx);
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001470 if (is_sbyte16(opx)) {
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001471 bytes[0] = data;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001472 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001473 NO_SEG);
1474 offset++;
1475 } else {
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001476 out(offset, segment, &data, OUT_ADDRESS, 2,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001477 opx->segment, opx->wrt);
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001478 offset += 2;
1479 }
1480 break;
1481
H. Peter Anvin507ae032008-10-09 15:37:10 -07001482 case4(0144):
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001483 EMIT_REX();
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001484 bytes[0] = *codes++;
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001485 if (is_sbyte16(opx))
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001486 bytes[0] |= 2; /* s-bit */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001487 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001488 offset++;
1489 break;
1490
H. Peter Anvin507ae032008-10-09 15:37:10 -07001491 case4(0150):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001492 data = opx->offset;
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001493 warn_overflow(4, opx);
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001494 if (is_sbyte32(opx)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001495 bytes[0] = data;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001496 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001497 NO_SEG);
1498 offset++;
1499 } else {
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001500 out(offset, segment, &data, OUT_ADDRESS, 4,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001501 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001502 offset += 4;
1503 }
1504 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001505
H. Peter Anvin507ae032008-10-09 15:37:10 -07001506 case4(0154):
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001507 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001508 bytes[0] = *codes++;
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001509 if (is_sbyte32(opx))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001510 bytes[0] |= 2; /* s-bit */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001511 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001512 offset++;
1513 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001514
H. Peter Anvin507ae032008-10-09 15:37:10 -07001515 case4(0160):
1516 case4(0164):
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001517 break;
1518
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001519 case 0171:
1520 bytes[0] =
1521 (ins->drexdst << 4) |
1522 (ins->rex & REX_OC ? 0x08 : 0) |
1523 (ins->rex & (REX_R|REX_X|REX_B));
1524 ins->rex = 0;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001525 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001526 offset++;
1527 break;
1528
H. Peter Anvind85d2502008-05-04 17:53:31 -07001529 case 0172:
1530 c = *codes++;
1531 opx = &ins->oprs[c >> 3];
H. Peter Anvina4835d42008-05-20 14:21:29 -07001532 bytes[0] = nasm_regvals[opx->basereg] << 4;
H. Peter Anvind85d2502008-05-04 17:53:31 -07001533 opx = &ins->oprs[c & 7];
1534 if (opx->segment != NO_SEG || opx->wrt != NO_SEG) {
1535 errfunc(ERR_NONFATAL,
1536 "non-absolute expression not permitted as argument %d",
1537 c & 7);
1538 } else {
1539 if (opx->offset & ~15) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001540 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
H. Peter Anvind85d2502008-05-04 17:53:31 -07001541 "four-bit argument exceeds bounds");
1542 }
1543 bytes[0] |= opx->offset & 15;
1544 }
1545 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1546 offset++;
1547 break;
1548
H. Peter Anvind58656f2008-05-06 20:11:14 -07001549 case 0173:
1550 c = *codes++;
1551 opx = &ins->oprs[c >> 4];
H. Peter Anvina4835d42008-05-20 14:21:29 -07001552 bytes[0] = nasm_regvals[opx->basereg] << 4;
H. Peter Anvind58656f2008-05-06 20:11:14 -07001553 bytes[0] |= c & 15;
1554 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1555 offset++;
1556 break;
1557
H. Peter Anvin52dc3532008-05-20 19:29:04 -07001558 case 0174:
1559 c = *codes++;
1560 opx = &ins->oprs[c];
1561 bytes[0] = nasm_regvals[opx->basereg] << 4;
1562 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1563 offset++;
1564 break;
1565
H. Peter Anvin507ae032008-10-09 15:37:10 -07001566 case4(0250):
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001567 data = opx->offset;
H. Peter Anvinad6b8592008-10-07 09:56:38 -07001568 if (opx->wrt == NO_SEG && opx->segment == NO_SEG &&
1569 (int32_t)data != (int64_t)data) {
1570 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
1571 "signed dword immediate exceeds bounds");
1572 }
1573 if (is_sbyte32(opx)) {
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001574 bytes[0] = data;
1575 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
1576 NO_SEG);
1577 offset++;
1578 } else {
1579 out(offset, segment, &data, OUT_ADDRESS, 4,
1580 opx->segment, opx->wrt);
1581 offset += 4;
1582 }
1583 break;
1584
H. Peter Anvin507ae032008-10-09 15:37:10 -07001585 case4(0254):
H. Peter Anvin588df782008-10-07 10:05:10 -07001586 data = opx->offset;
1587 if (opx->wrt == NO_SEG && opx->segment == NO_SEG &&
1588 (int32_t)data != (int64_t)data) {
1589 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
1590 "signed dword immediate exceeds bounds");
1591 }
1592 out(offset, segment, &data, OUT_ADDRESS, 4,
1593 opx->segment, opx->wrt);
1594 offset += 4;
1595 break;
1596
H. Peter Anvin507ae032008-10-09 15:37:10 -07001597 case4(0260):
H. Peter Anvind85d2502008-05-04 17:53:31 -07001598 case 0270:
1599 codes += 2;
H. Peter Anvina04019c2009-05-03 21:42:34 -07001600 if (ins->vex_cm != 1 || (ins->rex & (REX_W|REX_X|REX_B))) {
1601 bytes[0] = (ins->vex_cm >> 6) ? 0x8f : 0xc4;
1602 bytes[1] = (ins->vex_cm & 31) | ((~ins->rex & 7) << 5);
H. Peter Anvind85d2502008-05-04 17:53:31 -07001603 bytes[2] = ((ins->rex & REX_W) << (7-3)) |
H. Peter Anvin4d2c38c2008-05-04 23:15:13 -07001604 ((~ins->drexdst & 15)<< 3) | (ins->vex_wlp & 07);
H. Peter Anvind85d2502008-05-04 17:53:31 -07001605 out(offset, segment, &bytes, OUT_RAWDATA, 3, NO_SEG, NO_SEG);
1606 offset += 3;
1607 } else {
1608 bytes[0] = 0xc5;
H. Peter Anvin4d2c38c2008-05-04 23:15:13 -07001609 bytes[1] = ((~ins->rex & REX_R) << (7-2)) |
1610 ((~ins->drexdst & 15) << 3) | (ins->vex_wlp & 07);
H. Peter Anvind85d2502008-05-04 17:53:31 -07001611 out(offset, segment, &bytes, OUT_RAWDATA, 2, NO_SEG, NO_SEG);
1612 offset += 2;
1613 }
1614 break;
1615
H. Peter Anvin507ae032008-10-09 15:37:10 -07001616 case4(0274):
H. Peter Anvinc1377e92008-10-06 23:40:31 -07001617 {
1618 uint64_t uv, um;
1619 int s;
1620
1621 if (ins->rex & REX_W)
1622 s = 64;
1623 else if (ins->prefixes[PPS_OSIZE] == P_O16)
1624 s = 16;
1625 else if (ins->prefixes[PPS_OSIZE] == P_O32)
1626 s = 32;
1627 else
1628 s = bits;
1629
1630 um = (uint64_t)2 << (s-1);
1631 uv = opx->offset;
1632
1633 if (uv > 127 && uv < (uint64_t)-128 &&
1634 (uv < um-128 || uv > um-1)) {
1635 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
1636 "signed byte value exceeds bounds");
1637 }
1638 if (opx->segment != NO_SEG) {
H. Peter Anvin779ed8b2008-10-16 13:01:43 -07001639 data = uv;
H. Peter Anvinc1377e92008-10-06 23:40:31 -07001640 out(offset, segment, &data, OUT_ADDRESS, 1,
1641 opx->segment, opx->wrt);
1642 } else {
H. Peter Anvin779ed8b2008-10-16 13:01:43 -07001643 bytes[0] = uv;
H. Peter Anvinc1377e92008-10-06 23:40:31 -07001644 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
1645 NO_SEG);
1646 }
1647 offset += 1;
1648 break;
1649 }
1650
H. Peter Anvin507ae032008-10-09 15:37:10 -07001651 case4(0300):
H. Peter Anvine2c80182005-01-15 22:15:51 +00001652 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001653
H. Peter Anvine2c80182005-01-15 22:15:51 +00001654 case 0310:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001655 if (bits == 32 && !has_prefix(ins, PPS_ASIZE, P_A16)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001656 *bytes = 0x67;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001657 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001658 offset += 1;
1659 } else
1660 offset += 0;
1661 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001662
H. Peter Anvine2c80182005-01-15 22:15:51 +00001663 case 0311:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001664 if (bits != 32 && !has_prefix(ins, PPS_ASIZE, P_A32)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001665 *bytes = 0x67;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001666 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001667 offset += 1;
1668 } else
1669 offset += 0;
1670 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001671
H. Peter Anvine2c80182005-01-15 22:15:51 +00001672 case 0312:
1673 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001674
Keith Kaniosb7a89542007-04-12 02:40:54 +00001675 case 0313:
1676 ins->rex = 0;
1677 break;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07001678
H. Peter Anvin507ae032008-10-09 15:37:10 -07001679 case4(0314):
H. Peter Anvin23440102007-11-12 21:02:33 -08001680 break;
1681
H. Peter Anvine2c80182005-01-15 22:15:51 +00001682 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001683 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001684 *bytes = 0x66;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001685 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001686 offset += 1;
1687 } else
1688 offset += 0;
1689 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001690
H. Peter Anvine2c80182005-01-15 22:15:51 +00001691 case 0321:
1692 if (bits == 16) {
1693 *bytes = 0x66;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001694 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001695 offset += 1;
1696 } else
1697 offset += 0;
1698 break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001699
H. Peter Anvine2c80182005-01-15 22:15:51 +00001700 case 0322:
H. Peter Anvin70653092007-10-19 14:42:29 -07001701 case 0323:
1702 break;
1703
Keith Kaniosb7a89542007-04-12 02:40:54 +00001704 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001705 ins->rex |= REX_W;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001706 break;
H. Peter Anvin70653092007-10-19 14:42:29 -07001707
H. Peter Anvin9472dab2009-06-24 21:38:29 -07001708 case 0325:
1709 break;
1710
H. Peter Anvine2c80182005-01-15 22:15:51 +00001711 case 0330:
1712 *bytes = *codes++ ^ condval[ins->condition];
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001713 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001714 offset += 1;
1715 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001716
H. Peter Anvine2c80182005-01-15 22:15:51 +00001717 case 0331:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001718 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001719
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001720 case 0332:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001721 case 0333:
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001722 *bytes = c - 0332 + 0xF2;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001723 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001724 offset += 1;
1725 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001726
Keith Kanios48af1772007-08-17 07:37:52 +00001727 case 0334:
1728 if (ins->rex & REX_R) {
1729 *bytes = 0xF0;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001730 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
Keith Kanios48af1772007-08-17 07:37:52 +00001731 offset += 1;
1732 }
1733 ins->rex &= ~(REX_L|REX_R);
1734 break;
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001735
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001736 case 0335:
1737 break;
1738
H. Peter Anvin962e3052008-08-28 17:47:16 -07001739 case 0336:
1740 case 0337:
1741 break;
1742
H. Peter Anvine2c80182005-01-15 22:15:51 +00001743 case 0340:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001744 if (ins->oprs[0].segment != NO_SEG)
1745 errfunc(ERR_PANIC, "non-constant BSS size in pass two");
1746 else {
H. Peter Anvin428fd672007-11-15 10:25:52 -08001747 int64_t size = ins->oprs[0].offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001748 if (size > 0)
1749 out(offset, segment, NULL,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001750 OUT_RESERVE, size, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001751 offset += size;
1752 }
1753 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001754
H. Peter Anvinc2acf7b2009-02-21 18:22:56 -08001755 case 0341:
1756 break;
1757
H. Peter Anvinff6e12d2008-10-08 21:17:32 -07001758 case 0344:
1759 case 0345:
1760 bytes[0] = c & 1;
1761 switch (ins->oprs[0].basereg) {
1762 case R_CS:
1763 bytes[0] += 0x0E;
1764 break;
1765 case R_DS:
1766 bytes[0] += 0x1E;
1767 break;
1768 case R_ES:
1769 bytes[0] += 0x06;
1770 break;
1771 case R_SS:
1772 bytes[0] += 0x16;
1773 break;
1774 default:
1775 errfunc(ERR_PANIC,
1776 "bizarre 8086 segment register received");
1777 }
1778 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1779 offset++;
1780 break;
1781
1782 case 0346:
1783 case 0347:
1784 bytes[0] = c & 1;
1785 switch (ins->oprs[0].basereg) {
1786 case R_FS:
1787 bytes[0] += 0xA0;
1788 break;
1789 case R_GS:
1790 bytes[0] += 0xA8;
1791 break;
1792 default:
1793 errfunc(ERR_PANIC,
1794 "bizarre 386 segment register received");
1795 }
1796 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1797 offset++;
1798 break;
1799
H. Peter Anvinfff5a472008-05-20 09:46:24 -07001800 case 0360:
1801 break;
1802
1803 case 0361:
1804 bytes[0] = 0x66;
1805 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1806 offset += 1;
1807 break;
1808
1809 case 0362:
1810 case 0363:
1811 bytes[0] = c - 0362 + 0xf2;
1812 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1813 offset += 1;
1814 break;
1815
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001816 case 0364:
1817 case 0365:
1818 break;
1819
Keith Kanios48af1772007-08-17 07:37:52 +00001820 case 0366:
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001821 case 0367:
1822 *bytes = c - 0366 + 0x66;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001823 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
Keith Kanios48af1772007-08-17 07:37:52 +00001824 offset += 1;
1825 break;
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001826
H. Peter Anvine2c80182005-01-15 22:15:51 +00001827 case 0370:
1828 case 0371:
1829 case 0372:
1830 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 Anvin507ae032008-10-09 15:37:10 -07001838 case4(0100):
1839 case4(0110):
1840 case4(0120):
1841 case4(0130):
1842 case4(0200):
1843 case4(0204):
1844 case4(0210):
1845 case4(0214):
1846 case4(0220):
1847 case4(0224):
1848 case4(0230):
1849 case4(0234):
1850 {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001851 ea ea_data;
1852 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001853 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001854 uint8_t *p;
1855 int32_t s;
H. Peter Anvin9f817132008-10-06 19:11:07 -07001856 enum out_type type;
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001857 struct operand *opy = &ins->oprs[op2];
H. Peter Anvin70653092007-10-19 14:42:29 -07001858
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001859 if (c <= 0177) {
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001860 /* pick rfield from operand b (opx) */
1861 rflags = regflag(opx);
1862 rfield = nasm_regvals[opx->basereg];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001863 } else {
1864 /* rfield is constant */
1865 rflags = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001866 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001867 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001868
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001869 if (!process_ea(opy, &ea_data, bits, ins->addr_size,
1870 rfield, rflags)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001871 errfunc(ERR_NONFATAL, "invalid effective address");
1872 }
H. Peter Anvin70653092007-10-19 14:42:29 -07001873
Charles Crayne7e975552007-11-03 22:06:13 -07001874
H. Peter Anvine2c80182005-01-15 22:15:51 +00001875 p = bytes;
1876 *p++ = ea_data.modrm;
1877 if (ea_data.sib_present)
1878 *p++ = ea_data.sib;
1879
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001880 /* DREX suffixes come between the SIB and the displacement */
1881 if (ins->rex & REX_D) {
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001882 *p++ = (ins->drexdst << 4) |
1883 (ins->rex & REX_OC ? 0x08 : 0) |
1884 (ins->rex & (REX_R|REX_X|REX_B));
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001885 ins->rex = 0;
1886 }
1887
H. Peter Anvine2c80182005-01-15 22:15:51 +00001888 s = p - bytes;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001889 out(offset, segment, bytes, OUT_RAWDATA, s, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001890
Victor van den Elzencf9332c2008-10-01 12:18:28 +02001891 /*
1892 * Make sure the address gets the right offset in case
1893 * the line breaks in the .lst file (BR 1197827)
1894 */
1895 offset += s;
1896 s = 0;
1897
H. Peter Anvine2c80182005-01-15 22:15:51 +00001898 switch (ea_data.bytes) {
1899 case 0:
1900 break;
1901 case 1:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001902 case 2:
1903 case 4:
Victor van den Elzen352fe062008-12-10 13:04:58 +01001904 case 8:
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001905 data = opy->offset;
1906 warn_overflow(ea_data.bytes, opy);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001907 s += ea_data.bytes;
H. Peter Anvin9f817132008-10-06 19:11:07 -07001908 if (ea_data.rip) {
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001909 if (opy->segment == segment) {
H. Peter Anvine286c7e2008-10-22 11:15:00 -07001910 data -= insn_end;
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001911 out(offset, segment, &data, OUT_ADDRESS,
1912 ea_data.bytes, NO_SEG, NO_SEG);
H. Peter Anvine286c7e2008-10-22 11:15:00 -07001913 } else {
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001914 out(offset, segment, &data, OUT_REL4ADR,
1915 insn_end - offset, opy->segment, opy->wrt);
H. Peter Anvine286c7e2008-10-22 11:15:00 -07001916 }
H. Peter Anvin9f817132008-10-06 19:11:07 -07001917 } else {
1918 type = OUT_ADDRESS;
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001919 out(offset, segment, &data, OUT_ADDRESS,
1920 ea_data.bytes, opy->segment, opy->wrt);
H. Peter Anvin9f817132008-10-06 19:11:07 -07001921 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001922 break;
Victor van den Elzen352fe062008-12-10 13:04:58 +01001923 default:
1924 /* Impossible! */
1925 errfunc(ERR_PANIC,
1926 "Invalid amount of bytes (%d) for offset?!",
1927 ea_data.bytes);
1928 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001929 }
1930 offset += s;
H. Peter Anvin839eca22007-10-29 23:12:47 -07001931 }
H. Peter Anvin507ae032008-10-09 15:37:10 -07001932 break;
1933
1934 default:
1935 errfunc(ERR_PANIC, "internal instruction table corrupt"
H. Peter Anvin16a856c2009-03-01 00:22:16 -08001936 ": instruction code \\%o (0x%02X) given", c, c);
H. Peter Anvin507ae032008-10-09 15:37:10 -07001937 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001938 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001939 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001940}
1941
H. Peter Anvin0ec60e62007-07-07 01:59:52 +00001942static int32_t regflag(const operand * o)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001943{
1944 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1945 errfunc(ERR_PANIC, "invalid operand passed to regflag()");
1946 }
H. Peter Anvina4835d42008-05-20 14:21:29 -07001947 return nasm_reg_flags[o->basereg];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001948}
1949
H. Peter Anvin5b0e3ec2007-07-07 02:01:08 +00001950static int32_t regval(const operand * o)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001951{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001952 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1953 errfunc(ERR_PANIC, "invalid operand passed to regval()");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001954 }
H. Peter Anvina4835d42008-05-20 14:21:29 -07001955 return nasm_regvals[o->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001956}
1957
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001958static int op_rexflags(const operand * o, int mask)
1959{
1960 int32_t flags;
1961 int val;
1962
1963 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1964 errfunc(ERR_PANIC, "invalid operand passed to op_rexflags()");
1965 }
1966
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
1973static int rexflags(int val, int32_t flags, int mask)
1974{
1975 int rex = 0;
1976
1977 if (val >= 8)
1978 rex |= REX_B|REX_X|REX_R;
1979 if (flags & BITS64)
1980 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;
1985
1986 return rex & mask;
1987}
1988
H. Peter Anvin65289e82009-07-25 17:25:11 -07001989static enum match_result matches(const struct itemplate *itemp,
1990 insn *instruction, int bits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001991{
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001992 int i, size[MAX_OPERANDS], asize, oprs, ret;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001993
H. Peter Anvin65289e82009-07-25 17:25:11 -07001994 ret = MOK_GOOD;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001995
1996 /*
1997 * Check the opcode
1998 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001999 if (itemp->opcode != instruction->opcode)
H. Peter Anvin65289e82009-07-25 17:25:11 -07002000 return MERR_INVALOP;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002001
2002 /*
2003 * Count the operands
2004 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002005 if (itemp->operands != instruction->operands)
H. Peter Anvin65289e82009-07-25 17:25:11 -07002006 return MERR_INVALOP;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002007
2008 /*
2009 * Check that no spurious colons or TOs are present
2010 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002011 for (i = 0; i < itemp->operands; i++)
2012 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON | TO))
H. Peter Anvin65289e82009-07-25 17:25:11 -07002013 return MERR_INVALOP;
H. Peter Anvin70653092007-10-19 14:42:29 -07002014
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002015 /*
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002016 * Process size flags
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002017 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002018 if (itemp->flags & IF_ARMASK) {
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002019 memset(size, 0, sizeof size);
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002020
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002021 i = ((itemp->flags & IF_ARMASK) >> IF_ARSHFT) - 1;
2022
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002023 switch (itemp->flags & IF_SMASK) {
2024 case IF_SB:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002025 size[i] = BITS8;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002026 break;
2027 case IF_SW:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002028 size[i] = BITS16;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002029 break;
2030 case IF_SD:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002031 size[i] = BITS32;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002032 break;
2033 case IF_SQ:
Keith Kaniosb7a89542007-04-12 02:40:54 +00002034 size[i] = BITS64;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002035 break;
H. Peter Anvin41c9f6f2007-09-18 13:01:32 -07002036 case IF_SO:
2037 size[i] = BITS128;
2038 break;
H. Peter Anvindfb91802008-05-20 11:43:53 -07002039 case IF_SY:
2040 size[i] = BITS256;
2041 break;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002042 case IF_SZ:
2043 switch (bits) {
2044 case 16:
2045 size[i] = BITS16;
2046 break;
2047 case 32:
2048 size[i] = BITS32;
2049 break;
2050 case 64:
2051 size[i] = BITS64;
2052 break;
2053 }
2054 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002055 default:
2056 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002057 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002058 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002059 asize = 0;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002060 switch (itemp->flags & IF_SMASK) {
2061 case IF_SB:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002062 asize = BITS8;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002063 break;
2064 case IF_SW:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002065 asize = BITS16;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002066 break;
2067 case IF_SD:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002068 asize = BITS32;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002069 break;
2070 case IF_SQ:
Keith Kaniosb7a89542007-04-12 02:40:54 +00002071 asize = BITS64;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002072 break;
H. Peter Anvin41c9f6f2007-09-18 13:01:32 -07002073 case IF_SO:
2074 asize = BITS128;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002075 break;
H. Peter Anvindfb91802008-05-20 11:43:53 -07002076 case IF_SY:
2077 asize = BITS256;
2078 break;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002079 case IF_SZ:
2080 switch (bits) {
2081 case 16:
2082 asize = BITS16;
2083 break;
2084 case 32:
2085 asize = BITS32;
2086 break;
2087 case 64:
2088 asize = BITS64;
2089 break;
2090 }
H. Peter Anvin41c9f6f2007-09-18 13:01:32 -07002091 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002092 default:
2093 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002094 }
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002095 for (i = 0; i < MAX_OPERANDS; i++)
2096 size[i] = asize;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002097 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002098
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002099 /*
2100 * Check that the operand flags all match up
2101 */
2102 for (i = 0; i < itemp->operands; i++) {
2103 int32_t type = instruction->oprs[i].type;
2104 if (!(type & SIZE_MASK))
2105 type |= size[i];
H. Peter Anvind85d2502008-05-04 17:53:31 -07002106
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002107 if (itemp->opd[i] & SAME_AS) {
2108 int j = itemp->opd[i] & ~SAME_AS;
2109 if (type != instruction->oprs[j].type ||
2110 instruction->oprs[i].basereg != instruction->oprs[j].basereg)
H. Peter Anvin65289e82009-07-25 17:25:11 -07002111 return MERR_INVALOP;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002112 } else if (itemp->opd[i] & ~type ||
2113 ((itemp->opd[i] & SIZE_MASK) &&
2114 ((itemp->opd[i] ^ type) & SIZE_MASK))) {
2115 if ((itemp->opd[i] & ~type & ~SIZE_MASK) ||
2116 (type & SIZE_MASK))
H. Peter Anvin65289e82009-07-25 17:25:11 -07002117 return MERR_INVALOP;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002118 else
H. Peter Anvin65289e82009-07-25 17:25:11 -07002119 return MERR_OPSIZEMISSING;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002120 }
2121 }
2122
2123 /*
2124 * Check operand sizes
2125 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002126 if (itemp->flags & (IF_SM | IF_SM2)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002127 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
2128 asize = 0;
2129 for (i = 0; i < oprs; i++) {
2130 if ((asize = itemp->opd[i] & SIZE_MASK) != 0) {
2131 int j;
2132 for (j = 0; j < oprs; j++)
2133 size[j] = asize;
2134 break;
2135 }
2136 }
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002137 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002138 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002139 }
2140
Keith Kaniosb7a89542007-04-12 02:40:54 +00002141 for (i = 0; i < itemp->operands; i++) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002142 if (!(itemp->opd[i] & SIZE_MASK) &&
2143 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvin65289e82009-07-25 17:25:11 -07002144 return MERR_OPSIZEMISMATCH;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002145 }
2146
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002147 /*
2148 * Check template is okay at the set cpu level
2149 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002150 if (((itemp->flags & IF_PLEVEL) > cpu))
H. Peter Anvin65289e82009-07-25 17:25:11 -07002151 return MERR_BADCPU;
H. Peter Anvin70653092007-10-19 14:42:29 -07002152
Keith Kaniosb7a89542007-04-12 02:40:54 +00002153 /*
H. Peter Anvin6cda4142008-12-29 20:52:28 -08002154 * Verify the appropriate long mode flag.
Keith Kaniosb7a89542007-04-12 02:40:54 +00002155 */
H. Peter Anvin6cda4142008-12-29 20:52:28 -08002156 if ((itemp->flags & (bits == 64 ? IF_NOLONG : IF_LONG)))
H. Peter Anvin65289e82009-07-25 17:25:11 -07002157 return MERR_BADMODE;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002158
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002159 /*
2160 * Check if special handling needed for Jumps
2161 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002162 if ((uint8_t)(itemp->code[0]) >= 0370)
H. Peter Anvin65289e82009-07-25 17:25:11 -07002163 return MOK_JUMP;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002164
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002165 return ret;
2166}
2167
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002168static ea *process_ea(operand * input, ea * output, int bits,
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07002169 int addrbits, int rfield, int32_t rflags)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002170{
H. Peter Anvin9945fee2009-02-26 14:48:03 -08002171 bool forw_ref = !!(input->opflags & OPFLAG_UNKNOWN);
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07002172
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002173 output->rip = false;
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00002174
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002175 /* REX flags for the rfield operand */
2176 output->rex |= rexflags(rfield, rflags, REX_R|REX_P|REX_W|REX_H);
2177
Keith Kaniosb7a89542007-04-12 02:40:54 +00002178 if (!(REGISTER & ~input->type)) { /* register direct */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002179 int i;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002180 int32_t f;
2181
2182 if (input->basereg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002183 || input->basereg >= REG_ENUM_LIMIT)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002184 return NULL;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002185 f = regflag(input);
H. Peter Anvina4835d42008-05-20 14:21:29 -07002186 i = nasm_regvals[input->basereg];
Keith Kaniosb7a89542007-04-12 02:40:54 +00002187
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002188 if (REG_EA & ~f)
2189 return NULL; /* Invalid EA register */
H. Peter Anvin70653092007-10-19 14:42:29 -07002190
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002191 output->rex |= op_rexflags(input, REX_B|REX_P|REX_W|REX_H);
2192
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002193 output->sib_present = false; /* no SIB necessary */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002194 output->bytes = 0; /* no offset necessary either */
2195 output->modrm = 0xC0 | ((rfield & 7) << 3) | (i & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002196 } else { /* it's a memory reference */
2197 if (input->basereg == -1
2198 && (input->indexreg == -1 || input->scale == 0)) {
2199 /* it's a pure offset */
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002200 if (bits == 64 && (~input->type & IP_REL)) {
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002201 int scale, index, base;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002202 output->sib_present = true;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002203 scale = 0;
2204 index = 4;
2205 base = 5;
2206 output->sib = (scale << 6) | (index << 3) | base;
2207 output->bytes = 4;
2208 output->modrm = 4 | ((rfield & 7) << 3);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002209 output->rip = false;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002210 } else {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002211 output->sib_present = false;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002212 output->bytes = (addrbits != 16 ? 4 : 2);
2213 output->modrm = (addrbits != 16 ? 5 : 6) | ((rfield & 7) << 3);
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002214 output->rip = bits == 64;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002215 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002216 } else { /* it's an indirection */
2217 int i = input->indexreg, b = input->basereg, s = input->scale;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002218 int32_t o = input->offset, seg = input->segment;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002219 int hb = input->hintbase, ht = input->hinttype;
2220 int t;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002221 int it, bt;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002222 int32_t ix, bx; /* register flags */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002223
H. Peter Anvine2c80182005-01-15 22:15:51 +00002224 if (s == 0)
2225 i = -1; /* make this easy, at least */
H. Peter Anvin70653092007-10-19 14:42:29 -07002226
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002227 if (i >= EXPR_REG_START && i < REG_ENUM_LIMIT) {
H. Peter Anvina4835d42008-05-20 14:21:29 -07002228 it = nasm_regvals[i];
2229 ix = nasm_reg_flags[i];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002230 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00002231 it = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002232 ix = 0;
2233 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002234
H. Peter Anvinb0c54622007-10-28 23:21:46 -07002235 if (b >= EXPR_REG_START && b < REG_ENUM_LIMIT) {
H. Peter Anvina4835d42008-05-20 14:21:29 -07002236 bt = nasm_regvals[b];
2237 bx = nasm_reg_flags[b];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002238 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00002239 bt = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002240 bx = 0;
2241 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002242
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002243 /* check for a 32/64-bit memory reference... */
2244 if ((ix|bx) & (BITS32|BITS64)) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00002245 /* it must be a 32/64-bit memory reference. Firstly we have
2246 * to check that all registers involved are type E/Rxx. */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002247 int32_t sok = BITS32|BITS64;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002248
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002249 if (it != -1) {
2250 if (!(REG64 & ~ix) || !(REG32 & ~ix))
2251 sok &= ix;
2252 else
2253 return NULL;
2254 }
2255
2256 if (bt != -1) {
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00002257 if (REG_GPR & ~bx)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002258 return NULL; /* Invalid register */
H. Peter Anvina57e8d42007-05-30 03:44:02 +00002259 if (~sok & bx & SIZE_MASK)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002260 return NULL; /* Invalid size */
H. Peter Anvinb0c54622007-10-28 23:21:46 -07002261 sok &= bx;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002262 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002263
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002264 /* While we're here, ensure the user didn't specify
2265 WORD or QWORD. */
2266 if (input->disp_size == 16 || input->disp_size == 64)
2267 return NULL;
2268
2269 if (addrbits == 16 ||
2270 (addrbits == 32 && !(sok & BITS32)) ||
2271 (addrbits == 64 && !(sok & BITS64)))
2272 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002273
Keith Kaniosb7a89542007-04-12 02:40:54 +00002274 /* now reorganize base/index */
2275 if (s == 1 && bt != it && bt != -1 && it != -1 &&
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002276 ((hb == b && ht == EAH_NOTBASE)
2277 || (hb == i && ht == EAH_MAKEBASE))) {
2278 /* swap if hints say so */
2279 t = bt, bt = it, it = t;
2280 t = bx, bx = ix, ix = t;
2281 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00002282 if (bt == it) /* convert EAX+2*EAX to 3*EAX */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002283 bt = -1, bx = 0, s++;
2284 if (bt == -1 && s == 1 && !(hb == it && ht == EAH_NOTBASE)) {
2285 /* make single reg base, unless hint */
2286 bt = it, bx = ix, it = -1, ix = 0;
2287 }
H. Peter Anvinf5843c62007-09-10 18:59:26 +00002288 if (((s == 2 && it != REG_NUM_ESP
H. Peter Anvine2c80182005-01-15 22:15:51 +00002289 && !(input->eaflags & EAF_TIMESTWO)) || s == 3
Keith Kaniosb7a89542007-04-12 02:40:54 +00002290 || s == 5 || s == 9) && bt == -1)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002291 bt = it, bx = ix, s--; /* convert 3*EAX to EAX+2*EAX */
Keith Kanios48af1772007-08-17 07:37:52 +00002292 if (it == -1 && (bt & 7) != REG_NUM_ESP
H. Peter Anvine2c80182005-01-15 22:15:51 +00002293 && (input->eaflags & EAF_TIMESTWO))
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002294 it = bt, ix = bx, bt = -1, bx = 0, s = 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002295 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
Keith Kanios48af1772007-08-17 07:37:52 +00002296 if (s == 1 && it == REG_NUM_ESP) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002297 /* swap ESP into base if scale is 1 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002298 t = it, it = bt, bt = t;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002299 t = ix, ix = bx, bx = t;
2300 }
Keith Kanios48af1772007-08-17 07:37:52 +00002301 if (it == REG_NUM_ESP
Keith Kaniosb7a89542007-04-12 02:40:54 +00002302 || (s != 1 && s != 2 && s != 4 && s != 8 && it != -1))
H. Peter Anvine2c80182005-01-15 22:15:51 +00002303 return NULL; /* wrong, for various reasons */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002304
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002305 output->rex |= rexflags(it, ix, REX_X);
2306 output->rex |= rexflags(bt, bx, REX_B);
Keith Kaniosb7a89542007-04-12 02:40:54 +00002307
Keith Kanios48af1772007-08-17 07:37:52 +00002308 if (it == -1 && (bt & 7) != REG_NUM_ESP) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002309 /* no SIB needed */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002310 int mod, rm;
H. Peter Anvin70653092007-10-19 14:42:29 -07002311
Keith Kaniosb7a89542007-04-12 02:40:54 +00002312 if (bt == -1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002313 rm = 5;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002314 mod = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002315 } else {
2316 rm = (bt & 7);
Keith Kanios48af1772007-08-17 07:37:52 +00002317 if (rm != REG_NUM_EBP && o == 0 &&
Keith Kaniosb7a89542007-04-12 02:40:54 +00002318 seg == NO_SEG && !forw_ref &&
2319 !(input->eaflags &
2320 (EAF_BYTEOFFS | EAF_WORDOFFS)))
2321 mod = 0;
2322 else if (input->eaflags & EAF_BYTEOFFS ||
2323 (o >= -128 && o <= 127 && seg == NO_SEG
2324 && !forw_ref
2325 && !(input->eaflags & EAF_WORDOFFS)))
2326 mod = 1;
2327 else
2328 mod = 2;
2329 }
H. Peter Anvinea838272002-04-30 20:51:53 +00002330
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002331 output->sib_present = false;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002332 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
2333 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002334 } else {
2335 /* we need a SIB */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002336 int mod, scale, index, base;
H. Peter Anvin70653092007-10-19 14:42:29 -07002337
Keith Kaniosb7a89542007-04-12 02:40:54 +00002338 if (it == -1)
2339 index = 4, s = 1;
2340 else
2341 index = (it & 7);
H. Peter Anvin70653092007-10-19 14:42:29 -07002342
H. Peter Anvine2c80182005-01-15 22:15:51 +00002343 switch (s) {
2344 case 1:
2345 scale = 0;
2346 break;
2347 case 2:
2348 scale = 1;
2349 break;
2350 case 4:
2351 scale = 2;
2352 break;
2353 case 8:
2354 scale = 3;
2355 break;
2356 default: /* then what the smeg is it? */
2357 return NULL; /* panic */
2358 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002359
Keith Kaniosb7a89542007-04-12 02:40:54 +00002360 if (bt == -1) {
2361 base = 5;
2362 mod = 0;
2363 } else {
2364 base = (bt & 7);
Keith Kanios48af1772007-08-17 07:37:52 +00002365 if (base != REG_NUM_EBP && o == 0 &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00002366 seg == NO_SEG && !forw_ref &&
2367 !(input->eaflags &
Keith Kaniosb7a89542007-04-12 02:40:54 +00002368 (EAF_BYTEOFFS | EAF_WORDOFFS)))
2369 mod = 0;
2370 else if (input->eaflags & EAF_BYTEOFFS ||
2371 (o >= -128 && o <= 127 && seg == NO_SEG
2372 && !forw_ref
2373 && !(input->eaflags & EAF_WORDOFFS)))
2374 mod = 1;
2375 else
2376 mod = 2;
2377 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002378
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002379 output->sib_present = true;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002380 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
2381 output->modrm = (mod << 6) | ((rfield & 7) << 3) | 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002382 output->sib = (scale << 6) | (index << 3) | base;
2383 }
2384 } else { /* it's 16-bit */
2385 int mod, rm;
H. Peter Anvin70653092007-10-19 14:42:29 -07002386
Keith Kaniosb7a89542007-04-12 02:40:54 +00002387 /* check for 64-bit long mode */
2388 if (addrbits == 64)
2389 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002390
H. Peter Anvine2c80182005-01-15 22:15:51 +00002391 /* check all registers are BX, BP, SI or DI */
2392 if ((b != -1 && b != R_BP && b != R_BX && b != R_SI
2393 && b != R_DI) || (i != -1 && i != R_BP && i != R_BX
2394 && i != R_SI && i != R_DI))
2395 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002396
Keith Kaniosb7a89542007-04-12 02:40:54 +00002397 /* ensure the user didn't specify DWORD/QWORD */
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002398 if (input->disp_size == 32 || input->disp_size == 64)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002399 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002400
H. Peter Anvine2c80182005-01-15 22:15:51 +00002401 if (s != 1 && i != -1)
2402 return NULL; /* no can do, in 16-bit EA */
2403 if (b == -1 && i != -1) {
2404 int tmp = b;
2405 b = i;
2406 i = tmp;
2407 } /* swap */
2408 if ((b == R_SI || b == R_DI) && i != -1) {
2409 int tmp = b;
2410 b = i;
2411 i = tmp;
2412 }
2413 /* have BX/BP as base, SI/DI index */
2414 if (b == i)
2415 return NULL; /* shouldn't ever happen, in theory */
2416 if (i != -1 && b != -1 &&
2417 (i == R_BP || i == R_BX || b == R_SI || b == R_DI))
2418 return NULL; /* invalid combinations */
2419 if (b == -1) /* pure offset: handled above */
2420 return NULL; /* so if it gets to here, panic! */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002421
H. Peter Anvine2c80182005-01-15 22:15:51 +00002422 rm = -1;
2423 if (i != -1)
2424 switch (i * 256 + b) {
2425 case R_SI * 256 + R_BX:
2426 rm = 0;
2427 break;
2428 case R_DI * 256 + R_BX:
2429 rm = 1;
2430 break;
2431 case R_SI * 256 + R_BP:
2432 rm = 2;
2433 break;
2434 case R_DI * 256 + R_BP:
2435 rm = 3;
2436 break;
2437 } else
2438 switch (b) {
2439 case R_SI:
2440 rm = 4;
2441 break;
2442 case R_DI:
2443 rm = 5;
2444 break;
2445 case R_BP:
2446 rm = 6;
2447 break;
2448 case R_BX:
2449 rm = 7;
2450 break;
2451 }
2452 if (rm == -1) /* can't happen, in theory */
2453 return NULL; /* so panic if it does */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002454
H. Peter Anvine2c80182005-01-15 22:15:51 +00002455 if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
2456 !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
2457 mod = 0;
2458 else if (input->eaflags & EAF_BYTEOFFS ||
2459 (o >= -128 && o <= 127 && seg == NO_SEG
2460 && !forw_ref
2461 && !(input->eaflags & EAF_WORDOFFS)))
2462 mod = 1;
2463 else
2464 mod = 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002465
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002466 output->sib_present = false; /* no SIB - it's 16-bit */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002467 output->bytes = mod; /* bytes of offset needed */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002468 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002469 }
2470 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002471 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002472
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002473 output->size = 1 + output->sib_present + output->bytes;
2474 return output;
2475}
2476
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002477static void add_asp(insn *ins, int addrbits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002478{
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002479 int j, valid;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002480 int defdisp;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002481
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002482 valid = (addrbits == 64) ? 64|32 : 32|16;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002483
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002484 switch (ins->prefixes[PPS_ASIZE]) {
2485 case P_A16:
2486 valid &= 16;
2487 break;
2488 case P_A32:
2489 valid &= 32;
2490 break;
2491 case P_A64:
2492 valid &= 64;
2493 break;
2494 case P_ASP:
2495 valid &= (addrbits == 32) ? 16 : 32;
2496 break;
2497 default:
2498 break;
2499 }
2500
2501 for (j = 0; j < ins->operands; j++) {
2502 if (!(MEMORY & ~ins->oprs[j].type)) {
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002503 int32_t i, b;
H. Peter Anvin70653092007-10-19 14:42:29 -07002504
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002505 /* Verify as Register */
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002506 if (ins->oprs[j].indexreg < EXPR_REG_START
2507 || ins->oprs[j].indexreg >= REG_ENUM_LIMIT)
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002508 i = 0;
2509 else
H. Peter Anvina4835d42008-05-20 14:21:29 -07002510 i = nasm_reg_flags[ins->oprs[j].indexreg];
H. Peter Anvin70653092007-10-19 14:42:29 -07002511
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002512 /* Verify as Register */
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002513 if (ins->oprs[j].basereg < EXPR_REG_START
2514 || ins->oprs[j].basereg >= REG_ENUM_LIMIT)
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002515 b = 0;
2516 else
H. Peter Anvina4835d42008-05-20 14:21:29 -07002517 b = nasm_reg_flags[ins->oprs[j].basereg];
H. Peter Anvin70653092007-10-19 14:42:29 -07002518
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002519 if (ins->oprs[j].scale == 0)
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002520 i = 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002521
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002522 if (!i && !b) {
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002523 int ds = ins->oprs[j].disp_size;
2524 if ((addrbits != 64 && ds > 8) ||
2525 (addrbits == 64 && ds == 16))
2526 valid &= ds;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002527 } else {
2528 if (!(REG16 & ~b))
2529 valid &= 16;
2530 if (!(REG32 & ~b))
2531 valid &= 32;
2532 if (!(REG64 & ~b))
2533 valid &= 64;
H. Peter Anvin70653092007-10-19 14:42:29 -07002534
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002535 if (!(REG16 & ~i))
2536 valid &= 16;
2537 if (!(REG32 & ~i))
2538 valid &= 32;
2539 if (!(REG64 & ~i))
2540 valid &= 64;
2541 }
2542 }
2543 }
2544
2545 if (valid & addrbits) {
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002546 ins->addr_size = addrbits;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002547 } else if (valid & ((addrbits == 32) ? 16 : 32)) {
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002548 /* Add an address size prefix */
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002549 enum prefixes pref = (addrbits == 32) ? P_A16 : P_A32;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002550 ins->prefixes[PPS_ASIZE] = pref;
2551 ins->addr_size = (addrbits == 32) ? 16 : 32;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002552 } else {
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002553 /* Impossible... */
2554 errfunc(ERR_NONFATAL, "impossible combination of address sizes");
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002555 ins->addr_size = addrbits; /* Error recovery */
2556 }
2557
2558 defdisp = ins->addr_size == 16 ? 16 : 32;
2559
2560 for (j = 0; j < ins->operands; j++) {
2561 if (!(MEM_OFFS & ~ins->oprs[j].type) &&
2562 (ins->oprs[j].disp_size ? ins->oprs[j].disp_size : defdisp)
2563 != ins->addr_size) {
2564 /* mem_offs sizes must match the address size; if not,
2565 strip the MEM_OFFS bit and match only EA instructions */
2566 ins->oprs[j].type &= ~(MEM_OFFS & ~MEMORY);
2567 }
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002568 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002569}