blob: b72e5a6019920fb86a581cb825c693c0852de1c6 [file] [log] [blame]
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001/* assemble.c code generation for the Netwide Assembler
2 *
3 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
4 * Julian Hall. All rights reserved. The software is
Beroset095e6a22007-12-29 09:44:23 -05005 * redistributable under the license given in the file "LICENSE"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00006 * distributed in the NASM archive.
7 *
8 * the actual codes (C syntax, i.e. octal):
9 * \0 - terminates the code. (Unless it's a literal of course.)
H. Peter Anvindcffe4b2008-10-10 22:10:31 -070010 * \1..\4 - that many literal bytes follow in the code stream
11 * \5 - add 4 to the primary operand number (b, low octdigit)
12 * \6 - add 4 to the secondary operand number (a, middle octdigit)
13 * \7 - add 4 to both the primary and the secondary operand number
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070014 * \10..\13 - a literal byte follows in the code stream, to be added
15 * to the register value of operand 0..3
16 * \14..\17 - a signed byte immediate operand, from operand 0..3
17 * \20..\23 - a byte immediate operand, from operand 0..3
18 * \24..\27 - an unsigned byte immediate operand, from operand 0..3
19 * \30..\33 - a word immediate operand, from operand 0..3
20 * \34..\37 - select between \3[0-3] and \4[0-3] depending on 16/32 bit
H. Peter Anvin3ba46772002-05-27 23:19:35 +000021 * assembly mode or the operand-size override on the operand
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070022 * \40..\43 - a long immediate operand, from operand 0..3
23 * \44..\47 - select between \3[0-3], \4[0-3] and \5[4-7]
H. Peter Anvinde4b89b2007-10-01 15:41:25 -070024 * depending on the address size of the instruction.
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070025 * \50..\53 - a byte relative operand, from operand 0..3
26 * \54..\57 - a qword immediate operand, from operand 0..3
27 * \60..\63 - a word relative operand, from operand 0..3
28 * \64..\67 - select between \6[0-3] and \7[0-3] depending on 16/32 bit
H. Peter Anvin17799b42002-05-21 03:31:21 +000029 * assembly mode or the operand-size override on the operand
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070030 * \70..\73 - a long relative operand, from operand 0..3
H. Peter Anvinc1377e92008-10-06 23:40:31 -070031 * \74..\77 - a word constant, from the _segment_ part of operand 0..3
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000032 * \1ab - a ModRM, calculated on EA in operand a, with the spare
33 * field the register value of operand b.
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070034 * \140..\143 - an immediate word or signed byte for operand 0..3
H. Peter Anvina30cc072007-11-18 21:55:26 -080035 * \144..\147 - or 2 (s-field) into opcode byte if operand 0..3
36 * is a signed byte rather than a word. Opcode byte follows.
H. Peter Anvinc1377e92008-10-06 23:40:31 -070037 * \150..\153 - an immediate dword or signed byte for operand 0..3
H. Peter Anvina30cc072007-11-18 21:55:26 -080038 * \154..\157 - or 2 (s-field) into opcode byte if operand 0..3
H. Peter Anvin32cd4c22008-04-04 13:34:53 -070039 * is a signed byte rather than a dword. Opcode byte follows.
H. Peter Anvin401c07e2007-09-17 16:55:04 -070040 * \160..\163 - this instruction uses DREX rather than REX, with the
41 * OC0 field set to 0, and the dest field taken from
42 * operand 0..3.
43 * \164..\167 - this instruction uses DREX rather than REX, with the
44 * OC0 field set to 1, and the dest field taken from
45 * operand 0..3.
H. Peter Anvin401c07e2007-09-17 16:55:04 -070046 * \171 - placement of DREX suffix in the absence of an EA
H. Peter Anvind85d2502008-05-04 17:53:31 -070047 * \172\ab - the register number from operand a in bits 7..4, with
H. Peter Anvin52dc3532008-05-20 19:29:04 -070048 * the 4-bit immediate from operand b in bits 3..0.
H. Peter Anvind58656f2008-05-06 20:11:14 -070049 * \173\xab - the register number from operand a in bits 7..4, with
H. Peter Anvin52dc3532008-05-20 19:29:04 -070050 * the value b in bits 3..0.
51 * \174\a - the register number from operand a in bits 7..4, and
52 * an arbitrary value in bits 3..0 (assembled as zero.)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000053 * \2ab - a ModRM, calculated on EA in operand a, with the spare
54 * field equal to digit b.
H. Peter Anvin32cd4c22008-04-04 13:34:53 -070055 * \250..\253 - same as \150..\153, except warn if the 64-bit operand
56 * is not equal to the truncated and sign-extended 32-bit
57 * operand; used for 32-bit immediates in 64-bit mode.
H. Peter Anvin588df782008-10-07 10:05:10 -070058 * \254..\257 - a signed 32-bit operand to be extended to 64 bits.
H. Peter Anvina04019c2009-05-03 21:42:34 -070059 * \260..\263 - this instruction uses VEX/XOP rather than REX, with the
H. Peter Anvind85d2502008-05-04 17:53:31 -070060 * V field taken from operand 0..3.
H. Peter Anvina04019c2009-05-03 21:42:34 -070061 * \270 - this instruction uses VEX/XOP rather than REX, with the
H. Peter Anvind85d2502008-05-04 17:53:31 -070062 * V field set to 1111b.
63 *
H. Peter Anvina04019c2009-05-03 21:42:34 -070064 * VEX/XOP prefixes are followed by the sequence:
65 * \tmm\wlp where mm is the M field; and wlp is:
H. Peter Anvinaaa088f2008-05-12 11:13:41 -070066 * 00 0ww lpp
H. Peter Anvinbd420c72008-05-22 11:24:35 -070067 * [w0] ww = 0 for W = 0
68 * [w1] ww = 1 for W = 1
69 * [wx] ww = 2 for W don't care (always assembled as 0)
70 * [ww] ww = 3 for W used as REX.W
71 *
H. Peter Anvina04019c2009-05-03 21:42:34 -070072 * t = 0 for VEX (C4/C5), t = 1 for XOP (8F).
H. Peter Anvind85d2502008-05-04 17:53:31 -070073 *
H. Peter Anvinc1377e92008-10-06 23:40:31 -070074 * \274..\277 - a signed byte immediate operand, from operand 0..3,
75 * which is to be extended to the operand size.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000076 * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
77 * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
Keith Kanios48af1772007-08-17 07:37:52 +000078 * \312 - (disassembler only) marker on LOOP, LOOPxx instructions.
H. Peter Anvince2b3972007-05-30 22:21:11 +000079 * \313 - indicates fixed 64-bit address size, 0x67 invalid.
H. Peter Anvin23440102007-11-12 21:02:33 -080080 * \314 - (disassembler only) invalid with REX.B
81 * \315 - (disassembler only) invalid with REX.X
82 * \316 - (disassembler only) invalid with REX.R
83 * \317 - (disassembler only) invalid with REX.W
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000084 * \320 - indicates fixed 16-bit operand size, i.e. optional 0x66.
85 * \321 - indicates fixed 32-bit operand size, i.e. optional 0x66.
86 * \322 - indicates that this instruction is only valid when the
87 * operand size is the default (instruction to disassembler,
88 * generates no code in the assembler)
H. Peter Anvince2b3972007-05-30 22:21:11 +000089 * \323 - indicates fixed 64-bit operand size, REX on extensions only.
Keith Kaniosb7a89542007-04-12 02:40:54 +000090 * \324 - indicates 64-bit operand size requiring REX prefix.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000091 * \330 - a literal byte follows in the code stream, to be added
92 * to the condition code value of the instruction.
Keith Kanios48af1772007-08-17 07:37:52 +000093 * \331 - instruction not valid with REP prefix. Hint for
H. Peter Anvinef7468f2002-04-30 20:57:59 +000094 * disassembler only; for SSE instructions.
H. Peter Anvincb9b6902007-09-12 21:58:51 -070095 * \332 - REP prefix (0xF2 byte) used as opcode extension.
96 * \333 - REP prefix (0xF3 byte) used as opcode extension.
Keith Kanios48af1772007-08-17 07:37:52 +000097 * \334 - LOCK prefix used instead of REX.R
H. Peter Anvincb9b6902007-09-12 21:58:51 -070098 * \335 - disassemble a rep (0xF3 byte) prefix as repe not rep.
H. Peter Anvin962e3052008-08-28 17:47:16 -070099 * \336 - force a REP(E) prefix (0xF2) even if not specified.
100 * \337 - force a REPNE prefix (0xF3) even if not specified.
101 * \336-\337 are still listed as prefixes in the disassembler.
Keith Kaniosb7a89542007-04-12 02:40:54 +0000102 * \340 - reserve <operand 0> bytes of uninitialized storage.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000103 * Operand 0 had better be a segmentless constant.
H. Peter Anvinc2acf7b2009-02-21 18:22:56 -0800104 * \341 - this instruction needs a WAIT "prefix"
H. Peter Anvinff6e12d2008-10-08 21:17:32 -0700105 * \344,\345 - the PUSH/POP (respectively) codes for CS, DS, ES, SS
106 * (POP is never used for CS) depending on operand 0
107 * \346,\347 - the second byte of PUSH/POP codes for FS, GS, depending
108 * on operand 0
H. Peter Anvinfff5a472008-05-20 09:46:24 -0700109 * \360 - no SSE prefix (== \364\331)
110 * \361 - 66 SSE prefix (== \366\331)
111 * \362 - F2 SSE prefix (== \364\332)
112 * \363 - F3 SSE prefix (== \364\333)
H. Peter Anvin62cb6062007-09-11 22:44:03 +0000113 * \364 - operand-size prefix (0x66) not permitted
114 * \365 - address-size prefix (0x67) not permitted
115 * \366 - operand-size prefix (0x66) used as opcode extension
116 * \367 - address-size prefix (0x67) used as opcode extension
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000117 * \370,\371,\372 - match only if operand 0 meets byte jump criteria.
118 * 370 is used for Jcc, 371 is used for JMP.
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000119 * \373 - assemble 0x03 if bits==16, 0x05 if bits==32;
120 * used for conditional jump over longer jump
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000121 */
122
H. Peter Anvinfe501952007-10-02 21:53:51 -0700123#include "compiler.h"
124
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000125#include <stdio.h>
126#include <string.h>
Keith Kaniosb7a89542007-04-12 02:40:54 +0000127#include <inttypes.h>
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000128
129#include "nasm.h"
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000130#include "nasmlib.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000131#include "assemble.h"
132#include "insns.h"
H. Peter Anvina4835d42008-05-20 14:21:29 -0700133#include "tables.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000134
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000135typedef struct {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000136 int sib_present; /* is a SIB byte necessary? */
137 int bytes; /* # of bytes of offset needed */
138 int size; /* lazy - this is sib+bytes+1 */
139 uint8_t modrm, sib, rex, rip; /* the bytes themselves */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000140} ea;
141
Keith Kaniosb7a89542007-04-12 02:40:54 +0000142static uint32_t cpu; /* cpu level received from nasm.c */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000143static efunc errfunc;
144static struct ofmt *outfmt;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000145static ListGen *list;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000146
H. Peter Anvin3720f7b2008-05-12 11:00:50 -0700147static int64_t calcsize(int32_t, int64_t, int, insn *, const uint8_t *);
H. Peter Anvin833caea2008-10-04 19:02:30 -0700148static void gencode(int32_t segment, int64_t offset, int bits,
149 insn * ins, const struct itemplate *temp,
150 int64_t insn_end);
H. Peter Anvin3360d792007-09-11 04:16:57 +0000151static int matches(const struct itemplate *, insn *, int bits);
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000152static int32_t regflag(const operand *);
153static int32_t regval(const operand *);
154static int rexflags(int, int32_t, int);
155static int op_rexflags(const operand *, int);
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700156static ea *process_ea(operand *, ea *, int, int, int, int32_t);
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700157static void add_asp(insn *, int);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000158
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700159static int has_prefix(insn * ins, enum prefix_pos pos, enum prefixes prefix)
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000160{
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700161 return ins->prefixes[pos] == prefix;
162}
163
164static void assert_no_prefix(insn * ins, enum prefix_pos pos)
165{
166 if (ins->prefixes[pos])
167 errfunc(ERR_NONFATAL, "invalid %s prefix",
168 prefix_name(ins->prefixes[pos]));
169}
170
171static const char *size_name(int size)
172{
173 switch (size) {
174 case 1:
175 return "byte";
176 case 2:
177 return "word";
178 case 4:
179 return "dword";
180 case 8:
181 return "qword";
182 case 10:
183 return "tword";
184 case 16:
185 return "oword";
H. Peter Anvindfb91802008-05-20 11:43:53 -0700186 case 32:
187 return "yword";
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700188 default:
189 return "???";
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000190 }
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700191}
192
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700193static void warn_overflow(int size, const struct operand *o)
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700194{
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700195 if (size < 8 && o->wrt == NO_SEG && o->segment == NO_SEG) {
Charles Craynedd462c82007-11-04 15:28:30 -0800196 int64_t lim = ((int64_t)1 << (size*8))-1;
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700197 int64_t data = o->offset;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000198
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700199 if (data < ~lim || data > lim)
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700200 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700201 "%s data exceeds bounds", size_name(size));
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700202 }
203}
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000204/*
205 * This routine wrappers the real output format's output routine,
206 * in order to pass a copy of the data off to the listing file
207 * generator at the same time.
208 */
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800209static void out(int64_t offset, int32_t segto, const void *data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800210 enum out_type type, uint64_t size,
211 int32_t segment, int32_t wrt)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000212{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000213 static int32_t lineno = 0; /* static!!! */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000214 static char *lnfname = NULL;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800215 uint8_t p[8];
H. Peter Anvineba20a72002-04-30 20:53:55 +0000216
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800217 if (type == OUT_ADDRESS && segment == NO_SEG && wrt == NO_SEG) {
218 /*
219 * This is a non-relocated address, and we're going to
220 * convert it into RAWDATA format.
221 */
222 uint8_t *q = p;
H. Peter Anvind1fb15c2007-11-13 09:37:59 -0800223
224 if (size > 8) {
225 errfunc(ERR_PANIC, "OUT_ADDRESS with size > 8");
226 return;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800227 }
H. Peter Anvind85d2502008-05-04 17:53:31 -0700228
H. Peter Anvind1fb15c2007-11-13 09:37:59 -0800229 WRITEADDR(q, *(int64_t *)data, size);
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800230 data = p;
231 type = OUT_RAWDATA;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000232 }
233
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800234 list->output(offset, data, type, size);
235
Frank Kotlerabebb082003-09-06 04:45:37 +0000236 /*
237 * this call to src_get determines when we call the
238 * debug-format-specific "linenum" function
239 * it updates lineno and lnfname to the current values
240 * returning 0 if "same as last time", -2 if lnfname
241 * changed, and the amount by which lineno changed,
242 * if it did. thus, these variables must be static
243 */
244
H. Peter Anvine2c80182005-01-15 22:15:51 +0000245 if (src_get(&lineno, &lnfname)) {
246 outfmt->current_dfmt->linenum(lnfname, lineno, segto);
H. Peter Anvince616072002-04-30 21:02:23 +0000247 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000248
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800249 outfmt->output(segto, data, type, size, segment, wrt);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000250}
251
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700252static bool jmp_match(int32_t segment, int64_t offset, int bits,
H. Peter Anvin3720f7b2008-05-12 11:00:50 -0700253 insn * ins, const uint8_t *code)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000254{
Charles Crayne5fbbc8c2007-11-07 19:03:46 -0800255 int64_t isize;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000256 uint8_t c = code[0];
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000257
Charles Craynef1aefd82008-09-30 16:11:32 -0700258 if ((c != 0370 && c != 0371) || (ins->oprs[0].type & STRICT))
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700259 return false;
260 if (!optimizing)
261 return false;
262 if (optimizing < 0 && c == 0371)
263 return false;
264
H. Peter Anvine2c80182005-01-15 22:15:51 +0000265 isize = calcsize(segment, offset, bits, ins, code);
Victor van den Elzenccafc3c2009-02-23 04:35:00 +0100266
Victor van den Elzen154e5922009-02-25 17:32:00 +0100267 if (ins->oprs[0].opflags & OPFLAG_UNKNOWN)
Victor van den Elzenccafc3c2009-02-23 04:35:00 +0100268 /* Be optimistic in pass 1 */
269 return true;
270
H. Peter Anvine2c80182005-01-15 22:15:51 +0000271 if (ins->oprs[0].segment != segment)
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700272 return false;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000273
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700274 isize = ins->oprs[0].offset - offset - isize; /* isize is delta */
275 return (isize >= -128 && isize <= 127); /* is it byte size? */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000276}
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000277
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800278int64_t assemble(int32_t segment, int64_t offset, int bits, uint32_t cp,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000279 insn * instruction, struct ofmt *output, efunc error,
280 ListGen * listgen)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000281{
H. Peter Anvin3360d792007-09-11 04:16:57 +0000282 const struct itemplate *temp;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000283 int j;
284 int size_prob;
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800285 int64_t insn_end;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000286 int32_t itimes;
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800287 int64_t start = offset;
288 int64_t wsize = 0; /* size for DB etc. */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000289
H. Peter Anvine2c80182005-01-15 22:15:51 +0000290 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000291 cpu = cp;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000292 outfmt = output; /* likewise */
293 list = listgen; /* and again */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000294
H. Peter Anvine2c80182005-01-15 22:15:51 +0000295 switch (instruction->opcode) {
296 case -1:
297 return 0;
298 case I_DB:
299 wsize = 1;
300 break;
301 case I_DW:
302 wsize = 2;
303 break;
304 case I_DD:
305 wsize = 4;
306 break;
307 case I_DQ:
308 wsize = 8;
309 break;
310 case I_DT:
311 wsize = 10;
312 break;
H. Peter Anvincfbe7c32007-09-18 17:49:09 -0700313 case I_DO:
314 wsize = 16;
315 break;
H. Peter Anvindfb91802008-05-20 11:43:53 -0700316 case I_DY:
317 wsize = 32;
318 break;
H. Peter Anvin16b0a332007-09-12 20:27:41 -0700319 default:
320 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000321 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000322
H. Peter Anvineba20a72002-04-30 20:53:55 +0000323 if (wsize) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000324 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000325 int32_t t = instruction->times;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000326 if (t < 0)
327 errfunc(ERR_PANIC,
328 "instruction->times < 0 (%ld) in assemble()", t);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000329
H. Peter Anvine2c80182005-01-15 22:15:51 +0000330 while (t--) { /* repeat TIMES times */
331 for (e = instruction->eops; e; e = e->next) {
332 if (e->type == EOT_DB_NUMBER) {
333 if (wsize == 1) {
334 if (e->segment != NO_SEG)
335 errfunc(ERR_NONFATAL,
336 "one-byte relocation attempted");
337 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000338 uint8_t out_byte = e->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000339 out(offset, segment, &out_byte,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800340 OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000341 }
Keith Kanios61ff53c2007-04-14 18:54:52 +0000342 } else if (wsize > 8) {
H. Peter Anvin3be5d852008-05-20 14:49:32 -0700343 errfunc(ERR_NONFATAL,
344 "integer supplied to a DT, DO or DY"
Keith Kanios61ff53c2007-04-14 18:54:52 +0000345 " instruction");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000346 } else
347 out(offset, segment, &e->offset,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800348 OUT_ADDRESS, wsize, e->segment, e->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000349 offset += wsize;
H. Peter Anvin518df302008-06-14 16:53:48 -0700350 } else if (e->type == EOT_DB_STRING ||
351 e->type == EOT_DB_STRING_FREE) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000352 int align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000353
H. Peter Anvine2c80182005-01-15 22:15:51 +0000354 out(offset, segment, e->stringval,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800355 OUT_RAWDATA, e->stringlen, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000356 align = e->stringlen % wsize;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000357
H. Peter Anvine2c80182005-01-15 22:15:51 +0000358 if (align) {
359 align = wsize - align;
H. Peter Anvin999868f2009-02-09 11:03:33 +0100360 out(offset, segment, zero_buffer,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800361 OUT_RAWDATA, align, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000362 }
363 offset += e->stringlen + align;
364 }
365 }
366 if (t > 0 && t == instruction->times - 1) {
367 /*
368 * Dummy call to list->output to give the offset to the
369 * listing module.
370 */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800371 list->output(offset, NULL, OUT_RAWDATA, 0);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000372 list->uplevel(LIST_TIMES);
373 }
374 }
375 if (instruction->times > 1)
376 list->downlevel(LIST_TIMES);
377 return offset - start;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000378 }
379
H. Peter Anvine2c80182005-01-15 22:15:51 +0000380 if (instruction->opcode == I_INCBIN) {
H. Peter Anvin518df302008-06-14 16:53:48 -0700381 const char *fname = instruction->eops->stringval;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000382 FILE *fp;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000383
H. Peter Anvin418ca702008-05-30 10:42:30 -0700384 fp = fopen(fname, "rb");
385 if (!fp) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000386 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
387 fname);
H. Peter Anvin418ca702008-05-30 10:42:30 -0700388 } else if (fseek(fp, 0L, SEEK_END) < 0) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000389 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
390 fname);
H. Peter Anvin418ca702008-05-30 10:42:30 -0700391 } else {
H. Peter Anvin518df302008-06-14 16:53:48 -0700392 static char buf[4096];
393 size_t t = instruction->times;
394 size_t base = 0;
395 size_t len;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000396
H. Peter Anvine2c80182005-01-15 22:15:51 +0000397 len = ftell(fp);
398 if (instruction->eops->next) {
399 base = instruction->eops->next->offset;
400 len -= base;
401 if (instruction->eops->next->next &&
H. Peter Anvin518df302008-06-14 16:53:48 -0700402 len > (size_t)instruction->eops->next->next->offset)
403 len = (size_t)instruction->eops->next->next->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000404 }
405 /*
406 * Dummy call to list->output to give the offset to the
407 * listing module.
408 */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800409 list->output(offset, NULL, OUT_RAWDATA, 0);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000410 list->uplevel(LIST_INCBIN);
411 while (t--) {
H. Peter Anvin518df302008-06-14 16:53:48 -0700412 size_t l;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000413
H. Peter Anvine2c80182005-01-15 22:15:51 +0000414 fseek(fp, base, SEEK_SET);
415 l = len;
416 while (l > 0) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000417 int32_t m =
Charles Crayne192d5b52007-10-18 19:02:42 -0700418 fread(buf, 1, (l > (int32_t) sizeof(buf) ? (int32_t) sizeof(buf) : l),
H. Peter Anvine2c80182005-01-15 22:15:51 +0000419 fp);
420 if (!m) {
421 /*
422 * This shouldn't happen unless the file
423 * actually changes while we are reading
424 * it.
425 */
426 error(ERR_NONFATAL,
427 "`incbin': unexpected EOF while"
428 " reading file `%s'", fname);
429 t = 0; /* Try to exit cleanly */
430 break;
431 }
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800432 out(offset, segment, buf, OUT_RAWDATA, m,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000433 NO_SEG, NO_SEG);
434 l -= m;
435 }
436 }
437 list->downlevel(LIST_INCBIN);
438 if (instruction->times > 1) {
439 /*
440 * Dummy call to list->output to give the offset to the
441 * listing module.
442 */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800443 list->output(offset, NULL, OUT_RAWDATA, 0);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000444 list->uplevel(LIST_TIMES);
445 list->downlevel(LIST_TIMES);
446 }
447 fclose(fp);
448 return instruction->times * len;
449 }
450 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000451 }
452
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700453 /* Check to see if we need an address-size prefix */
454 add_asp(instruction, bits);
455
H. Peter Anvin6cda4142008-12-29 20:52:28 -0800456 size_prob = 0;
H. Peter Anvin70653092007-10-19 14:42:29 -0700457
458 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++){
Keith Kaniosb7a89542007-04-12 02:40:54 +0000459 int m = matches(temp, instruction, bits);
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700460 if (m == 100 ||
461 (m == 99 && jmp_match(segment, offset, bits,
462 instruction, temp->code))) {
463 /* Matches! */
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800464 int64_t insn_size = calcsize(segment, offset, bits,
H. Peter Anvin833caea2008-10-04 19:02:30 -0700465 instruction, temp->code);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000466 itimes = instruction->times;
467 if (insn_size < 0) /* shouldn't be, on pass two */
468 error(ERR_PANIC, "errors made it through from pass one");
469 else
470 while (itimes--) {
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700471 for (j = 0; j < MAXPREFIX; j++) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000472 uint8_t c = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000473 switch (instruction->prefixes[j]) {
H. Peter Anvinc2acf7b2009-02-21 18:22:56 -0800474 case P_WAIT:
475 c = 0x9B;
476 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000477 case P_LOCK:
478 c = 0xF0;
479 break;
480 case P_REPNE:
481 case P_REPNZ:
482 c = 0xF2;
483 break;
484 case P_REPE:
485 case P_REPZ:
486 case P_REP:
487 c = 0xF3;
488 break;
489 case R_CS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000490 if (bits == 64) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700491 error(ERR_WARNING | ERR_PASS2,
Charles Crayne1b851dc2007-11-05 21:49:49 -0800492 "cs segment base generated, but will be ignored in 64-bit mode");
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000493 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000494 c = 0x2E;
495 break;
496 case R_DS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000497 if (bits == 64) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700498 error(ERR_WARNING | ERR_PASS2,
Charles Crayne1b851dc2007-11-05 21:49:49 -0800499 "ds segment base generated, but will be ignored in 64-bit mode");
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000500 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000501 c = 0x3E;
502 break;
503 case R_ES:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000504 if (bits == 64) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700505 error(ERR_WARNING | ERR_PASS2,
Charles Crayne1b851dc2007-11-05 21:49:49 -0800506 "es segment base generated, but will be ignored in 64-bit mode");
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000507 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000508 c = 0x26;
509 break;
510 case R_FS:
511 c = 0x64;
512 break;
513 case R_GS:
514 c = 0x65;
515 break;
516 case R_SS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000517 if (bits == 64) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700518 error(ERR_WARNING | ERR_PASS2,
Charles Crayne1b851dc2007-11-05 21:49:49 -0800519 "ss segment base generated, but will be ignored in 64-bit mode");
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000520 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000521 c = 0x36;
522 break;
523 case R_SEGR6:
524 case R_SEGR7:
525 error(ERR_NONFATAL,
526 "segr6 and segr7 cannot be used as prefixes");
527 break;
528 case P_A16:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000529 if (bits == 64) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000530 error(ERR_NONFATAL,
531 "16-bit addressing is not supported "
532 "in 64-bit mode");
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700533 } else if (bits != 16)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000534 c = 0x67;
535 break;
536 case P_A32:
537 if (bits != 32)
538 c = 0x67;
539 break;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700540 case P_A64:
541 if (bits != 64) {
542 error(ERR_NONFATAL,
543 "64-bit addressing is only supported "
544 "in 64-bit mode");
545 }
546 break;
547 case P_ASP:
548 c = 0x67;
549 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000550 case P_O16:
551 if (bits != 16)
552 c = 0x66;
553 break;
554 case P_O32:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000555 if (bits == 16)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000556 c = 0x66;
557 break;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700558 case P_O64:
559 /* REX.W */
560 break;
561 case P_OSP:
562 c = 0x66;
563 break;
564 case P_none:
565 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000566 default:
567 error(ERR_PANIC, "invalid instruction prefix");
568 }
569 if (c != 0) {
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800570 out(offset, segment, &c, OUT_RAWDATA, 1,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000571 NO_SEG, NO_SEG);
572 offset++;
573 }
H. Peter Anvin70653092007-10-19 14:42:29 -0700574 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000575 insn_end = offset + insn_size;
H. Peter Anvin833caea2008-10-04 19:02:30 -0700576 gencode(segment, offset, bits, instruction,
577 temp, insn_end);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000578 offset += insn_size;
579 if (itimes > 0 && itimes == instruction->times - 1) {
580 /*
581 * Dummy call to list->output to give the offset to the
582 * listing module.
583 */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800584 list->output(offset, NULL, OUT_RAWDATA, 0);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000585 list->uplevel(LIST_TIMES);
586 }
587 }
588 if (instruction->times > 1)
589 list->downlevel(LIST_TIMES);
590 return offset - start;
591 } else if (m > 0 && m > size_prob) {
592 size_prob = m;
593 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000594 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000595
H. Peter Anvine2c80182005-01-15 22:15:51 +0000596 if (temp->opcode == -1) { /* didn't match any instruction */
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000597 switch (size_prob) {
598 case 1:
599 error(ERR_NONFATAL, "operation size not specified");
600 break;
601 case 2:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000602 error(ERR_NONFATAL, "mismatch in operand sizes");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000603 break;
604 case 3:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000605 error(ERR_NONFATAL, "no instruction for this cpu level");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000606 break;
607 case 4:
H. Peter Anvin6cda4142008-12-29 20:52:28 -0800608 error(ERR_NONFATAL, "instruction not supported in %d-bit mode",
609 bits);
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000610 break;
611 default:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000612 error(ERR_NONFATAL,
613 "invalid combination of opcode and operands");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000614 break;
615 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000616 }
617 return 0;
618}
619
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800620int64_t insn_size(int32_t segment, int64_t offset, int bits, uint32_t cp,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000621 insn * instruction, efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000622{
H. Peter Anvin3360d792007-09-11 04:16:57 +0000623 const struct itemplate *temp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000624
H. Peter Anvine2c80182005-01-15 22:15:51 +0000625 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000626 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000627
628 if (instruction->opcode == -1)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000629 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000630
H. Peter Anvincfbe7c32007-09-18 17:49:09 -0700631 if (instruction->opcode == I_DB || instruction->opcode == I_DW ||
632 instruction->opcode == I_DD || instruction->opcode == I_DQ ||
H. Peter Anvindfb91802008-05-20 11:43:53 -0700633 instruction->opcode == I_DT || instruction->opcode == I_DO ||
634 instruction->opcode == I_DY) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000635 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000636 int32_t isize, osize, wsize = 0; /* placate gcc */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000637
H. Peter Anvine2c80182005-01-15 22:15:51 +0000638 isize = 0;
639 switch (instruction->opcode) {
640 case I_DB:
641 wsize = 1;
642 break;
643 case I_DW:
644 wsize = 2;
645 break;
646 case I_DD:
647 wsize = 4;
648 break;
649 case I_DQ:
650 wsize = 8;
651 break;
652 case I_DT:
653 wsize = 10;
654 break;
H. Peter Anvincfbe7c32007-09-18 17:49:09 -0700655 case I_DO:
656 wsize = 16;
657 break;
H. Peter Anvindfb91802008-05-20 11:43:53 -0700658 case I_DY:
659 wsize = 32;
660 break;
H. Peter Anvin16b0a332007-09-12 20:27:41 -0700661 default:
662 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000663 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000664
H. Peter Anvine2c80182005-01-15 22:15:51 +0000665 for (e = instruction->eops; e; e = e->next) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000666 int32_t align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000667
H. Peter Anvine2c80182005-01-15 22:15:51 +0000668 osize = 0;
669 if (e->type == EOT_DB_NUMBER)
670 osize = 1;
H. Peter Anvin518df302008-06-14 16:53:48 -0700671 else if (e->type == EOT_DB_STRING ||
672 e->type == EOT_DB_STRING_FREE)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000673 osize = e->stringlen;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000674
H. Peter Anvine2c80182005-01-15 22:15:51 +0000675 align = (-osize) % wsize;
676 if (align < 0)
677 align += wsize;
678 isize += osize + align;
679 }
680 return isize * instruction->times;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000681 }
682
H. Peter Anvine2c80182005-01-15 22:15:51 +0000683 if (instruction->opcode == I_INCBIN) {
H. Peter Anvin518df302008-06-14 16:53:48 -0700684 const char *fname = instruction->eops->stringval;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000685 FILE *fp;
H. Peter Anvin518df302008-06-14 16:53:48 -0700686 size_t len;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000687
H. Peter Anvin418ca702008-05-30 10:42:30 -0700688 fp = fopen(fname, "rb");
689 if (!fp)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000690 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
691 fname);
692 else if (fseek(fp, 0L, SEEK_END) < 0)
693 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
694 fname);
695 else {
696 len = ftell(fp);
697 fclose(fp);
698 if (instruction->eops->next) {
699 len -= instruction->eops->next->offset;
700 if (instruction->eops->next->next &&
H. Peter Anvin518df302008-06-14 16:53:48 -0700701 len > (size_t)instruction->eops->next->next->offset) {
702 len = (size_t)instruction->eops->next->next->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000703 }
704 }
705 return instruction->times * len;
706 }
707 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000708 }
709
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700710 /* Check to see if we need an address-size prefix */
711 add_asp(instruction, bits);
712
Keith Kaniosb7a89542007-04-12 02:40:54 +0000713 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++) {
714 int m = matches(temp, instruction, bits);
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700715 if (m == 100 ||
716 (m == 99 && jmp_match(segment, offset, bits,
717 instruction, temp->code))) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000718 /* we've matched an instruction. */
Charles Crayne5fbbc8c2007-11-07 19:03:46 -0800719 int64_t isize;
H. Peter Anvin3720f7b2008-05-12 11:00:50 -0700720 const uint8_t *codes = temp->code;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000721 int j;
722
723 isize = calcsize(segment, offset, bits, instruction, codes);
724 if (isize < 0)
725 return -1;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700726 for (j = 0; j < MAXPREFIX; j++) {
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700727 switch (instruction->prefixes[j]) {
728 case P_A16:
729 if (bits != 16)
730 isize++;
731 break;
732 case P_A32:
733 if (bits != 32)
734 isize++;
735 break;
736 case P_O16:
737 if (bits != 16)
738 isize++;
739 break;
740 case P_O32:
741 if (bits == 16)
742 isize++;
743 break;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700744 case P_A64:
745 case P_O64:
746 case P_none:
747 break;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700748 default:
749 isize++;
750 break;
751 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000752 }
753 return isize * instruction->times;
754 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000755 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000756 return -1; /* didn't match any instruction */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000757}
758
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700759static bool possible_sbyte(operand *o)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000760{
H. Peter Anvinad6b8592008-10-07 09:56:38 -0700761 return o->wrt == NO_SEG && o->segment == NO_SEG &&
H. Peter Anvine8ab8912009-02-26 16:34:56 -0800762 !(o->opflags & OPFLAG_UNKNOWN) &&
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700763 optimizing >= 0 && !(o->type & STRICT);
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000764}
765
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700766/* check that opn[op] is a signed byte of size 16 or 32 */
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700767static bool is_sbyte16(operand *o)
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700768{
769 int16_t v;
770
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700771 if (!possible_sbyte(o))
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700772 return false;
773
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700774 v = o->offset;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700775 return v >= -128 && v <= 127;
776}
777
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700778static bool is_sbyte32(operand *o)
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700779{
780 int32_t v;
781
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700782 if (!possible_sbyte(o))
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700783 return false;
784
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700785 v = o->offset;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700786 return v >= -128 && v <= 127;
787}
788
H. Peter Anvin507ae032008-10-09 15:37:10 -0700789/* Common construct */
790#define case4(x) case (x): case (x)+1: case (x)+2: case (x)+3
791
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800792static int64_t calcsize(int32_t segment, int64_t offset, int bits,
H. Peter Anvin9f817132008-10-06 19:11:07 -0700793 insn * ins, const uint8_t *codes)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000794{
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800795 int64_t length = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000796 uint8_t c;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000797 int rex_mask = ~0;
H. Peter Anvindcffe4b2008-10-10 22:10:31 -0700798 int op1, op2;
H. Peter Anvin839eca22007-10-29 23:12:47 -0700799 struct operand *opx;
H. Peter Anvindcffe4b2008-10-10 22:10:31 -0700800 uint8_t opex = 0;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000801
H. Peter Anvine3917fc2007-11-01 14:53:32 -0700802 ins->rex = 0; /* Ensure REX is reset */
803
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700804 if (ins->prefixes[PPS_OSIZE] == P_O64)
805 ins->rex |= REX_W;
806
H. Peter Anvine2c80182005-01-15 22:15:51 +0000807 (void)segment; /* Don't warn that this parameter is unused */
808 (void)offset; /* Don't warn that this parameter is unused */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000809
H. Peter Anvin839eca22007-10-29 23:12:47 -0700810 while (*codes) {
811 c = *codes++;
H. Peter Anvindcffe4b2008-10-10 22:10:31 -0700812 op1 = (c & 3) + ((opex & 1) << 2);
813 op2 = ((c >> 3) & 3) + ((opex & 2) << 1);
814 opx = &ins->oprs[op1];
815 opex = 0; /* For the next iteration */
816
H. Peter Anvin839eca22007-10-29 23:12:47 -0700817 switch (c) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000818 case 01:
819 case 02:
820 case 03:
H. Peter Anvindcffe4b2008-10-10 22:10:31 -0700821 case 04:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000822 codes += c, length += c;
823 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700824
H. Peter Anvindcffe4b2008-10-10 22:10:31 -0700825 case 05:
826 case 06:
827 case 07:
828 opex = c;
829 break;
830
H. Peter Anvin507ae032008-10-09 15:37:10 -0700831 case4(010):
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000832 ins->rex |=
H. Peter Anvin839eca22007-10-29 23:12:47 -0700833 op_rexflags(opx, REX_B|REX_H|REX_P|REX_W);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000834 codes++, length++;
835 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700836
837 case4(014):
838 case4(020):
839 case4(024):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000840 length++;
841 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700842
843 case4(030):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000844 length += 2;
845 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700846
847 case4(034):
H. Peter Anvin839eca22007-10-29 23:12:47 -0700848 if (opx->type & (BITS16 | BITS32 | BITS64))
849 length += (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000850 else
851 length += (bits == 16) ? 2 : 4;
852 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700853
854 case4(040):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000855 length += 4;
856 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700857
858 case4(044):
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700859 length += ins->addr_size >> 3;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000860 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700861
862 case4(050):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000863 length++;
864 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700865
866 case4(054):
Keith Kaniosb7a89542007-04-12 02:40:54 +0000867 length += 8; /* MOV reg64/imm */
868 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700869
870 case4(060):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000871 length += 2;
872 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700873
874 case4(064):
H. Peter Anvin839eca22007-10-29 23:12:47 -0700875 if (opx->type & (BITS16 | BITS32 | BITS64))
876 length += (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000877 else
878 length += (bits == 16) ? 2 : 4;
879 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700880
881 case4(070):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000882 length += 4;
883 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700884
885 case4(074):
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700886 length += 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000887 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700888
889 case4(0140):
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700890 length += is_sbyte16(opx) ? 1 : 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000891 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700892
893 case4(0144):
H. Peter Anvina30cc072007-11-18 21:55:26 -0800894 codes++;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000895 length++;
896 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700897
898 case4(0150):
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700899 length += is_sbyte32(opx) ? 1 : 4;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700900 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700901
902 case4(0154):
H. Peter Anvina30cc072007-11-18 21:55:26 -0800903 codes++;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700904 length++;
905 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700906
907 case4(0160):
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700908 length++;
909 ins->rex |= REX_D;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700910 ins->drexdst = regval(opx);
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700911 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700912
913 case4(0164):
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700914 length++;
915 ins->rex |= REX_D|REX_OC;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700916 ins->drexdst = regval(opx);
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700917 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700918
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700919 case 0171:
920 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700921
H. Peter Anvind85d2502008-05-04 17:53:31 -0700922 case 0172:
H. Peter Anvind58656f2008-05-06 20:11:14 -0700923 case 0173:
H. Peter Anvin52dc3532008-05-20 19:29:04 -0700924 case 0174:
H. Peter Anvind85d2502008-05-04 17:53:31 -0700925 codes++;
926 length++;
927 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700928
929 case4(0250):
H. Peter Anvinad6b8592008-10-07 09:56:38 -0700930 length += is_sbyte32(opx) ? 1 : 4;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700931 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700932
933 case4(0254):
H. Peter Anvin588df782008-10-07 10:05:10 -0700934 length += 4;
935 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700936
937 case4(0260):
H. Peter Anvind85d2502008-05-04 17:53:31 -0700938 ins->rex |= REX_V;
939 ins->drexdst = regval(opx);
H. Peter Anvina04019c2009-05-03 21:42:34 -0700940 ins->vex_cm = *codes++;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700941 ins->vex_wlp = *codes++;
942 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700943
H. Peter Anvind85d2502008-05-04 17:53:31 -0700944 case 0270:
H. Peter Anvind85d2502008-05-04 17:53:31 -0700945 ins->rex |= REX_V;
946 ins->drexdst = 0;
H. Peter Anvina04019c2009-05-03 21:42:34 -0700947 ins->vex_cm = *codes++;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700948 ins->vex_wlp = *codes++;
949 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700950
951 case4(0274):
H. Peter Anvinc1377e92008-10-06 23:40:31 -0700952 length++;
953 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700954
955 case4(0300):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000956 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700957
H. Peter Anvine2c80182005-01-15 22:15:51 +0000958 case 0310:
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700959 if (bits == 64)
960 return -1;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700961 length += (bits != 16) && !has_prefix(ins, PPS_ASIZE, P_A16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000962 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700963
H. Peter Anvine2c80182005-01-15 22:15:51 +0000964 case 0311:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700965 length += (bits != 32) && !has_prefix(ins, PPS_ASIZE, P_A32);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000966 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700967
H. Peter Anvine2c80182005-01-15 22:15:51 +0000968 case 0312:
H. Peter Anvin70653092007-10-19 14:42:29 -0700969 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700970
Keith Kaniosb7a89542007-04-12 02:40:54 +0000971 case 0313:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700972 if (bits != 64 || has_prefix(ins, PPS_ASIZE, P_A16) ||
973 has_prefix(ins, PPS_ASIZE, P_A32))
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700974 return -1;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000975 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700976
977 case4(0314):
H. Peter Anvin23440102007-11-12 21:02:33 -0800978 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700979
H. Peter Anvine2c80182005-01-15 22:15:51 +0000980 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000981 length += (bits != 16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000982 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700983
H. Peter Anvine2c80182005-01-15 22:15:51 +0000984 case 0321:
985 length += (bits == 16);
986 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700987
H. Peter Anvine2c80182005-01-15 22:15:51 +0000988 case 0322:
989 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700990
Keith Kaniosb7a89542007-04-12 02:40:54 +0000991 case 0323:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000992 rex_mask &= ~REX_W;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000993 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700994
Keith Kaniosb7a89542007-04-12 02:40:54 +0000995 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000996 ins->rex |= REX_W;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000997 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700998
H. Peter Anvine2c80182005-01-15 22:15:51 +0000999 case 0330:
1000 codes++, length++;
1001 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001002
H. Peter Anvine2c80182005-01-15 22:15:51 +00001003 case 0331:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001004 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001005
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001006 case 0332:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001007 case 0333:
1008 length++;
1009 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001010
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001011 case 0334:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001012 ins->rex |= REX_L;
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001013 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001014
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001015 case 0335:
1016 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001017
H. Peter Anvin962e3052008-08-28 17:47:16 -07001018 case 0336:
1019 if (!ins->prefixes[PPS_LREP])
1020 ins->prefixes[PPS_LREP] = P_REP;
1021 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001022
H. Peter Anvin962e3052008-08-28 17:47:16 -07001023 case 0337:
1024 if (!ins->prefixes[PPS_LREP])
1025 ins->prefixes[PPS_LREP] = P_REPNE;
1026 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001027
H. Peter Anvine2c80182005-01-15 22:15:51 +00001028 case 0340:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001029 if (ins->oprs[0].segment != NO_SEG)
1030 errfunc(ERR_NONFATAL, "attempt to reserve non-constant"
1031 " quantity of BSS space");
1032 else
H. Peter Anvin428fd672007-11-15 10:25:52 -08001033 length += ins->oprs[0].offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001034 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001035
H. Peter Anvinc2acf7b2009-02-21 18:22:56 -08001036 case 0341:
1037 if (!ins->prefixes[PPS_WAIT])
1038 ins->prefixes[PPS_WAIT] = P_WAIT;
1039 break;
1040
H. Peter Anvin507ae032008-10-09 15:37:10 -07001041 case4(0344):
H. Peter Anvinff6e12d2008-10-08 21:17:32 -07001042 length++;
1043 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001044
H. Peter Anvinfff5a472008-05-20 09:46:24 -07001045 case 0360:
1046 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001047
H. Peter Anvinfff5a472008-05-20 09:46:24 -07001048 case 0361:
1049 case 0362:
1050 case 0363:
1051 length++;
1052 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001053
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001054 case 0364:
1055 case 0365:
1056 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001057
Keith Kanios48af1772007-08-17 07:37:52 +00001058 case 0366:
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001059 case 0367:
1060 length++;
1061 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001062
H. Peter Anvine2c80182005-01-15 22:15:51 +00001063 case 0370:
1064 case 0371:
1065 case 0372:
1066 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001067
H. Peter Anvine2c80182005-01-15 22:15:51 +00001068 case 0373:
1069 length++;
1070 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001071
1072 case4(0100):
1073 case4(0110):
1074 case4(0120):
1075 case4(0130):
1076 case4(0200):
1077 case4(0204):
1078 case4(0210):
1079 case4(0214):
1080 case4(0220):
1081 case4(0224):
1082 case4(0230):
1083 case4(0234):
1084 {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001085 ea ea_data;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001086 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001087 int32_t rflags;
H. Peter Anvinae64c9d2008-10-25 00:41:00 -07001088 struct operand *opy = &ins->oprs[op2];
1089
Keith Kaniosb7a89542007-04-12 02:40:54 +00001090 ea_data.rex = 0; /* Ensure ea.REX is initially 0 */
H. Peter Anvin70653092007-10-19 14:42:29 -07001091
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001092 if (c <= 0177) {
H. Peter Anvinae64c9d2008-10-25 00:41:00 -07001093 /* pick rfield from operand b (opx) */
1094 rflags = regflag(opx);
1095 rfield = nasm_regvals[opx->basereg];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001096 } else {
1097 rflags = 0;
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001098 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001099 }
H. Peter Anvinae64c9d2008-10-25 00:41:00 -07001100 if (!process_ea(opy, &ea_data, bits,
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001101 ins->addr_size, rfield, rflags)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001102 errfunc(ERR_NONFATAL, "invalid effective address");
1103 return -1;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001104 } else {
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001105 ins->rex |= ea_data.rex;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001106 length += ea_data.size;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001107 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001108 }
H. Peter Anvin507ae032008-10-09 15:37:10 -07001109 break;
1110
1111 default:
1112 errfunc(ERR_PANIC, "internal instruction table corrupt"
H. Peter Anvin16a856c2009-03-01 00:22:16 -08001113 ": instruction code \\%o (0x%02X) given", c, c);
H. Peter Anvin507ae032008-10-09 15:37:10 -07001114 break;
1115 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001116 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001117
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001118 ins->rex &= rex_mask;
H. Peter Anvin70653092007-10-19 14:42:29 -07001119
H. Peter Anvind85d2502008-05-04 17:53:31 -07001120 if (ins->rex & REX_V) {
1121 int bad32 = REX_R|REX_W|REX_X|REX_B;
1122
1123 if (ins->rex & REX_H) {
1124 errfunc(ERR_NONFATAL, "cannot use high register in vex instruction");
1125 return -1;
1126 }
1127 switch (ins->vex_wlp & 030) {
1128 case 000:
H. Peter Anvinbd420c72008-05-22 11:24:35 -07001129 case 020:
H. Peter Anvind85d2502008-05-04 17:53:31 -07001130 ins->rex &= ~REX_W;
1131 break;
1132 case 010:
1133 ins->rex |= REX_W;
1134 bad32 &= ~REX_W;
1135 break;
H. Peter Anvinbd420c72008-05-22 11:24:35 -07001136 case 030:
H. Peter Anvind85d2502008-05-04 17:53:31 -07001137 /* Follow REX_W */
1138 break;
1139 }
1140
1141 if (bits != 64 && ((ins->rex & bad32) || ins->drexdst > 7)) {
1142 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
1143 return -1;
1144 }
H. Peter Anvina04019c2009-05-03 21:42:34 -07001145 if (ins->vex_cm != 1 || (ins->rex & (REX_W|REX_R|REX_B)))
H. Peter Anvind85d2502008-05-04 17:53:31 -07001146 length += 3;
1147 else
1148 length += 2;
1149 } else if (ins->rex & REX_D) {
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001150 if (ins->rex & REX_H) {
1151 errfunc(ERR_NONFATAL, "cannot use high register in drex instruction");
1152 return -1;
1153 }
H. Peter Anvind85d2502008-05-04 17:53:31 -07001154 if (bits != 64 && ((ins->rex & (REX_R|REX_W|REX_X|REX_B)) ||
H. Peter Anvincf5180a2007-09-17 17:25:27 -07001155 ins->drexdst > 7)) {
1156 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
1157 return -1;
1158 }
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001159 length++;
1160 } else if (ins->rex & REX_REAL) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001161 if (ins->rex & REX_H) {
1162 errfunc(ERR_NONFATAL, "cannot use high register in rex instruction");
1163 return -1;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001164 } else if (bits == 64) {
1165 length++;
1166 } else if ((ins->rex & REX_L) &&
1167 !(ins->rex & (REX_P|REX_W|REX_X|REX_B)) &&
1168 cpu >= IF_X86_64) {
1169 /* LOCK-as-REX.R */
1170 assert_no_prefix(ins, PPS_LREP);
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001171 length++;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +00001172 } else {
H. Peter Anvincf5180a2007-09-17 17:25:27 -07001173 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
1174 return -1;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +00001175 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001176 }
1177
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001178 return length;
1179}
Keith Kaniosb7a89542007-04-12 02:40:54 +00001180
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001181#define EMIT_REX() \
H. Peter Anvind85d2502008-05-04 17:53:31 -07001182 if (!(ins->rex & (REX_D|REX_V)) && (ins->rex & REX_REAL) && (bits == 64)) { \
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001183 ins->rex = (ins->rex & REX_REAL)|REX_P; \
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001184 out(offset, segment, &ins->rex, OUT_RAWDATA, 1, NO_SEG, NO_SEG); \
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001185 ins->rex = 0; \
1186 offset += 1; \
1187 }
1188
Charles Crayne1f8bc4c2007-11-06 18:27:23 -08001189static void gencode(int32_t segment, int64_t offset, int bits,
H. Peter Anvin833caea2008-10-04 19:02:30 -07001190 insn * ins, const struct itemplate *temp,
1191 int64_t insn_end)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001192{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001193 static char condval[] = { /* conditional opcodes */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001194 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
1195 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
1196 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001197 };
Keith Kaniosb7a89542007-04-12 02:40:54 +00001198 uint8_t c;
1199 uint8_t bytes[4];
Charles Crayne1f8bc4c2007-11-06 18:27:23 -08001200 int64_t size;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001201 int64_t data;
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001202 int op1, op2;
H. Peter Anvin839eca22007-10-29 23:12:47 -07001203 struct operand *opx;
H. Peter Anvin833caea2008-10-04 19:02:30 -07001204 const uint8_t *codes = temp->code;
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001205 uint8_t opex = 0;
H. Peter Anvin70653092007-10-19 14:42:29 -07001206
H. Peter Anvin839eca22007-10-29 23:12:47 -07001207 while (*codes) {
1208 c = *codes++;
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001209 op1 = (c & 3) + ((opex & 1) << 2);
1210 op2 = ((c >> 3) & 3) + ((opex & 2) << 1);
1211 opx = &ins->oprs[op1];
1212 opex = 0; /* For the next iteration */
1213
H. Peter Anvin839eca22007-10-29 23:12:47 -07001214 switch (c) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001215 case 01:
1216 case 02:
1217 case 03:
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001218 case 04:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001219 EMIT_REX();
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001220 out(offset, segment, codes, OUT_RAWDATA, c, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001221 codes += c;
1222 offset += c;
1223 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001224
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001225 case 05:
1226 case 06:
1227 case 07:
1228 opex = c;
1229 break;
1230
H. Peter Anvin507ae032008-10-09 15:37:10 -07001231 case4(010):
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001232 EMIT_REX();
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001233 bytes[0] = *codes++ + (regval(opx) & 7);
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001234 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001235 offset += 1;
1236 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001237
H. Peter Anvin507ae032008-10-09 15:37:10 -07001238 case4(014):
H. Peter Anvin6c80ab62008-10-04 18:50:47 -07001239 /* The test for BITS8 and SBYTE here is intended to avoid
1240 warning on optimizer actions due to SBYTE, while still
1241 warn on explicit BYTE directives. Also warn, obviously,
1242 if the optimizer isn't enabled. */
1243 if (((opx->type & BITS8) ||
H. Peter Anvindcffe4b2008-10-10 22:10:31 -07001244 !(opx->type & temp->opd[op1] & BYTENESS)) &&
H. Peter Anvin6c80ab62008-10-04 18:50:47 -07001245 (opx->offset < -128 || opx->offset > 127)) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001246 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
H. Peter Anvin72c64372008-01-08 22:13:48 -08001247 "signed byte value exceeds bounds");
H. Peter Anvin6c80ab62008-10-04 18:50:47 -07001248 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001249 if (opx->segment != NO_SEG) {
1250 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001251 out(offset, segment, &data, OUT_ADDRESS, 1,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001252 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001253 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001254 bytes[0] = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001255 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001256 NO_SEG);
1257 }
1258 offset += 1;
1259 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001260
H. Peter Anvin507ae032008-10-09 15:37:10 -07001261 case4(020):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001262 if (opx->offset < -256 || opx->offset > 255) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001263 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
H. Peter Anvin72c64372008-01-08 22:13:48 -08001264 "byte value exceeds bounds");
H. Peter Anvine2c80182005-01-15 22:15:51 +00001265 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001266 if (opx->segment != NO_SEG) {
1267 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001268 out(offset, segment, &data, OUT_ADDRESS, 1,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001269 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001270 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001271 bytes[0] = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001272 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001273 NO_SEG);
1274 }
1275 offset += 1;
1276 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001277
H. Peter Anvin507ae032008-10-09 15:37:10 -07001278 case4(024):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001279 if (opx->offset < 0 || opx->offset > 255)
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001280 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
H. Peter Anvin72c64372008-01-08 22:13:48 -08001281 "unsigned byte value exceeds bounds");
H. Peter Anvin839eca22007-10-29 23:12:47 -07001282 if (opx->segment != NO_SEG) {
1283 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001284 out(offset, segment, &data, OUT_ADDRESS, 1,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001285 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001286 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001287 bytes[0] = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001288 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001289 NO_SEG);
1290 }
1291 offset += 1;
1292 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001293
H. Peter Anvin507ae032008-10-09 15:37:10 -07001294 case4(030):
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001295 warn_overflow(2, opx);
H. Peter Anvin839eca22007-10-29 23:12:47 -07001296 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001297 out(offset, segment, &data, OUT_ADDRESS, 2,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001298 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001299 offset += 2;
1300 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001301
H. Peter Anvin507ae032008-10-09 15:37:10 -07001302 case4(034):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001303 if (opx->type & (BITS16 | BITS32))
1304 size = (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001305 else
1306 size = (bits == 16) ? 2 : 4;
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001307 warn_overflow(size, opx);
H. Peter Anvin839eca22007-10-29 23:12:47 -07001308 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001309 out(offset, segment, &data, OUT_ADDRESS, size,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001310 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001311 offset += size;
1312 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001313
H. Peter Anvin507ae032008-10-09 15:37:10 -07001314 case4(040):
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001315 warn_overflow(4, opx);
H. Peter Anvin839eca22007-10-29 23:12:47 -07001316 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001317 out(offset, segment, &data, OUT_ADDRESS, 4,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001318 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001319 offset += 4;
1320 break;
H. Peter Anvin3ba46772002-05-27 23:19:35 +00001321
H. Peter Anvin507ae032008-10-09 15:37:10 -07001322 case4(044):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001323 data = opx->offset;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001324 size = ins->addr_size >> 3;
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001325 warn_overflow(size, opx);
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001326 out(offset, segment, &data, OUT_ADDRESS, size,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001327 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001328 offset += size;
1329 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001330
H. Peter Anvin507ae032008-10-09 15:37:10 -07001331 case4(050):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001332 if (opx->segment != segment)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001333 errfunc(ERR_NONFATAL,
1334 "short relative jump outside segment");
H. Peter Anvin839eca22007-10-29 23:12:47 -07001335 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001336 if (data > 127 || data < -128)
1337 errfunc(ERR_NONFATAL, "short jump is out of range");
1338 bytes[0] = data;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001339 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001340 offset += 1;
1341 break;
H. Peter Anvin70653092007-10-19 14:42:29 -07001342
H. Peter Anvin507ae032008-10-09 15:37:10 -07001343 case4(054):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001344 data = (int64_t)opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001345 out(offset, segment, &data, OUT_ADDRESS, 8,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001346 opx->segment, opx->wrt);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001347 offset += 8;
1348 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001349
H. Peter Anvin507ae032008-10-09 15:37:10 -07001350 case4(060):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001351 if (opx->segment != segment) {
1352 data = opx->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001353 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001354 OUT_REL2ADR, insn_end - offset,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001355 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001356 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001357 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001358 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001359 OUT_ADDRESS, 2, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001360 }
1361 offset += 2;
1362 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001363
H. Peter Anvin507ae032008-10-09 15:37:10 -07001364 case4(064):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001365 if (opx->type & (BITS16 | BITS32 | BITS64))
1366 size = (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001367 else
1368 size = (bits == 16) ? 2 : 4;
H. Peter Anvin839eca22007-10-29 23:12:47 -07001369 if (opx->segment != segment) {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001370 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001371 out(offset, segment, &data,
1372 size == 2 ? OUT_REL2ADR : OUT_REL4ADR,
1373 insn_end - offset, opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001374 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001375 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001376 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001377 OUT_ADDRESS, size, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001378 }
1379 offset += size;
1380 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001381
H. Peter Anvin507ae032008-10-09 15:37:10 -07001382 case4(070):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001383 if (opx->segment != segment) {
1384 data = opx->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001385 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001386 OUT_REL4ADR, insn_end - offset,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001387 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001388 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001389 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001390 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001391 OUT_ADDRESS, 4, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001392 }
1393 offset += 4;
1394 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001395
H. Peter Anvin507ae032008-10-09 15:37:10 -07001396 case4(074):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001397 if (opx->segment == NO_SEG)
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001398 errfunc(ERR_NONFATAL, "value referenced by FAR is not"
1399 " relocatable");
H. Peter Anvindfb91802008-05-20 11:43:53 -07001400 data = 0;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001401 out(offset, segment, &data, OUT_ADDRESS, 2,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001402 outfmt->segbase(1 + opx->segment),
1403 opx->wrt);
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001404 offset += 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001405 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001406
H. Peter Anvin507ae032008-10-09 15:37:10 -07001407 case4(0140):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001408 data = opx->offset;
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001409 warn_overflow(2, opx);
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001410 if (is_sbyte16(opx)) {
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001411 bytes[0] = data;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001412 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001413 NO_SEG);
1414 offset++;
1415 } else {
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001416 out(offset, segment, &data, OUT_ADDRESS, 2,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001417 opx->segment, opx->wrt);
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001418 offset += 2;
1419 }
1420 break;
1421
H. Peter Anvin507ae032008-10-09 15:37:10 -07001422 case4(0144):
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001423 EMIT_REX();
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001424 bytes[0] = *codes++;
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001425 if (is_sbyte16(opx))
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001426 bytes[0] |= 2; /* s-bit */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001427 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001428 offset++;
1429 break;
1430
H. Peter Anvin507ae032008-10-09 15:37:10 -07001431 case4(0150):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001432 data = opx->offset;
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001433 warn_overflow(4, opx);
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001434 if (is_sbyte32(opx)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001435 bytes[0] = data;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001436 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001437 NO_SEG);
1438 offset++;
1439 } else {
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001440 out(offset, segment, &data, OUT_ADDRESS, 4,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001441 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001442 offset += 4;
1443 }
1444 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001445
H. Peter Anvin507ae032008-10-09 15:37:10 -07001446 case4(0154):
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001447 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001448 bytes[0] = *codes++;
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001449 if (is_sbyte32(opx))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001450 bytes[0] |= 2; /* s-bit */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001451 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001452 offset++;
1453 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001454
H. Peter Anvin507ae032008-10-09 15:37:10 -07001455 case4(0160):
1456 case4(0164):
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001457 break;
1458
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001459 case 0171:
1460 bytes[0] =
1461 (ins->drexdst << 4) |
1462 (ins->rex & REX_OC ? 0x08 : 0) |
1463 (ins->rex & (REX_R|REX_X|REX_B));
1464 ins->rex = 0;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001465 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001466 offset++;
1467 break;
1468
H. Peter Anvind85d2502008-05-04 17:53:31 -07001469 case 0172:
1470 c = *codes++;
1471 opx = &ins->oprs[c >> 3];
H. Peter Anvina4835d42008-05-20 14:21:29 -07001472 bytes[0] = nasm_regvals[opx->basereg] << 4;
H. Peter Anvind85d2502008-05-04 17:53:31 -07001473 opx = &ins->oprs[c & 7];
1474 if (opx->segment != NO_SEG || opx->wrt != NO_SEG) {
1475 errfunc(ERR_NONFATAL,
1476 "non-absolute expression not permitted as argument %d",
1477 c & 7);
1478 } else {
1479 if (opx->offset & ~15) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001480 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
H. Peter Anvind85d2502008-05-04 17:53:31 -07001481 "four-bit argument exceeds bounds");
1482 }
1483 bytes[0] |= opx->offset & 15;
1484 }
1485 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1486 offset++;
1487 break;
1488
H. Peter Anvind58656f2008-05-06 20:11:14 -07001489 case 0173:
1490 c = *codes++;
1491 opx = &ins->oprs[c >> 4];
H. Peter Anvina4835d42008-05-20 14:21:29 -07001492 bytes[0] = nasm_regvals[opx->basereg] << 4;
H. Peter Anvind58656f2008-05-06 20:11:14 -07001493 bytes[0] |= c & 15;
1494 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1495 offset++;
1496 break;
1497
H. Peter Anvin52dc3532008-05-20 19:29:04 -07001498 case 0174:
1499 c = *codes++;
1500 opx = &ins->oprs[c];
1501 bytes[0] = nasm_regvals[opx->basereg] << 4;
1502 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1503 offset++;
1504 break;
1505
H. Peter Anvin507ae032008-10-09 15:37:10 -07001506 case4(0250):
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001507 data = opx->offset;
H. Peter Anvinad6b8592008-10-07 09:56:38 -07001508 if (opx->wrt == NO_SEG && opx->segment == NO_SEG &&
1509 (int32_t)data != (int64_t)data) {
1510 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
1511 "signed dword immediate exceeds bounds");
1512 }
1513 if (is_sbyte32(opx)) {
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001514 bytes[0] = data;
1515 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
1516 NO_SEG);
1517 offset++;
1518 } else {
1519 out(offset, segment, &data, OUT_ADDRESS, 4,
1520 opx->segment, opx->wrt);
1521 offset += 4;
1522 }
1523 break;
1524
H. Peter Anvin507ae032008-10-09 15:37:10 -07001525 case4(0254):
H. Peter Anvin588df782008-10-07 10:05:10 -07001526 data = opx->offset;
1527 if (opx->wrt == NO_SEG && opx->segment == NO_SEG &&
1528 (int32_t)data != (int64_t)data) {
1529 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
1530 "signed dword immediate exceeds bounds");
1531 }
1532 out(offset, segment, &data, OUT_ADDRESS, 4,
1533 opx->segment, opx->wrt);
1534 offset += 4;
1535 break;
1536
H. Peter Anvin507ae032008-10-09 15:37:10 -07001537 case4(0260):
H. Peter Anvind85d2502008-05-04 17:53:31 -07001538 case 0270:
1539 codes += 2;
H. Peter Anvina04019c2009-05-03 21:42:34 -07001540 if (ins->vex_cm != 1 || (ins->rex & (REX_W|REX_X|REX_B))) {
1541 bytes[0] = (ins->vex_cm >> 6) ? 0x8f : 0xc4;
1542 bytes[1] = (ins->vex_cm & 31) | ((~ins->rex & 7) << 5);
H. Peter Anvind85d2502008-05-04 17:53:31 -07001543 bytes[2] = ((ins->rex & REX_W) << (7-3)) |
H. Peter Anvin4d2c38c2008-05-04 23:15:13 -07001544 ((~ins->drexdst & 15)<< 3) | (ins->vex_wlp & 07);
H. Peter Anvind85d2502008-05-04 17:53:31 -07001545 out(offset, segment, &bytes, OUT_RAWDATA, 3, NO_SEG, NO_SEG);
1546 offset += 3;
1547 } else {
1548 bytes[0] = 0xc5;
H. Peter Anvin4d2c38c2008-05-04 23:15:13 -07001549 bytes[1] = ((~ins->rex & REX_R) << (7-2)) |
1550 ((~ins->drexdst & 15) << 3) | (ins->vex_wlp & 07);
H. Peter Anvind85d2502008-05-04 17:53:31 -07001551 out(offset, segment, &bytes, OUT_RAWDATA, 2, NO_SEG, NO_SEG);
1552 offset += 2;
1553 }
1554 break;
1555
H. Peter Anvin507ae032008-10-09 15:37:10 -07001556 case4(0274):
H. Peter Anvinc1377e92008-10-06 23:40:31 -07001557 {
1558 uint64_t uv, um;
1559 int s;
1560
1561 if (ins->rex & REX_W)
1562 s = 64;
1563 else if (ins->prefixes[PPS_OSIZE] == P_O16)
1564 s = 16;
1565 else if (ins->prefixes[PPS_OSIZE] == P_O32)
1566 s = 32;
1567 else
1568 s = bits;
1569
1570 um = (uint64_t)2 << (s-1);
1571 uv = opx->offset;
1572
1573 if (uv > 127 && uv < (uint64_t)-128 &&
1574 (uv < um-128 || uv > um-1)) {
1575 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
1576 "signed byte value exceeds bounds");
1577 }
1578 if (opx->segment != NO_SEG) {
H. Peter Anvin779ed8b2008-10-16 13:01:43 -07001579 data = uv;
H. Peter Anvinc1377e92008-10-06 23:40:31 -07001580 out(offset, segment, &data, OUT_ADDRESS, 1,
1581 opx->segment, opx->wrt);
1582 } else {
H. Peter Anvin779ed8b2008-10-16 13:01:43 -07001583 bytes[0] = uv;
H. Peter Anvinc1377e92008-10-06 23:40:31 -07001584 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
1585 NO_SEG);
1586 }
1587 offset += 1;
1588 break;
1589 }
1590
H. Peter Anvin507ae032008-10-09 15:37:10 -07001591 case4(0300):
H. Peter Anvine2c80182005-01-15 22:15:51 +00001592 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001593
H. Peter Anvine2c80182005-01-15 22:15:51 +00001594 case 0310:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001595 if (bits == 32 && !has_prefix(ins, PPS_ASIZE, P_A16)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001596 *bytes = 0x67;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001597 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001598 offset += 1;
1599 } else
1600 offset += 0;
1601 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001602
H. Peter Anvine2c80182005-01-15 22:15:51 +00001603 case 0311:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001604 if (bits != 32 && !has_prefix(ins, PPS_ASIZE, P_A32)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001605 *bytes = 0x67;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001606 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001607 offset += 1;
1608 } else
1609 offset += 0;
1610 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001611
H. Peter Anvine2c80182005-01-15 22:15:51 +00001612 case 0312:
1613 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001614
Keith Kaniosb7a89542007-04-12 02:40:54 +00001615 case 0313:
1616 ins->rex = 0;
1617 break;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07001618
H. Peter Anvin507ae032008-10-09 15:37:10 -07001619 case4(0314):
H. Peter Anvin23440102007-11-12 21:02:33 -08001620 break;
1621
H. Peter Anvine2c80182005-01-15 22:15:51 +00001622 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001623 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001624 *bytes = 0x66;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001625 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001626 offset += 1;
1627 } else
1628 offset += 0;
1629 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001630
H. Peter Anvine2c80182005-01-15 22:15:51 +00001631 case 0321:
1632 if (bits == 16) {
1633 *bytes = 0x66;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001634 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001635 offset += 1;
1636 } else
1637 offset += 0;
1638 break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001639
H. Peter Anvine2c80182005-01-15 22:15:51 +00001640 case 0322:
H. Peter Anvin70653092007-10-19 14:42:29 -07001641 case 0323:
1642 break;
1643
Keith Kaniosb7a89542007-04-12 02:40:54 +00001644 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001645 ins->rex |= REX_W;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001646 break;
H. Peter Anvin70653092007-10-19 14:42:29 -07001647
H. Peter Anvine2c80182005-01-15 22:15:51 +00001648 case 0330:
1649 *bytes = *codes++ ^ condval[ins->condition];
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001650 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001651 offset += 1;
1652 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001653
H. Peter Anvine2c80182005-01-15 22:15:51 +00001654 case 0331:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001655 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001656
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001657 case 0332:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001658 case 0333:
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001659 *bytes = c - 0332 + 0xF2;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001660 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001661 offset += 1;
1662 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001663
Keith Kanios48af1772007-08-17 07:37:52 +00001664 case 0334:
1665 if (ins->rex & REX_R) {
1666 *bytes = 0xF0;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001667 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
Keith Kanios48af1772007-08-17 07:37:52 +00001668 offset += 1;
1669 }
1670 ins->rex &= ~(REX_L|REX_R);
1671 break;
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001672
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001673 case 0335:
1674 break;
1675
H. Peter Anvin962e3052008-08-28 17:47:16 -07001676 case 0336:
1677 case 0337:
1678 break;
1679
H. Peter Anvine2c80182005-01-15 22:15:51 +00001680 case 0340:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001681 if (ins->oprs[0].segment != NO_SEG)
1682 errfunc(ERR_PANIC, "non-constant BSS size in pass two");
1683 else {
H. Peter Anvin428fd672007-11-15 10:25:52 -08001684 int64_t size = ins->oprs[0].offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001685 if (size > 0)
1686 out(offset, segment, NULL,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001687 OUT_RESERVE, size, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001688 offset += size;
1689 }
1690 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001691
H. Peter Anvinc2acf7b2009-02-21 18:22:56 -08001692 case 0341:
1693 break;
1694
H. Peter Anvinff6e12d2008-10-08 21:17:32 -07001695 case 0344:
1696 case 0345:
1697 bytes[0] = c & 1;
1698 switch (ins->oprs[0].basereg) {
1699 case R_CS:
1700 bytes[0] += 0x0E;
1701 break;
1702 case R_DS:
1703 bytes[0] += 0x1E;
1704 break;
1705 case R_ES:
1706 bytes[0] += 0x06;
1707 break;
1708 case R_SS:
1709 bytes[0] += 0x16;
1710 break;
1711 default:
1712 errfunc(ERR_PANIC,
1713 "bizarre 8086 segment register received");
1714 }
1715 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1716 offset++;
1717 break;
1718
1719 case 0346:
1720 case 0347:
1721 bytes[0] = c & 1;
1722 switch (ins->oprs[0].basereg) {
1723 case R_FS:
1724 bytes[0] += 0xA0;
1725 break;
1726 case R_GS:
1727 bytes[0] += 0xA8;
1728 break;
1729 default:
1730 errfunc(ERR_PANIC,
1731 "bizarre 386 segment register received");
1732 }
1733 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1734 offset++;
1735 break;
1736
H. Peter Anvinfff5a472008-05-20 09:46:24 -07001737 case 0360:
1738 break;
1739
1740 case 0361:
1741 bytes[0] = 0x66;
1742 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1743 offset += 1;
1744 break;
1745
1746 case 0362:
1747 case 0363:
1748 bytes[0] = c - 0362 + 0xf2;
1749 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1750 offset += 1;
1751 break;
1752
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001753 case 0364:
1754 case 0365:
1755 break;
1756
Keith Kanios48af1772007-08-17 07:37:52 +00001757 case 0366:
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001758 case 0367:
1759 *bytes = c - 0366 + 0x66;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001760 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
Keith Kanios48af1772007-08-17 07:37:52 +00001761 offset += 1;
1762 break;
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001763
H. Peter Anvine2c80182005-01-15 22:15:51 +00001764 case 0370:
1765 case 0371:
1766 case 0372:
1767 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001768
H. Peter Anvine2c80182005-01-15 22:15:51 +00001769 case 0373:
1770 *bytes = bits == 16 ? 3 : 5;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001771 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001772 offset += 1;
1773 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001774
H. Peter Anvin507ae032008-10-09 15:37:10 -07001775 case4(0100):
1776 case4(0110):
1777 case4(0120):
1778 case4(0130):
1779 case4(0200):
1780 case4(0204):
1781 case4(0210):
1782 case4(0214):
1783 case4(0220):
1784 case4(0224):
1785 case4(0230):
1786 case4(0234):
1787 {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001788 ea ea_data;
1789 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001790 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001791 uint8_t *p;
1792 int32_t s;
H. Peter Anvin9f817132008-10-06 19:11:07 -07001793 enum out_type type;
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001794 struct operand *opy = &ins->oprs[op2];
H. Peter Anvin70653092007-10-19 14:42:29 -07001795
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001796 if (c <= 0177) {
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001797 /* pick rfield from operand b (opx) */
1798 rflags = regflag(opx);
1799 rfield = nasm_regvals[opx->basereg];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001800 } else {
1801 /* rfield is constant */
1802 rflags = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001803 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001804 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001805
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001806 if (!process_ea(opy, &ea_data, bits, ins->addr_size,
1807 rfield, rflags)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001808 errfunc(ERR_NONFATAL, "invalid effective address");
1809 }
H. Peter Anvin70653092007-10-19 14:42:29 -07001810
Charles Crayne7e975552007-11-03 22:06:13 -07001811
H. Peter Anvine2c80182005-01-15 22:15:51 +00001812 p = bytes;
1813 *p++ = ea_data.modrm;
1814 if (ea_data.sib_present)
1815 *p++ = ea_data.sib;
1816
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001817 /* DREX suffixes come between the SIB and the displacement */
1818 if (ins->rex & REX_D) {
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001819 *p++ = (ins->drexdst << 4) |
1820 (ins->rex & REX_OC ? 0x08 : 0) |
1821 (ins->rex & (REX_R|REX_X|REX_B));
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001822 ins->rex = 0;
1823 }
1824
H. Peter Anvine2c80182005-01-15 22:15:51 +00001825 s = p - bytes;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001826 out(offset, segment, bytes, OUT_RAWDATA, s, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001827
Victor van den Elzencf9332c2008-10-01 12:18:28 +02001828 /*
1829 * Make sure the address gets the right offset in case
1830 * the line breaks in the .lst file (BR 1197827)
1831 */
1832 offset += s;
1833 s = 0;
1834
H. Peter Anvine2c80182005-01-15 22:15:51 +00001835 switch (ea_data.bytes) {
1836 case 0:
1837 break;
1838 case 1:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001839 case 2:
1840 case 4:
Victor van den Elzen352fe062008-12-10 13:04:58 +01001841 case 8:
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001842 data = opy->offset;
1843 warn_overflow(ea_data.bytes, opy);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001844 s += ea_data.bytes;
H. Peter Anvin9f817132008-10-06 19:11:07 -07001845 if (ea_data.rip) {
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001846 if (opy->segment == segment) {
H. Peter Anvine286c7e2008-10-22 11:15:00 -07001847 data -= insn_end;
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001848 out(offset, segment, &data, OUT_ADDRESS,
1849 ea_data.bytes, NO_SEG, NO_SEG);
H. Peter Anvine286c7e2008-10-22 11:15:00 -07001850 } else {
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001851 out(offset, segment, &data, OUT_REL4ADR,
1852 insn_end - offset, opy->segment, opy->wrt);
H. Peter Anvine286c7e2008-10-22 11:15:00 -07001853 }
H. Peter Anvin9f817132008-10-06 19:11:07 -07001854 } else {
1855 type = OUT_ADDRESS;
H. Peter Anvin33d5fc02008-10-23 23:07:53 -07001856 out(offset, segment, &data, OUT_ADDRESS,
1857 ea_data.bytes, opy->segment, opy->wrt);
H. Peter Anvin9f817132008-10-06 19:11:07 -07001858 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001859 break;
Victor van den Elzen352fe062008-12-10 13:04:58 +01001860 default:
1861 /* Impossible! */
1862 errfunc(ERR_PANIC,
1863 "Invalid amount of bytes (%d) for offset?!",
1864 ea_data.bytes);
1865 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001866 }
1867 offset += s;
H. Peter Anvin839eca22007-10-29 23:12:47 -07001868 }
H. Peter Anvin507ae032008-10-09 15:37:10 -07001869 break;
1870
1871 default:
1872 errfunc(ERR_PANIC, "internal instruction table corrupt"
H. Peter Anvin16a856c2009-03-01 00:22:16 -08001873 ": instruction code \\%o (0x%02X) given", c, c);
H. Peter Anvin507ae032008-10-09 15:37:10 -07001874 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001875 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001876 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001877}
1878
H. Peter Anvin0ec60e62007-07-07 01:59:52 +00001879static int32_t regflag(const operand * o)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001880{
1881 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1882 errfunc(ERR_PANIC, "invalid operand passed to regflag()");
1883 }
H. Peter Anvina4835d42008-05-20 14:21:29 -07001884 return nasm_reg_flags[o->basereg];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001885}
1886
H. Peter Anvin5b0e3ec2007-07-07 02:01:08 +00001887static int32_t regval(const operand * o)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001888{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001889 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1890 errfunc(ERR_PANIC, "invalid operand passed to regval()");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001891 }
H. Peter Anvina4835d42008-05-20 14:21:29 -07001892 return nasm_regvals[o->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001893}
1894
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001895static int op_rexflags(const operand * o, int mask)
1896{
1897 int32_t flags;
1898 int val;
1899
1900 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1901 errfunc(ERR_PANIC, "invalid operand passed to op_rexflags()");
1902 }
1903
H. Peter Anvina4835d42008-05-20 14:21:29 -07001904 flags = nasm_reg_flags[o->basereg];
1905 val = nasm_regvals[o->basereg];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001906
1907 return rexflags(val, flags, mask);
1908}
1909
1910static int rexflags(int val, int32_t flags, int mask)
1911{
1912 int rex = 0;
1913
1914 if (val >= 8)
1915 rex |= REX_B|REX_X|REX_R;
1916 if (flags & BITS64)
1917 rex |= REX_W;
1918 if (!(REG_HIGH & ~flags)) /* AH, CH, DH, BH */
1919 rex |= REX_H;
1920 else if (!(REG8 & ~flags) && val >= 4) /* SPL, BPL, SIL, DIL */
1921 rex |= REX_P;
1922
1923 return rex & mask;
1924}
1925
H. Peter Anvin3360d792007-09-11 04:16:57 +00001926static int matches(const struct itemplate *itemp, insn * instruction, int bits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001927{
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001928 int i, size[MAX_OPERANDS], asize, oprs, ret;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001929
1930 ret = 100;
1931
1932 /*
1933 * Check the opcode
1934 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001935 if (itemp->opcode != instruction->opcode)
1936 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001937
1938 /*
1939 * Count the operands
1940 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001941 if (itemp->operands != instruction->operands)
1942 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001943
1944 /*
1945 * Check that no spurious colons or TOs are present
1946 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001947 for (i = 0; i < itemp->operands; i++)
1948 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON | TO))
1949 return 0;
H. Peter Anvin70653092007-10-19 14:42:29 -07001950
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001951 /*
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001952 * Process size flags
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001953 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001954 if (itemp->flags & IF_ARMASK) {
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001955 memset(size, 0, sizeof size);
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001956
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001957 i = ((itemp->flags & IF_ARMASK) >> IF_ARSHFT) - 1;
1958
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001959 switch (itemp->flags & IF_SMASK) {
1960 case IF_SB:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001961 size[i] = BITS8;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001962 break;
1963 case IF_SW:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001964 size[i] = BITS16;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001965 break;
1966 case IF_SD:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001967 size[i] = BITS32;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001968 break;
1969 case IF_SQ:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001970 size[i] = BITS64;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001971 break;
H. Peter Anvin41c9f6f2007-09-18 13:01:32 -07001972 case IF_SO:
1973 size[i] = BITS128;
1974 break;
H. Peter Anvindfb91802008-05-20 11:43:53 -07001975 case IF_SY:
1976 size[i] = BITS256;
1977 break;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001978 case IF_SZ:
1979 switch (bits) {
1980 case 16:
1981 size[i] = BITS16;
1982 break;
1983 case 32:
1984 size[i] = BITS32;
1985 break;
1986 case 64:
1987 size[i] = BITS64;
1988 break;
1989 }
1990 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001991 default:
1992 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001993 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001994 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001995 asize = 0;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001996 switch (itemp->flags & IF_SMASK) {
1997 case IF_SB:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001998 asize = BITS8;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001999 break;
2000 case IF_SW:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002001 asize = BITS16;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002002 break;
2003 case IF_SD:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002004 asize = BITS32;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002005 break;
2006 case IF_SQ:
Keith Kaniosb7a89542007-04-12 02:40:54 +00002007 asize = BITS64;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002008 break;
H. Peter Anvin41c9f6f2007-09-18 13:01:32 -07002009 case IF_SO:
2010 asize = BITS128;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002011 break;
H. Peter Anvindfb91802008-05-20 11:43:53 -07002012 case IF_SY:
2013 asize = BITS256;
2014 break;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002015 case IF_SZ:
2016 switch (bits) {
2017 case 16:
2018 asize = BITS16;
2019 break;
2020 case 32:
2021 asize = BITS32;
2022 break;
2023 case 64:
2024 asize = BITS64;
2025 break;
2026 }
H. Peter Anvin41c9f6f2007-09-18 13:01:32 -07002027 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002028 default:
2029 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002030 }
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002031 for (i = 0; i < MAX_OPERANDS; i++)
2032 size[i] = asize;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002033 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002034
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002035 /*
2036 * Check that the operand flags all match up
2037 */
2038 for (i = 0; i < itemp->operands; i++) {
2039 int32_t type = instruction->oprs[i].type;
2040 if (!(type & SIZE_MASK))
2041 type |= size[i];
H. Peter Anvind85d2502008-05-04 17:53:31 -07002042
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002043 if (itemp->opd[i] & SAME_AS) {
2044 int j = itemp->opd[i] & ~SAME_AS;
2045 if (type != instruction->oprs[j].type ||
2046 instruction->oprs[i].basereg != instruction->oprs[j].basereg)
2047 return 0;
2048 } else if (itemp->opd[i] & ~type ||
2049 ((itemp->opd[i] & SIZE_MASK) &&
2050 ((itemp->opd[i] ^ type) & SIZE_MASK))) {
2051 if ((itemp->opd[i] & ~type & ~SIZE_MASK) ||
2052 (type & SIZE_MASK))
2053 return 0;
2054 else
2055 return 1;
2056 }
2057 }
2058
2059 /*
2060 * Check operand sizes
2061 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002062 if (itemp->flags & (IF_SM | IF_SM2)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002063 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
2064 asize = 0;
2065 for (i = 0; i < oprs; i++) {
2066 if ((asize = itemp->opd[i] & SIZE_MASK) != 0) {
2067 int j;
2068 for (j = 0; j < oprs; j++)
2069 size[j] = asize;
2070 break;
2071 }
2072 }
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002073 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002074 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002075 }
2076
Keith Kaniosb7a89542007-04-12 02:40:54 +00002077 for (i = 0; i < itemp->operands; i++) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002078 if (!(itemp->opd[i] & SIZE_MASK) &&
2079 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvine2c80182005-01-15 22:15:51 +00002080 return 2;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002081 }
2082
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002083 /*
2084 * Check template is okay at the set cpu level
2085 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002086 if (((itemp->flags & IF_PLEVEL) > cpu))
H. Peter Anvine2c80182005-01-15 22:15:51 +00002087 return 3;
H. Peter Anvin70653092007-10-19 14:42:29 -07002088
Keith Kaniosb7a89542007-04-12 02:40:54 +00002089 /*
H. Peter Anvin6cda4142008-12-29 20:52:28 -08002090 * Verify the appropriate long mode flag.
Keith Kaniosb7a89542007-04-12 02:40:54 +00002091 */
H. Peter Anvin6cda4142008-12-29 20:52:28 -08002092 if ((itemp->flags & (bits == 64 ? IF_NOLONG : IF_LONG)))
Keith Kaniosb7a89542007-04-12 02:40:54 +00002093 return 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002094
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002095 /*
2096 * Check if special handling needed for Jumps
2097 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002098 if ((uint8_t)(itemp->code[0]) >= 0370)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002099 return 99;
2100
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002101 return ret;
2102}
2103
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002104static ea *process_ea(operand * input, ea * output, int bits,
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07002105 int addrbits, int rfield, int32_t rflags)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002106{
H. Peter Anvin9945fee2009-02-26 14:48:03 -08002107 bool forw_ref = !!(input->opflags & OPFLAG_UNKNOWN);
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07002108
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002109 output->rip = false;
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00002110
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002111 /* REX flags for the rfield operand */
2112 output->rex |= rexflags(rfield, rflags, REX_R|REX_P|REX_W|REX_H);
2113
Keith Kaniosb7a89542007-04-12 02:40:54 +00002114 if (!(REGISTER & ~input->type)) { /* register direct */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002115 int i;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002116 int32_t f;
2117
2118 if (input->basereg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002119 || input->basereg >= REG_ENUM_LIMIT)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002120 return NULL;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002121 f = regflag(input);
H. Peter Anvina4835d42008-05-20 14:21:29 -07002122 i = nasm_regvals[input->basereg];
Keith Kaniosb7a89542007-04-12 02:40:54 +00002123
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002124 if (REG_EA & ~f)
2125 return NULL; /* Invalid EA register */
H. Peter Anvin70653092007-10-19 14:42:29 -07002126
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002127 output->rex |= op_rexflags(input, REX_B|REX_P|REX_W|REX_H);
2128
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002129 output->sib_present = false; /* no SIB necessary */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002130 output->bytes = 0; /* no offset necessary either */
2131 output->modrm = 0xC0 | ((rfield & 7) << 3) | (i & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002132 } else { /* it's a memory reference */
2133 if (input->basereg == -1
2134 && (input->indexreg == -1 || input->scale == 0)) {
2135 /* it's a pure offset */
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002136 if (bits == 64 && (~input->type & IP_REL)) {
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002137 int scale, index, base;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002138 output->sib_present = true;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002139 scale = 0;
2140 index = 4;
2141 base = 5;
2142 output->sib = (scale << 6) | (index << 3) | base;
2143 output->bytes = 4;
2144 output->modrm = 4 | ((rfield & 7) << 3);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002145 output->rip = false;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002146 } else {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002147 output->sib_present = false;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002148 output->bytes = (addrbits != 16 ? 4 : 2);
2149 output->modrm = (addrbits != 16 ? 5 : 6) | ((rfield & 7) << 3);
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002150 output->rip = bits == 64;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002151 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002152 } else { /* it's an indirection */
2153 int i = input->indexreg, b = input->basereg, s = input->scale;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002154 int32_t o = input->offset, seg = input->segment;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002155 int hb = input->hintbase, ht = input->hinttype;
2156 int t;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002157 int it, bt;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002158 int32_t ix, bx; /* register flags */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002159
H. Peter Anvine2c80182005-01-15 22:15:51 +00002160 if (s == 0)
2161 i = -1; /* make this easy, at least */
H. Peter Anvin70653092007-10-19 14:42:29 -07002162
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002163 if (i >= EXPR_REG_START && i < REG_ENUM_LIMIT) {
H. Peter Anvina4835d42008-05-20 14:21:29 -07002164 it = nasm_regvals[i];
2165 ix = nasm_reg_flags[i];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002166 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00002167 it = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002168 ix = 0;
2169 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002170
H. Peter Anvinb0c54622007-10-28 23:21:46 -07002171 if (b >= EXPR_REG_START && b < REG_ENUM_LIMIT) {
H. Peter Anvina4835d42008-05-20 14:21:29 -07002172 bt = nasm_regvals[b];
2173 bx = nasm_reg_flags[b];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002174 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00002175 bt = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002176 bx = 0;
2177 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002178
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002179 /* check for a 32/64-bit memory reference... */
2180 if ((ix|bx) & (BITS32|BITS64)) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00002181 /* it must be a 32/64-bit memory reference. Firstly we have
2182 * to check that all registers involved are type E/Rxx. */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002183 int32_t sok = BITS32|BITS64;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002184
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002185 if (it != -1) {
2186 if (!(REG64 & ~ix) || !(REG32 & ~ix))
2187 sok &= ix;
2188 else
2189 return NULL;
2190 }
2191
2192 if (bt != -1) {
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00002193 if (REG_GPR & ~bx)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002194 return NULL; /* Invalid register */
H. Peter Anvina57e8d42007-05-30 03:44:02 +00002195 if (~sok & bx & SIZE_MASK)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002196 return NULL; /* Invalid size */
H. Peter Anvinb0c54622007-10-28 23:21:46 -07002197 sok &= bx;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002198 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002199
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002200 /* While we're here, ensure the user didn't specify
2201 WORD or QWORD. */
2202 if (input->disp_size == 16 || input->disp_size == 64)
2203 return NULL;
2204
2205 if (addrbits == 16 ||
2206 (addrbits == 32 && !(sok & BITS32)) ||
2207 (addrbits == 64 && !(sok & BITS64)))
2208 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002209
Keith Kaniosb7a89542007-04-12 02:40:54 +00002210 /* now reorganize base/index */
2211 if (s == 1 && bt != it && bt != -1 && it != -1 &&
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002212 ((hb == b && ht == EAH_NOTBASE)
2213 || (hb == i && ht == EAH_MAKEBASE))) {
2214 /* swap if hints say so */
2215 t = bt, bt = it, it = t;
2216 t = bx, bx = ix, ix = t;
2217 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00002218 if (bt == it) /* convert EAX+2*EAX to 3*EAX */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002219 bt = -1, bx = 0, s++;
2220 if (bt == -1 && s == 1 && !(hb == it && ht == EAH_NOTBASE)) {
2221 /* make single reg base, unless hint */
2222 bt = it, bx = ix, it = -1, ix = 0;
2223 }
H. Peter Anvinf5843c62007-09-10 18:59:26 +00002224 if (((s == 2 && it != REG_NUM_ESP
H. Peter Anvine2c80182005-01-15 22:15:51 +00002225 && !(input->eaflags & EAF_TIMESTWO)) || s == 3
Keith Kaniosb7a89542007-04-12 02:40:54 +00002226 || s == 5 || s == 9) && bt == -1)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002227 bt = it, bx = ix, s--; /* convert 3*EAX to EAX+2*EAX */
Keith Kanios48af1772007-08-17 07:37:52 +00002228 if (it == -1 && (bt & 7) != REG_NUM_ESP
H. Peter Anvine2c80182005-01-15 22:15:51 +00002229 && (input->eaflags & EAF_TIMESTWO))
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002230 it = bt, ix = bx, bt = -1, bx = 0, s = 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002231 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
Keith Kanios48af1772007-08-17 07:37:52 +00002232 if (s == 1 && it == REG_NUM_ESP) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002233 /* swap ESP into base if scale is 1 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002234 t = it, it = bt, bt = t;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002235 t = ix, ix = bx, bx = t;
2236 }
Keith Kanios48af1772007-08-17 07:37:52 +00002237 if (it == REG_NUM_ESP
Keith Kaniosb7a89542007-04-12 02:40:54 +00002238 || (s != 1 && s != 2 && s != 4 && s != 8 && it != -1))
H. Peter Anvine2c80182005-01-15 22:15:51 +00002239 return NULL; /* wrong, for various reasons */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002240
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002241 output->rex |= rexflags(it, ix, REX_X);
2242 output->rex |= rexflags(bt, bx, REX_B);
Keith Kaniosb7a89542007-04-12 02:40:54 +00002243
Keith Kanios48af1772007-08-17 07:37:52 +00002244 if (it == -1 && (bt & 7) != REG_NUM_ESP) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002245 /* no SIB needed */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002246 int mod, rm;
H. Peter Anvin70653092007-10-19 14:42:29 -07002247
Keith Kaniosb7a89542007-04-12 02:40:54 +00002248 if (bt == -1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002249 rm = 5;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002250 mod = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002251 } else {
2252 rm = (bt & 7);
Keith Kanios48af1772007-08-17 07:37:52 +00002253 if (rm != REG_NUM_EBP && o == 0 &&
Keith Kaniosb7a89542007-04-12 02:40:54 +00002254 seg == NO_SEG && !forw_ref &&
2255 !(input->eaflags &
2256 (EAF_BYTEOFFS | EAF_WORDOFFS)))
2257 mod = 0;
2258 else if (input->eaflags & EAF_BYTEOFFS ||
2259 (o >= -128 && o <= 127 && seg == NO_SEG
2260 && !forw_ref
2261 && !(input->eaflags & EAF_WORDOFFS)))
2262 mod = 1;
2263 else
2264 mod = 2;
2265 }
H. Peter Anvinea838272002-04-30 20:51:53 +00002266
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002267 output->sib_present = false;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002268 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
2269 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002270 } else {
2271 /* we need a SIB */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002272 int mod, scale, index, base;
H. Peter Anvin70653092007-10-19 14:42:29 -07002273
Keith Kaniosb7a89542007-04-12 02:40:54 +00002274 if (it == -1)
2275 index = 4, s = 1;
2276 else
2277 index = (it & 7);
H. Peter Anvin70653092007-10-19 14:42:29 -07002278
H. Peter Anvine2c80182005-01-15 22:15:51 +00002279 switch (s) {
2280 case 1:
2281 scale = 0;
2282 break;
2283 case 2:
2284 scale = 1;
2285 break;
2286 case 4:
2287 scale = 2;
2288 break;
2289 case 8:
2290 scale = 3;
2291 break;
2292 default: /* then what the smeg is it? */
2293 return NULL; /* panic */
2294 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002295
Keith Kaniosb7a89542007-04-12 02:40:54 +00002296 if (bt == -1) {
2297 base = 5;
2298 mod = 0;
2299 } else {
2300 base = (bt & 7);
Keith Kanios48af1772007-08-17 07:37:52 +00002301 if (base != REG_NUM_EBP && o == 0 &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00002302 seg == NO_SEG && !forw_ref &&
2303 !(input->eaflags &
Keith Kaniosb7a89542007-04-12 02:40:54 +00002304 (EAF_BYTEOFFS | EAF_WORDOFFS)))
2305 mod = 0;
2306 else if (input->eaflags & EAF_BYTEOFFS ||
2307 (o >= -128 && o <= 127 && seg == NO_SEG
2308 && !forw_ref
2309 && !(input->eaflags & EAF_WORDOFFS)))
2310 mod = 1;
2311 else
2312 mod = 2;
2313 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002314
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002315 output->sib_present = true;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002316 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
2317 output->modrm = (mod << 6) | ((rfield & 7) << 3) | 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002318 output->sib = (scale << 6) | (index << 3) | base;
2319 }
2320 } else { /* it's 16-bit */
2321 int mod, rm;
H. Peter Anvin70653092007-10-19 14:42:29 -07002322
Keith Kaniosb7a89542007-04-12 02:40:54 +00002323 /* check for 64-bit long mode */
2324 if (addrbits == 64)
2325 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002326
H. Peter Anvine2c80182005-01-15 22:15:51 +00002327 /* check all registers are BX, BP, SI or DI */
2328 if ((b != -1 && b != R_BP && b != R_BX && b != R_SI
2329 && b != R_DI) || (i != -1 && i != R_BP && i != R_BX
2330 && i != R_SI && i != R_DI))
2331 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002332
Keith Kaniosb7a89542007-04-12 02:40:54 +00002333 /* ensure the user didn't specify DWORD/QWORD */
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002334 if (input->disp_size == 32 || input->disp_size == 64)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002335 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002336
H. Peter Anvine2c80182005-01-15 22:15:51 +00002337 if (s != 1 && i != -1)
2338 return NULL; /* no can do, in 16-bit EA */
2339 if (b == -1 && i != -1) {
2340 int tmp = b;
2341 b = i;
2342 i = tmp;
2343 } /* swap */
2344 if ((b == R_SI || b == R_DI) && i != -1) {
2345 int tmp = b;
2346 b = i;
2347 i = tmp;
2348 }
2349 /* have BX/BP as base, SI/DI index */
2350 if (b == i)
2351 return NULL; /* shouldn't ever happen, in theory */
2352 if (i != -1 && b != -1 &&
2353 (i == R_BP || i == R_BX || b == R_SI || b == R_DI))
2354 return NULL; /* invalid combinations */
2355 if (b == -1) /* pure offset: handled above */
2356 return NULL; /* so if it gets to here, panic! */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002357
H. Peter Anvine2c80182005-01-15 22:15:51 +00002358 rm = -1;
2359 if (i != -1)
2360 switch (i * 256 + b) {
2361 case R_SI * 256 + R_BX:
2362 rm = 0;
2363 break;
2364 case R_DI * 256 + R_BX:
2365 rm = 1;
2366 break;
2367 case R_SI * 256 + R_BP:
2368 rm = 2;
2369 break;
2370 case R_DI * 256 + R_BP:
2371 rm = 3;
2372 break;
2373 } else
2374 switch (b) {
2375 case R_SI:
2376 rm = 4;
2377 break;
2378 case R_DI:
2379 rm = 5;
2380 break;
2381 case R_BP:
2382 rm = 6;
2383 break;
2384 case R_BX:
2385 rm = 7;
2386 break;
2387 }
2388 if (rm == -1) /* can't happen, in theory */
2389 return NULL; /* so panic if it does */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002390
H. Peter Anvine2c80182005-01-15 22:15:51 +00002391 if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
2392 !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
2393 mod = 0;
2394 else if (input->eaflags & EAF_BYTEOFFS ||
2395 (o >= -128 && o <= 127 && seg == NO_SEG
2396 && !forw_ref
2397 && !(input->eaflags & EAF_WORDOFFS)))
2398 mod = 1;
2399 else
2400 mod = 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002401
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002402 output->sib_present = false; /* no SIB - it's 16-bit */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002403 output->bytes = mod; /* bytes of offset needed */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002404 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002405 }
2406 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002407 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002408
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002409 output->size = 1 + output->sib_present + output->bytes;
2410 return output;
2411}
2412
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002413static void add_asp(insn *ins, int addrbits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002414{
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002415 int j, valid;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002416 int defdisp;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002417
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002418 valid = (addrbits == 64) ? 64|32 : 32|16;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002419
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002420 switch (ins->prefixes[PPS_ASIZE]) {
2421 case P_A16:
2422 valid &= 16;
2423 break;
2424 case P_A32:
2425 valid &= 32;
2426 break;
2427 case P_A64:
2428 valid &= 64;
2429 break;
2430 case P_ASP:
2431 valid &= (addrbits == 32) ? 16 : 32;
2432 break;
2433 default:
2434 break;
2435 }
2436
2437 for (j = 0; j < ins->operands; j++) {
2438 if (!(MEMORY & ~ins->oprs[j].type)) {
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002439 int32_t i, b;
H. Peter Anvin70653092007-10-19 14:42:29 -07002440
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002441 /* Verify as Register */
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002442 if (ins->oprs[j].indexreg < EXPR_REG_START
2443 || ins->oprs[j].indexreg >= REG_ENUM_LIMIT)
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002444 i = 0;
2445 else
H. Peter Anvina4835d42008-05-20 14:21:29 -07002446 i = nasm_reg_flags[ins->oprs[j].indexreg];
H. Peter Anvin70653092007-10-19 14:42:29 -07002447
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002448 /* Verify as Register */
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002449 if (ins->oprs[j].basereg < EXPR_REG_START
2450 || ins->oprs[j].basereg >= REG_ENUM_LIMIT)
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002451 b = 0;
2452 else
H. Peter Anvina4835d42008-05-20 14:21:29 -07002453 b = nasm_reg_flags[ins->oprs[j].basereg];
H. Peter Anvin70653092007-10-19 14:42:29 -07002454
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002455 if (ins->oprs[j].scale == 0)
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002456 i = 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002457
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002458 if (!i && !b) {
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002459 int ds = ins->oprs[j].disp_size;
2460 if ((addrbits != 64 && ds > 8) ||
2461 (addrbits == 64 && ds == 16))
2462 valid &= ds;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002463 } else {
2464 if (!(REG16 & ~b))
2465 valid &= 16;
2466 if (!(REG32 & ~b))
2467 valid &= 32;
2468 if (!(REG64 & ~b))
2469 valid &= 64;
H. Peter Anvin70653092007-10-19 14:42:29 -07002470
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002471 if (!(REG16 & ~i))
2472 valid &= 16;
2473 if (!(REG32 & ~i))
2474 valid &= 32;
2475 if (!(REG64 & ~i))
2476 valid &= 64;
2477 }
2478 }
2479 }
2480
2481 if (valid & addrbits) {
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002482 ins->addr_size = addrbits;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002483 } else if (valid & ((addrbits == 32) ? 16 : 32)) {
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002484 /* Add an address size prefix */
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002485 enum prefixes pref = (addrbits == 32) ? P_A16 : P_A32;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002486 ins->prefixes[PPS_ASIZE] = pref;
2487 ins->addr_size = (addrbits == 32) ? 16 : 32;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002488 } else {
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002489 /* Impossible... */
2490 errfunc(ERR_NONFATAL, "impossible combination of address sizes");
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002491 ins->addr_size = addrbits; /* Error recovery */
2492 }
2493
2494 defdisp = ins->addr_size == 16 ? 16 : 32;
2495
2496 for (j = 0; j < ins->operands; j++) {
2497 if (!(MEM_OFFS & ~ins->oprs[j].type) &&
2498 (ins->oprs[j].disp_size ? ins->oprs[j].disp_size : defdisp)
2499 != ins->addr_size) {
2500 /* mem_offs sizes must match the address size; if not,
2501 strip the MEM_OFFS bit and match only EA instructions */
2502 ins->oprs[j].type &= ~(MEM_OFFS & ~MEMORY);
2503 }
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002504 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002505}