blob: 3f7299189e1e5bc5ca30e84f4e704e290de9e2ec [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.)
10 * \1, \2, \3 - that many literal bytes follow in the code stream
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070011 * \10..\13 - a literal byte follows in the code stream, to be added
12 * to the register value of operand 0..3
13 * \14..\17 - a signed byte immediate operand, from operand 0..3
14 * \20..\23 - a byte immediate operand, from operand 0..3
15 * \24..\27 - an unsigned byte immediate operand, from operand 0..3
16 * \30..\33 - a word immediate operand, from operand 0..3
17 * \34..\37 - select between \3[0-3] and \4[0-3] depending on 16/32 bit
H. Peter Anvin3ba46772002-05-27 23:19:35 +000018 * assembly mode or the operand-size override on the operand
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070019 * \40..\43 - a long immediate operand, from operand 0..3
20 * \44..\47 - select between \3[0-3], \4[0-3] and \5[4-7]
H. Peter Anvinde4b89b2007-10-01 15:41:25 -070021 * depending on the address size of the instruction.
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070022 * \50..\53 - a byte relative operand, from operand 0..3
23 * \54..\57 - a qword immediate operand, from operand 0..3
24 * \60..\63 - a word relative operand, from operand 0..3
25 * \64..\67 - select between \6[0-3] and \7[0-3] depending on 16/32 bit
H. Peter Anvin17799b42002-05-21 03:31:21 +000026 * assembly mode or the operand-size override on the operand
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070027 * \70..\73 - a long relative operand, from operand 0..3
H. Peter Anvinc1377e92008-10-06 23:40:31 -070028 * \74..\77 - a word constant, from the _segment_ part of operand 0..3
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000029 * \1ab - a ModRM, calculated on EA in operand a, with the spare
30 * field the register value of operand b.
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070031 * \140..\143 - an immediate word or signed byte for operand 0..3
H. Peter Anvina30cc072007-11-18 21:55:26 -080032 * \144..\147 - or 2 (s-field) into opcode byte if operand 0..3
33 * is a signed byte rather than a word. Opcode byte follows.
H. Peter Anvinc1377e92008-10-06 23:40:31 -070034 * \150..\153 - an immediate dword or signed byte for operand 0..3
H. Peter Anvina30cc072007-11-18 21:55:26 -080035 * \154..\157 - or 2 (s-field) into opcode byte if operand 0..3
H. Peter Anvin32cd4c22008-04-04 13:34:53 -070036 * is a signed byte rather than a dword. Opcode byte follows.
H. Peter Anvin401c07e2007-09-17 16:55:04 -070037 * \160..\163 - this instruction uses DREX rather than REX, with the
38 * OC0 field set to 0, and the dest field taken from
39 * operand 0..3.
40 * \164..\167 - this instruction uses DREX rather than REX, with the
41 * OC0 field set to 1, and the dest field taken from
42 * operand 0..3.
H. Peter Anvin401c07e2007-09-17 16:55:04 -070043 * \171 - placement of DREX suffix in the absence of an EA
H. Peter Anvind85d2502008-05-04 17:53:31 -070044 * \172\ab - the register number from operand a in bits 7..4, with
H. Peter Anvin52dc3532008-05-20 19:29:04 -070045 * the 4-bit immediate from operand b in bits 3..0.
H. Peter Anvind58656f2008-05-06 20:11:14 -070046 * \173\xab - the register number from operand a in bits 7..4, with
H. Peter Anvin52dc3532008-05-20 19:29:04 -070047 * the value b in bits 3..0.
48 * \174\a - the register number from operand a in bits 7..4, and
49 * an arbitrary value in bits 3..0 (assembled as zero.)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000050 * \2ab - a ModRM, calculated on EA in operand a, with the spare
51 * field equal to digit b.
H. Peter Anvin32cd4c22008-04-04 13:34:53 -070052 * \250..\253 - same as \150..\153, except warn if the 64-bit operand
53 * is not equal to the truncated and sign-extended 32-bit
54 * operand; used for 32-bit immediates in 64-bit mode.
H. Peter Anvin588df782008-10-07 10:05:10 -070055 * \254..\257 - a signed 32-bit operand to be extended to 64 bits.
H. Peter Anvind85d2502008-05-04 17:53:31 -070056 * \260..\263 - this instruction uses VEX rather than REX, with the
57 * V field taken from operand 0..3.
58 * \270 - this instruction uses VEX rather than REX, with the
59 * V field set to 1111b.
60 *
61 * VEX prefixes are followed by the sequence:
H. Peter Anvinaaa088f2008-05-12 11:13:41 -070062 * \mm\wlp where mm is the M field; and wlp is:
63 * 00 0ww lpp
H. Peter Anvinbd420c72008-05-22 11:24:35 -070064 * [w0] ww = 0 for W = 0
65 * [w1] ww = 1 for W = 1
66 * [wx] ww = 2 for W don't care (always assembled as 0)
67 * [ww] ww = 3 for W used as REX.W
68 *
H. Peter Anvind85d2502008-05-04 17:53:31 -070069 *
H. Peter Anvinc1377e92008-10-06 23:40:31 -070070 * \274..\277 - a signed byte immediate operand, from operand 0..3,
71 * which is to be extended to the operand size.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000072 * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
73 * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
Keith Kanios48af1772007-08-17 07:37:52 +000074 * \312 - (disassembler only) marker on LOOP, LOOPxx instructions.
H. Peter Anvince2b3972007-05-30 22:21:11 +000075 * \313 - indicates fixed 64-bit address size, 0x67 invalid.
H. Peter Anvin23440102007-11-12 21:02:33 -080076 * \314 - (disassembler only) invalid with REX.B
77 * \315 - (disassembler only) invalid with REX.X
78 * \316 - (disassembler only) invalid with REX.R
79 * \317 - (disassembler only) invalid with REX.W
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000080 * \320 - indicates fixed 16-bit operand size, i.e. optional 0x66.
81 * \321 - indicates fixed 32-bit operand size, i.e. optional 0x66.
82 * \322 - indicates that this instruction is only valid when the
83 * operand size is the default (instruction to disassembler,
84 * generates no code in the assembler)
H. Peter Anvince2b3972007-05-30 22:21:11 +000085 * \323 - indicates fixed 64-bit operand size, REX on extensions only.
Keith Kaniosb7a89542007-04-12 02:40:54 +000086 * \324 - indicates 64-bit operand size requiring REX prefix.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000087 * \330 - a literal byte follows in the code stream, to be added
88 * to the condition code value of the instruction.
Keith Kanios48af1772007-08-17 07:37:52 +000089 * \331 - instruction not valid with REP prefix. Hint for
H. Peter Anvinef7468f2002-04-30 20:57:59 +000090 * disassembler only; for SSE instructions.
H. Peter Anvincb9b6902007-09-12 21:58:51 -070091 * \332 - REP prefix (0xF2 byte) used as opcode extension.
92 * \333 - REP prefix (0xF3 byte) used as opcode extension.
Keith Kanios48af1772007-08-17 07:37:52 +000093 * \334 - LOCK prefix used instead of REX.R
H. Peter Anvincb9b6902007-09-12 21:58:51 -070094 * \335 - disassemble a rep (0xF3 byte) prefix as repe not rep.
H. Peter Anvin962e3052008-08-28 17:47:16 -070095 * \336 - force a REP(E) prefix (0xF2) even if not specified.
96 * \337 - force a REPNE prefix (0xF3) even if not specified.
97 * \336-\337 are still listed as prefixes in the disassembler.
Keith Kaniosb7a89542007-04-12 02:40:54 +000098 * \340 - reserve <operand 0> bytes of uninitialized storage.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000099 * Operand 0 had better be a segmentless constant.
H. Peter Anvinff6e12d2008-10-08 21:17:32 -0700100 * \344,\345 - the PUSH/POP (respectively) codes for CS, DS, ES, SS
101 * (POP is never used for CS) depending on operand 0
102 * \346,\347 - the second byte of PUSH/POP codes for FS, GS, depending
103 * on operand 0
H. Peter Anvinfff5a472008-05-20 09:46:24 -0700104 * \360 - no SSE prefix (== \364\331)
105 * \361 - 66 SSE prefix (== \366\331)
106 * \362 - F2 SSE prefix (== \364\332)
107 * \363 - F3 SSE prefix (== \364\333)
H. Peter Anvin62cb6062007-09-11 22:44:03 +0000108 * \364 - operand-size prefix (0x66) not permitted
109 * \365 - address-size prefix (0x67) not permitted
110 * \366 - operand-size prefix (0x66) used as opcode extension
111 * \367 - address-size prefix (0x67) used as opcode extension
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000112 * \370,\371,\372 - match only if operand 0 meets byte jump criteria.
113 * 370 is used for Jcc, 371 is used for JMP.
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000114 * \373 - assemble 0x03 if bits==16, 0x05 if bits==32;
115 * used for conditional jump over longer jump
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000116 */
117
H. Peter Anvinfe501952007-10-02 21:53:51 -0700118#include "compiler.h"
119
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000120#include <stdio.h>
121#include <string.h>
Keith Kaniosb7a89542007-04-12 02:40:54 +0000122#include <inttypes.h>
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000123
124#include "nasm.h"
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000125#include "nasmlib.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000126#include "assemble.h"
127#include "insns.h"
H. Peter Anvina4835d42008-05-20 14:21:29 -0700128#include "tables.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000129
H. Peter Anvindfb91802008-05-20 11:43:53 -0700130/* Initialized to zero by the C standard */
131static const uint8_t const_zero_buf[256];
132
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000133typedef struct {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000134 int sib_present; /* is a SIB byte necessary? */
135 int bytes; /* # of bytes of offset needed */
136 int size; /* lazy - this is sib+bytes+1 */
137 uint8_t modrm, sib, rex, rip; /* the bytes themselves */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000138} ea;
139
Keith Kaniosb7a89542007-04-12 02:40:54 +0000140static uint32_t cpu; /* cpu level received from nasm.c */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000141static efunc errfunc;
142static struct ofmt *outfmt;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000143static ListGen *list;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000144
H. Peter Anvin3720f7b2008-05-12 11:00:50 -0700145static int64_t calcsize(int32_t, int64_t, int, insn *, const uint8_t *);
H. Peter Anvin833caea2008-10-04 19:02:30 -0700146static void gencode(int32_t segment, int64_t offset, int bits,
147 insn * ins, const struct itemplate *temp,
148 int64_t insn_end);
H. Peter Anvin3360d792007-09-11 04:16:57 +0000149static int matches(const struct itemplate *, insn *, int bits);
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000150static int32_t regflag(const operand *);
151static int32_t regval(const operand *);
152static int rexflags(int, int32_t, int);
153static int op_rexflags(const operand *, int);
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700154static ea *process_ea(operand *, ea *, int, int, int, int32_t);
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700155static void add_asp(insn *, int);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000156
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700157static int has_prefix(insn * ins, enum prefix_pos pos, enum prefixes prefix)
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000158{
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700159 return ins->prefixes[pos] == prefix;
160}
161
162static void assert_no_prefix(insn * ins, enum prefix_pos pos)
163{
164 if (ins->prefixes[pos])
165 errfunc(ERR_NONFATAL, "invalid %s prefix",
166 prefix_name(ins->prefixes[pos]));
167}
168
169static const char *size_name(int size)
170{
171 switch (size) {
172 case 1:
173 return "byte";
174 case 2:
175 return "word";
176 case 4:
177 return "dword";
178 case 8:
179 return "qword";
180 case 10:
181 return "tword";
182 case 16:
183 return "oword";
H. Peter Anvindfb91802008-05-20 11:43:53 -0700184 case 32:
185 return "yword";
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700186 default:
187 return "???";
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000188 }
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700189}
190
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700191static void warn_overflow(int size, const struct operand *o)
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700192{
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700193 if (size < 8 && o->wrt == NO_SEG && o->segment == NO_SEG) {
Charles Craynedd462c82007-11-04 15:28:30 -0800194 int64_t lim = ((int64_t)1 << (size*8))-1;
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700195 int64_t data = o->offset;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000196
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700197 if (data < ~lim || data > lim)
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700198 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700199 "%s data exceeds bounds", size_name(size));
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700200 }
201}
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000202/*
203 * This routine wrappers the real output format's output routine,
204 * in order to pass a copy of the data off to the listing file
205 * generator at the same time.
206 */
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800207static void out(int64_t offset, int32_t segto, const void *data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800208 enum out_type type, uint64_t size,
209 int32_t segment, int32_t wrt)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000210{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000211 static int32_t lineno = 0; /* static!!! */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000212 static char *lnfname = NULL;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800213 uint8_t p[8];
H. Peter Anvineba20a72002-04-30 20:53:55 +0000214
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800215 if (type == OUT_ADDRESS && segment == NO_SEG && wrt == NO_SEG) {
216 /*
217 * This is a non-relocated address, and we're going to
218 * convert it into RAWDATA format.
219 */
220 uint8_t *q = p;
H. Peter Anvind1fb15c2007-11-13 09:37:59 -0800221
222 if (size > 8) {
223 errfunc(ERR_PANIC, "OUT_ADDRESS with size > 8");
224 return;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800225 }
H. Peter Anvind85d2502008-05-04 17:53:31 -0700226
H. Peter Anvind1fb15c2007-11-13 09:37:59 -0800227 WRITEADDR(q, *(int64_t *)data, size);
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800228 data = p;
229 type = OUT_RAWDATA;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000230 }
231
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800232 list->output(offset, data, type, size);
233
Frank Kotlerabebb082003-09-06 04:45:37 +0000234 /*
235 * this call to src_get determines when we call the
236 * debug-format-specific "linenum" function
237 * it updates lineno and lnfname to the current values
238 * returning 0 if "same as last time", -2 if lnfname
239 * changed, and the amount by which lineno changed,
240 * if it did. thus, these variables must be static
241 */
242
H. Peter Anvine2c80182005-01-15 22:15:51 +0000243 if (src_get(&lineno, &lnfname)) {
244 outfmt->current_dfmt->linenum(lnfname, lineno, segto);
H. Peter Anvince616072002-04-30 21:02:23 +0000245 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000246
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800247 outfmt->output(segto, data, type, size, segment, wrt);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000248}
249
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700250static bool jmp_match(int32_t segment, int64_t offset, int bits,
H. Peter Anvin3720f7b2008-05-12 11:00:50 -0700251 insn * ins, const uint8_t *code)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000252{
Charles Crayne5fbbc8c2007-11-07 19:03:46 -0800253 int64_t isize;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000254 uint8_t c = code[0];
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000255
Charles Craynef1aefd82008-09-30 16:11:32 -0700256 if ((c != 0370 && c != 0371) || (ins->oprs[0].type & STRICT))
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700257 return false;
258 if (!optimizing)
259 return false;
260 if (optimizing < 0 && c == 0371)
261 return false;
262
H. Peter Anvine2c80182005-01-15 22:15:51 +0000263 isize = calcsize(segment, offset, bits, ins, code);
264 if (ins->oprs[0].segment != segment)
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700265 return false;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000266
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700267 isize = ins->oprs[0].offset - offset - isize; /* isize is delta */
268 return (isize >= -128 && isize <= 127); /* is it byte size? */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000269}
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000270
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800271int64_t assemble(int32_t segment, int64_t offset, int bits, uint32_t cp,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000272 insn * instruction, struct ofmt *output, efunc error,
273 ListGen * listgen)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000274{
H. Peter Anvin3360d792007-09-11 04:16:57 +0000275 const struct itemplate *temp;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000276 int j;
277 int size_prob;
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800278 int64_t insn_end;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000279 int32_t itimes;
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800280 int64_t start = offset;
281 int64_t wsize = 0; /* size for DB etc. */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000282
H. Peter Anvine2c80182005-01-15 22:15:51 +0000283 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000284 cpu = cp;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000285 outfmt = output; /* likewise */
286 list = listgen; /* and again */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000287
H. Peter Anvine2c80182005-01-15 22:15:51 +0000288 switch (instruction->opcode) {
289 case -1:
290 return 0;
291 case I_DB:
292 wsize = 1;
293 break;
294 case I_DW:
295 wsize = 2;
296 break;
297 case I_DD:
298 wsize = 4;
299 break;
300 case I_DQ:
301 wsize = 8;
302 break;
303 case I_DT:
304 wsize = 10;
305 break;
H. Peter Anvincfbe7c32007-09-18 17:49:09 -0700306 case I_DO:
307 wsize = 16;
308 break;
H. Peter Anvindfb91802008-05-20 11:43:53 -0700309 case I_DY:
310 wsize = 32;
311 break;
H. Peter Anvin16b0a332007-09-12 20:27:41 -0700312 default:
313 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000314 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000315
H. Peter Anvineba20a72002-04-30 20:53:55 +0000316 if (wsize) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000317 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000318 int32_t t = instruction->times;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000319 if (t < 0)
320 errfunc(ERR_PANIC,
321 "instruction->times < 0 (%ld) in assemble()", t);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000322
H. Peter Anvine2c80182005-01-15 22:15:51 +0000323 while (t--) { /* repeat TIMES times */
324 for (e = instruction->eops; e; e = e->next) {
325 if (e->type == EOT_DB_NUMBER) {
326 if (wsize == 1) {
327 if (e->segment != NO_SEG)
328 errfunc(ERR_NONFATAL,
329 "one-byte relocation attempted");
330 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000331 uint8_t out_byte = e->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000332 out(offset, segment, &out_byte,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800333 OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000334 }
Keith Kanios61ff53c2007-04-14 18:54:52 +0000335 } else if (wsize > 8) {
H. Peter Anvin3be5d852008-05-20 14:49:32 -0700336 errfunc(ERR_NONFATAL,
337 "integer supplied to a DT, DO or DY"
Keith Kanios61ff53c2007-04-14 18:54:52 +0000338 " instruction");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000339 } else
340 out(offset, segment, &e->offset,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800341 OUT_ADDRESS, wsize, e->segment, e->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000342 offset += wsize;
H. Peter Anvin518df302008-06-14 16:53:48 -0700343 } else if (e->type == EOT_DB_STRING ||
344 e->type == EOT_DB_STRING_FREE) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000345 int align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000346
H. Peter Anvine2c80182005-01-15 22:15:51 +0000347 out(offset, segment, e->stringval,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800348 OUT_RAWDATA, e->stringlen, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000349 align = e->stringlen % wsize;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000350
H. Peter Anvine2c80182005-01-15 22:15:51 +0000351 if (align) {
352 align = wsize - align;
H. Peter Anvindfb91802008-05-20 11:43:53 -0700353 out(offset, segment, const_zero_buf,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800354 OUT_RAWDATA, align, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000355 }
356 offset += e->stringlen + align;
357 }
358 }
359 if (t > 0 && t == instruction->times - 1) {
360 /*
361 * Dummy call to list->output to give the offset to the
362 * listing module.
363 */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800364 list->output(offset, NULL, OUT_RAWDATA, 0);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000365 list->uplevel(LIST_TIMES);
366 }
367 }
368 if (instruction->times > 1)
369 list->downlevel(LIST_TIMES);
370 return offset - start;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000371 }
372
H. Peter Anvine2c80182005-01-15 22:15:51 +0000373 if (instruction->opcode == I_INCBIN) {
H. Peter Anvin518df302008-06-14 16:53:48 -0700374 const char *fname = instruction->eops->stringval;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000375 FILE *fp;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000376
H. Peter Anvin418ca702008-05-30 10:42:30 -0700377 fp = fopen(fname, "rb");
378 if (!fp) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000379 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
380 fname);
H. Peter Anvin418ca702008-05-30 10:42:30 -0700381 } else if (fseek(fp, 0L, SEEK_END) < 0) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000382 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
383 fname);
H. Peter Anvin418ca702008-05-30 10:42:30 -0700384 } else {
H. Peter Anvin518df302008-06-14 16:53:48 -0700385 static char buf[4096];
386 size_t t = instruction->times;
387 size_t base = 0;
388 size_t len;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000389
H. Peter Anvine2c80182005-01-15 22:15:51 +0000390 len = ftell(fp);
391 if (instruction->eops->next) {
392 base = instruction->eops->next->offset;
393 len -= base;
394 if (instruction->eops->next->next &&
H. Peter Anvin518df302008-06-14 16:53:48 -0700395 len > (size_t)instruction->eops->next->next->offset)
396 len = (size_t)instruction->eops->next->next->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000397 }
398 /*
399 * Dummy call to list->output to give the offset to the
400 * listing module.
401 */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800402 list->output(offset, NULL, OUT_RAWDATA, 0);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000403 list->uplevel(LIST_INCBIN);
404 while (t--) {
H. Peter Anvin518df302008-06-14 16:53:48 -0700405 size_t l;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000406
H. Peter Anvine2c80182005-01-15 22:15:51 +0000407 fseek(fp, base, SEEK_SET);
408 l = len;
409 while (l > 0) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000410 int32_t m =
Charles Crayne192d5b52007-10-18 19:02:42 -0700411 fread(buf, 1, (l > (int32_t) sizeof(buf) ? (int32_t) sizeof(buf) : l),
H. Peter Anvine2c80182005-01-15 22:15:51 +0000412 fp);
413 if (!m) {
414 /*
415 * This shouldn't happen unless the file
416 * actually changes while we are reading
417 * it.
418 */
419 error(ERR_NONFATAL,
420 "`incbin': unexpected EOF while"
421 " reading file `%s'", fname);
422 t = 0; /* Try to exit cleanly */
423 break;
424 }
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800425 out(offset, segment, buf, OUT_RAWDATA, m,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000426 NO_SEG, NO_SEG);
427 l -= m;
428 }
429 }
430 list->downlevel(LIST_INCBIN);
431 if (instruction->times > 1) {
432 /*
433 * Dummy call to list->output to give the offset to the
434 * listing module.
435 */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800436 list->output(offset, NULL, OUT_RAWDATA, 0);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000437 list->uplevel(LIST_TIMES);
438 list->downlevel(LIST_TIMES);
439 }
440 fclose(fp);
441 return instruction->times * len;
442 }
443 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000444 }
445
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700446 /* Check to see if we need an address-size prefix */
447 add_asp(instruction, bits);
448
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700449 size_prob = false;
H. Peter Anvin70653092007-10-19 14:42:29 -0700450
451 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++){
Keith Kaniosb7a89542007-04-12 02:40:54 +0000452 int m = matches(temp, instruction, bits);
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700453 if (m == 100 ||
454 (m == 99 && jmp_match(segment, offset, bits,
455 instruction, temp->code))) {
456 /* Matches! */
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800457 int64_t insn_size = calcsize(segment, offset, bits,
H. Peter Anvin833caea2008-10-04 19:02:30 -0700458 instruction, temp->code);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000459 itimes = instruction->times;
460 if (insn_size < 0) /* shouldn't be, on pass two */
461 error(ERR_PANIC, "errors made it through from pass one");
462 else
463 while (itimes--) {
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700464 for (j = 0; j < MAXPREFIX; j++) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000465 uint8_t c = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000466 switch (instruction->prefixes[j]) {
467 case P_LOCK:
468 c = 0xF0;
469 break;
470 case P_REPNE:
471 case P_REPNZ:
472 c = 0xF2;
473 break;
474 case P_REPE:
475 case P_REPZ:
476 case P_REP:
477 c = 0xF3;
478 break;
479 case R_CS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000480 if (bits == 64) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700481 error(ERR_WARNING | ERR_PASS2,
Charles Crayne1b851dc2007-11-05 21:49:49 -0800482 "cs segment base generated, but will be ignored in 64-bit mode");
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000483 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000484 c = 0x2E;
485 break;
486 case R_DS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000487 if (bits == 64) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700488 error(ERR_WARNING | ERR_PASS2,
Charles Crayne1b851dc2007-11-05 21:49:49 -0800489 "ds segment base generated, but will be ignored in 64-bit mode");
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000490 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000491 c = 0x3E;
492 break;
493 case R_ES:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000494 if (bits == 64) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700495 error(ERR_WARNING | ERR_PASS2,
Charles Crayne1b851dc2007-11-05 21:49:49 -0800496 "es segment base generated, but will be ignored in 64-bit mode");
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000497 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000498 c = 0x26;
499 break;
500 case R_FS:
501 c = 0x64;
502 break;
503 case R_GS:
504 c = 0x65;
505 break;
506 case R_SS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000507 if (bits == 64) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700508 error(ERR_WARNING | ERR_PASS2,
Charles Crayne1b851dc2007-11-05 21:49:49 -0800509 "ss segment base generated, but will be ignored in 64-bit mode");
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000510 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000511 c = 0x36;
512 break;
513 case R_SEGR6:
514 case R_SEGR7:
515 error(ERR_NONFATAL,
516 "segr6 and segr7 cannot be used as prefixes");
517 break;
518 case P_A16:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000519 if (bits == 64) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000520 error(ERR_NONFATAL,
521 "16-bit addressing is not supported "
522 "in 64-bit mode");
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700523 } else if (bits != 16)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000524 c = 0x67;
525 break;
526 case P_A32:
527 if (bits != 32)
528 c = 0x67;
529 break;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700530 case P_A64:
531 if (bits != 64) {
532 error(ERR_NONFATAL,
533 "64-bit addressing is only supported "
534 "in 64-bit mode");
535 }
536 break;
537 case P_ASP:
538 c = 0x67;
539 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000540 case P_O16:
541 if (bits != 16)
542 c = 0x66;
543 break;
544 case P_O32:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000545 if (bits == 16)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000546 c = 0x66;
547 break;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700548 case P_O64:
549 /* REX.W */
550 break;
551 case P_OSP:
552 c = 0x66;
553 break;
554 case P_none:
555 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000556 default:
557 error(ERR_PANIC, "invalid instruction prefix");
558 }
559 if (c != 0) {
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800560 out(offset, segment, &c, OUT_RAWDATA, 1,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000561 NO_SEG, NO_SEG);
562 offset++;
563 }
H. Peter Anvin70653092007-10-19 14:42:29 -0700564 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000565 insn_end = offset + insn_size;
H. Peter Anvin833caea2008-10-04 19:02:30 -0700566 gencode(segment, offset, bits, instruction,
567 temp, insn_end);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000568 offset += insn_size;
569 if (itimes > 0 && itimes == instruction->times - 1) {
570 /*
571 * Dummy call to list->output to give the offset to the
572 * listing module.
573 */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800574 list->output(offset, NULL, OUT_RAWDATA, 0);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000575 list->uplevel(LIST_TIMES);
576 }
577 }
578 if (instruction->times > 1)
579 list->downlevel(LIST_TIMES);
580 return offset - start;
581 } else if (m > 0 && m > size_prob) {
582 size_prob = m;
583 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000584 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000585
H. Peter Anvine2c80182005-01-15 22:15:51 +0000586 if (temp->opcode == -1) { /* didn't match any instruction */
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000587 switch (size_prob) {
588 case 1:
589 error(ERR_NONFATAL, "operation size not specified");
590 break;
591 case 2:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000592 error(ERR_NONFATAL, "mismatch in operand sizes");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000593 break;
594 case 3:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000595 error(ERR_NONFATAL, "no instruction for this cpu level");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000596 break;
597 case 4:
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000598 error(ERR_NONFATAL, "instruction not supported in 64-bit mode");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000599 break;
600 default:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000601 error(ERR_NONFATAL,
602 "invalid combination of opcode and operands");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000603 break;
604 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000605 }
606 return 0;
607}
608
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800609int64_t insn_size(int32_t segment, int64_t offset, int bits, uint32_t cp,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000610 insn * instruction, efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000611{
H. Peter Anvin3360d792007-09-11 04:16:57 +0000612 const struct itemplate *temp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000613
H. Peter Anvine2c80182005-01-15 22:15:51 +0000614 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000615 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000616
617 if (instruction->opcode == -1)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000618 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000619
H. Peter Anvincfbe7c32007-09-18 17:49:09 -0700620 if (instruction->opcode == I_DB || instruction->opcode == I_DW ||
621 instruction->opcode == I_DD || instruction->opcode == I_DQ ||
H. Peter Anvindfb91802008-05-20 11:43:53 -0700622 instruction->opcode == I_DT || instruction->opcode == I_DO ||
623 instruction->opcode == I_DY) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000624 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000625 int32_t isize, osize, wsize = 0; /* placate gcc */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000626
H. Peter Anvine2c80182005-01-15 22:15:51 +0000627 isize = 0;
628 switch (instruction->opcode) {
629 case I_DB:
630 wsize = 1;
631 break;
632 case I_DW:
633 wsize = 2;
634 break;
635 case I_DD:
636 wsize = 4;
637 break;
638 case I_DQ:
639 wsize = 8;
640 break;
641 case I_DT:
642 wsize = 10;
643 break;
H. Peter Anvincfbe7c32007-09-18 17:49:09 -0700644 case I_DO:
645 wsize = 16;
646 break;
H. Peter Anvindfb91802008-05-20 11:43:53 -0700647 case I_DY:
648 wsize = 32;
649 break;
H. Peter Anvin16b0a332007-09-12 20:27:41 -0700650 default:
651 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000652 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000653
H. Peter Anvine2c80182005-01-15 22:15:51 +0000654 for (e = instruction->eops; e; e = e->next) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000655 int32_t align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000656
H. Peter Anvine2c80182005-01-15 22:15:51 +0000657 osize = 0;
658 if (e->type == EOT_DB_NUMBER)
659 osize = 1;
H. Peter Anvin518df302008-06-14 16:53:48 -0700660 else if (e->type == EOT_DB_STRING ||
661 e->type == EOT_DB_STRING_FREE)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000662 osize = e->stringlen;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000663
H. Peter Anvine2c80182005-01-15 22:15:51 +0000664 align = (-osize) % wsize;
665 if (align < 0)
666 align += wsize;
667 isize += osize + align;
668 }
669 return isize * instruction->times;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000670 }
671
H. Peter Anvine2c80182005-01-15 22:15:51 +0000672 if (instruction->opcode == I_INCBIN) {
H. Peter Anvin518df302008-06-14 16:53:48 -0700673 const char *fname = instruction->eops->stringval;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000674 FILE *fp;
H. Peter Anvin518df302008-06-14 16:53:48 -0700675 size_t len;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000676
H. Peter Anvin418ca702008-05-30 10:42:30 -0700677 fp = fopen(fname, "rb");
678 if (!fp)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000679 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
680 fname);
681 else if (fseek(fp, 0L, SEEK_END) < 0)
682 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
683 fname);
684 else {
685 len = ftell(fp);
686 fclose(fp);
687 if (instruction->eops->next) {
688 len -= instruction->eops->next->offset;
689 if (instruction->eops->next->next &&
H. Peter Anvin518df302008-06-14 16:53:48 -0700690 len > (size_t)instruction->eops->next->next->offset) {
691 len = (size_t)instruction->eops->next->next->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000692 }
693 }
694 return instruction->times * len;
695 }
696 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000697 }
698
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700699 /* Check to see if we need an address-size prefix */
700 add_asp(instruction, bits);
701
Keith Kaniosb7a89542007-04-12 02:40:54 +0000702 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++) {
703 int m = matches(temp, instruction, bits);
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700704 if (m == 100 ||
705 (m == 99 && jmp_match(segment, offset, bits,
706 instruction, temp->code))) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000707 /* we've matched an instruction. */
Charles Crayne5fbbc8c2007-11-07 19:03:46 -0800708 int64_t isize;
H. Peter Anvin3720f7b2008-05-12 11:00:50 -0700709 const uint8_t *codes = temp->code;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000710 int j;
711
712 isize = calcsize(segment, offset, bits, instruction, codes);
713 if (isize < 0)
714 return -1;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700715 for (j = 0; j < MAXPREFIX; j++) {
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700716 switch (instruction->prefixes[j]) {
717 case P_A16:
718 if (bits != 16)
719 isize++;
720 break;
721 case P_A32:
722 if (bits != 32)
723 isize++;
724 break;
725 case P_O16:
726 if (bits != 16)
727 isize++;
728 break;
729 case P_O32:
730 if (bits == 16)
731 isize++;
732 break;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700733 case P_A64:
734 case P_O64:
735 case P_none:
736 break;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700737 default:
738 isize++;
739 break;
740 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000741 }
742 return isize * instruction->times;
743 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000744 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000745 return -1; /* didn't match any instruction */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000746}
747
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700748static bool possible_sbyte(operand *o)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000749{
H. Peter Anvinad6b8592008-10-07 09:56:38 -0700750 return o->wrt == NO_SEG && o->segment == NO_SEG &&
751 !(o->opflags & OPFLAG_FORWARD) &&
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700752 optimizing >= 0 && !(o->type & STRICT);
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000753}
754
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700755/* check that opn[op] is a signed byte of size 16 or 32 */
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700756static bool is_sbyte16(operand *o)
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700757{
758 int16_t v;
759
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700760 if (!possible_sbyte(o))
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700761 return false;
762
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700763 v = o->offset;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700764 return v >= -128 && v <= 127;
765}
766
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700767static bool is_sbyte32(operand *o)
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700768{
769 int32_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 Anvin507ae032008-10-09 15:37:10 -0700778/* Common construct */
779#define case4(x) case (x): case (x)+1: case (x)+2: case (x)+3
780
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800781static int64_t calcsize(int32_t segment, int64_t offset, int bits,
H. Peter Anvin9f817132008-10-06 19:11:07 -0700782 insn * ins, const uint8_t *codes)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000783{
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800784 int64_t length = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000785 uint8_t c;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000786 int rex_mask = ~0;
H. Peter Anvin839eca22007-10-29 23:12:47 -0700787 struct operand *opx;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000788
H. Peter Anvine3917fc2007-11-01 14:53:32 -0700789 ins->rex = 0; /* Ensure REX is reset */
790
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700791 if (ins->prefixes[PPS_OSIZE] == P_O64)
792 ins->rex |= REX_W;
793
H. Peter Anvine2c80182005-01-15 22:15:51 +0000794 (void)segment; /* Don't warn that this parameter is unused */
795 (void)offset; /* Don't warn that this parameter is unused */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000796
H. Peter Anvin839eca22007-10-29 23:12:47 -0700797 while (*codes) {
798 c = *codes++;
799 opx = &ins->oprs[c & 3];
800 switch (c) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000801 case 01:
802 case 02:
803 case 03:
804 codes += c, length += c;
805 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700806
807 case4(010):
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000808 ins->rex |=
H. Peter Anvin839eca22007-10-29 23:12:47 -0700809 op_rexflags(opx, REX_B|REX_H|REX_P|REX_W);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000810 codes++, length++;
811 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700812
813 case4(014):
814 case4(020):
815 case4(024):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000816 length++;
817 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700818
819 case4(030):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000820 length += 2;
821 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700822
823 case4(034):
H. Peter Anvin839eca22007-10-29 23:12:47 -0700824 if (opx->type & (BITS16 | BITS32 | BITS64))
825 length += (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000826 else
827 length += (bits == 16) ? 2 : 4;
828 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700829
830 case4(040):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000831 length += 4;
832 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700833
834 case4(044):
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700835 length += ins->addr_size >> 3;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000836 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700837
838 case4(050):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000839 length++;
840 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700841
842 case4(054):
Keith Kaniosb7a89542007-04-12 02:40:54 +0000843 length += 8; /* MOV reg64/imm */
844 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700845
846 case4(060):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000847 length += 2;
848 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700849
850 case4(064):
H. Peter Anvin839eca22007-10-29 23:12:47 -0700851 if (opx->type & (BITS16 | BITS32 | BITS64))
852 length += (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000853 else
854 length += (bits == 16) ? 2 : 4;
855 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700856
857 case4(070):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000858 length += 4;
859 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700860
861 case4(074):
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700862 length += 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000863 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700864
865 case4(0140):
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700866 length += is_sbyte16(opx) ? 1 : 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000867 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700868
869 case4(0144):
H. Peter Anvina30cc072007-11-18 21:55:26 -0800870 codes++;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000871 length++;
872 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700873
874 case4(0150):
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700875 length += is_sbyte32(opx) ? 1 : 4;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700876 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700877
878 case4(0154):
H. Peter Anvina30cc072007-11-18 21:55:26 -0800879 codes++;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700880 length++;
881 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700882
883 case4(0160):
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700884 length++;
885 ins->rex |= REX_D;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700886 ins->drexdst = regval(opx);
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700887 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700888
889 case4(0164):
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700890 length++;
891 ins->rex |= REX_D|REX_OC;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700892 ins->drexdst = regval(opx);
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700893 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700894
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700895 case 0171:
896 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700897
H. Peter Anvind85d2502008-05-04 17:53:31 -0700898 case 0172:
H. Peter Anvind58656f2008-05-06 20:11:14 -0700899 case 0173:
H. Peter Anvin52dc3532008-05-20 19:29:04 -0700900 case 0174:
H. Peter Anvind85d2502008-05-04 17:53:31 -0700901 codes++;
902 length++;
903 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700904
905 case4(0250):
H. Peter Anvinad6b8592008-10-07 09:56:38 -0700906 length += is_sbyte32(opx) ? 1 : 4;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700907 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700908
909 case4(0254):
H. Peter Anvin588df782008-10-07 10:05:10 -0700910 length += 4;
911 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700912
913 case4(0260):
H. Peter Anvind85d2502008-05-04 17:53:31 -0700914 ins->rex |= REX_V;
915 ins->drexdst = regval(opx);
916 ins->vex_m = *codes++;
917 ins->vex_wlp = *codes++;
918 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700919
H. Peter Anvind85d2502008-05-04 17:53:31 -0700920 case 0270:
H. Peter Anvind85d2502008-05-04 17:53:31 -0700921 ins->rex |= REX_V;
922 ins->drexdst = 0;
923 ins->vex_m = *codes++;
924 ins->vex_wlp = *codes++;
925 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700926
927 case4(0274):
H. Peter Anvinc1377e92008-10-06 23:40:31 -0700928 length++;
929 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700930
931 case4(0300):
H. Peter Anvine2c80182005-01-15 22:15:51 +0000932 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700933
H. Peter Anvine2c80182005-01-15 22:15:51 +0000934 case 0310:
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700935 if (bits == 64)
936 return -1;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700937 length += (bits != 16) && !has_prefix(ins, PPS_ASIZE, P_A16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000938 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700939
H. Peter Anvine2c80182005-01-15 22:15:51 +0000940 case 0311:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700941 length += (bits != 32) && !has_prefix(ins, PPS_ASIZE, P_A32);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000942 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700943
H. Peter Anvine2c80182005-01-15 22:15:51 +0000944 case 0312:
H. Peter Anvin70653092007-10-19 14:42:29 -0700945 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700946
Keith Kaniosb7a89542007-04-12 02:40:54 +0000947 case 0313:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700948 if (bits != 64 || has_prefix(ins, PPS_ASIZE, P_A16) ||
949 has_prefix(ins, PPS_ASIZE, P_A32))
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700950 return -1;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000951 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700952
953 case4(0314):
H. Peter Anvin23440102007-11-12 21:02:33 -0800954 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700955
H. Peter Anvine2c80182005-01-15 22:15:51 +0000956 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000957 length += (bits != 16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000958 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700959
H. Peter Anvine2c80182005-01-15 22:15:51 +0000960 case 0321:
961 length += (bits == 16);
962 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700963
H. Peter Anvine2c80182005-01-15 22:15:51 +0000964 case 0322:
965 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700966
Keith Kaniosb7a89542007-04-12 02:40:54 +0000967 case 0323:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000968 rex_mask &= ~REX_W;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000969 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700970
Keith Kaniosb7a89542007-04-12 02:40:54 +0000971 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000972 ins->rex |= REX_W;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000973 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700974
H. Peter Anvine2c80182005-01-15 22:15:51 +0000975 case 0330:
976 codes++, length++;
977 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700978
H. Peter Anvine2c80182005-01-15 22:15:51 +0000979 case 0331:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000980 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700981
H. Peter Anvincb9b6902007-09-12 21:58:51 -0700982 case 0332:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000983 case 0333:
984 length++;
985 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700986
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000987 case 0334:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000988 ins->rex |= REX_L;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000989 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700990
H. Peter Anvincb9b6902007-09-12 21:58:51 -0700991 case 0335:
992 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700993
H. Peter Anvin962e3052008-08-28 17:47:16 -0700994 case 0336:
995 if (!ins->prefixes[PPS_LREP])
996 ins->prefixes[PPS_LREP] = P_REP;
997 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -0700998
H. Peter Anvin962e3052008-08-28 17:47:16 -0700999 case 0337:
1000 if (!ins->prefixes[PPS_LREP])
1001 ins->prefixes[PPS_LREP] = P_REPNE;
1002 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001003
H. Peter Anvine2c80182005-01-15 22:15:51 +00001004 case 0340:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001005 if (ins->oprs[0].segment != NO_SEG)
1006 errfunc(ERR_NONFATAL, "attempt to reserve non-constant"
1007 " quantity of BSS space");
1008 else
H. Peter Anvin428fd672007-11-15 10:25:52 -08001009 length += ins->oprs[0].offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001010 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001011
1012 case4(0344):
H. Peter Anvinff6e12d2008-10-08 21:17:32 -07001013 length++;
1014 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001015
H. Peter Anvinfff5a472008-05-20 09:46:24 -07001016 case 0360:
1017 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001018
H. Peter Anvinfff5a472008-05-20 09:46:24 -07001019 case 0361:
1020 case 0362:
1021 case 0363:
1022 length++;
1023 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001024
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001025 case 0364:
1026 case 0365:
1027 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001028
Keith Kanios48af1772007-08-17 07:37:52 +00001029 case 0366:
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001030 case 0367:
1031 length++;
1032 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001033
H. Peter Anvine2c80182005-01-15 22:15:51 +00001034 case 0370:
1035 case 0371:
1036 case 0372:
1037 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001038
H. Peter Anvine2c80182005-01-15 22:15:51 +00001039 case 0373:
1040 length++;
1041 break;
H. Peter Anvin507ae032008-10-09 15:37:10 -07001042
1043 case4(0100):
1044 case4(0110):
1045 case4(0120):
1046 case4(0130):
1047 case4(0200):
1048 case4(0204):
1049 case4(0210):
1050 case4(0214):
1051 case4(0220):
1052 case4(0224):
1053 case4(0230):
1054 case4(0234):
1055 {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001056 ea ea_data;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001057 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001058 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001059 ea_data.rex = 0; /* Ensure ea.REX is initially 0 */
H. Peter Anvin70653092007-10-19 14:42:29 -07001060
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001061 if (c <= 0177) {
1062 /* pick rfield from operand b */
1063 rflags = regflag(&ins->oprs[c & 7]);
H. Peter Anvina4835d42008-05-20 14:21:29 -07001064 rfield = nasm_regvals[ins->oprs[c & 7].basereg];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001065 } else {
1066 rflags = 0;
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001067 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001068 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001069
H. Peter Anvine2c80182005-01-15 22:15:51 +00001070 if (!process_ea
Keith Kaniosb7a89542007-04-12 02:40:54 +00001071 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001072 ins->addr_size, rfield, rflags)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001073 errfunc(ERR_NONFATAL, "invalid effective address");
1074 return -1;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001075 } else {
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001076 ins->rex |= ea_data.rex;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001077 length += ea_data.size;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001078 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001079 }
H. Peter Anvin507ae032008-10-09 15:37:10 -07001080 break;
1081
1082 default:
1083 errfunc(ERR_PANIC, "internal instruction table corrupt"
1084 ": instruction code 0x%02X given", c);
1085 break;
1086 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001087 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001088
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001089 ins->rex &= rex_mask;
H. Peter Anvin70653092007-10-19 14:42:29 -07001090
H. Peter Anvind85d2502008-05-04 17:53:31 -07001091 if (ins->rex & REX_V) {
1092 int bad32 = REX_R|REX_W|REX_X|REX_B;
1093
1094 if (ins->rex & REX_H) {
1095 errfunc(ERR_NONFATAL, "cannot use high register in vex instruction");
1096 return -1;
1097 }
1098 switch (ins->vex_wlp & 030) {
1099 case 000:
H. Peter Anvinbd420c72008-05-22 11:24:35 -07001100 case 020:
H. Peter Anvind85d2502008-05-04 17:53:31 -07001101 ins->rex &= ~REX_W;
1102 break;
1103 case 010:
1104 ins->rex |= REX_W;
1105 bad32 &= ~REX_W;
1106 break;
H. Peter Anvinbd420c72008-05-22 11:24:35 -07001107 case 030:
H. Peter Anvind85d2502008-05-04 17:53:31 -07001108 /* Follow REX_W */
1109 break;
1110 }
1111
1112 if (bits != 64 && ((ins->rex & bad32) || ins->drexdst > 7)) {
1113 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
1114 return -1;
1115 }
1116 if (ins->vex_m != 1 || (ins->rex & (REX_W|REX_R|REX_B)))
1117 length += 3;
1118 else
1119 length += 2;
1120 } else if (ins->rex & REX_D) {
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001121 if (ins->rex & REX_H) {
1122 errfunc(ERR_NONFATAL, "cannot use high register in drex instruction");
1123 return -1;
1124 }
H. Peter Anvind85d2502008-05-04 17:53:31 -07001125 if (bits != 64 && ((ins->rex & (REX_R|REX_W|REX_X|REX_B)) ||
H. Peter Anvincf5180a2007-09-17 17:25:27 -07001126 ins->drexdst > 7)) {
1127 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
1128 return -1;
1129 }
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001130 length++;
1131 } else if (ins->rex & REX_REAL) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001132 if (ins->rex & REX_H) {
1133 errfunc(ERR_NONFATAL, "cannot use high register in rex instruction");
1134 return -1;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001135 } else if (bits == 64) {
1136 length++;
1137 } else if ((ins->rex & REX_L) &&
1138 !(ins->rex & (REX_P|REX_W|REX_X|REX_B)) &&
1139 cpu >= IF_X86_64) {
1140 /* LOCK-as-REX.R */
1141 assert_no_prefix(ins, PPS_LREP);
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001142 length++;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +00001143 } else {
H. Peter Anvincf5180a2007-09-17 17:25:27 -07001144 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
1145 return -1;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +00001146 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001147 }
1148
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001149 return length;
1150}
Keith Kaniosb7a89542007-04-12 02:40:54 +00001151
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001152#define EMIT_REX() \
H. Peter Anvind85d2502008-05-04 17:53:31 -07001153 if (!(ins->rex & (REX_D|REX_V)) && (ins->rex & REX_REAL) && (bits == 64)) { \
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001154 ins->rex = (ins->rex & REX_REAL)|REX_P; \
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001155 out(offset, segment, &ins->rex, OUT_RAWDATA, 1, NO_SEG, NO_SEG); \
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001156 ins->rex = 0; \
1157 offset += 1; \
1158 }
1159
Charles Crayne1f8bc4c2007-11-06 18:27:23 -08001160static void gencode(int32_t segment, int64_t offset, int bits,
H. Peter Anvin833caea2008-10-04 19:02:30 -07001161 insn * ins, const struct itemplate *temp,
1162 int64_t insn_end)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001163{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001164 static char condval[] = { /* conditional opcodes */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001165 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
1166 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
1167 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001168 };
Keith Kaniosb7a89542007-04-12 02:40:54 +00001169 uint8_t c;
1170 uint8_t bytes[4];
Charles Crayne1f8bc4c2007-11-06 18:27:23 -08001171 int64_t size;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001172 int64_t data;
H. Peter Anvin839eca22007-10-29 23:12:47 -07001173 struct operand *opx;
H. Peter Anvin833caea2008-10-04 19:02:30 -07001174 const uint8_t *codes = temp->code;
H. Peter Anvin70653092007-10-19 14:42:29 -07001175
H. Peter Anvin839eca22007-10-29 23:12:47 -07001176 while (*codes) {
1177 c = *codes++;
1178 opx = &ins->oprs[c & 3];
1179 switch (c) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001180 case 01:
1181 case 02:
1182 case 03:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001183 EMIT_REX();
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001184 out(offset, segment, codes, OUT_RAWDATA, c, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001185 codes += c;
1186 offset += c;
1187 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001188
H. Peter Anvin507ae032008-10-09 15:37:10 -07001189 case4(010):
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001190 EMIT_REX();
H. Peter Anvin839eca22007-10-29 23:12:47 -07001191 bytes[0] = *codes++ + ((regval(opx)) & 7);
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001192 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001193 offset += 1;
1194 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001195
H. Peter Anvin507ae032008-10-09 15:37:10 -07001196 case4(014):
H. Peter Anvin6c80ab62008-10-04 18:50:47 -07001197 /* The test for BITS8 and SBYTE here is intended to avoid
1198 warning on optimizer actions due to SBYTE, while still
1199 warn on explicit BYTE directives. Also warn, obviously,
1200 if the optimizer isn't enabled. */
1201 if (((opx->type & BITS8) ||
H. Peter Anvin833caea2008-10-04 19:02:30 -07001202 !(opx->type & temp->opd[c & 3] & BYTENESS)) &&
H. Peter Anvin6c80ab62008-10-04 18:50:47 -07001203 (opx->offset < -128 || opx->offset > 127)) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001204 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
H. Peter Anvin72c64372008-01-08 22:13:48 -08001205 "signed byte value exceeds bounds");
H. Peter Anvin6c80ab62008-10-04 18:50:47 -07001206 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001207 if (opx->segment != NO_SEG) {
1208 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001209 out(offset, segment, &data, OUT_ADDRESS, 1,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001210 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001211 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001212 bytes[0] = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001213 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001214 NO_SEG);
1215 }
1216 offset += 1;
1217 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001218
H. Peter Anvin507ae032008-10-09 15:37:10 -07001219 case4(020):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001220 if (opx->offset < -256 || opx->offset > 255) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001221 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
H. Peter Anvin72c64372008-01-08 22:13:48 -08001222 "byte value exceeds bounds");
H. Peter Anvine2c80182005-01-15 22:15:51 +00001223 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001224 if (opx->segment != NO_SEG) {
1225 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001226 out(offset, segment, &data, OUT_ADDRESS, 1,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001227 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001228 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001229 bytes[0] = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001230 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001231 NO_SEG);
1232 }
1233 offset += 1;
1234 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001235
H. Peter Anvin507ae032008-10-09 15:37:10 -07001236 case4(024):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001237 if (opx->offset < 0 || opx->offset > 255)
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001238 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
H. Peter Anvin72c64372008-01-08 22:13:48 -08001239 "unsigned byte value exceeds bounds");
H. Peter Anvin839eca22007-10-29 23:12:47 -07001240 if (opx->segment != NO_SEG) {
1241 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001242 out(offset, segment, &data, OUT_ADDRESS, 1,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001243 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001244 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001245 bytes[0] = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001246 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001247 NO_SEG);
1248 }
1249 offset += 1;
1250 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001251
H. Peter Anvin507ae032008-10-09 15:37:10 -07001252 case4(030):
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001253 warn_overflow(2, opx);
H. Peter Anvin839eca22007-10-29 23:12:47 -07001254 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001255 out(offset, segment, &data, OUT_ADDRESS, 2,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001256 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001257 offset += 2;
1258 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001259
H. Peter Anvin507ae032008-10-09 15:37:10 -07001260 case4(034):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001261 if (opx->type & (BITS16 | BITS32))
1262 size = (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001263 else
1264 size = (bits == 16) ? 2 : 4;
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001265 warn_overflow(size, opx);
H. Peter Anvin839eca22007-10-29 23:12:47 -07001266 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001267 out(offset, segment, &data, OUT_ADDRESS, size,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001268 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001269 offset += size;
1270 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001271
H. Peter Anvin507ae032008-10-09 15:37:10 -07001272 case4(040):
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001273 warn_overflow(4, opx);
H. Peter Anvin839eca22007-10-29 23:12:47 -07001274 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001275 out(offset, segment, &data, OUT_ADDRESS, 4,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001276 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001277 offset += 4;
1278 break;
H. Peter Anvin3ba46772002-05-27 23:19:35 +00001279
H. Peter Anvin507ae032008-10-09 15:37:10 -07001280 case4(044):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001281 data = opx->offset;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001282 size = ins->addr_size >> 3;
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001283 warn_overflow(size, opx);
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001284 out(offset, segment, &data, OUT_ADDRESS, size,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001285 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001286 offset += size;
1287 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001288
H. Peter Anvin507ae032008-10-09 15:37:10 -07001289 case4(050):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001290 if (opx->segment != segment)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001291 errfunc(ERR_NONFATAL,
1292 "short relative jump outside segment");
H. Peter Anvin839eca22007-10-29 23:12:47 -07001293 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001294 if (data > 127 || data < -128)
1295 errfunc(ERR_NONFATAL, "short jump is out of range");
1296 bytes[0] = data;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001297 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001298 offset += 1;
1299 break;
H. Peter Anvin70653092007-10-19 14:42:29 -07001300
H. Peter Anvin507ae032008-10-09 15:37:10 -07001301 case4(054):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001302 data = (int64_t)opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001303 out(offset, segment, &data, OUT_ADDRESS, 8,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001304 opx->segment, opx->wrt);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001305 offset += 8;
1306 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001307
H. Peter Anvin507ae032008-10-09 15:37:10 -07001308 case4(060):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001309 if (opx->segment != segment) {
1310 data = opx->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001311 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001312 OUT_REL2ADR, insn_end - offset,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001313 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001314 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001315 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001316 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001317 OUT_ADDRESS, 2, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001318 }
1319 offset += 2;
1320 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001321
H. Peter Anvin507ae032008-10-09 15:37:10 -07001322 case4(064):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001323 if (opx->type & (BITS16 | BITS32 | BITS64))
1324 size = (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001325 else
1326 size = (bits == 16) ? 2 : 4;
H. Peter Anvin839eca22007-10-29 23:12:47 -07001327 if (opx->segment != segment) {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001328 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001329 out(offset, segment, &data,
1330 size == 2 ? OUT_REL2ADR : OUT_REL4ADR,
1331 insn_end - offset, opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001332 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001333 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001334 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001335 OUT_ADDRESS, size, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001336 }
1337 offset += size;
1338 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001339
H. Peter Anvin507ae032008-10-09 15:37:10 -07001340 case4(070):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001341 if (opx->segment != segment) {
1342 data = opx->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001343 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001344 OUT_REL4ADR, insn_end - offset,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001345 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001346 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001347 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001348 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001349 OUT_ADDRESS, 4, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001350 }
1351 offset += 4;
1352 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001353
H. Peter Anvin507ae032008-10-09 15:37:10 -07001354 case4(074):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001355 if (opx->segment == NO_SEG)
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001356 errfunc(ERR_NONFATAL, "value referenced by FAR is not"
1357 " relocatable");
H. Peter Anvindfb91802008-05-20 11:43:53 -07001358 data = 0;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001359 out(offset, segment, &data, OUT_ADDRESS, 2,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001360 outfmt->segbase(1 + opx->segment),
1361 opx->wrt);
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001362 offset += 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001363 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001364
H. Peter Anvin507ae032008-10-09 15:37:10 -07001365 case4(0140):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001366 data = opx->offset;
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001367 warn_overflow(2, opx);
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001368 if (is_sbyte16(opx)) {
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001369 bytes[0] = data;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001370 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001371 NO_SEG);
1372 offset++;
1373 } else {
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001374 out(offset, segment, &data, OUT_ADDRESS, 2,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001375 opx->segment, opx->wrt);
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001376 offset += 2;
1377 }
1378 break;
1379
H. Peter Anvin507ae032008-10-09 15:37:10 -07001380 case4(0144):
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001381 EMIT_REX();
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001382 bytes[0] = *codes++;
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001383 if (is_sbyte16(opx))
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001384 bytes[0] |= 2; /* s-bit */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001385 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001386 offset++;
1387 break;
1388
H. Peter Anvin507ae032008-10-09 15:37:10 -07001389 case4(0150):
H. Peter Anvin839eca22007-10-29 23:12:47 -07001390 data = opx->offset;
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001391 warn_overflow(4, opx);
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001392 if (is_sbyte32(opx)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001393 bytes[0] = data;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001394 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001395 NO_SEG);
1396 offset++;
1397 } else {
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001398 out(offset, segment, &data, OUT_ADDRESS, 4,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001399 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001400 offset += 4;
1401 }
1402 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001403
H. Peter Anvin507ae032008-10-09 15:37:10 -07001404 case4(0154):
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001405 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001406 bytes[0] = *codes++;
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001407 if (is_sbyte32(opx))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001408 bytes[0] |= 2; /* s-bit */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001409 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001410 offset++;
1411 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001412
H. Peter Anvin507ae032008-10-09 15:37:10 -07001413 case4(0160):
1414 case4(0164):
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001415 break;
1416
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001417 case 0171:
1418 bytes[0] =
1419 (ins->drexdst << 4) |
1420 (ins->rex & REX_OC ? 0x08 : 0) |
1421 (ins->rex & (REX_R|REX_X|REX_B));
1422 ins->rex = 0;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001423 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001424 offset++;
1425 break;
1426
H. Peter Anvind85d2502008-05-04 17:53:31 -07001427 case 0172:
1428 c = *codes++;
1429 opx = &ins->oprs[c >> 3];
H. Peter Anvina4835d42008-05-20 14:21:29 -07001430 bytes[0] = nasm_regvals[opx->basereg] << 4;
H. Peter Anvind85d2502008-05-04 17:53:31 -07001431 opx = &ins->oprs[c & 7];
1432 if (opx->segment != NO_SEG || opx->wrt != NO_SEG) {
1433 errfunc(ERR_NONFATAL,
1434 "non-absolute expression not permitted as argument %d",
1435 c & 7);
1436 } else {
1437 if (opx->offset & ~15) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001438 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
H. Peter Anvind85d2502008-05-04 17:53:31 -07001439 "four-bit argument exceeds bounds");
1440 }
1441 bytes[0] |= opx->offset & 15;
1442 }
1443 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1444 offset++;
1445 break;
1446
H. Peter Anvind58656f2008-05-06 20:11:14 -07001447 case 0173:
1448 c = *codes++;
1449 opx = &ins->oprs[c >> 4];
H. Peter Anvina4835d42008-05-20 14:21:29 -07001450 bytes[0] = nasm_regvals[opx->basereg] << 4;
H. Peter Anvind58656f2008-05-06 20:11:14 -07001451 bytes[0] |= c & 15;
1452 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1453 offset++;
1454 break;
1455
H. Peter Anvin52dc3532008-05-20 19:29:04 -07001456 case 0174:
1457 c = *codes++;
1458 opx = &ins->oprs[c];
1459 bytes[0] = nasm_regvals[opx->basereg] << 4;
1460 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1461 offset++;
1462 break;
1463
H. Peter Anvin507ae032008-10-09 15:37:10 -07001464 case4(0250):
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001465 data = opx->offset;
H. Peter Anvinad6b8592008-10-07 09:56:38 -07001466 if (opx->wrt == NO_SEG && opx->segment == NO_SEG &&
1467 (int32_t)data != (int64_t)data) {
1468 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
1469 "signed dword immediate exceeds bounds");
1470 }
1471 if (is_sbyte32(opx)) {
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001472 bytes[0] = data;
1473 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
1474 NO_SEG);
1475 offset++;
1476 } else {
1477 out(offset, segment, &data, OUT_ADDRESS, 4,
1478 opx->segment, opx->wrt);
1479 offset += 4;
1480 }
1481 break;
1482
H. Peter Anvin507ae032008-10-09 15:37:10 -07001483 case4(0254):
H. Peter Anvin588df782008-10-07 10:05:10 -07001484 data = opx->offset;
1485 if (opx->wrt == NO_SEG && opx->segment == NO_SEG &&
1486 (int32_t)data != (int64_t)data) {
1487 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
1488 "signed dword immediate exceeds bounds");
1489 }
1490 out(offset, segment, &data, OUT_ADDRESS, 4,
1491 opx->segment, opx->wrt);
1492 offset += 4;
1493 break;
1494
H. Peter Anvin507ae032008-10-09 15:37:10 -07001495 case4(0260):
H. Peter Anvind85d2502008-05-04 17:53:31 -07001496 case 0270:
1497 codes += 2;
1498 if (ins->vex_m != 1 || (ins->rex & (REX_W|REX_X|REX_B))) {
1499 bytes[0] = 0xc4;
H. Peter Anvin4d2c38c2008-05-04 23:15:13 -07001500 bytes[1] = ins->vex_m | ((~ins->rex & 7) << 5);
H. Peter Anvind85d2502008-05-04 17:53:31 -07001501 bytes[2] = ((ins->rex & REX_W) << (7-3)) |
H. Peter Anvin4d2c38c2008-05-04 23:15:13 -07001502 ((~ins->drexdst & 15)<< 3) | (ins->vex_wlp & 07);
H. Peter Anvind85d2502008-05-04 17:53:31 -07001503 out(offset, segment, &bytes, OUT_RAWDATA, 3, NO_SEG, NO_SEG);
1504 offset += 3;
1505 } else {
1506 bytes[0] = 0xc5;
H. Peter Anvin4d2c38c2008-05-04 23:15:13 -07001507 bytes[1] = ((~ins->rex & REX_R) << (7-2)) |
1508 ((~ins->drexdst & 15) << 3) | (ins->vex_wlp & 07);
H. Peter Anvind85d2502008-05-04 17:53:31 -07001509 out(offset, segment, &bytes, OUT_RAWDATA, 2, NO_SEG, NO_SEG);
1510 offset += 2;
1511 }
1512 break;
1513
H. Peter Anvin507ae032008-10-09 15:37:10 -07001514 case4(0274):
H. Peter Anvinc1377e92008-10-06 23:40:31 -07001515 {
1516 uint64_t uv, um;
1517 int s;
1518
1519 if (ins->rex & REX_W)
1520 s = 64;
1521 else if (ins->prefixes[PPS_OSIZE] == P_O16)
1522 s = 16;
1523 else if (ins->prefixes[PPS_OSIZE] == P_O32)
1524 s = 32;
1525 else
1526 s = bits;
1527
1528 um = (uint64_t)2 << (s-1);
1529 uv = opx->offset;
1530
1531 if (uv > 127 && uv < (uint64_t)-128 &&
1532 (uv < um-128 || uv > um-1)) {
1533 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
1534 "signed byte value exceeds bounds");
1535 }
1536 if (opx->segment != NO_SEG) {
H. Peter Anvin779ed8b2008-10-16 13:01:43 -07001537 data = uv;
H. Peter Anvinc1377e92008-10-06 23:40:31 -07001538 out(offset, segment, &data, OUT_ADDRESS, 1,
1539 opx->segment, opx->wrt);
1540 } else {
H. Peter Anvin779ed8b2008-10-16 13:01:43 -07001541 bytes[0] = uv;
H. Peter Anvinc1377e92008-10-06 23:40:31 -07001542 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
1543 NO_SEG);
1544 }
1545 offset += 1;
1546 break;
1547 }
1548
H. Peter Anvin507ae032008-10-09 15:37:10 -07001549 case4(0300):
H. Peter Anvine2c80182005-01-15 22:15:51 +00001550 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001551
H. Peter Anvine2c80182005-01-15 22:15:51 +00001552 case 0310:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001553 if (bits == 32 && !has_prefix(ins, PPS_ASIZE, P_A16)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001554 *bytes = 0x67;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001555 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001556 offset += 1;
1557 } else
1558 offset += 0;
1559 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001560
H. Peter Anvine2c80182005-01-15 22:15:51 +00001561 case 0311:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001562 if (bits != 32 && !has_prefix(ins, PPS_ASIZE, P_A32)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001563 *bytes = 0x67;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001564 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001565 offset += 1;
1566 } else
1567 offset += 0;
1568 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001569
H. Peter Anvine2c80182005-01-15 22:15:51 +00001570 case 0312:
1571 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001572
Keith Kaniosb7a89542007-04-12 02:40:54 +00001573 case 0313:
1574 ins->rex = 0;
1575 break;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07001576
H. Peter Anvin507ae032008-10-09 15:37:10 -07001577 case4(0314):
H. Peter Anvin23440102007-11-12 21:02:33 -08001578 break;
1579
H. Peter Anvine2c80182005-01-15 22:15:51 +00001580 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001581 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001582 *bytes = 0x66;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001583 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001584 offset += 1;
1585 } else
1586 offset += 0;
1587 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001588
H. Peter Anvine2c80182005-01-15 22:15:51 +00001589 case 0321:
1590 if (bits == 16) {
1591 *bytes = 0x66;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001592 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001593 offset += 1;
1594 } else
1595 offset += 0;
1596 break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001597
H. Peter Anvine2c80182005-01-15 22:15:51 +00001598 case 0322:
H. Peter Anvin70653092007-10-19 14:42:29 -07001599 case 0323:
1600 break;
1601
Keith Kaniosb7a89542007-04-12 02:40:54 +00001602 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001603 ins->rex |= REX_W;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001604 break;
H. Peter Anvin70653092007-10-19 14:42:29 -07001605
H. Peter Anvine2c80182005-01-15 22:15:51 +00001606 case 0330:
1607 *bytes = *codes++ ^ condval[ins->condition];
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001608 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001609 offset += 1;
1610 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001611
H. Peter Anvine2c80182005-01-15 22:15:51 +00001612 case 0331:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001613 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001614
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001615 case 0332:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001616 case 0333:
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001617 *bytes = c - 0332 + 0xF2;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001618 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001619 offset += 1;
1620 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001621
Keith Kanios48af1772007-08-17 07:37:52 +00001622 case 0334:
1623 if (ins->rex & REX_R) {
1624 *bytes = 0xF0;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001625 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
Keith Kanios48af1772007-08-17 07:37:52 +00001626 offset += 1;
1627 }
1628 ins->rex &= ~(REX_L|REX_R);
1629 break;
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001630
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001631 case 0335:
1632 break;
1633
H. Peter Anvin962e3052008-08-28 17:47:16 -07001634 case 0336:
1635 case 0337:
1636 break;
1637
H. Peter Anvine2c80182005-01-15 22:15:51 +00001638 case 0340:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001639 if (ins->oprs[0].segment != NO_SEG)
1640 errfunc(ERR_PANIC, "non-constant BSS size in pass two");
1641 else {
H. Peter Anvin428fd672007-11-15 10:25:52 -08001642 int64_t size = ins->oprs[0].offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001643 if (size > 0)
1644 out(offset, segment, NULL,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001645 OUT_RESERVE, size, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001646 offset += size;
1647 }
1648 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001649
H. Peter Anvinff6e12d2008-10-08 21:17:32 -07001650 case 0344:
1651 case 0345:
1652 bytes[0] = c & 1;
1653 switch (ins->oprs[0].basereg) {
1654 case R_CS:
1655 bytes[0] += 0x0E;
1656 break;
1657 case R_DS:
1658 bytes[0] += 0x1E;
1659 break;
1660 case R_ES:
1661 bytes[0] += 0x06;
1662 break;
1663 case R_SS:
1664 bytes[0] += 0x16;
1665 break;
1666 default:
1667 errfunc(ERR_PANIC,
1668 "bizarre 8086 segment register received");
1669 }
1670 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1671 offset++;
1672 break;
1673
1674 case 0346:
1675 case 0347:
1676 bytes[0] = c & 1;
1677 switch (ins->oprs[0].basereg) {
1678 case R_FS:
1679 bytes[0] += 0xA0;
1680 break;
1681 case R_GS:
1682 bytes[0] += 0xA8;
1683 break;
1684 default:
1685 errfunc(ERR_PANIC,
1686 "bizarre 386 segment register received");
1687 }
1688 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1689 offset++;
1690 break;
1691
H. Peter Anvinfff5a472008-05-20 09:46:24 -07001692 case 0360:
1693 break;
1694
1695 case 0361:
1696 bytes[0] = 0x66;
1697 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1698 offset += 1;
1699 break;
1700
1701 case 0362:
1702 case 0363:
1703 bytes[0] = c - 0362 + 0xf2;
1704 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1705 offset += 1;
1706 break;
1707
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001708 case 0364:
1709 case 0365:
1710 break;
1711
Keith Kanios48af1772007-08-17 07:37:52 +00001712 case 0366:
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001713 case 0367:
1714 *bytes = c - 0366 + 0x66;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001715 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
Keith Kanios48af1772007-08-17 07:37:52 +00001716 offset += 1;
1717 break;
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001718
H. Peter Anvine2c80182005-01-15 22:15:51 +00001719 case 0370:
1720 case 0371:
1721 case 0372:
1722 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001723
H. Peter Anvine2c80182005-01-15 22:15:51 +00001724 case 0373:
1725 *bytes = bits == 16 ? 3 : 5;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001726 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001727 offset += 1;
1728 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001729
H. Peter Anvin507ae032008-10-09 15:37:10 -07001730 case4(0100):
1731 case4(0110):
1732 case4(0120):
1733 case4(0130):
1734 case4(0200):
1735 case4(0204):
1736 case4(0210):
1737 case4(0214):
1738 case4(0220):
1739 case4(0224):
1740 case4(0230):
1741 case4(0234):
1742 {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001743 ea ea_data;
1744 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001745 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001746 uint8_t *p;
1747 int32_t s;
H. Peter Anvin9f817132008-10-06 19:11:07 -07001748 enum out_type type;
H. Peter Anvin70653092007-10-19 14:42:29 -07001749
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001750 if (c <= 0177) {
1751 /* pick rfield from operand b */
1752 rflags = regflag(&ins->oprs[c & 7]);
H. Peter Anvina4835d42008-05-20 14:21:29 -07001753 rfield = nasm_regvals[ins->oprs[c & 7].basereg];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001754 } else {
1755 /* rfield is constant */
1756 rflags = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001757 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001758 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001759
1760 if (!process_ea
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001761 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001762 ins->addr_size, rfield, rflags)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001763 errfunc(ERR_NONFATAL, "invalid effective address");
1764 }
H. Peter Anvin70653092007-10-19 14:42:29 -07001765
Charles Crayne7e975552007-11-03 22:06:13 -07001766
H. Peter Anvine2c80182005-01-15 22:15:51 +00001767 p = bytes;
1768 *p++ = ea_data.modrm;
1769 if (ea_data.sib_present)
1770 *p++ = ea_data.sib;
1771
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001772 /* DREX suffixes come between the SIB and the displacement */
1773 if (ins->rex & REX_D) {
1774 *p++ =
1775 (ins->drexdst << 4) |
1776 (ins->rex & REX_OC ? 0x08 : 0) |
1777 (ins->rex & (REX_R|REX_X|REX_B));
1778 ins->rex = 0;
1779 }
1780
H. Peter Anvine2c80182005-01-15 22:15:51 +00001781 s = p - bytes;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001782 out(offset, segment, bytes, OUT_RAWDATA, s, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001783
Victor van den Elzencf9332c2008-10-01 12:18:28 +02001784 /*
1785 * Make sure the address gets the right offset in case
1786 * the line breaks in the .lst file (BR 1197827)
1787 */
1788 offset += s;
1789 s = 0;
1790
H. Peter Anvine2c80182005-01-15 22:15:51 +00001791 switch (ea_data.bytes) {
1792 case 0:
1793 break;
1794 case 1:
1795 if (ins->oprs[(c >> 3) & 7].segment != NO_SEG) {
1796 data = ins->oprs[(c >> 3) & 7].offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001797 out(offset, segment, &data, OUT_ADDRESS, 1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001798 ins->oprs[(c >> 3) & 7].segment,
1799 ins->oprs[(c >> 3) & 7].wrt);
1800 } else {
1801 *bytes = ins->oprs[(c >> 3) & 7].offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001802 out(offset, segment, bytes, OUT_RAWDATA, 1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001803 NO_SEG, NO_SEG);
1804 }
1805 s++;
1806 break;
H. Peter Anvin70653092007-10-19 14:42:29 -07001807 case 8:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001808 case 2:
1809 case 4:
1810 data = ins->oprs[(c >> 3) & 7].offset;
H. Peter Anvinb21141a2008-10-23 20:49:09 -07001811 warn_overflow(ea_data.bytes, &ins->oprs[(c >> 3) & 7]);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001812 s += ea_data.bytes;
H. Peter Anvin9f817132008-10-06 19:11:07 -07001813 if (ea_data.rip) {
H. Peter Anvine286c7e2008-10-22 11:15:00 -07001814 if (ins->oprs[(c >> 3) & 7].segment == segment) {
1815 data -= insn_end;
1816 out(offset, segment, &data,
1817 OUT_ADDRESS, ea_data.bytes,
1818 NO_SEG, NO_SEG);
1819 } else {
1820 out(offset, segment, &data,
1821 OUT_REL4ADR, insn_end - offset,
1822 ins->oprs[(c >> 3) & 7].segment,
1823 ins->oprs[(c >> 3) & 7].wrt);
1824 }
H. Peter Anvin9f817132008-10-06 19:11:07 -07001825 } else {
1826 type = OUT_ADDRESS;
H. Peter Anvin0a20bcf2008-10-17 23:29:11 -07001827 out(offset, segment, &data,
1828 OUT_ADDRESS, ea_data.bytes,
1829 ins->oprs[(c >> 3) & 7].segment,
1830 ins->oprs[(c >> 3) & 7].wrt);
H. Peter Anvin9f817132008-10-06 19:11:07 -07001831 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001832 break;
1833 }
1834 offset += s;
H. Peter Anvin839eca22007-10-29 23:12:47 -07001835 }
H. Peter Anvin507ae032008-10-09 15:37:10 -07001836 break;
1837
1838 default:
1839 errfunc(ERR_PANIC, "internal instruction table corrupt"
1840 ": instruction code 0x%02X given", c);
1841 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001842 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001843 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001844}
1845
H. Peter Anvin0ec60e62007-07-07 01:59:52 +00001846static int32_t regflag(const operand * o)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001847{
1848 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1849 errfunc(ERR_PANIC, "invalid operand passed to regflag()");
1850 }
H. Peter Anvina4835d42008-05-20 14:21:29 -07001851 return nasm_reg_flags[o->basereg];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001852}
1853
H. Peter Anvin5b0e3ec2007-07-07 02:01:08 +00001854static int32_t regval(const operand * o)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001855{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001856 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1857 errfunc(ERR_PANIC, "invalid operand passed to regval()");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001858 }
H. Peter Anvina4835d42008-05-20 14:21:29 -07001859 return nasm_regvals[o->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001860}
1861
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001862static int op_rexflags(const operand * o, int mask)
1863{
1864 int32_t flags;
1865 int val;
1866
1867 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1868 errfunc(ERR_PANIC, "invalid operand passed to op_rexflags()");
1869 }
1870
H. Peter Anvina4835d42008-05-20 14:21:29 -07001871 flags = nasm_reg_flags[o->basereg];
1872 val = nasm_regvals[o->basereg];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001873
1874 return rexflags(val, flags, mask);
1875}
1876
1877static int rexflags(int val, int32_t flags, int mask)
1878{
1879 int rex = 0;
1880
1881 if (val >= 8)
1882 rex |= REX_B|REX_X|REX_R;
1883 if (flags & BITS64)
1884 rex |= REX_W;
1885 if (!(REG_HIGH & ~flags)) /* AH, CH, DH, BH */
1886 rex |= REX_H;
1887 else if (!(REG8 & ~flags) && val >= 4) /* SPL, BPL, SIL, DIL */
1888 rex |= REX_P;
1889
1890 return rex & mask;
1891}
1892
H. Peter Anvin3360d792007-09-11 04:16:57 +00001893static int matches(const struct itemplate *itemp, insn * instruction, int bits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001894{
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001895 int i, size[MAX_OPERANDS], asize, oprs, ret;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001896
1897 ret = 100;
1898
1899 /*
1900 * Check the opcode
1901 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001902 if (itemp->opcode != instruction->opcode)
1903 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001904
1905 /*
1906 * Count the operands
1907 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001908 if (itemp->operands != instruction->operands)
1909 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001910
1911 /*
1912 * Check that no spurious colons or TOs are present
1913 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001914 for (i = 0; i < itemp->operands; i++)
1915 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON | TO))
1916 return 0;
H. Peter Anvin70653092007-10-19 14:42:29 -07001917
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001918 /*
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001919 * Process size flags
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001920 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001921 if (itemp->flags & IF_ARMASK) {
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001922 memset(size, 0, sizeof size);
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001923
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001924 i = ((itemp->flags & IF_ARMASK) >> IF_ARSHFT) - 1;
1925
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001926 switch (itemp->flags & IF_SMASK) {
1927 case IF_SB:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001928 size[i] = BITS8;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001929 break;
1930 case IF_SW:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001931 size[i] = BITS16;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001932 break;
1933 case IF_SD:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001934 size[i] = BITS32;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001935 break;
1936 case IF_SQ:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001937 size[i] = BITS64;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001938 break;
H. Peter Anvin41c9f6f2007-09-18 13:01:32 -07001939 case IF_SO:
1940 size[i] = BITS128;
1941 break;
H. Peter Anvindfb91802008-05-20 11:43:53 -07001942 case IF_SY:
1943 size[i] = BITS256;
1944 break;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001945 case IF_SZ:
1946 switch (bits) {
1947 case 16:
1948 size[i] = BITS16;
1949 break;
1950 case 32:
1951 size[i] = BITS32;
1952 break;
1953 case 64:
1954 size[i] = BITS64;
1955 break;
1956 }
1957 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001958 default:
1959 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001960 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001961 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001962 asize = 0;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001963 switch (itemp->flags & IF_SMASK) {
1964 case IF_SB:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001965 asize = BITS8;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001966 break;
1967 case IF_SW:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001968 asize = BITS16;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001969 break;
1970 case IF_SD:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001971 asize = BITS32;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001972 break;
1973 case IF_SQ:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001974 asize = BITS64;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001975 break;
H. Peter Anvin41c9f6f2007-09-18 13:01:32 -07001976 case IF_SO:
1977 asize = BITS128;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001978 break;
H. Peter Anvindfb91802008-05-20 11:43:53 -07001979 case IF_SY:
1980 asize = BITS256;
1981 break;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001982 case IF_SZ:
1983 switch (bits) {
1984 case 16:
1985 asize = BITS16;
1986 break;
1987 case 32:
1988 asize = BITS32;
1989 break;
1990 case 64:
1991 asize = BITS64;
1992 break;
1993 }
H. Peter Anvin41c9f6f2007-09-18 13:01:32 -07001994 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001995 default:
1996 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001997 }
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001998 for (i = 0; i < MAX_OPERANDS; i++)
1999 size[i] = asize;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002000 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002001
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002002 /*
2003 * Check that the operand flags all match up
2004 */
2005 for (i = 0; i < itemp->operands; i++) {
2006 int32_t type = instruction->oprs[i].type;
2007 if (!(type & SIZE_MASK))
2008 type |= size[i];
H. Peter Anvind85d2502008-05-04 17:53:31 -07002009
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002010 if (itemp->opd[i] & SAME_AS) {
2011 int j = itemp->opd[i] & ~SAME_AS;
2012 if (type != instruction->oprs[j].type ||
2013 instruction->oprs[i].basereg != instruction->oprs[j].basereg)
2014 return 0;
2015 } else if (itemp->opd[i] & ~type ||
2016 ((itemp->opd[i] & SIZE_MASK) &&
2017 ((itemp->opd[i] ^ type) & SIZE_MASK))) {
2018 if ((itemp->opd[i] & ~type & ~SIZE_MASK) ||
2019 (type & SIZE_MASK))
2020 return 0;
2021 else
2022 return 1;
2023 }
2024 }
2025
2026 /*
2027 * Check operand sizes
2028 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002029 if (itemp->flags & (IF_SM | IF_SM2)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002030 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
2031 asize = 0;
2032 for (i = 0; i < oprs; i++) {
2033 if ((asize = itemp->opd[i] & SIZE_MASK) != 0) {
2034 int j;
2035 for (j = 0; j < oprs; j++)
2036 size[j] = asize;
2037 break;
2038 }
2039 }
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002040 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002041 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002042 }
2043
Keith Kaniosb7a89542007-04-12 02:40:54 +00002044 for (i = 0; i < itemp->operands; i++) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002045 if (!(itemp->opd[i] & SIZE_MASK) &&
2046 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvine2c80182005-01-15 22:15:51 +00002047 return 2;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002048 }
2049
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002050 /*
2051 * Check template is okay at the set cpu level
2052 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002053 if (((itemp->flags & IF_PLEVEL) > cpu))
H. Peter Anvine2c80182005-01-15 22:15:51 +00002054 return 3;
H. Peter Anvin70653092007-10-19 14:42:29 -07002055
Keith Kaniosb7a89542007-04-12 02:40:54 +00002056 /*
2057 * Check if instruction is available in long mode
2058 */
2059 if ((itemp->flags & IF_NOLONG) && (bits == 64))
2060 return 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002061
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002062 /*
2063 * Check if special handling needed for Jumps
2064 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002065 if ((uint8_t)(itemp->code[0]) >= 0370)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002066 return 99;
2067
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002068 return ret;
2069}
2070
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002071static ea *process_ea(operand * input, ea * output, int bits,
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07002072 int addrbits, int rfield, int32_t rflags)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002073{
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07002074 bool forw_ref = !!(input->opflags & OPFLAG_FORWARD);
2075
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002076 output->rip = false;
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00002077
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002078 /* REX flags for the rfield operand */
2079 output->rex |= rexflags(rfield, rflags, REX_R|REX_P|REX_W|REX_H);
2080
Keith Kaniosb7a89542007-04-12 02:40:54 +00002081 if (!(REGISTER & ~input->type)) { /* register direct */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002082 int i;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002083 int32_t f;
2084
2085 if (input->basereg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002086 || input->basereg >= REG_ENUM_LIMIT)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002087 return NULL;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002088 f = regflag(input);
H. Peter Anvina4835d42008-05-20 14:21:29 -07002089 i = nasm_regvals[input->basereg];
Keith Kaniosb7a89542007-04-12 02:40:54 +00002090
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002091 if (REG_EA & ~f)
2092 return NULL; /* Invalid EA register */
H. Peter Anvin70653092007-10-19 14:42:29 -07002093
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002094 output->rex |= op_rexflags(input, REX_B|REX_P|REX_W|REX_H);
2095
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002096 output->sib_present = false; /* no SIB necessary */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002097 output->bytes = 0; /* no offset necessary either */
2098 output->modrm = 0xC0 | ((rfield & 7) << 3) | (i & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002099 } else { /* it's a memory reference */
2100 if (input->basereg == -1
2101 && (input->indexreg == -1 || input->scale == 0)) {
2102 /* it's a pure offset */
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002103 if (bits == 64 && (~input->type & IP_REL)) {
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002104 int scale, index, base;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002105 output->sib_present = true;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002106 scale = 0;
2107 index = 4;
2108 base = 5;
2109 output->sib = (scale << 6) | (index << 3) | base;
2110 output->bytes = 4;
2111 output->modrm = 4 | ((rfield & 7) << 3);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002112 output->rip = false;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002113 } else {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002114 output->sib_present = false;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002115 output->bytes = (addrbits != 16 ? 4 : 2);
2116 output->modrm = (addrbits != 16 ? 5 : 6) | ((rfield & 7) << 3);
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002117 output->rip = bits == 64;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002118 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002119 } else { /* it's an indirection */
2120 int i = input->indexreg, b = input->basereg, s = input->scale;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002121 int32_t o = input->offset, seg = input->segment;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002122 int hb = input->hintbase, ht = input->hinttype;
2123 int t;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002124 int it, bt;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002125 int32_t ix, bx; /* register flags */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002126
H. Peter Anvine2c80182005-01-15 22:15:51 +00002127 if (s == 0)
2128 i = -1; /* make this easy, at least */
H. Peter Anvin70653092007-10-19 14:42:29 -07002129
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002130 if (i >= EXPR_REG_START && i < REG_ENUM_LIMIT) {
H. Peter Anvina4835d42008-05-20 14:21:29 -07002131 it = nasm_regvals[i];
2132 ix = nasm_reg_flags[i];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002133 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00002134 it = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002135 ix = 0;
2136 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002137
H. Peter Anvinb0c54622007-10-28 23:21:46 -07002138 if (b >= EXPR_REG_START && b < REG_ENUM_LIMIT) {
H. Peter Anvina4835d42008-05-20 14:21:29 -07002139 bt = nasm_regvals[b];
2140 bx = nasm_reg_flags[b];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002141 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00002142 bt = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002143 bx = 0;
2144 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002145
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002146 /* check for a 32/64-bit memory reference... */
2147 if ((ix|bx) & (BITS32|BITS64)) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00002148 /* it must be a 32/64-bit memory reference. Firstly we have
2149 * to check that all registers involved are type E/Rxx. */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002150 int32_t sok = BITS32|BITS64;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002151
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002152 if (it != -1) {
2153 if (!(REG64 & ~ix) || !(REG32 & ~ix))
2154 sok &= ix;
2155 else
2156 return NULL;
2157 }
2158
2159 if (bt != -1) {
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00002160 if (REG_GPR & ~bx)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002161 return NULL; /* Invalid register */
H. Peter Anvina57e8d42007-05-30 03:44:02 +00002162 if (~sok & bx & SIZE_MASK)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002163 return NULL; /* Invalid size */
H. Peter Anvinb0c54622007-10-28 23:21:46 -07002164 sok &= bx;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002165 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002166
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002167 /* While we're here, ensure the user didn't specify
2168 WORD or QWORD. */
2169 if (input->disp_size == 16 || input->disp_size == 64)
2170 return NULL;
2171
2172 if (addrbits == 16 ||
2173 (addrbits == 32 && !(sok & BITS32)) ||
2174 (addrbits == 64 && !(sok & BITS64)))
2175 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002176
Keith Kaniosb7a89542007-04-12 02:40:54 +00002177 /* now reorganize base/index */
2178 if (s == 1 && bt != it && bt != -1 && it != -1 &&
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002179 ((hb == b && ht == EAH_NOTBASE)
2180 || (hb == i && ht == EAH_MAKEBASE))) {
2181 /* swap if hints say so */
2182 t = bt, bt = it, it = t;
2183 t = bx, bx = ix, ix = t;
2184 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00002185 if (bt == it) /* convert EAX+2*EAX to 3*EAX */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002186 bt = -1, bx = 0, s++;
2187 if (bt == -1 && s == 1 && !(hb == it && ht == EAH_NOTBASE)) {
2188 /* make single reg base, unless hint */
2189 bt = it, bx = ix, it = -1, ix = 0;
2190 }
H. Peter Anvinf5843c62007-09-10 18:59:26 +00002191 if (((s == 2 && it != REG_NUM_ESP
H. Peter Anvine2c80182005-01-15 22:15:51 +00002192 && !(input->eaflags & EAF_TIMESTWO)) || s == 3
Keith Kaniosb7a89542007-04-12 02:40:54 +00002193 || s == 5 || s == 9) && bt == -1)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002194 bt = it, bx = ix, s--; /* convert 3*EAX to EAX+2*EAX */
Keith Kanios48af1772007-08-17 07:37:52 +00002195 if (it == -1 && (bt & 7) != REG_NUM_ESP
H. Peter Anvine2c80182005-01-15 22:15:51 +00002196 && (input->eaflags & EAF_TIMESTWO))
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002197 it = bt, ix = bx, bt = -1, bx = 0, s = 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002198 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
Keith Kanios48af1772007-08-17 07:37:52 +00002199 if (s == 1 && it == REG_NUM_ESP) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002200 /* swap ESP into base if scale is 1 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002201 t = it, it = bt, bt = t;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002202 t = ix, ix = bx, bx = t;
2203 }
Keith Kanios48af1772007-08-17 07:37:52 +00002204 if (it == REG_NUM_ESP
Keith Kaniosb7a89542007-04-12 02:40:54 +00002205 || (s != 1 && s != 2 && s != 4 && s != 8 && it != -1))
H. Peter Anvine2c80182005-01-15 22:15:51 +00002206 return NULL; /* wrong, for various reasons */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002207
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002208 output->rex |= rexflags(it, ix, REX_X);
2209 output->rex |= rexflags(bt, bx, REX_B);
Keith Kaniosb7a89542007-04-12 02:40:54 +00002210
Keith Kanios48af1772007-08-17 07:37:52 +00002211 if (it == -1 && (bt & 7) != REG_NUM_ESP) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002212 /* no SIB needed */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002213 int mod, rm;
H. Peter Anvin70653092007-10-19 14:42:29 -07002214
Keith Kaniosb7a89542007-04-12 02:40:54 +00002215 if (bt == -1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002216 rm = 5;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002217 mod = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002218 } else {
2219 rm = (bt & 7);
Keith Kanios48af1772007-08-17 07:37:52 +00002220 if (rm != REG_NUM_EBP && o == 0 &&
Keith Kaniosb7a89542007-04-12 02:40:54 +00002221 seg == NO_SEG && !forw_ref &&
2222 !(input->eaflags &
2223 (EAF_BYTEOFFS | EAF_WORDOFFS)))
2224 mod = 0;
2225 else if (input->eaflags & EAF_BYTEOFFS ||
2226 (o >= -128 && o <= 127 && seg == NO_SEG
2227 && !forw_ref
2228 && !(input->eaflags & EAF_WORDOFFS)))
2229 mod = 1;
2230 else
2231 mod = 2;
2232 }
H. Peter Anvinea838272002-04-30 20:51:53 +00002233
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002234 output->sib_present = false;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002235 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
2236 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002237 } else {
2238 /* we need a SIB */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002239 int mod, scale, index, base;
H. Peter Anvin70653092007-10-19 14:42:29 -07002240
Keith Kaniosb7a89542007-04-12 02:40:54 +00002241 if (it == -1)
2242 index = 4, s = 1;
2243 else
2244 index = (it & 7);
H. Peter Anvin70653092007-10-19 14:42:29 -07002245
H. Peter Anvine2c80182005-01-15 22:15:51 +00002246 switch (s) {
2247 case 1:
2248 scale = 0;
2249 break;
2250 case 2:
2251 scale = 1;
2252 break;
2253 case 4:
2254 scale = 2;
2255 break;
2256 case 8:
2257 scale = 3;
2258 break;
2259 default: /* then what the smeg is it? */
2260 return NULL; /* panic */
2261 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002262
Keith Kaniosb7a89542007-04-12 02:40:54 +00002263 if (bt == -1) {
2264 base = 5;
2265 mod = 0;
2266 } else {
2267 base = (bt & 7);
Keith Kanios48af1772007-08-17 07:37:52 +00002268 if (base != REG_NUM_EBP && o == 0 &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00002269 seg == NO_SEG && !forw_ref &&
2270 !(input->eaflags &
Keith Kaniosb7a89542007-04-12 02:40:54 +00002271 (EAF_BYTEOFFS | EAF_WORDOFFS)))
2272 mod = 0;
2273 else if (input->eaflags & EAF_BYTEOFFS ||
2274 (o >= -128 && o <= 127 && seg == NO_SEG
2275 && !forw_ref
2276 && !(input->eaflags & EAF_WORDOFFS)))
2277 mod = 1;
2278 else
2279 mod = 2;
2280 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002281
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002282 output->sib_present = true;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002283 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
2284 output->modrm = (mod << 6) | ((rfield & 7) << 3) | 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002285 output->sib = (scale << 6) | (index << 3) | base;
2286 }
2287 } else { /* it's 16-bit */
2288 int mod, rm;
H. Peter Anvin70653092007-10-19 14:42:29 -07002289
Keith Kaniosb7a89542007-04-12 02:40:54 +00002290 /* check for 64-bit long mode */
2291 if (addrbits == 64)
2292 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002293
H. Peter Anvine2c80182005-01-15 22:15:51 +00002294 /* check all registers are BX, BP, SI or DI */
2295 if ((b != -1 && b != R_BP && b != R_BX && b != R_SI
2296 && b != R_DI) || (i != -1 && i != R_BP && i != R_BX
2297 && i != R_SI && i != R_DI))
2298 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002299
Keith Kaniosb7a89542007-04-12 02:40:54 +00002300 /* ensure the user didn't specify DWORD/QWORD */
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002301 if (input->disp_size == 32 || input->disp_size == 64)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002302 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002303
H. Peter Anvine2c80182005-01-15 22:15:51 +00002304 if (s != 1 && i != -1)
2305 return NULL; /* no can do, in 16-bit EA */
2306 if (b == -1 && i != -1) {
2307 int tmp = b;
2308 b = i;
2309 i = tmp;
2310 } /* swap */
2311 if ((b == R_SI || b == R_DI) && i != -1) {
2312 int tmp = b;
2313 b = i;
2314 i = tmp;
2315 }
2316 /* have BX/BP as base, SI/DI index */
2317 if (b == i)
2318 return NULL; /* shouldn't ever happen, in theory */
2319 if (i != -1 && b != -1 &&
2320 (i == R_BP || i == R_BX || b == R_SI || b == R_DI))
2321 return NULL; /* invalid combinations */
2322 if (b == -1) /* pure offset: handled above */
2323 return NULL; /* so if it gets to here, panic! */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002324
H. Peter Anvine2c80182005-01-15 22:15:51 +00002325 rm = -1;
2326 if (i != -1)
2327 switch (i * 256 + b) {
2328 case R_SI * 256 + R_BX:
2329 rm = 0;
2330 break;
2331 case R_DI * 256 + R_BX:
2332 rm = 1;
2333 break;
2334 case R_SI * 256 + R_BP:
2335 rm = 2;
2336 break;
2337 case R_DI * 256 + R_BP:
2338 rm = 3;
2339 break;
2340 } else
2341 switch (b) {
2342 case R_SI:
2343 rm = 4;
2344 break;
2345 case R_DI:
2346 rm = 5;
2347 break;
2348 case R_BP:
2349 rm = 6;
2350 break;
2351 case R_BX:
2352 rm = 7;
2353 break;
2354 }
2355 if (rm == -1) /* can't happen, in theory */
2356 return NULL; /* so panic if it does */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002357
H. Peter Anvine2c80182005-01-15 22:15:51 +00002358 if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
2359 !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
2360 mod = 0;
2361 else if (input->eaflags & EAF_BYTEOFFS ||
2362 (o >= -128 && o <= 127 && seg == NO_SEG
2363 && !forw_ref
2364 && !(input->eaflags & EAF_WORDOFFS)))
2365 mod = 1;
2366 else
2367 mod = 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002368
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002369 output->sib_present = false; /* no SIB - it's 16-bit */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002370 output->bytes = mod; /* bytes of offset needed */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002371 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002372 }
2373 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002374 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002375
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002376 output->size = 1 + output->sib_present + output->bytes;
2377 return output;
2378}
2379
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002380static void add_asp(insn *ins, int addrbits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002381{
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002382 int j, valid;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002383 int defdisp;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002384
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002385 valid = (addrbits == 64) ? 64|32 : 32|16;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002386
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002387 switch (ins->prefixes[PPS_ASIZE]) {
2388 case P_A16:
2389 valid &= 16;
2390 break;
2391 case P_A32:
2392 valid &= 32;
2393 break;
2394 case P_A64:
2395 valid &= 64;
2396 break;
2397 case P_ASP:
2398 valid &= (addrbits == 32) ? 16 : 32;
2399 break;
2400 default:
2401 break;
2402 }
2403
2404 for (j = 0; j < ins->operands; j++) {
2405 if (!(MEMORY & ~ins->oprs[j].type)) {
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002406 int32_t i, b;
H. Peter Anvin70653092007-10-19 14:42:29 -07002407
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002408 /* Verify as Register */
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002409 if (ins->oprs[j].indexreg < EXPR_REG_START
2410 || ins->oprs[j].indexreg >= REG_ENUM_LIMIT)
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002411 i = 0;
2412 else
H. Peter Anvina4835d42008-05-20 14:21:29 -07002413 i = nasm_reg_flags[ins->oprs[j].indexreg];
H. Peter Anvin70653092007-10-19 14:42:29 -07002414
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002415 /* Verify as Register */
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002416 if (ins->oprs[j].basereg < EXPR_REG_START
2417 || ins->oprs[j].basereg >= REG_ENUM_LIMIT)
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002418 b = 0;
2419 else
H. Peter Anvina4835d42008-05-20 14:21:29 -07002420 b = nasm_reg_flags[ins->oprs[j].basereg];
H. Peter Anvin70653092007-10-19 14:42:29 -07002421
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002422 if (ins->oprs[j].scale == 0)
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002423 i = 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002424
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002425 if (!i && !b) {
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002426 int ds = ins->oprs[j].disp_size;
2427 if ((addrbits != 64 && ds > 8) ||
2428 (addrbits == 64 && ds == 16))
2429 valid &= ds;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002430 } else {
2431 if (!(REG16 & ~b))
2432 valid &= 16;
2433 if (!(REG32 & ~b))
2434 valid &= 32;
2435 if (!(REG64 & ~b))
2436 valid &= 64;
H. Peter Anvin70653092007-10-19 14:42:29 -07002437
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002438 if (!(REG16 & ~i))
2439 valid &= 16;
2440 if (!(REG32 & ~i))
2441 valid &= 32;
2442 if (!(REG64 & ~i))
2443 valid &= 64;
2444 }
2445 }
2446 }
2447
2448 if (valid & addrbits) {
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002449 ins->addr_size = addrbits;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002450 } else if (valid & ((addrbits == 32) ? 16 : 32)) {
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002451 /* Add an address size prefix */
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002452 enum prefixes pref = (addrbits == 32) ? P_A16 : P_A32;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002453 ins->prefixes[PPS_ASIZE] = pref;
2454 ins->addr_size = (addrbits == 32) ? 16 : 32;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002455 } else {
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002456 /* Impossible... */
2457 errfunc(ERR_NONFATAL, "impossible combination of address sizes");
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002458 ins->addr_size = addrbits; /* Error recovery */
2459 }
2460
2461 defdisp = ins->addr_size == 16 ? 16 : 32;
2462
2463 for (j = 0; j < ins->operands; j++) {
2464 if (!(MEM_OFFS & ~ins->oprs[j].type) &&
2465 (ins->oprs[j].disp_size ? ins->oprs[j].disp_size : defdisp)
2466 != ins->addr_size) {
2467 /* mem_offs sizes must match the address size; if not,
2468 strip the MEM_OFFS bit and match only EA instructions */
2469 ins->oprs[j].type &= ~(MEM_OFFS & ~MEMORY);
2470 }
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002471 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002472}