blob: 1ed78bbf877aeb976b3e210d1616e814a302adce [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
11 * \4, \6 - the POP/PUSH (respectively) codes for CS, DS, ES, SS
12 * (POP is never used for CS) depending on operand 0
13 * \5, \7 - the second byte of POP/PUSH codes for FS, GS, depending
14 * on operand 0
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070015 * \10..\13 - a literal byte follows in the code stream, to be added
16 * to the register value of operand 0..3
17 * \14..\17 - a signed byte immediate operand, from operand 0..3
18 * \20..\23 - a byte immediate operand, from operand 0..3
19 * \24..\27 - an unsigned byte immediate operand, from operand 0..3
20 * \30..\33 - a word immediate operand, from operand 0..3
21 * \34..\37 - select between \3[0-3] and \4[0-3] depending on 16/32 bit
H. Peter Anvin3ba46772002-05-27 23:19:35 +000022 * assembly mode or the operand-size override on the operand
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070023 * \40..\43 - a long immediate operand, from operand 0..3
24 * \44..\47 - select between \3[0-3], \4[0-3] and \5[4-7]
H. Peter Anvinde4b89b2007-10-01 15:41:25 -070025 * depending on the address size of the instruction.
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070026 * \50..\53 - a byte relative operand, from operand 0..3
27 * \54..\57 - a qword immediate operand, from operand 0..3
28 * \60..\63 - a word relative operand, from operand 0..3
29 * \64..\67 - select between \6[0-3] and \7[0-3] depending on 16/32 bit
H. Peter Anvin17799b42002-05-21 03:31:21 +000030 * assembly mode or the operand-size override on the operand
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070031 * \70..\73 - a long relative operand, from operand 0..3
H. Peter Anvinc1377e92008-10-06 23:40:31 -070032 * \74..\77 - a word constant, from the _segment_ part of operand 0..3
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000033 * \1ab - a ModRM, calculated on EA in operand a, with the spare
34 * field the register value of operand b.
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070035 * \140..\143 - an immediate word or signed byte for operand 0..3
H. Peter Anvina30cc072007-11-18 21:55:26 -080036 * \144..\147 - or 2 (s-field) into opcode byte if operand 0..3
37 * is a signed byte rather than a word. Opcode byte follows.
H. Peter Anvinc1377e92008-10-06 23:40:31 -070038 * \150..\153 - an immediate dword or signed byte for operand 0..3
H. Peter Anvina30cc072007-11-18 21:55:26 -080039 * \154..\157 - or 2 (s-field) into opcode byte if operand 0..3
H. Peter Anvin32cd4c22008-04-04 13:34:53 -070040 * is a signed byte rather than a dword. Opcode byte follows.
H. Peter Anvin401c07e2007-09-17 16:55:04 -070041 * \160..\163 - this instruction uses DREX rather than REX, with the
42 * OC0 field set to 0, and the dest field taken from
43 * operand 0..3.
44 * \164..\167 - this instruction uses DREX rather than REX, with the
45 * OC0 field set to 1, and the dest field taken from
46 * operand 0..3.
H. Peter Anvin401c07e2007-09-17 16:55:04 -070047 * \171 - placement of DREX suffix in the absence of an EA
H. Peter Anvind85d2502008-05-04 17:53:31 -070048 * \172\ab - the register number from operand a in bits 7..4, with
H. Peter Anvin52dc3532008-05-20 19:29:04 -070049 * the 4-bit immediate from operand b in bits 3..0.
H. Peter Anvind58656f2008-05-06 20:11:14 -070050 * \173\xab - the register number from operand a in bits 7..4, with
H. Peter Anvin52dc3532008-05-20 19:29:04 -070051 * the value b in bits 3..0.
52 * \174\a - the register number from operand a in bits 7..4, and
53 * an arbitrary value in bits 3..0 (assembled as zero.)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000054 * \2ab - a ModRM, calculated on EA in operand a, with the spare
55 * field equal to digit b.
H. Peter Anvin32cd4c22008-04-04 13:34:53 -070056 * \250..\253 - same as \150..\153, except warn if the 64-bit operand
57 * is not equal to the truncated and sign-extended 32-bit
58 * operand; used for 32-bit immediates in 64-bit mode.
H. Peter Anvind85d2502008-05-04 17:53:31 -070059 * \260..\263 - this instruction uses VEX rather than REX, with the
60 * V field taken from operand 0..3.
61 * \270 - this instruction uses VEX rather than REX, with the
62 * V field set to 1111b.
63 *
64 * VEX prefixes are followed by the sequence:
H. Peter Anvinaaa088f2008-05-12 11:13:41 -070065 * \mm\wlp where mm is the M field; and wlp is:
66 * 00 0ww lpp
H. Peter Anvinbd420c72008-05-22 11:24:35 -070067 * [w0] ww = 0 for W = 0
68 * [w1] ww = 1 for W = 1
69 * [wx] ww = 2 for W don't care (always assembled as 0)
70 * [ww] ww = 3 for W used as REX.W
71 *
H. Peter Anvind85d2502008-05-04 17:53:31 -070072 *
H. Peter Anvinc1377e92008-10-06 23:40:31 -070073 * \274..\277 - a signed byte immediate operand, from operand 0..3,
74 * which is to be extended to the operand size.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000075 * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
76 * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
Keith Kanios48af1772007-08-17 07:37:52 +000077 * \312 - (disassembler only) marker on LOOP, LOOPxx instructions.
H. Peter Anvince2b3972007-05-30 22:21:11 +000078 * \313 - indicates fixed 64-bit address size, 0x67 invalid.
H. Peter Anvin23440102007-11-12 21:02:33 -080079 * \314 - (disassembler only) invalid with REX.B
80 * \315 - (disassembler only) invalid with REX.X
81 * \316 - (disassembler only) invalid with REX.R
82 * \317 - (disassembler only) invalid with REX.W
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000083 * \320 - indicates fixed 16-bit operand size, i.e. optional 0x66.
84 * \321 - indicates fixed 32-bit operand size, i.e. optional 0x66.
85 * \322 - indicates that this instruction is only valid when the
86 * operand size is the default (instruction to disassembler,
87 * generates no code in the assembler)
H. Peter Anvince2b3972007-05-30 22:21:11 +000088 * \323 - indicates fixed 64-bit operand size, REX on extensions only.
Keith Kaniosb7a89542007-04-12 02:40:54 +000089 * \324 - indicates 64-bit operand size requiring REX prefix.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000090 * \330 - a literal byte follows in the code stream, to be added
91 * to the condition code value of the instruction.
Keith Kanios48af1772007-08-17 07:37:52 +000092 * \331 - instruction not valid with REP prefix. Hint for
H. Peter Anvinef7468f2002-04-30 20:57:59 +000093 * disassembler only; for SSE instructions.
H. Peter Anvincb9b6902007-09-12 21:58:51 -070094 * \332 - REP prefix (0xF2 byte) used as opcode extension.
95 * \333 - REP prefix (0xF3 byte) used as opcode extension.
Keith Kanios48af1772007-08-17 07:37:52 +000096 * \334 - LOCK prefix used instead of REX.R
H. Peter Anvincb9b6902007-09-12 21:58:51 -070097 * \335 - disassemble a rep (0xF3 byte) prefix as repe not rep.
H. Peter Anvin962e3052008-08-28 17:47:16 -070098 * \336 - force a REP(E) prefix (0xF2) even if not specified.
99 * \337 - force a REPNE prefix (0xF3) even if not specified.
100 * \336-\337 are still listed as prefixes in the disassembler.
Keith Kaniosb7a89542007-04-12 02:40:54 +0000101 * \340 - reserve <operand 0> bytes of uninitialized storage.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000102 * Operand 0 had better be a segmentless constant.
H. Peter Anvinfff5a472008-05-20 09:46:24 -0700103 * \360 - no SSE prefix (== \364\331)
104 * \361 - 66 SSE prefix (== \366\331)
105 * \362 - F2 SSE prefix (== \364\332)
106 * \363 - F3 SSE prefix (== \364\333)
H. Peter Anvin62cb6062007-09-11 22:44:03 +0000107 * \364 - operand-size prefix (0x66) not permitted
108 * \365 - address-size prefix (0x67) not permitted
109 * \366 - operand-size prefix (0x66) used as opcode extension
110 * \367 - address-size prefix (0x67) used as opcode extension
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000111 * \370,\371,\372 - match only if operand 0 meets byte jump criteria.
112 * 370 is used for Jcc, 371 is used for JMP.
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000113 * \373 - assemble 0x03 if bits==16, 0x05 if bits==32;
114 * used for conditional jump over longer jump
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000115 */
116
H. Peter Anvinfe501952007-10-02 21:53:51 -0700117#include "compiler.h"
118
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000119#include <stdio.h>
120#include <string.h>
Keith Kaniosb7a89542007-04-12 02:40:54 +0000121#include <inttypes.h>
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000122
123#include "nasm.h"
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000124#include "nasmlib.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000125#include "assemble.h"
126#include "insns.h"
H. Peter Anvina4835d42008-05-20 14:21:29 -0700127#include "tables.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000128
H. Peter Anvindfb91802008-05-20 11:43:53 -0700129/* Initialized to zero by the C standard */
130static const uint8_t const_zero_buf[256];
131
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000132typedef struct {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000133 int sib_present; /* is a SIB byte necessary? */
134 int bytes; /* # of bytes of offset needed */
135 int size; /* lazy - this is sib+bytes+1 */
136 uint8_t modrm, sib, rex, rip; /* the bytes themselves */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000137} ea;
138
Keith Kaniosb7a89542007-04-12 02:40:54 +0000139static uint32_t cpu; /* cpu level received from nasm.c */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000140static efunc errfunc;
141static struct ofmt *outfmt;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000142static ListGen *list;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000143
H. Peter Anvin3720f7b2008-05-12 11:00:50 -0700144static int64_t calcsize(int32_t, int64_t, int, insn *, const uint8_t *);
H. Peter Anvin833caea2008-10-04 19:02:30 -0700145static void gencode(int32_t segment, int64_t offset, int bits,
146 insn * ins, const struct itemplate *temp,
147 int64_t insn_end);
H. Peter Anvin3360d792007-09-11 04:16:57 +0000148static int matches(const struct itemplate *, insn *, int bits);
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000149static int32_t regflag(const operand *);
150static int32_t regval(const operand *);
151static int rexflags(int, int32_t, int);
152static int op_rexflags(const operand *, int);
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700153static ea *process_ea(operand *, ea *, int, int, int, int32_t);
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700154static void add_asp(insn *, int);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000155
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700156static int has_prefix(insn * ins, enum prefix_pos pos, enum prefixes prefix)
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000157{
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700158 return ins->prefixes[pos] == prefix;
159}
160
161static void assert_no_prefix(insn * ins, enum prefix_pos pos)
162{
163 if (ins->prefixes[pos])
164 errfunc(ERR_NONFATAL, "invalid %s prefix",
165 prefix_name(ins->prefixes[pos]));
166}
167
168static const char *size_name(int size)
169{
170 switch (size) {
171 case 1:
172 return "byte";
173 case 2:
174 return "word";
175 case 4:
176 return "dword";
177 case 8:
178 return "qword";
179 case 10:
180 return "tword";
181 case 16:
182 return "oword";
H. Peter Anvindfb91802008-05-20 11:43:53 -0700183 case 32:
184 return "yword";
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700185 default:
186 return "???";
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000187 }
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700188}
189
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700190static void warn_overflow(int size, const struct operand *o)
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700191{
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700192 if (size < 8 && o->wrt == NO_SEG && o->segment == NO_SEG) {
Charles Craynedd462c82007-11-04 15:28:30 -0800193 int64_t lim = ((int64_t)1 << (size*8))-1;
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700194 int64_t data = o->offset;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000195
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700196 if (data < ~lim || data > lim)
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700197 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700198 "%s data exceeds bounds", size_name(size));
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700199 }
200}
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000201/*
202 * This routine wrappers the real output format's output routine,
203 * in order to pass a copy of the data off to the listing file
204 * generator at the same time.
205 */
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800206static void out(int64_t offset, int32_t segto, const void *data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800207 enum out_type type, uint64_t size,
208 int32_t segment, int32_t wrt)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000209{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000210 static int32_t lineno = 0; /* static!!! */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000211 static char *lnfname = NULL;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800212 uint8_t p[8];
H. Peter Anvineba20a72002-04-30 20:53:55 +0000213
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800214 if (type == OUT_ADDRESS && segment == NO_SEG && wrt == NO_SEG) {
215 /*
216 * This is a non-relocated address, and we're going to
217 * convert it into RAWDATA format.
218 */
219 uint8_t *q = p;
H. Peter Anvind1fb15c2007-11-13 09:37:59 -0800220
221 if (size > 8) {
222 errfunc(ERR_PANIC, "OUT_ADDRESS with size > 8");
223 return;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800224 }
H. Peter Anvind85d2502008-05-04 17:53:31 -0700225
H. Peter Anvind1fb15c2007-11-13 09:37:59 -0800226 WRITEADDR(q, *(int64_t *)data, size);
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800227 data = p;
228 type = OUT_RAWDATA;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000229 }
230
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800231 list->output(offset, data, type, size);
232
Frank Kotlerabebb082003-09-06 04:45:37 +0000233 /*
234 * this call to src_get determines when we call the
235 * debug-format-specific "linenum" function
236 * it updates lineno and lnfname to the current values
237 * returning 0 if "same as last time", -2 if lnfname
238 * changed, and the amount by which lineno changed,
239 * if it did. thus, these variables must be static
240 */
241
H. Peter Anvine2c80182005-01-15 22:15:51 +0000242 if (src_get(&lineno, &lnfname)) {
243 outfmt->current_dfmt->linenum(lnfname, lineno, segto);
H. Peter Anvince616072002-04-30 21:02:23 +0000244 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000245
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800246 outfmt->output(segto, data, type, size, segment, wrt);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000247}
248
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700249static bool jmp_match(int32_t segment, int64_t offset, int bits,
H. Peter Anvin3720f7b2008-05-12 11:00:50 -0700250 insn * ins, const uint8_t *code)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000251{
Charles Crayne5fbbc8c2007-11-07 19:03:46 -0800252 int64_t isize;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000253 uint8_t c = code[0];
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000254
Charles Craynef1aefd82008-09-30 16:11:32 -0700255 if ((c != 0370 && c != 0371) || (ins->oprs[0].type & STRICT))
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700256 return false;
257 if (!optimizing)
258 return false;
259 if (optimizing < 0 && c == 0371)
260 return false;
261
H. Peter Anvine2c80182005-01-15 22:15:51 +0000262 isize = calcsize(segment, offset, bits, ins, code);
263 if (ins->oprs[0].segment != segment)
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700264 return false;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000265
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700266 isize = ins->oprs[0].offset - offset - isize; /* isize is delta */
267 return (isize >= -128 && isize <= 127); /* is it byte size? */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000268}
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000269
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800270int64_t assemble(int32_t segment, int64_t offset, int bits, uint32_t cp,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000271 insn * instruction, struct ofmt *output, efunc error,
272 ListGen * listgen)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000273{
H. Peter Anvin3360d792007-09-11 04:16:57 +0000274 const struct itemplate *temp;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000275 int j;
276 int size_prob;
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800277 int64_t insn_end;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000278 int32_t itimes;
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800279 int64_t start = offset;
280 int64_t wsize = 0; /* size for DB etc. */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000281
H. Peter Anvine2c80182005-01-15 22:15:51 +0000282 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000283 cpu = cp;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000284 outfmt = output; /* likewise */
285 list = listgen; /* and again */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000286
H. Peter Anvine2c80182005-01-15 22:15:51 +0000287 switch (instruction->opcode) {
288 case -1:
289 return 0;
290 case I_DB:
291 wsize = 1;
292 break;
293 case I_DW:
294 wsize = 2;
295 break;
296 case I_DD:
297 wsize = 4;
298 break;
299 case I_DQ:
300 wsize = 8;
301 break;
302 case I_DT:
303 wsize = 10;
304 break;
H. Peter Anvincfbe7c32007-09-18 17:49:09 -0700305 case I_DO:
306 wsize = 16;
307 break;
H. Peter Anvindfb91802008-05-20 11:43:53 -0700308 case I_DY:
309 wsize = 32;
310 break;
H. Peter Anvin16b0a332007-09-12 20:27:41 -0700311 default:
312 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000313 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000314
H. Peter Anvineba20a72002-04-30 20:53:55 +0000315 if (wsize) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000316 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000317 int32_t t = instruction->times;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000318 if (t < 0)
319 errfunc(ERR_PANIC,
320 "instruction->times < 0 (%ld) in assemble()", t);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000321
H. Peter Anvine2c80182005-01-15 22:15:51 +0000322 while (t--) { /* repeat TIMES times */
323 for (e = instruction->eops; e; e = e->next) {
324 if (e->type == EOT_DB_NUMBER) {
325 if (wsize == 1) {
326 if (e->segment != NO_SEG)
327 errfunc(ERR_NONFATAL,
328 "one-byte relocation attempted");
329 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000330 uint8_t out_byte = e->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000331 out(offset, segment, &out_byte,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800332 OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000333 }
Keith Kanios61ff53c2007-04-14 18:54:52 +0000334 } else if (wsize > 8) {
H. Peter Anvin3be5d852008-05-20 14:49:32 -0700335 errfunc(ERR_NONFATAL,
336 "integer supplied to a DT, DO or DY"
Keith Kanios61ff53c2007-04-14 18:54:52 +0000337 " instruction");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000338 } else
339 out(offset, segment, &e->offset,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800340 OUT_ADDRESS, wsize, e->segment, e->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000341 offset += wsize;
H. Peter Anvin518df302008-06-14 16:53:48 -0700342 } else if (e->type == EOT_DB_STRING ||
343 e->type == EOT_DB_STRING_FREE) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000344 int align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000345
H. Peter Anvine2c80182005-01-15 22:15:51 +0000346 out(offset, segment, e->stringval,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800347 OUT_RAWDATA, e->stringlen, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000348 align = e->stringlen % wsize;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000349
H. Peter Anvine2c80182005-01-15 22:15:51 +0000350 if (align) {
351 align = wsize - align;
H. Peter Anvindfb91802008-05-20 11:43:53 -0700352 out(offset, segment, const_zero_buf,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800353 OUT_RAWDATA, align, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000354 }
355 offset += e->stringlen + align;
356 }
357 }
358 if (t > 0 && t == instruction->times - 1) {
359 /*
360 * Dummy call to list->output to give the offset to the
361 * listing module.
362 */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800363 list->output(offset, NULL, OUT_RAWDATA, 0);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000364 list->uplevel(LIST_TIMES);
365 }
366 }
367 if (instruction->times > 1)
368 list->downlevel(LIST_TIMES);
369 return offset - start;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000370 }
371
H. Peter Anvine2c80182005-01-15 22:15:51 +0000372 if (instruction->opcode == I_INCBIN) {
H. Peter Anvin518df302008-06-14 16:53:48 -0700373 const char *fname = instruction->eops->stringval;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000374 FILE *fp;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000375
H. Peter Anvin418ca702008-05-30 10:42:30 -0700376 fp = fopen(fname, "rb");
377 if (!fp) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000378 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
379 fname);
H. Peter Anvin418ca702008-05-30 10:42:30 -0700380 } else if (fseek(fp, 0L, SEEK_END) < 0) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000381 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
382 fname);
H. Peter Anvin418ca702008-05-30 10:42:30 -0700383 } else {
H. Peter Anvin518df302008-06-14 16:53:48 -0700384 static char buf[4096];
385 size_t t = instruction->times;
386 size_t base = 0;
387 size_t len;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000388
H. Peter Anvine2c80182005-01-15 22:15:51 +0000389 len = ftell(fp);
390 if (instruction->eops->next) {
391 base = instruction->eops->next->offset;
392 len -= base;
393 if (instruction->eops->next->next &&
H. Peter Anvin518df302008-06-14 16:53:48 -0700394 len > (size_t)instruction->eops->next->next->offset)
395 len = (size_t)instruction->eops->next->next->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000396 }
397 /*
398 * Dummy call to list->output to give the offset to the
399 * listing module.
400 */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800401 list->output(offset, NULL, OUT_RAWDATA, 0);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000402 list->uplevel(LIST_INCBIN);
403 while (t--) {
H. Peter Anvin518df302008-06-14 16:53:48 -0700404 size_t l;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000405
H. Peter Anvine2c80182005-01-15 22:15:51 +0000406 fseek(fp, base, SEEK_SET);
407 l = len;
408 while (l > 0) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000409 int32_t m =
Charles Crayne192d5b52007-10-18 19:02:42 -0700410 fread(buf, 1, (l > (int32_t) sizeof(buf) ? (int32_t) sizeof(buf) : l),
H. Peter Anvine2c80182005-01-15 22:15:51 +0000411 fp);
412 if (!m) {
413 /*
414 * This shouldn't happen unless the file
415 * actually changes while we are reading
416 * it.
417 */
418 error(ERR_NONFATAL,
419 "`incbin': unexpected EOF while"
420 " reading file `%s'", fname);
421 t = 0; /* Try to exit cleanly */
422 break;
423 }
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800424 out(offset, segment, buf, OUT_RAWDATA, m,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000425 NO_SEG, NO_SEG);
426 l -= m;
427 }
428 }
429 list->downlevel(LIST_INCBIN);
430 if (instruction->times > 1) {
431 /*
432 * Dummy call to list->output to give the offset to the
433 * listing module.
434 */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800435 list->output(offset, NULL, OUT_RAWDATA, 0);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000436 list->uplevel(LIST_TIMES);
437 list->downlevel(LIST_TIMES);
438 }
439 fclose(fp);
440 return instruction->times * len;
441 }
442 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000443 }
444
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700445 /* Check to see if we need an address-size prefix */
446 add_asp(instruction, bits);
447
H. Peter Anvin6867acc2007-10-10 14:58:45 -0700448 size_prob = false;
H. Peter Anvin70653092007-10-19 14:42:29 -0700449
450 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++){
Keith Kaniosb7a89542007-04-12 02:40:54 +0000451 int m = matches(temp, instruction, bits);
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700452 if (m == 100 ||
453 (m == 99 && jmp_match(segment, offset, bits,
454 instruction, temp->code))) {
455 /* Matches! */
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800456 int64_t insn_size = calcsize(segment, offset, bits,
H. Peter Anvin833caea2008-10-04 19:02:30 -0700457 instruction, temp->code);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000458 itimes = instruction->times;
459 if (insn_size < 0) /* shouldn't be, on pass two */
460 error(ERR_PANIC, "errors made it through from pass one");
461 else
462 while (itimes--) {
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700463 for (j = 0; j < MAXPREFIX; j++) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000464 uint8_t c = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000465 switch (instruction->prefixes[j]) {
466 case P_LOCK:
467 c = 0xF0;
468 break;
469 case P_REPNE:
470 case P_REPNZ:
471 c = 0xF2;
472 break;
473 case P_REPE:
474 case P_REPZ:
475 case P_REP:
476 c = 0xF3;
477 break;
478 case R_CS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000479 if (bits == 64) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700480 error(ERR_WARNING | ERR_PASS2,
Charles Crayne1b851dc2007-11-05 21:49:49 -0800481 "cs segment base generated, but will be ignored in 64-bit mode");
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000482 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000483 c = 0x2E;
484 break;
485 case R_DS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000486 if (bits == 64) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700487 error(ERR_WARNING | ERR_PASS2,
Charles Crayne1b851dc2007-11-05 21:49:49 -0800488 "ds segment base generated, but will be ignored in 64-bit mode");
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000489 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000490 c = 0x3E;
491 break;
492 case R_ES:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000493 if (bits == 64) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700494 error(ERR_WARNING | ERR_PASS2,
Charles Crayne1b851dc2007-11-05 21:49:49 -0800495 "es segment base generated, but will be ignored in 64-bit mode");
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000496 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000497 c = 0x26;
498 break;
499 case R_FS:
500 c = 0x64;
501 break;
502 case R_GS:
503 c = 0x65;
504 break;
505 case R_SS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000506 if (bits == 64) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700507 error(ERR_WARNING | ERR_PASS2,
Charles Crayne1b851dc2007-11-05 21:49:49 -0800508 "ss segment base generated, but will be ignored in 64-bit mode");
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000509 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000510 c = 0x36;
511 break;
512 case R_SEGR6:
513 case R_SEGR7:
514 error(ERR_NONFATAL,
515 "segr6 and segr7 cannot be used as prefixes");
516 break;
517 case P_A16:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000518 if (bits == 64) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000519 error(ERR_NONFATAL,
520 "16-bit addressing is not supported "
521 "in 64-bit mode");
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700522 } else if (bits != 16)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000523 c = 0x67;
524 break;
525 case P_A32:
526 if (bits != 32)
527 c = 0x67;
528 break;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700529 case P_A64:
530 if (bits != 64) {
531 error(ERR_NONFATAL,
532 "64-bit addressing is only supported "
533 "in 64-bit mode");
534 }
535 break;
536 case P_ASP:
537 c = 0x67;
538 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000539 case P_O16:
540 if (bits != 16)
541 c = 0x66;
542 break;
543 case P_O32:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000544 if (bits == 16)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000545 c = 0x66;
546 break;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700547 case P_O64:
548 /* REX.W */
549 break;
550 case P_OSP:
551 c = 0x66;
552 break;
553 case P_none:
554 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000555 default:
556 error(ERR_PANIC, "invalid instruction prefix");
557 }
558 if (c != 0) {
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800559 out(offset, segment, &c, OUT_RAWDATA, 1,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000560 NO_SEG, NO_SEG);
561 offset++;
562 }
H. Peter Anvin70653092007-10-19 14:42:29 -0700563 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000564 insn_end = offset + insn_size;
H. Peter Anvin833caea2008-10-04 19:02:30 -0700565 gencode(segment, offset, bits, instruction,
566 temp, insn_end);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000567 offset += insn_size;
568 if (itimes > 0 && itimes == instruction->times - 1) {
569 /*
570 * Dummy call to list->output to give the offset to the
571 * listing module.
572 */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800573 list->output(offset, NULL, OUT_RAWDATA, 0);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000574 list->uplevel(LIST_TIMES);
575 }
576 }
577 if (instruction->times > 1)
578 list->downlevel(LIST_TIMES);
579 return offset - start;
580 } else if (m > 0 && m > size_prob) {
581 size_prob = m;
582 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000583 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000584
H. Peter Anvine2c80182005-01-15 22:15:51 +0000585 if (temp->opcode == -1) { /* didn't match any instruction */
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000586 switch (size_prob) {
587 case 1:
588 error(ERR_NONFATAL, "operation size not specified");
589 break;
590 case 2:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000591 error(ERR_NONFATAL, "mismatch in operand sizes");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000592 break;
593 case 3:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000594 error(ERR_NONFATAL, "no instruction for this cpu level");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000595 break;
596 case 4:
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000597 error(ERR_NONFATAL, "instruction not supported in 64-bit mode");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000598 break;
599 default:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000600 error(ERR_NONFATAL,
601 "invalid combination of opcode and operands");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000602 break;
603 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000604 }
605 return 0;
606}
607
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800608int64_t insn_size(int32_t segment, int64_t offset, int bits, uint32_t cp,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000609 insn * instruction, efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000610{
H. Peter Anvin3360d792007-09-11 04:16:57 +0000611 const struct itemplate *temp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000612
H. Peter Anvine2c80182005-01-15 22:15:51 +0000613 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000614 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000615
616 if (instruction->opcode == -1)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000617 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000618
H. Peter Anvincfbe7c32007-09-18 17:49:09 -0700619 if (instruction->opcode == I_DB || instruction->opcode == I_DW ||
620 instruction->opcode == I_DD || instruction->opcode == I_DQ ||
H. Peter Anvindfb91802008-05-20 11:43:53 -0700621 instruction->opcode == I_DT || instruction->opcode == I_DO ||
622 instruction->opcode == I_DY) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000623 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000624 int32_t isize, osize, wsize = 0; /* placate gcc */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000625
H. Peter Anvine2c80182005-01-15 22:15:51 +0000626 isize = 0;
627 switch (instruction->opcode) {
628 case I_DB:
629 wsize = 1;
630 break;
631 case I_DW:
632 wsize = 2;
633 break;
634 case I_DD:
635 wsize = 4;
636 break;
637 case I_DQ:
638 wsize = 8;
639 break;
640 case I_DT:
641 wsize = 10;
642 break;
H. Peter Anvincfbe7c32007-09-18 17:49:09 -0700643 case I_DO:
644 wsize = 16;
645 break;
H. Peter Anvindfb91802008-05-20 11:43:53 -0700646 case I_DY:
647 wsize = 32;
648 break;
H. Peter Anvin16b0a332007-09-12 20:27:41 -0700649 default:
650 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000651 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000652
H. Peter Anvine2c80182005-01-15 22:15:51 +0000653 for (e = instruction->eops; e; e = e->next) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000654 int32_t align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000655
H. Peter Anvine2c80182005-01-15 22:15:51 +0000656 osize = 0;
657 if (e->type == EOT_DB_NUMBER)
658 osize = 1;
H. Peter Anvin518df302008-06-14 16:53:48 -0700659 else if (e->type == EOT_DB_STRING ||
660 e->type == EOT_DB_STRING_FREE)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000661 osize = e->stringlen;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000662
H. Peter Anvine2c80182005-01-15 22:15:51 +0000663 align = (-osize) % wsize;
664 if (align < 0)
665 align += wsize;
666 isize += osize + align;
667 }
668 return isize * instruction->times;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000669 }
670
H. Peter Anvine2c80182005-01-15 22:15:51 +0000671 if (instruction->opcode == I_INCBIN) {
H. Peter Anvin518df302008-06-14 16:53:48 -0700672 const char *fname = instruction->eops->stringval;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000673 FILE *fp;
H. Peter Anvin518df302008-06-14 16:53:48 -0700674 size_t len;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000675
H. Peter Anvin418ca702008-05-30 10:42:30 -0700676 fp = fopen(fname, "rb");
677 if (!fp)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000678 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
679 fname);
680 else if (fseek(fp, 0L, SEEK_END) < 0)
681 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
682 fname);
683 else {
684 len = ftell(fp);
685 fclose(fp);
686 if (instruction->eops->next) {
687 len -= instruction->eops->next->offset;
688 if (instruction->eops->next->next &&
H. Peter Anvin518df302008-06-14 16:53:48 -0700689 len > (size_t)instruction->eops->next->next->offset) {
690 len = (size_t)instruction->eops->next->next->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000691 }
692 }
693 return instruction->times * len;
694 }
695 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000696 }
697
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700698 /* Check to see if we need an address-size prefix */
699 add_asp(instruction, bits);
700
Keith Kaniosb7a89542007-04-12 02:40:54 +0000701 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++) {
702 int m = matches(temp, instruction, bits);
H. Peter Anvin2d5baaa2008-09-30 16:31:06 -0700703 if (m == 100 ||
704 (m == 99 && jmp_match(segment, offset, bits,
705 instruction, temp->code))) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000706 /* we've matched an instruction. */
Charles Crayne5fbbc8c2007-11-07 19:03:46 -0800707 int64_t isize;
H. Peter Anvin3720f7b2008-05-12 11:00:50 -0700708 const uint8_t *codes = temp->code;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000709 int j;
710
711 isize = calcsize(segment, offset, bits, instruction, codes);
712 if (isize < 0)
713 return -1;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700714 for (j = 0; j < MAXPREFIX; j++) {
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700715 switch (instruction->prefixes[j]) {
716 case P_A16:
717 if (bits != 16)
718 isize++;
719 break;
720 case P_A32:
721 if (bits != 32)
722 isize++;
723 break;
724 case P_O16:
725 if (bits != 16)
726 isize++;
727 break;
728 case P_O32:
729 if (bits == 16)
730 isize++;
731 break;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700732 case P_A64:
733 case P_O64:
734 case P_none:
735 break;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700736 default:
737 isize++;
738 break;
739 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000740 }
741 return isize * instruction->times;
742 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000743 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000744 return -1; /* didn't match any instruction */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000745}
746
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700747static bool possible_sbyte(operand *o)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000748{
H. Peter Anvinad6b8592008-10-07 09:56:38 -0700749 return o->wrt == NO_SEG && o->segment == NO_SEG &&
750 !(o->opflags & OPFLAG_FORWARD) &&
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -0700751 optimizing >= 0 && !(o->type & STRICT);
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000752}
753
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700754/* check that opn[op] is a signed byte of size 16 or 32 */
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700755static bool is_sbyte16(operand *o)
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700756{
757 int16_t v;
758
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700759 if (!possible_sbyte(o))
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700760 return false;
761
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700762 v = o->offset;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700763 return v >= -128 && v <= 127;
764}
765
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700766static bool is_sbyte32(operand *o)
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700767{
768 int32_t v;
769
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700770 if (!possible_sbyte(o))
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700771 return false;
772
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700773 v = o->offset;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700774 return v >= -128 && v <= 127;
775}
776
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800777static int64_t calcsize(int32_t segment, int64_t offset, int bits,
H. Peter Anvin9f817132008-10-06 19:11:07 -0700778 insn * ins, const uint8_t *codes)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000779{
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800780 int64_t length = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000781 uint8_t c;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000782 int rex_mask = ~0;
H. Peter Anvin839eca22007-10-29 23:12:47 -0700783 struct operand *opx;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000784
H. Peter Anvine3917fc2007-11-01 14:53:32 -0700785 ins->rex = 0; /* Ensure REX is reset */
786
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700787 if (ins->prefixes[PPS_OSIZE] == P_O64)
788 ins->rex |= REX_W;
789
H. Peter Anvine2c80182005-01-15 22:15:51 +0000790 (void)segment; /* Don't warn that this parameter is unused */
791 (void)offset; /* Don't warn that this parameter is unused */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000792
H. Peter Anvin839eca22007-10-29 23:12:47 -0700793 while (*codes) {
794 c = *codes++;
795 opx = &ins->oprs[c & 3];
796 switch (c) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000797 case 01:
798 case 02:
799 case 03:
800 codes += c, length += c;
801 break;
802 case 04:
803 case 05:
804 case 06:
805 case 07:
806 length++;
807 break;
808 case 010:
809 case 011:
810 case 012:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700811 case 013:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000812 ins->rex |=
H. Peter Anvin839eca22007-10-29 23:12:47 -0700813 op_rexflags(opx, REX_B|REX_H|REX_P|REX_W);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000814 codes++, length++;
815 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000816 case 014:
817 case 015:
818 case 016:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700819 case 017:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000820 length++;
821 break;
822 case 020:
823 case 021:
824 case 022:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700825 case 023:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000826 length++;
827 break;
828 case 024:
829 case 025:
830 case 026:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700831 case 027:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000832 length++;
833 break;
834 case 030:
835 case 031:
836 case 032:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700837 case 033:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000838 length += 2;
839 break;
840 case 034:
841 case 035:
842 case 036:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700843 case 037:
H. Peter Anvin839eca22007-10-29 23:12:47 -0700844 if (opx->type & (BITS16 | BITS32 | BITS64))
845 length += (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000846 else
847 length += (bits == 16) ? 2 : 4;
848 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000849 case 040:
850 case 041:
851 case 042:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700852 case 043:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000853 length += 4;
854 break;
855 case 044:
856 case 045:
857 case 046:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700858 case 047:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700859 length += ins->addr_size >> 3;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000860 break;
861 case 050:
862 case 051:
863 case 052:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700864 case 053:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000865 length++;
866 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000867 case 054:
868 case 055:
869 case 056:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700870 case 057:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000871 length += 8; /* MOV reg64/imm */
872 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000873 case 060:
874 case 061:
875 case 062:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700876 case 063:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000877 length += 2;
878 break;
879 case 064:
880 case 065:
881 case 066:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700882 case 067:
H. Peter Anvin839eca22007-10-29 23:12:47 -0700883 if (opx->type & (BITS16 | BITS32 | BITS64))
884 length += (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000885 else
886 length += (bits == 16) ? 2 : 4;
887 break;
888 case 070:
889 case 071:
890 case 072:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700891 case 073:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000892 length += 4;
893 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700894 case 074:
895 case 075:
896 case 076:
897 case 077:
898 length += 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000899 break;
900 case 0140:
901 case 0141:
902 case 0142:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700903 case 0143:
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700904 length += is_sbyte16(opx) ? 1 : 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000905 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000906 case 0144:
907 case 0145:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700908 case 0146:
909 case 0147:
H. Peter Anvina30cc072007-11-18 21:55:26 -0800910 codes++;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000911 length++;
912 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700913 case 0150:
914 case 0151:
915 case 0152:
916 case 0153:
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700917 length += is_sbyte32(opx) ? 1 : 4;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700918 break;
919 case 0154:
920 case 0155:
921 case 0156:
922 case 0157:
H. Peter Anvina30cc072007-11-18 21:55:26 -0800923 codes++;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700924 length++;
925 break;
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700926 case 0160:
927 case 0161:
928 case 0162:
929 case 0163:
930 length++;
931 ins->rex |= REX_D;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700932 ins->drexdst = regval(opx);
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700933 break;
934 case 0164:
935 case 0165:
936 case 0166:
937 case 0167:
938 length++;
939 ins->rex |= REX_D|REX_OC;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700940 ins->drexdst = regval(opx);
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700941 break;
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700942 case 0171:
943 break;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700944 case 0172:
H. Peter Anvind58656f2008-05-06 20:11:14 -0700945 case 0173:
H. Peter Anvin52dc3532008-05-20 19:29:04 -0700946 case 0174:
H. Peter Anvind85d2502008-05-04 17:53:31 -0700947 codes++;
948 length++;
949 break;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700950 case 0250:
951 case 0251:
952 case 0252:
953 case 0253:
H. Peter Anvinad6b8592008-10-07 09:56:38 -0700954 length += is_sbyte32(opx) ? 1 : 4;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700955 break;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700956 case 0260:
957 case 0261:
958 case 0262:
959 case 0263:
H. Peter Anvind85d2502008-05-04 17:53:31 -0700960 ins->rex |= REX_V;
961 ins->drexdst = regval(opx);
962 ins->vex_m = *codes++;
963 ins->vex_wlp = *codes++;
964 break;
965 case 0270:
H. Peter Anvind85d2502008-05-04 17:53:31 -0700966 ins->rex |= REX_V;
967 ins->drexdst = 0;
968 ins->vex_m = *codes++;
969 ins->vex_wlp = *codes++;
970 break;
H. Peter Anvinc1377e92008-10-06 23:40:31 -0700971 case 0274:
972 case 0275:
973 case 0276:
974 case 0277:
975 length++;
976 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000977 case 0300:
978 case 0301:
H. Peter Anvin70653092007-10-19 14:42:29 -0700979 case 0302:
980 case 0303:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000981 break;
982 case 0310:
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700983 if (bits == 64)
984 return -1;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700985 length += (bits != 16) && !has_prefix(ins, PPS_ASIZE, P_A16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000986 break;
987 case 0311:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700988 length += (bits != 32) && !has_prefix(ins, PPS_ASIZE, P_A32);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000989 break;
990 case 0312:
H. Peter Anvin70653092007-10-19 14:42:29 -0700991 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000992 case 0313:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700993 if (bits != 64 || has_prefix(ins, PPS_ASIZE, P_A16) ||
994 has_prefix(ins, PPS_ASIZE, P_A32))
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700995 return -1;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000996 break;
H. Peter Anvin23440102007-11-12 21:02:33 -0800997 case 0314:
998 case 0315:
999 case 0316:
1000 case 0317:
1001 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001002 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001003 length += (bits != 16);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001004 break;
1005 case 0321:
1006 length += (bits == 16);
1007 break;
1008 case 0322:
1009 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001010 case 0323:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001011 rex_mask &= ~REX_W;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001012 break;
1013 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001014 ins->rex |= REX_W;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +00001015 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001016 case 0330:
1017 codes++, length++;
1018 break;
1019 case 0331:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001020 break;
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001021 case 0332:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001022 case 0333:
1023 length++;
1024 break;
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001025 case 0334:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001026 ins->rex |= REX_L;
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001027 break;
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001028 case 0335:
1029 break;
H. Peter Anvin962e3052008-08-28 17:47:16 -07001030 case 0336:
1031 if (!ins->prefixes[PPS_LREP])
1032 ins->prefixes[PPS_LREP] = P_REP;
1033 break;
1034 case 0337:
1035 if (!ins->prefixes[PPS_LREP])
1036 ins->prefixes[PPS_LREP] = P_REPNE;
1037 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001038 case 0340:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001039 if (ins->oprs[0].segment != NO_SEG)
1040 errfunc(ERR_NONFATAL, "attempt to reserve non-constant"
1041 " quantity of BSS space");
1042 else
H. Peter Anvin428fd672007-11-15 10:25:52 -08001043 length += ins->oprs[0].offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001044 break;
H. Peter Anvinfff5a472008-05-20 09:46:24 -07001045 case 0360:
1046 break;
1047 case 0361:
1048 case 0362:
1049 case 0363:
1050 length++;
1051 break;
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001052 case 0364:
1053 case 0365:
1054 break;
Keith Kanios48af1772007-08-17 07:37:52 +00001055 case 0366:
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001056 case 0367:
1057 length++;
1058 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001059 case 0370:
1060 case 0371:
1061 case 0372:
1062 break;
1063 case 0373:
1064 length++;
1065 break;
1066 default: /* can't do it by 'case' statements */
1067 if (c >= 0100 && c <= 0277) { /* it's an EA */
1068 ea ea_data;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001069 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001070 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001071 ea_data.rex = 0; /* Ensure ea.REX is initially 0 */
H. Peter Anvin70653092007-10-19 14:42:29 -07001072
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001073 if (c <= 0177) {
1074 /* pick rfield from operand b */
1075 rflags = regflag(&ins->oprs[c & 7]);
H. Peter Anvina4835d42008-05-20 14:21:29 -07001076 rfield = nasm_regvals[ins->oprs[c & 7].basereg];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001077 } else {
1078 rflags = 0;
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001079 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001080 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001081
H. Peter Anvine2c80182005-01-15 22:15:51 +00001082 if (!process_ea
Keith Kaniosb7a89542007-04-12 02:40:54 +00001083 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001084 ins->addr_size, rfield, rflags)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001085 errfunc(ERR_NONFATAL, "invalid effective address");
1086 return -1;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001087 } else {
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001088 ins->rex |= ea_data.rex;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001089 length += ea_data.size;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001090 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001091 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001092 errfunc(ERR_PANIC, "internal instruction table corrupt"
1093 ": instruction code 0x%02X given", c);
H. Peter Anvin839eca22007-10-29 23:12:47 -07001094 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001095 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001096 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001097
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001098 ins->rex &= rex_mask;
H. Peter Anvin70653092007-10-19 14:42:29 -07001099
H. Peter Anvind85d2502008-05-04 17:53:31 -07001100 if (ins->rex & REX_V) {
1101 int bad32 = REX_R|REX_W|REX_X|REX_B;
1102
1103 if (ins->rex & REX_H) {
1104 errfunc(ERR_NONFATAL, "cannot use high register in vex instruction");
1105 return -1;
1106 }
1107 switch (ins->vex_wlp & 030) {
1108 case 000:
H. Peter Anvinbd420c72008-05-22 11:24:35 -07001109 case 020:
H. Peter Anvind85d2502008-05-04 17:53:31 -07001110 ins->rex &= ~REX_W;
1111 break;
1112 case 010:
1113 ins->rex |= REX_W;
1114 bad32 &= ~REX_W;
1115 break;
H. Peter Anvinbd420c72008-05-22 11:24:35 -07001116 case 030:
H. Peter Anvind85d2502008-05-04 17:53:31 -07001117 /* Follow REX_W */
1118 break;
1119 }
1120
1121 if (bits != 64 && ((ins->rex & bad32) || ins->drexdst > 7)) {
1122 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
1123 return -1;
1124 }
1125 if (ins->vex_m != 1 || (ins->rex & (REX_W|REX_R|REX_B)))
1126 length += 3;
1127 else
1128 length += 2;
1129 } else if (ins->rex & REX_D) {
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001130 if (ins->rex & REX_H) {
1131 errfunc(ERR_NONFATAL, "cannot use high register in drex instruction");
1132 return -1;
1133 }
H. Peter Anvind85d2502008-05-04 17:53:31 -07001134 if (bits != 64 && ((ins->rex & (REX_R|REX_W|REX_X|REX_B)) ||
H. Peter Anvincf5180a2007-09-17 17:25:27 -07001135 ins->drexdst > 7)) {
1136 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
1137 return -1;
1138 }
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001139 length++;
1140 } else if (ins->rex & REX_REAL) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001141 if (ins->rex & REX_H) {
1142 errfunc(ERR_NONFATAL, "cannot use high register in rex instruction");
1143 return -1;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001144 } else if (bits == 64) {
1145 length++;
1146 } else if ((ins->rex & REX_L) &&
1147 !(ins->rex & (REX_P|REX_W|REX_X|REX_B)) &&
1148 cpu >= IF_X86_64) {
1149 /* LOCK-as-REX.R */
1150 assert_no_prefix(ins, PPS_LREP);
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001151 length++;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +00001152 } else {
H. Peter Anvincf5180a2007-09-17 17:25:27 -07001153 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
1154 return -1;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +00001155 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001156 }
1157
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001158 return length;
1159}
Keith Kaniosb7a89542007-04-12 02:40:54 +00001160
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001161#define EMIT_REX() \
H. Peter Anvind85d2502008-05-04 17:53:31 -07001162 if (!(ins->rex & (REX_D|REX_V)) && (ins->rex & REX_REAL) && (bits == 64)) { \
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001163 ins->rex = (ins->rex & REX_REAL)|REX_P; \
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001164 out(offset, segment, &ins->rex, OUT_RAWDATA, 1, NO_SEG, NO_SEG); \
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001165 ins->rex = 0; \
1166 offset += 1; \
1167 }
1168
Charles Crayne1f8bc4c2007-11-06 18:27:23 -08001169static void gencode(int32_t segment, int64_t offset, int bits,
H. Peter Anvin833caea2008-10-04 19:02:30 -07001170 insn * ins, const struct itemplate *temp,
1171 int64_t insn_end)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001172{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001173 static char condval[] = { /* conditional opcodes */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001174 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
1175 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
1176 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001177 };
Keith Kaniosb7a89542007-04-12 02:40:54 +00001178 uint8_t c;
1179 uint8_t bytes[4];
Charles Crayne1f8bc4c2007-11-06 18:27:23 -08001180 int64_t size;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001181 int64_t data;
H. Peter Anvin839eca22007-10-29 23:12:47 -07001182 struct operand *opx;
H. Peter Anvin833caea2008-10-04 19:02:30 -07001183 const uint8_t *codes = temp->code;
H. Peter Anvin70653092007-10-19 14:42:29 -07001184
H. Peter Anvin839eca22007-10-29 23:12:47 -07001185 while (*codes) {
1186 c = *codes++;
1187 opx = &ins->oprs[c & 3];
1188 switch (c) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001189 case 01:
1190 case 02:
1191 case 03:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001192 EMIT_REX();
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001193 out(offset, segment, codes, OUT_RAWDATA, c, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001194 codes += c;
1195 offset += c;
1196 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001197
H. Peter Anvine2c80182005-01-15 22:15:51 +00001198 case 04:
1199 case 06:
1200 switch (ins->oprs[0].basereg) {
1201 case R_CS:
1202 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0);
1203 break;
1204 case R_DS:
1205 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0);
1206 break;
1207 case R_ES:
1208 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0);
1209 break;
1210 case R_SS:
1211 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0);
1212 break;
1213 default:
1214 errfunc(ERR_PANIC,
1215 "bizarre 8086 segment register received");
1216 }
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001217 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001218 offset++;
1219 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001220
H. Peter Anvine2c80182005-01-15 22:15:51 +00001221 case 05:
1222 case 07:
1223 switch (ins->oprs[0].basereg) {
1224 case R_FS:
1225 bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0);
1226 break;
1227 case R_GS:
1228 bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0);
1229 break;
1230 default:
1231 errfunc(ERR_PANIC,
1232 "bizarre 386 segment register received");
1233 }
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001234 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001235 offset++;
1236 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001237
H. Peter Anvine2c80182005-01-15 22:15:51 +00001238 case 010:
1239 case 011:
1240 case 012:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001241 case 013:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001242 EMIT_REX();
H. Peter Anvin839eca22007-10-29 23:12:47 -07001243 bytes[0] = *codes++ + ((regval(opx)) & 7);
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001244 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001245 offset += 1;
1246 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001247
H. Peter Anvine2c80182005-01-15 22:15:51 +00001248 case 014:
1249 case 015:
1250 case 016:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001251 case 017:
H. Peter Anvin6c80ab62008-10-04 18:50:47 -07001252 /* The test for BITS8 and SBYTE here is intended to avoid
1253 warning on optimizer actions due to SBYTE, while still
1254 warn on explicit BYTE directives. Also warn, obviously,
1255 if the optimizer isn't enabled. */
1256 if (((opx->type & BITS8) ||
H. Peter Anvin833caea2008-10-04 19:02:30 -07001257 !(opx->type & temp->opd[c & 3] & BYTENESS)) &&
H. Peter Anvin6c80ab62008-10-04 18:50:47 -07001258 (opx->offset < -128 || opx->offset > 127)) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001259 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
H. Peter Anvin72c64372008-01-08 22:13:48 -08001260 "signed byte value exceeds bounds");
H. Peter Anvin6c80ab62008-10-04 18:50:47 -07001261 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001262 if (opx->segment != NO_SEG) {
1263 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001264 out(offset, segment, &data, OUT_ADDRESS, 1,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001265 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001266 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001267 bytes[0] = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001268 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001269 NO_SEG);
1270 }
1271 offset += 1;
1272 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001273
H. Peter Anvine2c80182005-01-15 22:15:51 +00001274 case 020:
1275 case 021:
1276 case 022:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001277 case 023:
H. Peter Anvin839eca22007-10-29 23:12:47 -07001278 if (opx->offset < -256 || opx->offset > 255) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001279 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
H. Peter Anvin72c64372008-01-08 22:13:48 -08001280 "byte value exceeds bounds");
H. Peter Anvine2c80182005-01-15 22:15:51 +00001281 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001282 if (opx->segment != NO_SEG) {
1283 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001284 out(offset, segment, &data, OUT_ADDRESS, 1,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001285 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001286 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001287 bytes[0] = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001288 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001289 NO_SEG);
1290 }
1291 offset += 1;
1292 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001293
H. Peter Anvine2c80182005-01-15 22:15:51 +00001294 case 024:
1295 case 025:
1296 case 026:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001297 case 027:
H. Peter Anvin839eca22007-10-29 23:12:47 -07001298 if (opx->offset < 0 || opx->offset > 255)
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001299 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
H. Peter Anvin72c64372008-01-08 22:13:48 -08001300 "unsigned byte value exceeds bounds");
H. Peter Anvin839eca22007-10-29 23:12:47 -07001301 if (opx->segment != NO_SEG) {
1302 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001303 out(offset, segment, &data, OUT_ADDRESS, 1,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001304 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001305 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001306 bytes[0] = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001307 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001308 NO_SEG);
1309 }
1310 offset += 1;
1311 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001312
H. Peter Anvine2c80182005-01-15 22:15:51 +00001313 case 030:
1314 case 031:
1315 case 032:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001316 case 033:
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001317 warn_overflow(2, opx);
H. Peter Anvin839eca22007-10-29 23:12:47 -07001318 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001319 out(offset, segment, &data, OUT_ADDRESS, 2,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001320 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001321 offset += 2;
1322 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001323
H. Peter Anvine2c80182005-01-15 22:15:51 +00001324 case 034:
1325 case 035:
1326 case 036:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001327 case 037:
H. Peter Anvin839eca22007-10-29 23:12:47 -07001328 if (opx->type & (BITS16 | BITS32))
1329 size = (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001330 else
1331 size = (bits == 16) ? 2 : 4;
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001332 warn_overflow(size, opx);
H. Peter Anvin839eca22007-10-29 23:12:47 -07001333 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001334 out(offset, segment, &data, OUT_ADDRESS, size,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001335 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001336 offset += size;
1337 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001338
H. Peter Anvine2c80182005-01-15 22:15:51 +00001339 case 040:
1340 case 041:
1341 case 042:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001342 case 043:
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001343 warn_overflow(4, opx);
H. Peter Anvin839eca22007-10-29 23:12:47 -07001344 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001345 out(offset, segment, &data, OUT_ADDRESS, 4,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001346 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001347 offset += 4;
1348 break;
H. Peter Anvin3ba46772002-05-27 23:19:35 +00001349
H. Peter Anvine2c80182005-01-15 22:15:51 +00001350 case 044:
1351 case 045:
1352 case 046:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001353 case 047:
H. Peter Anvin839eca22007-10-29 23:12:47 -07001354 data = opx->offset;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001355 size = ins->addr_size >> 3;
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001356 warn_overflow(size, opx);
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001357 out(offset, segment, &data, OUT_ADDRESS, size,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001358 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001359 offset += size;
1360 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001361
H. Peter Anvine2c80182005-01-15 22:15:51 +00001362 case 050:
1363 case 051:
1364 case 052:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001365 case 053:
H. Peter Anvin839eca22007-10-29 23:12:47 -07001366 if (opx->segment != segment)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001367 errfunc(ERR_NONFATAL,
1368 "short relative jump outside segment");
H. Peter Anvin839eca22007-10-29 23:12:47 -07001369 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001370 if (data > 127 || data < -128)
1371 errfunc(ERR_NONFATAL, "short jump is out of range");
1372 bytes[0] = data;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001373 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001374 offset += 1;
1375 break;
H. Peter Anvin70653092007-10-19 14:42:29 -07001376
Keith Kaniosb7a89542007-04-12 02:40:54 +00001377 case 054:
1378 case 055:
1379 case 056:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001380 case 057:
H. Peter Anvin839eca22007-10-29 23:12:47 -07001381 data = (int64_t)opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001382 out(offset, segment, &data, OUT_ADDRESS, 8,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001383 opx->segment, opx->wrt);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001384 offset += 8;
1385 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001386
H. Peter Anvine2c80182005-01-15 22:15:51 +00001387 case 060:
1388 case 061:
1389 case 062:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001390 case 063:
H. Peter Anvin839eca22007-10-29 23:12:47 -07001391 if (opx->segment != segment) {
1392 data = opx->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001393 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001394 OUT_REL2ADR, insn_end - offset,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001395 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001396 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001397 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001398 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001399 OUT_ADDRESS, 2, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001400 }
1401 offset += 2;
1402 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001403
H. Peter Anvine2c80182005-01-15 22:15:51 +00001404 case 064:
1405 case 065:
1406 case 066:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001407 case 067:
H. Peter Anvin839eca22007-10-29 23:12:47 -07001408 if (opx->type & (BITS16 | BITS32 | BITS64))
1409 size = (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001410 else
1411 size = (bits == 16) ? 2 : 4;
H. Peter Anvin839eca22007-10-29 23:12:47 -07001412 if (opx->segment != segment) {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001413 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001414 out(offset, segment, &data,
1415 size == 2 ? OUT_REL2ADR : OUT_REL4ADR,
1416 insn_end - offset, opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001417 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001418 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001419 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001420 OUT_ADDRESS, size, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001421 }
1422 offset += size;
1423 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001424
H. Peter Anvine2c80182005-01-15 22:15:51 +00001425 case 070:
1426 case 071:
1427 case 072:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001428 case 073:
H. Peter Anvin839eca22007-10-29 23:12:47 -07001429 if (opx->segment != segment) {
1430 data = opx->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001431 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001432 OUT_REL4ADR, insn_end - offset,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001433 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001434 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001435 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001436 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001437 OUT_ADDRESS, 4, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001438 }
1439 offset += 4;
1440 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001441
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001442 case 074:
1443 case 075:
1444 case 076:
1445 case 077:
H. Peter Anvin839eca22007-10-29 23:12:47 -07001446 if (opx->segment == NO_SEG)
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001447 errfunc(ERR_NONFATAL, "value referenced by FAR is not"
1448 " relocatable");
H. Peter Anvindfb91802008-05-20 11:43:53 -07001449 data = 0;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001450 out(offset, segment, &data, OUT_ADDRESS, 2,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001451 outfmt->segbase(1 + opx->segment),
1452 opx->wrt);
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001453 offset += 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001454 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001455
H. Peter Anvine2c80182005-01-15 22:15:51 +00001456 case 0140:
1457 case 0141:
1458 case 0142:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001459 case 0143:
H. Peter Anvin839eca22007-10-29 23:12:47 -07001460 data = opx->offset;
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001461 warn_overflow(2, opx);
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001462 if (is_sbyte16(opx)) {
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001463 bytes[0] = data;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001464 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001465 NO_SEG);
1466 offset++;
1467 } else {
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001468 out(offset, segment, &data, OUT_ADDRESS, 2,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001469 opx->segment, opx->wrt);
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001470 offset += 2;
1471 }
1472 break;
1473
1474 case 0144:
1475 case 0145:
1476 case 0146:
1477 case 0147:
1478 EMIT_REX();
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001479 bytes[0] = *codes++;
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001480 if (is_sbyte16(opx))
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001481 bytes[0] |= 2; /* s-bit */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001482 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001483 offset++;
1484 break;
1485
1486 case 0150:
1487 case 0151:
1488 case 0152:
1489 case 0153:
H. Peter Anvin839eca22007-10-29 23:12:47 -07001490 data = opx->offset;
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001491 warn_overflow(4, opx);
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001492 if (is_sbyte32(opx)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001493 bytes[0] = data;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001494 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001495 NO_SEG);
1496 offset++;
1497 } else {
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001498 out(offset, segment, &data, OUT_ADDRESS, 4,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001499 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001500 offset += 4;
1501 }
1502 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001503
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001504 case 0154:
1505 case 0155:
1506 case 0156:
1507 case 0157:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001508 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001509 bytes[0] = *codes++;
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001510 if (is_sbyte32(opx))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001511 bytes[0] |= 2; /* s-bit */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001512 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001513 offset++;
1514 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001515
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001516 case 0160:
1517 case 0161:
1518 case 0162:
1519 case 0163:
1520 case 0164:
1521 case 0165:
1522 case 0166:
1523 case 0167:
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001524 break;
1525
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001526 case 0171:
1527 bytes[0] =
1528 (ins->drexdst << 4) |
1529 (ins->rex & REX_OC ? 0x08 : 0) |
1530 (ins->rex & (REX_R|REX_X|REX_B));
1531 ins->rex = 0;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001532 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001533 offset++;
1534 break;
1535
H. Peter Anvind85d2502008-05-04 17:53:31 -07001536 case 0172:
1537 c = *codes++;
1538 opx = &ins->oprs[c >> 3];
H. Peter Anvina4835d42008-05-20 14:21:29 -07001539 bytes[0] = nasm_regvals[opx->basereg] << 4;
H. Peter Anvind85d2502008-05-04 17:53:31 -07001540 opx = &ins->oprs[c & 7];
1541 if (opx->segment != NO_SEG || opx->wrt != NO_SEG) {
1542 errfunc(ERR_NONFATAL,
1543 "non-absolute expression not permitted as argument %d",
1544 c & 7);
1545 } else {
1546 if (opx->offset & ~15) {
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001547 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
H. Peter Anvind85d2502008-05-04 17:53:31 -07001548 "four-bit argument exceeds bounds");
1549 }
1550 bytes[0] |= opx->offset & 15;
1551 }
1552 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1553 offset++;
1554 break;
1555
H. Peter Anvind58656f2008-05-06 20:11:14 -07001556 case 0173:
1557 c = *codes++;
1558 opx = &ins->oprs[c >> 4];
H. Peter Anvina4835d42008-05-20 14:21:29 -07001559 bytes[0] = nasm_regvals[opx->basereg] << 4;
H. Peter Anvind58656f2008-05-06 20:11:14 -07001560 bytes[0] |= c & 15;
1561 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1562 offset++;
1563 break;
1564
H. Peter Anvin52dc3532008-05-20 19:29:04 -07001565 case 0174:
1566 c = *codes++;
1567 opx = &ins->oprs[c];
1568 bytes[0] = nasm_regvals[opx->basereg] << 4;
1569 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1570 offset++;
1571 break;
1572
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001573 case 0250:
1574 case 0251:
1575 case 0252:
1576 case 0253:
1577 data = opx->offset;
H. Peter Anvinad6b8592008-10-07 09:56:38 -07001578 if (opx->wrt == NO_SEG && opx->segment == NO_SEG &&
1579 (int32_t)data != (int64_t)data) {
1580 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
1581 "signed dword immediate exceeds bounds");
1582 }
1583 if (is_sbyte32(opx)) {
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001584 bytes[0] = data;
1585 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
1586 NO_SEG);
1587 offset++;
1588 } else {
1589 out(offset, segment, &data, OUT_ADDRESS, 4,
1590 opx->segment, opx->wrt);
1591 offset += 4;
1592 }
1593 break;
1594
H. Peter Anvind85d2502008-05-04 17:53:31 -07001595 case 0260:
1596 case 0261:
1597 case 0262:
1598 case 0263:
1599 case 0270:
1600 codes += 2;
1601 if (ins->vex_m != 1 || (ins->rex & (REX_W|REX_X|REX_B))) {
1602 bytes[0] = 0xc4;
H. Peter Anvin4d2c38c2008-05-04 23:15:13 -07001603 bytes[1] = ins->vex_m | ((~ins->rex & 7) << 5);
H. Peter Anvind85d2502008-05-04 17:53:31 -07001604 bytes[2] = ((ins->rex & REX_W) << (7-3)) |
H. Peter Anvin4d2c38c2008-05-04 23:15:13 -07001605 ((~ins->drexdst & 15)<< 3) | (ins->vex_wlp & 07);
H. Peter Anvind85d2502008-05-04 17:53:31 -07001606 out(offset, segment, &bytes, OUT_RAWDATA, 3, NO_SEG, NO_SEG);
1607 offset += 3;
1608 } else {
1609 bytes[0] = 0xc5;
H. Peter Anvin4d2c38c2008-05-04 23:15:13 -07001610 bytes[1] = ((~ins->rex & REX_R) << (7-2)) |
1611 ((~ins->drexdst & 15) << 3) | (ins->vex_wlp & 07);
H. Peter Anvind85d2502008-05-04 17:53:31 -07001612 out(offset, segment, &bytes, OUT_RAWDATA, 2, NO_SEG, NO_SEG);
1613 offset += 2;
1614 }
1615 break;
1616
H. Peter Anvinc1377e92008-10-06 23:40:31 -07001617 case 0274:
1618 case 0275:
1619 case 0276:
1620 case 0277:
1621 {
1622 uint64_t uv, um;
1623 int s;
1624
1625 if (ins->rex & REX_W)
1626 s = 64;
1627 else if (ins->prefixes[PPS_OSIZE] == P_O16)
1628 s = 16;
1629 else if (ins->prefixes[PPS_OSIZE] == P_O32)
1630 s = 32;
1631 else
1632 s = bits;
1633
1634 um = (uint64_t)2 << (s-1);
1635 uv = opx->offset;
1636
1637 if (uv > 127 && uv < (uint64_t)-128 &&
1638 (uv < um-128 || uv > um-1)) {
1639 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
1640 "signed byte value exceeds bounds");
1641 }
1642 if (opx->segment != NO_SEG) {
1643 data = um;
1644 out(offset, segment, &data, OUT_ADDRESS, 1,
1645 opx->segment, opx->wrt);
1646 } else {
1647 bytes[0] = um;
1648 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
1649 NO_SEG);
1650 }
1651 offset += 1;
1652 break;
1653 }
1654
H. Peter Anvine2c80182005-01-15 22:15:51 +00001655 case 0300:
1656 case 0301:
1657 case 0302:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001658 case 0303:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001659 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001660
H. Peter Anvine2c80182005-01-15 22:15:51 +00001661 case 0310:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001662 if (bits == 32 && !has_prefix(ins, PPS_ASIZE, P_A16)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001663 *bytes = 0x67;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001664 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001665 offset += 1;
1666 } else
1667 offset += 0;
1668 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001669
H. Peter Anvine2c80182005-01-15 22:15:51 +00001670 case 0311:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001671 if (bits != 32 && !has_prefix(ins, PPS_ASIZE, P_A32)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001672 *bytes = 0x67;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001673 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001674 offset += 1;
1675 } else
1676 offset += 0;
1677 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001678
H. Peter Anvine2c80182005-01-15 22:15:51 +00001679 case 0312:
1680 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001681
Keith Kaniosb7a89542007-04-12 02:40:54 +00001682 case 0313:
1683 ins->rex = 0;
1684 break;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07001685
H. Peter Anvin23440102007-11-12 21:02:33 -08001686 case 0314:
1687 case 0315:
1688 case 0316:
1689 case 0317:
1690 break;
1691
H. Peter Anvine2c80182005-01-15 22:15:51 +00001692 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001693 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001694 *bytes = 0x66;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001695 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001696 offset += 1;
1697 } else
1698 offset += 0;
1699 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001700
H. Peter Anvine2c80182005-01-15 22:15:51 +00001701 case 0321:
1702 if (bits == 16) {
1703 *bytes = 0x66;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001704 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001705 offset += 1;
1706 } else
1707 offset += 0;
1708 break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001709
H. Peter Anvine2c80182005-01-15 22:15:51 +00001710 case 0322:
H. Peter Anvin70653092007-10-19 14:42:29 -07001711 case 0323:
1712 break;
1713
Keith Kaniosb7a89542007-04-12 02:40:54 +00001714 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001715 ins->rex |= REX_W;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001716 break;
H. Peter Anvin70653092007-10-19 14:42:29 -07001717
H. Peter Anvine2c80182005-01-15 22:15:51 +00001718 case 0330:
1719 *bytes = *codes++ ^ condval[ins->condition];
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001720 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001721 offset += 1;
1722 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001723
H. Peter Anvine2c80182005-01-15 22:15:51 +00001724 case 0331:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001725 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001726
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001727 case 0332:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001728 case 0333:
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001729 *bytes = c - 0332 + 0xF2;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001730 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001731 offset += 1;
1732 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001733
Keith Kanios48af1772007-08-17 07:37:52 +00001734 case 0334:
1735 if (ins->rex & REX_R) {
1736 *bytes = 0xF0;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001737 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
Keith Kanios48af1772007-08-17 07:37:52 +00001738 offset += 1;
1739 }
1740 ins->rex &= ~(REX_L|REX_R);
1741 break;
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001742
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001743 case 0335:
1744 break;
1745
H. Peter Anvin962e3052008-08-28 17:47:16 -07001746 case 0336:
1747 case 0337:
1748 break;
1749
H. Peter Anvine2c80182005-01-15 22:15:51 +00001750 case 0340:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001751 if (ins->oprs[0].segment != NO_SEG)
1752 errfunc(ERR_PANIC, "non-constant BSS size in pass two");
1753 else {
H. Peter Anvin428fd672007-11-15 10:25:52 -08001754 int64_t size = ins->oprs[0].offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001755 if (size > 0)
1756 out(offset, segment, NULL,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001757 OUT_RESERVE, size, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001758 offset += size;
1759 }
1760 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001761
H. Peter Anvinfff5a472008-05-20 09:46:24 -07001762 case 0360:
1763 break;
1764
1765 case 0361:
1766 bytes[0] = 0x66;
1767 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1768 offset += 1;
1769 break;
1770
1771 case 0362:
1772 case 0363:
1773 bytes[0] = c - 0362 + 0xf2;
1774 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1775 offset += 1;
1776 break;
1777
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001778 case 0364:
1779 case 0365:
1780 break;
1781
Keith Kanios48af1772007-08-17 07:37:52 +00001782 case 0366:
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001783 case 0367:
1784 *bytes = c - 0366 + 0x66;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001785 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
Keith Kanios48af1772007-08-17 07:37:52 +00001786 offset += 1;
1787 break;
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001788
H. Peter Anvine2c80182005-01-15 22:15:51 +00001789 case 0370:
1790 case 0371:
1791 case 0372:
1792 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001793
H. Peter Anvine2c80182005-01-15 22:15:51 +00001794 case 0373:
1795 *bytes = bits == 16 ? 3 : 5;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001796 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001797 offset += 1;
1798 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001799
H. Peter Anvine2c80182005-01-15 22:15:51 +00001800 default: /* can't do it by 'case' statements */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001801 if (c >= 0100 && c <= 0277) { /* it's an EA */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001802 ea ea_data;
1803 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001804 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001805 uint8_t *p;
1806 int32_t s;
H. Peter Anvin9f817132008-10-06 19:11:07 -07001807 enum out_type type;
H. Peter Anvin70653092007-10-19 14:42:29 -07001808
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001809 if (c <= 0177) {
1810 /* pick rfield from operand b */
1811 rflags = regflag(&ins->oprs[c & 7]);
H. Peter Anvina4835d42008-05-20 14:21:29 -07001812 rfield = nasm_regvals[ins->oprs[c & 7].basereg];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001813 } else {
1814 /* rfield is constant */
1815 rflags = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001816 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001817 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001818
1819 if (!process_ea
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001820 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001821 ins->addr_size, rfield, rflags)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001822 errfunc(ERR_NONFATAL, "invalid effective address");
1823 }
H. Peter Anvin70653092007-10-19 14:42:29 -07001824
Charles Crayne7e975552007-11-03 22:06:13 -07001825
H. Peter Anvine2c80182005-01-15 22:15:51 +00001826 p = bytes;
1827 *p++ = ea_data.modrm;
1828 if (ea_data.sib_present)
1829 *p++ = ea_data.sib;
1830
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001831 /* DREX suffixes come between the SIB and the displacement */
1832 if (ins->rex & REX_D) {
1833 *p++ =
1834 (ins->drexdst << 4) |
1835 (ins->rex & REX_OC ? 0x08 : 0) |
1836 (ins->rex & (REX_R|REX_X|REX_B));
1837 ins->rex = 0;
1838 }
1839
H. Peter Anvine2c80182005-01-15 22:15:51 +00001840 s = p - bytes;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001841 out(offset, segment, bytes, OUT_RAWDATA, s, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001842
Victor van den Elzencf9332c2008-10-01 12:18:28 +02001843 /*
1844 * Make sure the address gets the right offset in case
1845 * the line breaks in the .lst file (BR 1197827)
1846 */
1847 offset += s;
1848 s = 0;
1849
H. Peter Anvine2c80182005-01-15 22:15:51 +00001850 switch (ea_data.bytes) {
1851 case 0:
1852 break;
1853 case 1:
1854 if (ins->oprs[(c >> 3) & 7].segment != NO_SEG) {
1855 data = ins->oprs[(c >> 3) & 7].offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001856 out(offset, segment, &data, OUT_ADDRESS, 1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001857 ins->oprs[(c >> 3) & 7].segment,
1858 ins->oprs[(c >> 3) & 7].wrt);
1859 } else {
1860 *bytes = ins->oprs[(c >> 3) & 7].offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001861 out(offset, segment, bytes, OUT_RAWDATA, 1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001862 NO_SEG, NO_SEG);
1863 }
1864 s++;
1865 break;
H. Peter Anvin70653092007-10-19 14:42:29 -07001866 case 8:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001867 case 2:
1868 case 4:
1869 data = ins->oprs[(c >> 3) & 7].offset;
H. Peter Anvine9d7f1a2008-10-05 19:42:55 -07001870 warn_overflow(ea_data.bytes, opx);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001871 s += ea_data.bytes;
H. Peter Anvin9f817132008-10-06 19:11:07 -07001872 if (ea_data.rip) {
1873 data -= insn_end - (offset+ea_data.bytes);
1874 type = OUT_REL4ADR;
1875 } else {
1876 type = OUT_ADDRESS;
1877 }
1878 out(offset, segment, &data, type, ea_data.bytes,
1879 ins->oprs[(c >> 3) & 7].segment,
1880 ins->oprs[(c >> 3) & 7].wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001881 break;
1882 }
1883 offset += s;
H. Peter Anvin839eca22007-10-29 23:12:47 -07001884 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001885 errfunc(ERR_PANIC, "internal instruction table corrupt"
1886 ": instruction code 0x%02X given", c);
H. Peter Anvin839eca22007-10-29 23:12:47 -07001887 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001888 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001889 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001890}
1891
H. Peter Anvin0ec60e62007-07-07 01:59:52 +00001892static int32_t regflag(const operand * o)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001893{
1894 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1895 errfunc(ERR_PANIC, "invalid operand passed to regflag()");
1896 }
H. Peter Anvina4835d42008-05-20 14:21:29 -07001897 return nasm_reg_flags[o->basereg];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001898}
1899
H. Peter Anvin5b0e3ec2007-07-07 02:01:08 +00001900static int32_t regval(const operand * o)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001901{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001902 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1903 errfunc(ERR_PANIC, "invalid operand passed to regval()");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001904 }
H. Peter Anvina4835d42008-05-20 14:21:29 -07001905 return nasm_regvals[o->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001906}
1907
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001908static int op_rexflags(const operand * o, int mask)
1909{
1910 int32_t flags;
1911 int val;
1912
1913 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1914 errfunc(ERR_PANIC, "invalid operand passed to op_rexflags()");
1915 }
1916
H. Peter Anvina4835d42008-05-20 14:21:29 -07001917 flags = nasm_reg_flags[o->basereg];
1918 val = nasm_regvals[o->basereg];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001919
1920 return rexflags(val, flags, mask);
1921}
1922
1923static int rexflags(int val, int32_t flags, int mask)
1924{
1925 int rex = 0;
1926
1927 if (val >= 8)
1928 rex |= REX_B|REX_X|REX_R;
1929 if (flags & BITS64)
1930 rex |= REX_W;
1931 if (!(REG_HIGH & ~flags)) /* AH, CH, DH, BH */
1932 rex |= REX_H;
1933 else if (!(REG8 & ~flags) && val >= 4) /* SPL, BPL, SIL, DIL */
1934 rex |= REX_P;
1935
1936 return rex & mask;
1937}
1938
H. Peter Anvin3360d792007-09-11 04:16:57 +00001939static int matches(const struct itemplate *itemp, insn * instruction, int bits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001940{
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001941 int i, size[MAX_OPERANDS], asize, oprs, ret;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001942
1943 ret = 100;
1944
1945 /*
1946 * Check the opcode
1947 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001948 if (itemp->opcode != instruction->opcode)
1949 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001950
1951 /*
1952 * Count the operands
1953 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001954 if (itemp->operands != instruction->operands)
1955 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001956
1957 /*
1958 * Check that no spurious colons or TOs are present
1959 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001960 for (i = 0; i < itemp->operands; i++)
1961 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON | TO))
1962 return 0;
H. Peter Anvin70653092007-10-19 14:42:29 -07001963
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001964 /*
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001965 * Process size flags
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001966 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001967 if (itemp->flags & IF_ARMASK) {
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001968 memset(size, 0, sizeof size);
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001969
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001970 i = ((itemp->flags & IF_ARMASK) >> IF_ARSHFT) - 1;
1971
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001972 switch (itemp->flags & IF_SMASK) {
1973 case IF_SB:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001974 size[i] = BITS8;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001975 break;
1976 case IF_SW:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001977 size[i] = BITS16;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001978 break;
1979 case IF_SD:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001980 size[i] = BITS32;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001981 break;
1982 case IF_SQ:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001983 size[i] = BITS64;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001984 break;
H. Peter Anvin41c9f6f2007-09-18 13:01:32 -07001985 case IF_SO:
1986 size[i] = BITS128;
1987 break;
H. Peter Anvindfb91802008-05-20 11:43:53 -07001988 case IF_SY:
1989 size[i] = BITS256;
1990 break;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001991 case IF_SZ:
1992 switch (bits) {
1993 case 16:
1994 size[i] = BITS16;
1995 break;
1996 case 32:
1997 size[i] = BITS32;
1998 break;
1999 case 64:
2000 size[i] = BITS64;
2001 break;
2002 }
2003 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002004 default:
2005 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002006 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002007 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002008 asize = 0;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002009 switch (itemp->flags & IF_SMASK) {
2010 case IF_SB:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002011 asize = BITS8;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002012 break;
2013 case IF_SW:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002014 asize = BITS16;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002015 break;
2016 case IF_SD:
H. Peter Anvine2c80182005-01-15 22:15:51 +00002017 asize = BITS32;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002018 break;
2019 case IF_SQ:
Keith Kaniosb7a89542007-04-12 02:40:54 +00002020 asize = BITS64;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002021 break;
H. Peter Anvin41c9f6f2007-09-18 13:01:32 -07002022 case IF_SO:
2023 asize = BITS128;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002024 break;
H. Peter Anvindfb91802008-05-20 11:43:53 -07002025 case IF_SY:
2026 asize = BITS256;
2027 break;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002028 case IF_SZ:
2029 switch (bits) {
2030 case 16:
2031 asize = BITS16;
2032 break;
2033 case 32:
2034 asize = BITS32;
2035 break;
2036 case 64:
2037 asize = BITS64;
2038 break;
2039 }
H. Peter Anvin41c9f6f2007-09-18 13:01:32 -07002040 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002041 default:
2042 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002043 }
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002044 for (i = 0; i < MAX_OPERANDS; i++)
2045 size[i] = asize;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002046 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002047
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002048 /*
2049 * Check that the operand flags all match up
2050 */
2051 for (i = 0; i < itemp->operands; i++) {
2052 int32_t type = instruction->oprs[i].type;
2053 if (!(type & SIZE_MASK))
2054 type |= size[i];
H. Peter Anvind85d2502008-05-04 17:53:31 -07002055
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002056 if (itemp->opd[i] & SAME_AS) {
2057 int j = itemp->opd[i] & ~SAME_AS;
2058 if (type != instruction->oprs[j].type ||
2059 instruction->oprs[i].basereg != instruction->oprs[j].basereg)
2060 return 0;
2061 } else if (itemp->opd[i] & ~type ||
2062 ((itemp->opd[i] & SIZE_MASK) &&
2063 ((itemp->opd[i] ^ type) & SIZE_MASK))) {
2064 if ((itemp->opd[i] & ~type & ~SIZE_MASK) ||
2065 (type & SIZE_MASK))
2066 return 0;
2067 else
2068 return 1;
2069 }
2070 }
2071
2072 /*
2073 * Check operand sizes
2074 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002075 if (itemp->flags & (IF_SM | IF_SM2)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002076 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
2077 asize = 0;
2078 for (i = 0; i < oprs; i++) {
2079 if ((asize = itemp->opd[i] & SIZE_MASK) != 0) {
2080 int j;
2081 for (j = 0; j < oprs; j++)
2082 size[j] = asize;
2083 break;
2084 }
2085 }
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002086 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002087 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002088 }
2089
Keith Kaniosb7a89542007-04-12 02:40:54 +00002090 for (i = 0; i < itemp->operands; i++) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002091 if (!(itemp->opd[i] & SIZE_MASK) &&
2092 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvine2c80182005-01-15 22:15:51 +00002093 return 2;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002094 }
2095
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002096 /*
2097 * Check template is okay at the set cpu level
2098 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002099 if (((itemp->flags & IF_PLEVEL) > cpu))
H. Peter Anvine2c80182005-01-15 22:15:51 +00002100 return 3;
H. Peter Anvin70653092007-10-19 14:42:29 -07002101
Keith Kaniosb7a89542007-04-12 02:40:54 +00002102 /*
2103 * Check if instruction is available in long mode
2104 */
2105 if ((itemp->flags & IF_NOLONG) && (bits == 64))
2106 return 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002107
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002108 /*
2109 * Check if special handling needed for Jumps
2110 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002111 if ((uint8_t)(itemp->code[0]) >= 0370)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002112 return 99;
2113
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002114 return ret;
2115}
2116
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002117static ea *process_ea(operand * input, ea * output, int bits,
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07002118 int addrbits, int rfield, int32_t rflags)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002119{
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07002120 bool forw_ref = !!(input->opflags & OPFLAG_FORWARD);
2121
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002122 output->rip = false;
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00002123
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002124 /* REX flags for the rfield operand */
2125 output->rex |= rexflags(rfield, rflags, REX_R|REX_P|REX_W|REX_H);
2126
Keith Kaniosb7a89542007-04-12 02:40:54 +00002127 if (!(REGISTER & ~input->type)) { /* register direct */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002128 int i;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002129 int32_t f;
2130
2131 if (input->basereg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002132 || input->basereg >= REG_ENUM_LIMIT)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002133 return NULL;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002134 f = regflag(input);
H. Peter Anvina4835d42008-05-20 14:21:29 -07002135 i = nasm_regvals[input->basereg];
Keith Kaniosb7a89542007-04-12 02:40:54 +00002136
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002137 if (REG_EA & ~f)
2138 return NULL; /* Invalid EA register */
H. Peter Anvin70653092007-10-19 14:42:29 -07002139
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002140 output->rex |= op_rexflags(input, REX_B|REX_P|REX_W|REX_H);
2141
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002142 output->sib_present = false; /* no SIB necessary */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002143 output->bytes = 0; /* no offset necessary either */
2144 output->modrm = 0xC0 | ((rfield & 7) << 3) | (i & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002145 } else { /* it's a memory reference */
2146 if (input->basereg == -1
2147 && (input->indexreg == -1 || input->scale == 0)) {
2148 /* it's a pure offset */
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002149 if (bits == 64 && (~input->type & IP_REL)) {
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002150 int scale, index, base;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002151 output->sib_present = true;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002152 scale = 0;
2153 index = 4;
2154 base = 5;
2155 output->sib = (scale << 6) | (index << 3) | base;
2156 output->bytes = 4;
2157 output->modrm = 4 | ((rfield & 7) << 3);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002158 output->rip = false;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002159 } else {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002160 output->sib_present = false;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002161 output->bytes = (addrbits != 16 ? 4 : 2);
2162 output->modrm = (addrbits != 16 ? 5 : 6) | ((rfield & 7) << 3);
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002163 output->rip = bits == 64;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002164 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002165 } else { /* it's an indirection */
2166 int i = input->indexreg, b = input->basereg, s = input->scale;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002167 int32_t o = input->offset, seg = input->segment;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002168 int hb = input->hintbase, ht = input->hinttype;
2169 int t;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002170 int it, bt;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002171 int32_t ix, bx; /* register flags */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002172
H. Peter Anvine2c80182005-01-15 22:15:51 +00002173 if (s == 0)
2174 i = -1; /* make this easy, at least */
H. Peter Anvin70653092007-10-19 14:42:29 -07002175
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002176 if (i >= EXPR_REG_START && i < REG_ENUM_LIMIT) {
H. Peter Anvina4835d42008-05-20 14:21:29 -07002177 it = nasm_regvals[i];
2178 ix = nasm_reg_flags[i];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002179 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00002180 it = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002181 ix = 0;
2182 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002183
H. Peter Anvinb0c54622007-10-28 23:21:46 -07002184 if (b >= EXPR_REG_START && b < REG_ENUM_LIMIT) {
H. Peter Anvina4835d42008-05-20 14:21:29 -07002185 bt = nasm_regvals[b];
2186 bx = nasm_reg_flags[b];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002187 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00002188 bt = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002189 bx = 0;
2190 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002191
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002192 /* check for a 32/64-bit memory reference... */
2193 if ((ix|bx) & (BITS32|BITS64)) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00002194 /* it must be a 32/64-bit memory reference. Firstly we have
2195 * to check that all registers involved are type E/Rxx. */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002196 int32_t sok = BITS32|BITS64;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002197
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002198 if (it != -1) {
2199 if (!(REG64 & ~ix) || !(REG32 & ~ix))
2200 sok &= ix;
2201 else
2202 return NULL;
2203 }
2204
2205 if (bt != -1) {
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00002206 if (REG_GPR & ~bx)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002207 return NULL; /* Invalid register */
H. Peter Anvina57e8d42007-05-30 03:44:02 +00002208 if (~sok & bx & SIZE_MASK)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002209 return NULL; /* Invalid size */
H. Peter Anvinb0c54622007-10-28 23:21:46 -07002210 sok &= bx;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002211 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002212
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002213 /* While we're here, ensure the user didn't specify
2214 WORD or QWORD. */
2215 if (input->disp_size == 16 || input->disp_size == 64)
2216 return NULL;
2217
2218 if (addrbits == 16 ||
2219 (addrbits == 32 && !(sok & BITS32)) ||
2220 (addrbits == 64 && !(sok & BITS64)))
2221 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002222
Keith Kaniosb7a89542007-04-12 02:40:54 +00002223 /* now reorganize base/index */
2224 if (s == 1 && bt != it && bt != -1 && it != -1 &&
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002225 ((hb == b && ht == EAH_NOTBASE)
2226 || (hb == i && ht == EAH_MAKEBASE))) {
2227 /* swap if hints say so */
2228 t = bt, bt = it, it = t;
2229 t = bx, bx = ix, ix = t;
2230 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00002231 if (bt == it) /* convert EAX+2*EAX to 3*EAX */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002232 bt = -1, bx = 0, s++;
2233 if (bt == -1 && s == 1 && !(hb == it && ht == EAH_NOTBASE)) {
2234 /* make single reg base, unless hint */
2235 bt = it, bx = ix, it = -1, ix = 0;
2236 }
H. Peter Anvinf5843c62007-09-10 18:59:26 +00002237 if (((s == 2 && it != REG_NUM_ESP
H. Peter Anvine2c80182005-01-15 22:15:51 +00002238 && !(input->eaflags & EAF_TIMESTWO)) || s == 3
Keith Kaniosb7a89542007-04-12 02:40:54 +00002239 || s == 5 || s == 9) && bt == -1)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002240 bt = it, bx = ix, s--; /* convert 3*EAX to EAX+2*EAX */
Keith Kanios48af1772007-08-17 07:37:52 +00002241 if (it == -1 && (bt & 7) != REG_NUM_ESP
H. Peter Anvine2c80182005-01-15 22:15:51 +00002242 && (input->eaflags & EAF_TIMESTWO))
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002243 it = bt, ix = bx, bt = -1, bx = 0, s = 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002244 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
Keith Kanios48af1772007-08-17 07:37:52 +00002245 if (s == 1 && it == REG_NUM_ESP) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002246 /* swap ESP into base if scale is 1 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002247 t = it, it = bt, bt = t;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002248 t = ix, ix = bx, bx = t;
2249 }
Keith Kanios48af1772007-08-17 07:37:52 +00002250 if (it == REG_NUM_ESP
Keith Kaniosb7a89542007-04-12 02:40:54 +00002251 || (s != 1 && s != 2 && s != 4 && s != 8 && it != -1))
H. Peter Anvine2c80182005-01-15 22:15:51 +00002252 return NULL; /* wrong, for various reasons */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002253
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002254 output->rex |= rexflags(it, ix, REX_X);
2255 output->rex |= rexflags(bt, bx, REX_B);
Keith Kaniosb7a89542007-04-12 02:40:54 +00002256
Keith Kanios48af1772007-08-17 07:37:52 +00002257 if (it == -1 && (bt & 7) != REG_NUM_ESP) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002258 /* no SIB needed */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002259 int mod, rm;
H. Peter Anvin70653092007-10-19 14:42:29 -07002260
Keith Kaniosb7a89542007-04-12 02:40:54 +00002261 if (bt == -1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002262 rm = 5;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002263 mod = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002264 } else {
2265 rm = (bt & 7);
Keith Kanios48af1772007-08-17 07:37:52 +00002266 if (rm != REG_NUM_EBP && o == 0 &&
Keith Kaniosb7a89542007-04-12 02:40:54 +00002267 seg == NO_SEG && !forw_ref &&
2268 !(input->eaflags &
2269 (EAF_BYTEOFFS | EAF_WORDOFFS)))
2270 mod = 0;
2271 else if (input->eaflags & EAF_BYTEOFFS ||
2272 (o >= -128 && o <= 127 && seg == NO_SEG
2273 && !forw_ref
2274 && !(input->eaflags & EAF_WORDOFFS)))
2275 mod = 1;
2276 else
2277 mod = 2;
2278 }
H. Peter Anvinea838272002-04-30 20:51:53 +00002279
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002280 output->sib_present = false;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002281 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
2282 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002283 } else {
2284 /* we need a SIB */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002285 int mod, scale, index, base;
H. Peter Anvin70653092007-10-19 14:42:29 -07002286
Keith Kaniosb7a89542007-04-12 02:40:54 +00002287 if (it == -1)
2288 index = 4, s = 1;
2289 else
2290 index = (it & 7);
H. Peter Anvin70653092007-10-19 14:42:29 -07002291
H. Peter Anvine2c80182005-01-15 22:15:51 +00002292 switch (s) {
2293 case 1:
2294 scale = 0;
2295 break;
2296 case 2:
2297 scale = 1;
2298 break;
2299 case 4:
2300 scale = 2;
2301 break;
2302 case 8:
2303 scale = 3;
2304 break;
2305 default: /* then what the smeg is it? */
2306 return NULL; /* panic */
2307 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002308
Keith Kaniosb7a89542007-04-12 02:40:54 +00002309 if (bt == -1) {
2310 base = 5;
2311 mod = 0;
2312 } else {
2313 base = (bt & 7);
Keith Kanios48af1772007-08-17 07:37:52 +00002314 if (base != REG_NUM_EBP && o == 0 &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00002315 seg == NO_SEG && !forw_ref &&
2316 !(input->eaflags &
Keith Kaniosb7a89542007-04-12 02:40:54 +00002317 (EAF_BYTEOFFS | EAF_WORDOFFS)))
2318 mod = 0;
2319 else if (input->eaflags & EAF_BYTEOFFS ||
2320 (o >= -128 && o <= 127 && seg == NO_SEG
2321 && !forw_ref
2322 && !(input->eaflags & EAF_WORDOFFS)))
2323 mod = 1;
2324 else
2325 mod = 2;
2326 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002327
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002328 output->sib_present = true;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002329 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
2330 output->modrm = (mod << 6) | ((rfield & 7) << 3) | 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002331 output->sib = (scale << 6) | (index << 3) | base;
2332 }
2333 } else { /* it's 16-bit */
2334 int mod, rm;
H. Peter Anvin70653092007-10-19 14:42:29 -07002335
Keith Kaniosb7a89542007-04-12 02:40:54 +00002336 /* check for 64-bit long mode */
2337 if (addrbits == 64)
2338 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002339
H. Peter Anvine2c80182005-01-15 22:15:51 +00002340 /* check all registers are BX, BP, SI or DI */
2341 if ((b != -1 && b != R_BP && b != R_BX && b != R_SI
2342 && b != R_DI) || (i != -1 && i != R_BP && i != R_BX
2343 && i != R_SI && i != R_DI))
2344 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002345
Keith Kaniosb7a89542007-04-12 02:40:54 +00002346 /* ensure the user didn't specify DWORD/QWORD */
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002347 if (input->disp_size == 32 || input->disp_size == 64)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002348 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002349
H. Peter Anvine2c80182005-01-15 22:15:51 +00002350 if (s != 1 && i != -1)
2351 return NULL; /* no can do, in 16-bit EA */
2352 if (b == -1 && i != -1) {
2353 int tmp = b;
2354 b = i;
2355 i = tmp;
2356 } /* swap */
2357 if ((b == R_SI || b == R_DI) && i != -1) {
2358 int tmp = b;
2359 b = i;
2360 i = tmp;
2361 }
2362 /* have BX/BP as base, SI/DI index */
2363 if (b == i)
2364 return NULL; /* shouldn't ever happen, in theory */
2365 if (i != -1 && b != -1 &&
2366 (i == R_BP || i == R_BX || b == R_SI || b == R_DI))
2367 return NULL; /* invalid combinations */
2368 if (b == -1) /* pure offset: handled above */
2369 return NULL; /* so if it gets to here, panic! */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002370
H. Peter Anvine2c80182005-01-15 22:15:51 +00002371 rm = -1;
2372 if (i != -1)
2373 switch (i * 256 + b) {
2374 case R_SI * 256 + R_BX:
2375 rm = 0;
2376 break;
2377 case R_DI * 256 + R_BX:
2378 rm = 1;
2379 break;
2380 case R_SI * 256 + R_BP:
2381 rm = 2;
2382 break;
2383 case R_DI * 256 + R_BP:
2384 rm = 3;
2385 break;
2386 } else
2387 switch (b) {
2388 case R_SI:
2389 rm = 4;
2390 break;
2391 case R_DI:
2392 rm = 5;
2393 break;
2394 case R_BP:
2395 rm = 6;
2396 break;
2397 case R_BX:
2398 rm = 7;
2399 break;
2400 }
2401 if (rm == -1) /* can't happen, in theory */
2402 return NULL; /* so panic if it does */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002403
H. Peter Anvine2c80182005-01-15 22:15:51 +00002404 if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
2405 !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
2406 mod = 0;
2407 else if (input->eaflags & EAF_BYTEOFFS ||
2408 (o >= -128 && o <= 127 && seg == NO_SEG
2409 && !forw_ref
2410 && !(input->eaflags & EAF_WORDOFFS)))
2411 mod = 1;
2412 else
2413 mod = 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002414
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002415 output->sib_present = false; /* no SIB - it's 16-bit */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002416 output->bytes = mod; /* bytes of offset needed */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002417 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002418 }
2419 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002420 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002421
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002422 output->size = 1 + output->sib_present + output->bytes;
2423 return output;
2424}
2425
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002426static void add_asp(insn *ins, int addrbits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002427{
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002428 int j, valid;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002429 int defdisp;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002430
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002431 valid = (addrbits == 64) ? 64|32 : 32|16;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002432
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002433 switch (ins->prefixes[PPS_ASIZE]) {
2434 case P_A16:
2435 valid &= 16;
2436 break;
2437 case P_A32:
2438 valid &= 32;
2439 break;
2440 case P_A64:
2441 valid &= 64;
2442 break;
2443 case P_ASP:
2444 valid &= (addrbits == 32) ? 16 : 32;
2445 break;
2446 default:
2447 break;
2448 }
2449
2450 for (j = 0; j < ins->operands; j++) {
2451 if (!(MEMORY & ~ins->oprs[j].type)) {
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002452 int32_t i, b;
H. Peter Anvin70653092007-10-19 14:42:29 -07002453
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002454 /* Verify as Register */
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002455 if (ins->oprs[j].indexreg < EXPR_REG_START
2456 || ins->oprs[j].indexreg >= REG_ENUM_LIMIT)
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002457 i = 0;
2458 else
H. Peter Anvina4835d42008-05-20 14:21:29 -07002459 i = nasm_reg_flags[ins->oprs[j].indexreg];
H. Peter Anvin70653092007-10-19 14:42:29 -07002460
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002461 /* Verify as Register */
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002462 if (ins->oprs[j].basereg < EXPR_REG_START
2463 || ins->oprs[j].basereg >= REG_ENUM_LIMIT)
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002464 b = 0;
2465 else
H. Peter Anvina4835d42008-05-20 14:21:29 -07002466 b = nasm_reg_flags[ins->oprs[j].basereg];
H. Peter Anvin70653092007-10-19 14:42:29 -07002467
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002468 if (ins->oprs[j].scale == 0)
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002469 i = 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002470
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002471 if (!i && !b) {
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002472 int ds = ins->oprs[j].disp_size;
2473 if ((addrbits != 64 && ds > 8) ||
2474 (addrbits == 64 && ds == 16))
2475 valid &= ds;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002476 } else {
2477 if (!(REG16 & ~b))
2478 valid &= 16;
2479 if (!(REG32 & ~b))
2480 valid &= 32;
2481 if (!(REG64 & ~b))
2482 valid &= 64;
H. Peter Anvin70653092007-10-19 14:42:29 -07002483
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002484 if (!(REG16 & ~i))
2485 valid &= 16;
2486 if (!(REG32 & ~i))
2487 valid &= 32;
2488 if (!(REG64 & ~i))
2489 valid &= 64;
2490 }
2491 }
2492 }
2493
2494 if (valid & addrbits) {
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002495 ins->addr_size = addrbits;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002496 } else if (valid & ((addrbits == 32) ? 16 : 32)) {
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002497 /* Add an address size prefix */
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002498 enum prefixes pref = (addrbits == 32) ? P_A16 : P_A32;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002499 ins->prefixes[PPS_ASIZE] = pref;
2500 ins->addr_size = (addrbits == 32) ? 16 : 32;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002501 } else {
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002502 /* Impossible... */
2503 errfunc(ERR_NONFATAL, "impossible combination of address sizes");
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002504 ins->addr_size = addrbits; /* Error recovery */
2505 }
2506
2507 defdisp = ins->addr_size == 16 ? 16 : 32;
2508
2509 for (j = 0; j < ins->operands; j++) {
2510 if (!(MEM_OFFS & ~ins->oprs[j].type) &&
2511 (ins->oprs[j].disp_size ? ins->oprs[j].disp_size : defdisp)
2512 != ins->addr_size) {
2513 /* mem_offs sizes must match the address size; if not,
2514 strip the MEM_OFFS bit and match only EA instructions */
2515 ins->oprs[j].type &= ~(MEM_OFFS & ~MEMORY);
2516 }
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002517 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002518}