blob: 9d23240bd962f3cb5635ba270848e38c416d10a2 [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
32 * \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 Anvin7eb4a382007-09-17 15:49:30 -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 Anvinea6e34d2002-04-30 20:51:32 +000073 * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
74 * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
Keith Kanios48af1772007-08-17 07:37:52 +000075 * \312 - (disassembler only) marker on LOOP, LOOPxx instructions.
H. Peter Anvince2b3972007-05-30 22:21:11 +000076 * \313 - indicates fixed 64-bit address size, 0x67 invalid.
H. Peter Anvin23440102007-11-12 21:02:33 -080077 * \314 - (disassembler only) invalid with REX.B
78 * \315 - (disassembler only) invalid with REX.X
79 * \316 - (disassembler only) invalid with REX.R
80 * \317 - (disassembler only) invalid with REX.W
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000081 * \320 - indicates fixed 16-bit operand size, i.e. optional 0x66.
82 * \321 - indicates fixed 32-bit operand size, i.e. optional 0x66.
83 * \322 - indicates that this instruction is only valid when the
84 * operand size is the default (instruction to disassembler,
85 * generates no code in the assembler)
H. Peter Anvince2b3972007-05-30 22:21:11 +000086 * \323 - indicates fixed 64-bit operand size, REX on extensions only.
Keith Kaniosb7a89542007-04-12 02:40:54 +000087 * \324 - indicates 64-bit operand size requiring REX prefix.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000088 * \330 - a literal byte follows in the code stream, to be added
89 * to the condition code value of the instruction.
Keith Kanios48af1772007-08-17 07:37:52 +000090 * \331 - instruction not valid with REP prefix. Hint for
H. Peter Anvinef7468f2002-04-30 20:57:59 +000091 * disassembler only; for SSE instructions.
H. Peter Anvincb9b6902007-09-12 21:58:51 -070092 * \332 - REP prefix (0xF2 byte) used as opcode extension.
93 * \333 - REP prefix (0xF3 byte) used as opcode extension.
Keith Kanios48af1772007-08-17 07:37:52 +000094 * \334 - LOCK prefix used instead of REX.R
H. Peter Anvincb9b6902007-09-12 21:58:51 -070095 * \335 - disassemble a rep (0xF3 byte) prefix as repe not rep.
H. Peter Anvin962e3052008-08-28 17:47:16 -070096 * \336 - force a REP(E) prefix (0xF2) even if not specified.
97 * \337 - force a REPNE prefix (0xF3) even if not specified.
98 * \336-\337 are still listed as prefixes in the disassembler.
Keith Kaniosb7a89542007-04-12 02:40:54 +000099 * \340 - reserve <operand 0> bytes of uninitialized storage.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000100 * Operand 0 had better be a segmentless constant.
H. Peter Anvinfff5a472008-05-20 09:46:24 -0700101 * \360 - no SSE prefix (== \364\331)
102 * \361 - 66 SSE prefix (== \366\331)
103 * \362 - F2 SSE prefix (== \364\332)
104 * \363 - F3 SSE prefix (== \364\333)
H. Peter Anvin62cb6062007-09-11 22:44:03 +0000105 * \364 - operand-size prefix (0x66) not permitted
106 * \365 - address-size prefix (0x67) not permitted
107 * \366 - operand-size prefix (0x66) used as opcode extension
108 * \367 - address-size prefix (0x67) used as opcode extension
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000109 * \370,\371,\372 - match only if operand 0 meets byte jump criteria.
110 * 370 is used for Jcc, 371 is used for JMP.
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000111 * \373 - assemble 0x03 if bits==16, 0x05 if bits==32;
112 * used for conditional jump over longer jump
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000113 */
114
H. Peter Anvinfe501952007-10-02 21:53:51 -0700115#include "compiler.h"
116
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000117#include <stdio.h>
118#include <string.h>
Keith Kaniosb7a89542007-04-12 02:40:54 +0000119#include <inttypes.h>
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000120
121#include "nasm.h"
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000122#include "nasmlib.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000123#include "assemble.h"
124#include "insns.h"
H. Peter Anvina4835d42008-05-20 14:21:29 -0700125#include "tables.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000126
H. Peter Anvindfb91802008-05-20 11:43:53 -0700127/* Initialized to zero by the C standard */
128static const uint8_t const_zero_buf[256];
129
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000130typedef struct {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000131 int sib_present; /* is a SIB byte necessary? */
132 int bytes; /* # of bytes of offset needed */
133 int size; /* lazy - this is sib+bytes+1 */
134 uint8_t modrm, sib, rex, rip; /* the bytes themselves */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000135} ea;
136
Keith Kaniosb7a89542007-04-12 02:40:54 +0000137static uint32_t cpu; /* cpu level received from nasm.c */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000138static efunc errfunc;
139static struct ofmt *outfmt;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000140static ListGen *list;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000141
H. Peter Anvin3720f7b2008-05-12 11:00:50 -0700142static int64_t calcsize(int32_t, int64_t, int, insn *, const uint8_t *);
143static void gencode(int32_t, int64_t, int, insn *, const uint8_t *, int64_t);
H. Peter Anvin3360d792007-09-11 04:16:57 +0000144static int matches(const struct itemplate *, insn *, int bits);
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000145static int32_t regflag(const operand *);
146static int32_t regval(const operand *);
147static int rexflags(int, int32_t, int);
148static int op_rexflags(const operand *, int);
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700149static ea *process_ea(operand *, ea *, int, int, int, int32_t);
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700150static void add_asp(insn *, int);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000151
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700152static int has_prefix(insn * ins, enum prefix_pos pos, enum prefixes prefix)
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000153{
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700154 return ins->prefixes[pos] == prefix;
155}
156
157static void assert_no_prefix(insn * ins, enum prefix_pos pos)
158{
159 if (ins->prefixes[pos])
160 errfunc(ERR_NONFATAL, "invalid %s prefix",
161 prefix_name(ins->prefixes[pos]));
162}
163
164static const char *size_name(int size)
165{
166 switch (size) {
167 case 1:
168 return "byte";
169 case 2:
170 return "word";
171 case 4:
172 return "dword";
173 case 8:
174 return "qword";
175 case 10:
176 return "tword";
177 case 16:
178 return "oword";
H. Peter Anvindfb91802008-05-20 11:43:53 -0700179 case 32:
180 return "yword";
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700181 default:
182 return "???";
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000183 }
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700184}
185
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700186static void warn_overflow(int size, int64_t data)
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700187{
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700188 if (size < 8) {
Charles Craynedd462c82007-11-04 15:28:30 -0800189 int64_t lim = ((int64_t)1 << (size*8))-1;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000190
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700191 if (data < ~lim || data > lim)
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700192 errfunc(ERR_WARNING | ERR_WARN_NOV,
193 "%s data exceeds bounds", size_name(size));
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700194 }
195}
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000196/*
197 * This routine wrappers the real output format's output routine,
198 * in order to pass a copy of the data off to the listing file
199 * generator at the same time.
200 */
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800201static void out(int64_t offset, int32_t segto, const void *data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800202 enum out_type type, uint64_t size,
203 int32_t segment, int32_t wrt)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000204{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000205 static int32_t lineno = 0; /* static!!! */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000206 static char *lnfname = NULL;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800207 uint8_t p[8];
H. Peter Anvineba20a72002-04-30 20:53:55 +0000208
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800209 if (type == OUT_ADDRESS && segment == NO_SEG && wrt == NO_SEG) {
210 /*
211 * This is a non-relocated address, and we're going to
212 * convert it into RAWDATA format.
213 */
214 uint8_t *q = p;
H. Peter Anvind1fb15c2007-11-13 09:37:59 -0800215
216 if (size > 8) {
217 errfunc(ERR_PANIC, "OUT_ADDRESS with size > 8");
218 return;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800219 }
H. Peter Anvind85d2502008-05-04 17:53:31 -0700220
H. Peter Anvind1fb15c2007-11-13 09:37:59 -0800221 WRITEADDR(q, *(int64_t *)data, size);
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800222 data = p;
223 type = OUT_RAWDATA;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000224 }
225
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800226 list->output(offset, data, type, size);
227
Frank Kotlerabebb082003-09-06 04:45:37 +0000228 /*
229 * this call to src_get determines when we call the
230 * debug-format-specific "linenum" function
231 * it updates lineno and lnfname to the current values
232 * returning 0 if "same as last time", -2 if lnfname
233 * changed, and the amount by which lineno changed,
234 * if it did. thus, these variables must be static
235 */
236
H. Peter Anvine2c80182005-01-15 22:15:51 +0000237 if (src_get(&lineno, &lnfname)) {
238 outfmt->current_dfmt->linenum(lnfname, lineno, segto);
H. Peter Anvince616072002-04-30 21:02:23 +0000239 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000240
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800241 outfmt->output(segto, data, type, size, segment, wrt);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000242}
243
Charles Crayne5fbbc8c2007-11-07 19:03:46 -0800244static int jmp_match(int32_t segment, int64_t offset, int bits,
H. Peter Anvin3720f7b2008-05-12 11:00:50 -0700245 insn * ins, const uint8_t *code)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000246{
Charles Crayne5fbbc8c2007-11-07 19:03:46 -0800247 int64_t isize;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000248 uint8_t c = code[0];
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000249
Charles Craynef1aefd82008-09-30 16:11:32 -0700250 if ((c != 0370 && c != 0371) || (ins->oprs[0].type & STRICT))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000251 return 0;
Charles Craynef1aefd82008-09-30 16:11:32 -0700252 if (optimizing == 0)
253 {
254 return 0;
255 }
256 if (optimizing < 0 && c == 0371 )
Charles Crayne2581c862008-09-10 19:21:52 -0700257 {
258 return 0;
259 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000260 isize = calcsize(segment, offset, bits, ins, code);
261 if (ins->oprs[0].segment != segment)
262 return 0;
263 isize = ins->oprs[0].offset - offset - isize; /* isize is now the delta */
264 if (isize >= -128L && isize <= 127L)
265 return 1; /* it is byte size */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000266
267 return 0;
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 Anvin70653092007-10-19 14:42:29 -0700452
H. Peter Anvine2c80182005-01-15 22:15:51 +0000453 if (m == 99)
454 m += jmp_match(segment, offset, bits, instruction, temp->code);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000455
H. Peter Anvine2c80182005-01-15 22:15:51 +0000456 if (m == 100) { /* matches! */
H. Peter Anvin3720f7b2008-05-12 11:00:50 -0700457 const uint8_t *codes = temp->code;
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800458 int64_t insn_size = calcsize(segment, offset, bits,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000459 instruction, codes);
460 itimes = instruction->times;
461 if (insn_size < 0) /* shouldn't be, on pass two */
462 error(ERR_PANIC, "errors made it through from pass one");
463 else
464 while (itimes--) {
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700465 for (j = 0; j < MAXPREFIX; j++) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000466 uint8_t c = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000467 switch (instruction->prefixes[j]) {
468 case P_LOCK:
469 c = 0xF0;
470 break;
471 case P_REPNE:
472 case P_REPNZ:
473 c = 0xF2;
474 break;
475 case P_REPE:
476 case P_REPZ:
477 case P_REP:
478 c = 0xF3;
479 break;
480 case R_CS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000481 if (bits == 64) {
482 error(ERR_WARNING,
Charles Crayne1b851dc2007-11-05 21:49:49 -0800483 "cs segment base generated, but will be ignored in 64-bit mode");
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000484 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000485 c = 0x2E;
486 break;
487 case R_DS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000488 if (bits == 64) {
489 error(ERR_WARNING,
Charles Crayne1b851dc2007-11-05 21:49:49 -0800490 "ds segment base generated, but will be ignored in 64-bit mode");
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000491 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000492 c = 0x3E;
493 break;
494 case R_ES:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000495 if (bits == 64) {
496 error(ERR_WARNING,
Charles Crayne1b851dc2007-11-05 21:49:49 -0800497 "es segment base generated, but will be ignored in 64-bit mode");
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000498 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000499 c = 0x26;
500 break;
501 case R_FS:
502 c = 0x64;
503 break;
504 case R_GS:
505 c = 0x65;
506 break;
507 case R_SS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000508 if (bits == 64) {
509 error(ERR_WARNING,
Charles Crayne1b851dc2007-11-05 21:49:49 -0800510 "ss segment base generated, but will be ignored in 64-bit mode");
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000511 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000512 c = 0x36;
513 break;
514 case R_SEGR6:
515 case R_SEGR7:
516 error(ERR_NONFATAL,
517 "segr6 and segr7 cannot be used as prefixes");
518 break;
519 case P_A16:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000520 if (bits == 64) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000521 error(ERR_NONFATAL,
522 "16-bit addressing is not supported "
523 "in 64-bit mode");
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700524 } else if (bits != 16)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000525 c = 0x67;
526 break;
527 case P_A32:
528 if (bits != 32)
529 c = 0x67;
530 break;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700531 case P_A64:
532 if (bits != 64) {
533 error(ERR_NONFATAL,
534 "64-bit addressing is only supported "
535 "in 64-bit mode");
536 }
537 break;
538 case P_ASP:
539 c = 0x67;
540 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000541 case P_O16:
542 if (bits != 16)
543 c = 0x66;
544 break;
545 case P_O32:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000546 if (bits == 16)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000547 c = 0x66;
548 break;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700549 case P_O64:
550 /* REX.W */
551 break;
552 case P_OSP:
553 c = 0x66;
554 break;
555 case P_none:
556 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000557 default:
558 error(ERR_PANIC, "invalid instruction prefix");
559 }
560 if (c != 0) {
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800561 out(offset, segment, &c, OUT_RAWDATA, 1,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000562 NO_SEG, NO_SEG);
563 offset++;
564 }
H. Peter Anvin70653092007-10-19 14:42:29 -0700565 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000566 insn_end = offset + insn_size;
567 gencode(segment, offset, bits, instruction, codes,
568 insn_end);
569 offset += insn_size;
570 if (itimes > 0 && itimes == instruction->times - 1) {
571 /*
572 * Dummy call to list->output to give the offset to the
573 * listing module.
574 */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -0800575 list->output(offset, NULL, OUT_RAWDATA, 0);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000576 list->uplevel(LIST_TIMES);
577 }
578 }
579 if (instruction->times > 1)
580 list->downlevel(LIST_TIMES);
581 return offset - start;
582 } else if (m > 0 && m > size_prob) {
583 size_prob = m;
584 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000585// temp++;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000586 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000587
H. Peter Anvine2c80182005-01-15 22:15:51 +0000588 if (temp->opcode == -1) { /* didn't match any instruction */
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000589 switch (size_prob) {
590 case 1:
591 error(ERR_NONFATAL, "operation size not specified");
592 break;
593 case 2:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000594 error(ERR_NONFATAL, "mismatch in operand sizes");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000595 break;
596 case 3:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000597 error(ERR_NONFATAL, "no instruction for this cpu level");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000598 break;
599 case 4:
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000600 error(ERR_NONFATAL, "instruction not supported in 64-bit mode");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000601 break;
602 default:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000603 error(ERR_NONFATAL,
604 "invalid combination of opcode and operands");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000605 break;
606 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000607 }
608 return 0;
609}
610
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800611int64_t insn_size(int32_t segment, int64_t offset, int bits, uint32_t cp,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000612 insn * instruction, efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000613{
H. Peter Anvin3360d792007-09-11 04:16:57 +0000614 const struct itemplate *temp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000615
H. Peter Anvine2c80182005-01-15 22:15:51 +0000616 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000617 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000618
619 if (instruction->opcode == -1)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000620 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000621
H. Peter Anvincfbe7c32007-09-18 17:49:09 -0700622 if (instruction->opcode == I_DB || instruction->opcode == I_DW ||
623 instruction->opcode == I_DD || instruction->opcode == I_DQ ||
H. Peter Anvindfb91802008-05-20 11:43:53 -0700624 instruction->opcode == I_DT || instruction->opcode == I_DO ||
625 instruction->opcode == I_DY) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000626 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000627 int32_t isize, osize, wsize = 0; /* placate gcc */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000628
H. Peter Anvine2c80182005-01-15 22:15:51 +0000629 isize = 0;
630 switch (instruction->opcode) {
631 case I_DB:
632 wsize = 1;
633 break;
634 case I_DW:
635 wsize = 2;
636 break;
637 case I_DD:
638 wsize = 4;
639 break;
640 case I_DQ:
641 wsize = 8;
642 break;
643 case I_DT:
644 wsize = 10;
645 break;
H. Peter Anvincfbe7c32007-09-18 17:49:09 -0700646 case I_DO:
647 wsize = 16;
648 break;
H. Peter Anvindfb91802008-05-20 11:43:53 -0700649 case I_DY:
650 wsize = 32;
651 break;
H. Peter Anvin16b0a332007-09-12 20:27:41 -0700652 default:
653 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000654 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000655
H. Peter Anvine2c80182005-01-15 22:15:51 +0000656 for (e = instruction->eops; e; e = e->next) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000657 int32_t align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000658
H. Peter Anvine2c80182005-01-15 22:15:51 +0000659 osize = 0;
660 if (e->type == EOT_DB_NUMBER)
661 osize = 1;
H. Peter Anvin518df302008-06-14 16:53:48 -0700662 else if (e->type == EOT_DB_STRING ||
663 e->type == EOT_DB_STRING_FREE)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000664 osize = e->stringlen;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000665
H. Peter Anvine2c80182005-01-15 22:15:51 +0000666 align = (-osize) % wsize;
667 if (align < 0)
668 align += wsize;
669 isize += osize + align;
670 }
671 return isize * instruction->times;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000672 }
673
H. Peter Anvine2c80182005-01-15 22:15:51 +0000674 if (instruction->opcode == I_INCBIN) {
H. Peter Anvin518df302008-06-14 16:53:48 -0700675 const char *fname = instruction->eops->stringval;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000676 FILE *fp;
H. Peter Anvin518df302008-06-14 16:53:48 -0700677 size_t len;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000678
H. Peter Anvin418ca702008-05-30 10:42:30 -0700679 fp = fopen(fname, "rb");
680 if (!fp)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000681 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
682 fname);
683 else if (fseek(fp, 0L, SEEK_END) < 0)
684 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
685 fname);
686 else {
687 len = ftell(fp);
688 fclose(fp);
689 if (instruction->eops->next) {
690 len -= instruction->eops->next->offset;
691 if (instruction->eops->next->next &&
H. Peter Anvin518df302008-06-14 16:53:48 -0700692 len > (size_t)instruction->eops->next->next->offset) {
693 len = (size_t)instruction->eops->next->next->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000694 }
695 }
696 return instruction->times * len;
697 }
698 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000699 }
700
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700701 /* Check to see if we need an address-size prefix */
702 add_asp(instruction, bits);
703
Keith Kaniosb7a89542007-04-12 02:40:54 +0000704 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++) {
705 int m = matches(temp, instruction, bits);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000706 if (m == 99)
707 m += jmp_match(segment, offset, bits, instruction, temp->code);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000708
H. Peter Anvine2c80182005-01-15 22:15:51 +0000709 if (m == 100) {
710 /* we've matched an instruction. */
Charles Crayne5fbbc8c2007-11-07 19:03:46 -0800711 int64_t isize;
H. Peter Anvin3720f7b2008-05-12 11:00:50 -0700712 const uint8_t *codes = temp->code;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000713 int j;
714
715 isize = calcsize(segment, offset, bits, instruction, codes);
716 if (isize < 0)
717 return -1;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700718 for (j = 0; j < MAXPREFIX; j++) {
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700719 switch (instruction->prefixes[j]) {
720 case P_A16:
721 if (bits != 16)
722 isize++;
723 break;
724 case P_A32:
725 if (bits != 32)
726 isize++;
727 break;
728 case P_O16:
729 if (bits != 16)
730 isize++;
731 break;
732 case P_O32:
733 if (bits == 16)
734 isize++;
735 break;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700736 case P_A64:
737 case P_O64:
738 case P_none:
739 break;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700740 default:
741 isize++;
742 break;
743 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000744 }
745 return isize * instruction->times;
746 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000747 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000748 return -1; /* didn't match any instruction */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000749}
750
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700751static bool possible_sbyte(operand *o)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000752{
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700753 return !(o->opflags & OPFLAG_FORWARD) &&
754 optimizing >= 0 && !(o->type & STRICT) &&
755 o->wrt == NO_SEG && o->segment == NO_SEG;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000756}
757
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700758/* check that opn[op] is a signed byte of size 16 or 32 */
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700759static bool is_sbyte16(operand *o)
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700760{
761 int16_t v;
762
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700763 if (!possible_sbyte(o))
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700764 return false;
765
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700766 v = o->offset;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700767 return v >= -128 && v <= 127;
768}
769
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700770static bool is_sbyte32(operand *o)
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700771{
772 int32_t v;
773
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700774 if (!possible_sbyte(o))
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700775 return false;
776
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700777 v = o->offset;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700778 return v >= -128 && v <= 127;
779}
780
781/* check that opn[op] is a signed byte of size 32; warn if this is not
782 the original value when extended to 64 bits */
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700783static bool is_sbyte64(operand *o)
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700784{
785 int64_t v64;
786 int32_t v32;
787
788 /* dead in the water on forward reference or External */
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700789 if (!possible_sbyte(o))
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700790 return false;
791
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700792 v64 = o->offset;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700793 v32 = (int32_t)v64;
794
795 warn_overflow(32, v64);
796
797 return v32 >= -128 && v32 <= 127;
798}
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800799static int64_t calcsize(int32_t segment, int64_t offset, int bits,
H. Peter Anvin3720f7b2008-05-12 11:00:50 -0700800 insn * ins, const uint8_t *codes)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000801{
Charles Crayne1f8bc4c2007-11-06 18:27:23 -0800802 int64_t length = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000803 uint8_t c;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000804 int rex_mask = ~0;
H. Peter Anvin839eca22007-10-29 23:12:47 -0700805 struct operand *opx;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000806
H. Peter Anvine3917fc2007-11-01 14:53:32 -0700807 ins->rex = 0; /* Ensure REX is reset */
808
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700809 if (ins->prefixes[PPS_OSIZE] == P_O64)
810 ins->rex |= REX_W;
811
H. Peter Anvine2c80182005-01-15 22:15:51 +0000812 (void)segment; /* Don't warn that this parameter is unused */
813 (void)offset; /* Don't warn that this parameter is unused */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000814
H. Peter Anvin839eca22007-10-29 23:12:47 -0700815 while (*codes) {
816 c = *codes++;
817 opx = &ins->oprs[c & 3];
818 switch (c) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000819 case 01:
820 case 02:
821 case 03:
822 codes += c, length += c;
823 break;
824 case 04:
825 case 05:
826 case 06:
827 case 07:
828 length++;
829 break;
830 case 010:
831 case 011:
832 case 012:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700833 case 013:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000834 ins->rex |=
H. Peter Anvin839eca22007-10-29 23:12:47 -0700835 op_rexflags(opx, REX_B|REX_H|REX_P|REX_W);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000836 codes++, length++;
837 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000838 case 014:
839 case 015:
840 case 016:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700841 case 017:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000842 length++;
843 break;
844 case 020:
845 case 021:
846 case 022:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700847 case 023:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000848 length++;
849 break;
850 case 024:
851 case 025:
852 case 026:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700853 case 027:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000854 length++;
855 break;
856 case 030:
857 case 031:
858 case 032:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700859 case 033:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000860 length += 2;
861 break;
862 case 034:
863 case 035:
864 case 036:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700865 case 037:
H. Peter Anvin839eca22007-10-29 23:12:47 -0700866 if (opx->type & (BITS16 | BITS32 | BITS64))
867 length += (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000868 else
869 length += (bits == 16) ? 2 : 4;
870 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000871 case 040:
872 case 041:
873 case 042:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700874 case 043:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000875 length += 4;
876 break;
877 case 044:
878 case 045:
879 case 046:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700880 case 047:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -0700881 length += ins->addr_size >> 3;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000882 break;
883 case 050:
884 case 051:
885 case 052:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700886 case 053:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000887 length++;
888 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000889 case 054:
890 case 055:
891 case 056:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700892 case 057:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000893 length += 8; /* MOV reg64/imm */
894 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000895 case 060:
896 case 061:
897 case 062:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700898 case 063:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000899 length += 2;
900 break;
901 case 064:
902 case 065:
903 case 066:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700904 case 067:
H. Peter Anvin839eca22007-10-29 23:12:47 -0700905 if (opx->type & (BITS16 | BITS32 | BITS64))
906 length += (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000907 else
908 length += (bits == 16) ? 2 : 4;
909 break;
910 case 070:
911 case 071:
912 case 072:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700913 case 073:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000914 length += 4;
915 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700916 case 074:
917 case 075:
918 case 076:
919 case 077:
920 length += 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000921 break;
922 case 0140:
923 case 0141:
924 case 0142:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700925 case 0143:
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700926 length += is_sbyte16(opx) ? 1 : 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000927 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000928 case 0144:
929 case 0145:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700930 case 0146:
931 case 0147:
H. Peter Anvina30cc072007-11-18 21:55:26 -0800932 codes++;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000933 length++;
934 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700935 case 0150:
936 case 0151:
937 case 0152:
938 case 0153:
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700939 length += is_sbyte32(opx) ? 1 : 4;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700940 break;
941 case 0154:
942 case 0155:
943 case 0156:
944 case 0157:
H. Peter Anvina30cc072007-11-18 21:55:26 -0800945 codes++;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700946 length++;
947 break;
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700948 case 0160:
949 case 0161:
950 case 0162:
951 case 0163:
952 length++;
953 ins->rex |= REX_D;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700954 ins->drexdst = regval(opx);
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700955 break;
956 case 0164:
957 case 0165:
958 case 0166:
959 case 0167:
960 length++;
961 ins->rex |= REX_D|REX_OC;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700962 ins->drexdst = regval(opx);
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700963 break;
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700964 case 0171:
965 break;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700966 case 0172:
H. Peter Anvind58656f2008-05-06 20:11:14 -0700967 case 0173:
H. Peter Anvin52dc3532008-05-20 19:29:04 -0700968 case 0174:
H. Peter Anvind85d2502008-05-04 17:53:31 -0700969 codes++;
970 length++;
971 break;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700972 case 0250:
973 case 0251:
974 case 0252:
975 case 0253:
H. Peter Anvin1c3277b2008-07-19 21:38:56 -0700976 length += is_sbyte64(opx) ? 1 : 4;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -0700977 break;
H. Peter Anvind85d2502008-05-04 17:53:31 -0700978 case 0260:
979 case 0261:
980 case 0262:
981 case 0263:
H. Peter Anvind85d2502008-05-04 17:53:31 -0700982 ins->rex |= REX_V;
983 ins->drexdst = regval(opx);
984 ins->vex_m = *codes++;
985 ins->vex_wlp = *codes++;
986 break;
987 case 0270:
H. Peter Anvind85d2502008-05-04 17:53:31 -0700988 ins->rex |= REX_V;
989 ins->drexdst = 0;
990 ins->vex_m = *codes++;
991 ins->vex_wlp = *codes++;
992 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000993 case 0300:
994 case 0301:
H. Peter Anvin70653092007-10-19 14:42:29 -0700995 case 0302:
996 case 0303:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000997 break;
998 case 0310:
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -0700999 if (bits == 64)
1000 return -1;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001001 length += (bits != 16) && !has_prefix(ins, PPS_ASIZE, P_A16);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001002 break;
1003 case 0311:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001004 length += (bits != 32) && !has_prefix(ins, PPS_ASIZE, P_A32);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001005 break;
1006 case 0312:
H. Peter Anvin70653092007-10-19 14:42:29 -07001007 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001008 case 0313:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001009 if (bits != 64 || has_prefix(ins, PPS_ASIZE, P_A16) ||
1010 has_prefix(ins, PPS_ASIZE, P_A32))
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07001011 return -1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001012 break;
H. Peter Anvin23440102007-11-12 21:02:33 -08001013 case 0314:
1014 case 0315:
1015 case 0316:
1016 case 0317:
1017 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001018 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001019 length += (bits != 16);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001020 break;
1021 case 0321:
1022 length += (bits == 16);
1023 break;
1024 case 0322:
1025 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001026 case 0323:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001027 rex_mask &= ~REX_W;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001028 break;
1029 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001030 ins->rex |= REX_W;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +00001031 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001032 case 0330:
1033 codes++, length++;
1034 break;
1035 case 0331:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001036 break;
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001037 case 0332:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001038 case 0333:
1039 length++;
1040 break;
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001041 case 0334:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001042 ins->rex |= REX_L;
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001043 break;
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001044 case 0335:
1045 break;
H. Peter Anvin962e3052008-08-28 17:47:16 -07001046 case 0336:
1047 if (!ins->prefixes[PPS_LREP])
1048 ins->prefixes[PPS_LREP] = P_REP;
1049 break;
1050 case 0337:
1051 if (!ins->prefixes[PPS_LREP])
1052 ins->prefixes[PPS_LREP] = P_REPNE;
1053 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001054 case 0340:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001055 if (ins->oprs[0].segment != NO_SEG)
1056 errfunc(ERR_NONFATAL, "attempt to reserve non-constant"
1057 " quantity of BSS space");
1058 else
H. Peter Anvin428fd672007-11-15 10:25:52 -08001059 length += ins->oprs[0].offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001060 break;
H. Peter Anvinfff5a472008-05-20 09:46:24 -07001061 case 0360:
1062 break;
1063 case 0361:
1064 case 0362:
1065 case 0363:
1066 length++;
1067 break;
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001068 case 0364:
1069 case 0365:
1070 break;
Keith Kanios48af1772007-08-17 07:37:52 +00001071 case 0366:
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001072 case 0367:
1073 length++;
1074 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001075 case 0370:
1076 case 0371:
1077 case 0372:
1078 break;
1079 case 0373:
1080 length++;
1081 break;
1082 default: /* can't do it by 'case' statements */
1083 if (c >= 0100 && c <= 0277) { /* it's an EA */
1084 ea ea_data;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001085 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001086 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001087 ea_data.rex = 0; /* Ensure ea.REX is initially 0 */
H. Peter Anvin70653092007-10-19 14:42:29 -07001088
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001089 if (c <= 0177) {
1090 /* pick rfield from operand b */
1091 rflags = regflag(&ins->oprs[c & 7]);
H. Peter Anvina4835d42008-05-20 14:21:29 -07001092 rfield = nasm_regvals[ins->oprs[c & 7].basereg];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001093 } else {
1094 rflags = 0;
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001095 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001096 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001097
H. Peter Anvine2c80182005-01-15 22:15:51 +00001098 if (!process_ea
Keith Kaniosb7a89542007-04-12 02:40:54 +00001099 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001100 ins->addr_size, rfield, rflags)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001101 errfunc(ERR_NONFATAL, "invalid effective address");
1102 return -1;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001103 } else {
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001104 ins->rex |= ea_data.rex;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001105 length += ea_data.size;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001106 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001107 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001108 errfunc(ERR_PANIC, "internal instruction table corrupt"
1109 ": instruction code 0x%02X given", c);
H. Peter Anvin839eca22007-10-29 23:12:47 -07001110 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001111 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001112 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001113
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001114 ins->rex &= rex_mask;
H. Peter Anvin70653092007-10-19 14:42:29 -07001115
H. Peter Anvind85d2502008-05-04 17:53:31 -07001116 if (ins->rex & REX_V) {
1117 int bad32 = REX_R|REX_W|REX_X|REX_B;
1118
1119 if (ins->rex & REX_H) {
1120 errfunc(ERR_NONFATAL, "cannot use high register in vex instruction");
1121 return -1;
1122 }
1123 switch (ins->vex_wlp & 030) {
1124 case 000:
H. Peter Anvinbd420c72008-05-22 11:24:35 -07001125 case 020:
H. Peter Anvind85d2502008-05-04 17:53:31 -07001126 ins->rex &= ~REX_W;
1127 break;
1128 case 010:
1129 ins->rex |= REX_W;
1130 bad32 &= ~REX_W;
1131 break;
H. Peter Anvinbd420c72008-05-22 11:24:35 -07001132 case 030:
H. Peter Anvind85d2502008-05-04 17:53:31 -07001133 /* Follow REX_W */
1134 break;
1135 }
1136
1137 if (bits != 64 && ((ins->rex & bad32) || ins->drexdst > 7)) {
1138 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
1139 return -1;
1140 }
1141 if (ins->vex_m != 1 || (ins->rex & (REX_W|REX_R|REX_B)))
1142 length += 3;
1143 else
1144 length += 2;
1145 } else if (ins->rex & REX_D) {
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001146 if (ins->rex & REX_H) {
1147 errfunc(ERR_NONFATAL, "cannot use high register in drex instruction");
1148 return -1;
1149 }
H. Peter Anvind85d2502008-05-04 17:53:31 -07001150 if (bits != 64 && ((ins->rex & (REX_R|REX_W|REX_X|REX_B)) ||
H. Peter Anvincf5180a2007-09-17 17:25:27 -07001151 ins->drexdst > 7)) {
1152 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
1153 return -1;
1154 }
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001155 length++;
1156 } else if (ins->rex & REX_REAL) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001157 if (ins->rex & REX_H) {
1158 errfunc(ERR_NONFATAL, "cannot use high register in rex instruction");
1159 return -1;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001160 } else if (bits == 64) {
1161 length++;
1162 } else if ((ins->rex & REX_L) &&
1163 !(ins->rex & (REX_P|REX_W|REX_X|REX_B)) &&
1164 cpu >= IF_X86_64) {
1165 /* LOCK-as-REX.R */
1166 assert_no_prefix(ins, PPS_LREP);
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001167 length++;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +00001168 } else {
H. Peter Anvincf5180a2007-09-17 17:25:27 -07001169 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
1170 return -1;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +00001171 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001172 }
1173
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001174 return length;
1175}
Keith Kaniosb7a89542007-04-12 02:40:54 +00001176
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001177#define EMIT_REX() \
H. Peter Anvind85d2502008-05-04 17:53:31 -07001178 if (!(ins->rex & (REX_D|REX_V)) && (ins->rex & REX_REAL) && (bits == 64)) { \
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001179 ins->rex = (ins->rex & REX_REAL)|REX_P; \
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001180 out(offset, segment, &ins->rex, OUT_RAWDATA, 1, NO_SEG, NO_SEG); \
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001181 ins->rex = 0; \
1182 offset += 1; \
1183 }
1184
Charles Crayne1f8bc4c2007-11-06 18:27:23 -08001185static void gencode(int32_t segment, int64_t offset, int bits,
H. Peter Anvin3720f7b2008-05-12 11:00:50 -07001186 insn * ins, const uint8_t *codes, int64_t insn_end)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001187{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001188 static char condval[] = { /* conditional opcodes */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001189 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
1190 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
1191 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001192 };
Keith Kaniosb7a89542007-04-12 02:40:54 +00001193 uint8_t c;
1194 uint8_t bytes[4];
Charles Crayne1f8bc4c2007-11-06 18:27:23 -08001195 int64_t size;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001196 int64_t data;
H. Peter Anvin839eca22007-10-29 23:12:47 -07001197 struct operand *opx;
H. Peter Anvin70653092007-10-19 14:42:29 -07001198
H. Peter Anvin839eca22007-10-29 23:12:47 -07001199 while (*codes) {
1200 c = *codes++;
1201 opx = &ins->oprs[c & 3];
1202 switch (c) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001203 case 01:
1204 case 02:
1205 case 03:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001206 EMIT_REX();
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001207 out(offset, segment, codes, OUT_RAWDATA, c, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001208 codes += c;
1209 offset += c;
1210 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001211
H. Peter Anvine2c80182005-01-15 22:15:51 +00001212 case 04:
1213 case 06:
1214 switch (ins->oprs[0].basereg) {
1215 case R_CS:
1216 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0);
1217 break;
1218 case R_DS:
1219 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0);
1220 break;
1221 case R_ES:
1222 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0);
1223 break;
1224 case R_SS:
1225 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0);
1226 break;
1227 default:
1228 errfunc(ERR_PANIC,
1229 "bizarre 8086 segment register received");
1230 }
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001231 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001232 offset++;
1233 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001234
H. Peter Anvine2c80182005-01-15 22:15:51 +00001235 case 05:
1236 case 07:
1237 switch (ins->oprs[0].basereg) {
1238 case R_FS:
1239 bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0);
1240 break;
1241 case R_GS:
1242 bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0);
1243 break;
1244 default:
1245 errfunc(ERR_PANIC,
1246 "bizarre 386 segment register received");
1247 }
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001248 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001249 offset++;
1250 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001251
H. Peter Anvine2c80182005-01-15 22:15:51 +00001252 case 010:
1253 case 011:
1254 case 012:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001255 case 013:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001256 EMIT_REX();
H. Peter Anvin839eca22007-10-29 23:12:47 -07001257 bytes[0] = *codes++ + ((regval(opx)) & 7);
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001258 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001259 offset += 1;
1260 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001261
H. Peter Anvine2c80182005-01-15 22:15:51 +00001262 case 014:
1263 case 015:
1264 case 016:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001265 case 017:
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001266 /* XXX: warns for legitimate optimizer actions */
H. Peter Anvin839eca22007-10-29 23:12:47 -07001267 if (opx->offset < -128 || opx->offset > 127) {
H. Peter Anvin72c64372008-01-08 22:13:48 -08001268 errfunc(ERR_WARNING | ERR_WARN_NOV,
1269 "signed byte value exceeds bounds");
H. Peter Anvine2c80182005-01-15 22:15:51 +00001270 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001271
H. Peter Anvin839eca22007-10-29 23:12:47 -07001272 if (opx->segment != NO_SEG) {
1273 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001274 out(offset, segment, &data, OUT_ADDRESS, 1,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001275 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001276 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001277 bytes[0] = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001278 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001279 NO_SEG);
1280 }
1281 offset += 1;
1282 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001283
H. Peter Anvine2c80182005-01-15 22:15:51 +00001284 case 020:
1285 case 021:
1286 case 022:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001287 case 023:
H. Peter Anvin839eca22007-10-29 23:12:47 -07001288 if (opx->offset < -256 || opx->offset > 255) {
H. Peter Anvin72c64372008-01-08 22:13:48 -08001289 errfunc(ERR_WARNING | ERR_WARN_NOV,
1290 "byte value exceeds bounds");
H. Peter Anvine2c80182005-01-15 22:15:51 +00001291 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001292 if (opx->segment != NO_SEG) {
1293 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001294 out(offset, segment, &data, OUT_ADDRESS, 1,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001295 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001296 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001297 bytes[0] = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001298 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001299 NO_SEG);
1300 }
1301 offset += 1;
1302 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001303
H. Peter Anvine2c80182005-01-15 22:15:51 +00001304 case 024:
1305 case 025:
1306 case 026:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001307 case 027:
H. Peter Anvin839eca22007-10-29 23:12:47 -07001308 if (opx->offset < 0 || opx->offset > 255)
H. Peter Anvin72c64372008-01-08 22:13:48 -08001309 errfunc(ERR_WARNING | ERR_WARN_NOV,
1310 "unsigned byte value exceeds bounds");
H. Peter Anvin839eca22007-10-29 23:12:47 -07001311 if (opx->segment != NO_SEG) {
1312 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001313 out(offset, segment, &data, OUT_ADDRESS, 1,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001314 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001315 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001316 bytes[0] = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001317 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001318 NO_SEG);
1319 }
1320 offset += 1;
1321 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001322
H. Peter Anvine2c80182005-01-15 22:15:51 +00001323 case 030:
1324 case 031:
1325 case 032:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001326 case 033:
H. Peter Anvin839eca22007-10-29 23:12:47 -07001327 data = opx->offset;
1328 if (opx->segment == NO_SEG && opx->wrt == NO_SEG)
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001329 warn_overflow(2, data);
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001330 out(offset, segment, &data, OUT_ADDRESS, 2,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001331 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001332 offset += 2;
1333 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001334
H. Peter Anvine2c80182005-01-15 22:15:51 +00001335 case 034:
1336 case 035:
1337 case 036:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001338 case 037:
H. Peter Anvin839eca22007-10-29 23:12:47 -07001339 if (opx->type & (BITS16 | BITS32))
1340 size = (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001341 else
1342 size = (bits == 16) ? 2 : 4;
H. Peter Anvin839eca22007-10-29 23:12:47 -07001343 data = opx->offset;
1344 if (opx->segment == NO_SEG && opx->wrt == NO_SEG)
H. Peter Anvin10e27272007-10-29 22:56:08 -07001345 warn_overflow(size, data);
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001346 out(offset, segment, &data, OUT_ADDRESS, size,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001347 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001348 offset += size;
1349 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001350
H. Peter Anvine2c80182005-01-15 22:15:51 +00001351 case 040:
1352 case 041:
1353 case 042:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001354 case 043:
H. Peter Anvin839eca22007-10-29 23:12:47 -07001355 data = opx->offset;
H. Peter Anvin72c64372008-01-08 22:13:48 -08001356 if (opx->segment == NO_SEG && opx->wrt == NO_SEG)
1357 warn_overflow(4, data);
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001358 out(offset, segment, &data, OUT_ADDRESS, 4,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001359 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001360 offset += 4;
1361 break;
H. Peter Anvin3ba46772002-05-27 23:19:35 +00001362
H. Peter Anvine2c80182005-01-15 22:15:51 +00001363 case 044:
1364 case 045:
1365 case 046:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001366 case 047:
H. Peter Anvin839eca22007-10-29 23:12:47 -07001367 data = opx->offset;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001368 size = ins->addr_size >> 3;
H. Peter Anvin839eca22007-10-29 23:12:47 -07001369 if (opx->segment == NO_SEG &&
1370 opx->wrt == NO_SEG)
H. Peter Anvin10e27272007-10-29 22:56:08 -07001371 warn_overflow(size, data);
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001372 out(offset, segment, &data, OUT_ADDRESS, size,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001373 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001374 offset += size;
1375 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001376
H. Peter Anvine2c80182005-01-15 22:15:51 +00001377 case 050:
1378 case 051:
1379 case 052:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001380 case 053:
H. Peter Anvin839eca22007-10-29 23:12:47 -07001381 if (opx->segment != segment)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001382 errfunc(ERR_NONFATAL,
1383 "short relative jump outside segment");
H. Peter Anvin839eca22007-10-29 23:12:47 -07001384 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001385 if (data > 127 || data < -128)
1386 errfunc(ERR_NONFATAL, "short jump is out of range");
1387 bytes[0] = data;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001388 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001389 offset += 1;
1390 break;
H. Peter Anvin70653092007-10-19 14:42:29 -07001391
Keith Kaniosb7a89542007-04-12 02:40:54 +00001392 case 054:
1393 case 055:
1394 case 056:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001395 case 057:
H. Peter Anvin839eca22007-10-29 23:12:47 -07001396 data = (int64_t)opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001397 out(offset, segment, &data, OUT_ADDRESS, 8,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001398 opx->segment, opx->wrt);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001399 offset += 8;
1400 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001401
H. Peter Anvine2c80182005-01-15 22:15:51 +00001402 case 060:
1403 case 061:
1404 case 062:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001405 case 063:
H. Peter Anvin839eca22007-10-29 23:12:47 -07001406 if (opx->segment != segment) {
1407 data = opx->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001408 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001409 OUT_REL2ADR, insn_end - offset,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001410 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001411 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001412 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001413 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001414 OUT_ADDRESS, 2, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001415 }
1416 offset += 2;
1417 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001418
H. Peter Anvine2c80182005-01-15 22:15:51 +00001419 case 064:
1420 case 065:
1421 case 066:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001422 case 067:
H. Peter Anvin839eca22007-10-29 23:12:47 -07001423 if (opx->type & (BITS16 | BITS32 | BITS64))
1424 size = (opx->type & BITS16) ? 2 : 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001425 else
1426 size = (bits == 16) ? 2 : 4;
H. Peter Anvin839eca22007-10-29 23:12:47 -07001427 if (opx->segment != segment) {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001428 data = opx->offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001429 out(offset, segment, &data,
1430 size == 2 ? OUT_REL2ADR : OUT_REL4ADR,
1431 insn_end - offset, opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001432 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001433 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001434 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001435 OUT_ADDRESS, size, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001436 }
1437 offset += size;
1438 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001439
H. Peter Anvine2c80182005-01-15 22:15:51 +00001440 case 070:
1441 case 071:
1442 case 072:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001443 case 073:
H. Peter Anvin839eca22007-10-29 23:12:47 -07001444 if (opx->segment != segment) {
1445 data = opx->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001446 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001447 OUT_REL4ADR, insn_end - offset,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001448 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001449 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001450 data = opx->offset - insn_end;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001451 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001452 OUT_ADDRESS, 4, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001453 }
1454 offset += 4;
1455 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001456
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001457 case 074:
1458 case 075:
1459 case 076:
1460 case 077:
H. Peter Anvin839eca22007-10-29 23:12:47 -07001461 if (opx->segment == NO_SEG)
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001462 errfunc(ERR_NONFATAL, "value referenced by FAR is not"
1463 " relocatable");
H. Peter Anvindfb91802008-05-20 11:43:53 -07001464 data = 0;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001465 out(offset, segment, &data, OUT_ADDRESS, 2,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001466 outfmt->segbase(1 + opx->segment),
1467 opx->wrt);
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001468 offset += 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001469 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001470
H. Peter Anvine2c80182005-01-15 22:15:51 +00001471 case 0140:
1472 case 0141:
1473 case 0142:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001474 case 0143:
H. Peter Anvin839eca22007-10-29 23:12:47 -07001475 data = opx->offset;
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001476 if (is_sbyte16(opx)) {
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001477 bytes[0] = data;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001478 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001479 NO_SEG);
1480 offset++;
1481 } else {
H. Peter Anvin839eca22007-10-29 23:12:47 -07001482 if (opx->segment == NO_SEG &&
1483 opx->wrt == NO_SEG)
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001484 warn_overflow(2, data);
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001485 out(offset, segment, &data, OUT_ADDRESS, 2,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001486 opx->segment, opx->wrt);
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001487 offset += 2;
1488 }
1489 break;
1490
1491 case 0144:
1492 case 0145:
1493 case 0146:
1494 case 0147:
1495 EMIT_REX();
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001496 bytes[0] = *codes++;
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001497 if (is_sbyte16(opx))
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001498 bytes[0] |= 2; /* s-bit */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001499 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001500 offset++;
1501 break;
1502
1503 case 0150:
1504 case 0151:
1505 case 0152:
1506 case 0153:
H. Peter Anvin839eca22007-10-29 23:12:47 -07001507 data = opx->offset;
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001508 if (is_sbyte32(opx)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001509 bytes[0] = data;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001510 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001511 NO_SEG);
1512 offset++;
1513 } else {
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001514 out(offset, segment, &data, OUT_ADDRESS, 4,
H. Peter Anvin839eca22007-10-29 23:12:47 -07001515 opx->segment, opx->wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001516 offset += 4;
1517 }
1518 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001519
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001520 case 0154:
1521 case 0155:
1522 case 0156:
1523 case 0157:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001524 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001525 bytes[0] = *codes++;
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001526 if (is_sbyte32(opx))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001527 bytes[0] |= 2; /* s-bit */
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001528 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001529 offset++;
1530 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001531
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001532 case 0160:
1533 case 0161:
1534 case 0162:
1535 case 0163:
1536 case 0164:
1537 case 0165:
1538 case 0166:
1539 case 0167:
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001540 break;
1541
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001542 case 0171:
1543 bytes[0] =
1544 (ins->drexdst << 4) |
1545 (ins->rex & REX_OC ? 0x08 : 0) |
1546 (ins->rex & (REX_R|REX_X|REX_B));
1547 ins->rex = 0;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001548 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001549 offset++;
1550 break;
1551
H. Peter Anvind85d2502008-05-04 17:53:31 -07001552 case 0172:
1553 c = *codes++;
1554 opx = &ins->oprs[c >> 3];
H. Peter Anvina4835d42008-05-20 14:21:29 -07001555 bytes[0] = nasm_regvals[opx->basereg] << 4;
H. Peter Anvind85d2502008-05-04 17:53:31 -07001556 opx = &ins->oprs[c & 7];
1557 if (opx->segment != NO_SEG || opx->wrt != NO_SEG) {
1558 errfunc(ERR_NONFATAL,
1559 "non-absolute expression not permitted as argument %d",
1560 c & 7);
1561 } else {
1562 if (opx->offset & ~15) {
1563 errfunc(ERR_WARNING | ERR_WARN_NOV,
1564 "four-bit argument exceeds bounds");
1565 }
1566 bytes[0] |= opx->offset & 15;
1567 }
1568 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1569 offset++;
1570 break;
1571
H. Peter Anvind58656f2008-05-06 20:11:14 -07001572 case 0173:
1573 c = *codes++;
1574 opx = &ins->oprs[c >> 4];
H. Peter Anvina4835d42008-05-20 14:21:29 -07001575 bytes[0] = nasm_regvals[opx->basereg] << 4;
H. Peter Anvind58656f2008-05-06 20:11:14 -07001576 bytes[0] |= c & 15;
1577 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1578 offset++;
1579 break;
1580
H. Peter Anvin52dc3532008-05-20 19:29:04 -07001581 case 0174:
1582 c = *codes++;
1583 opx = &ins->oprs[c];
1584 bytes[0] = nasm_regvals[opx->basereg] << 4;
1585 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1586 offset++;
1587 break;
1588
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001589 case 0250:
1590 case 0251:
1591 case 0252:
1592 case 0253:
1593 data = opx->offset;
1594 /* is_sbyte32() is right here, we have already warned */
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001595 if (is_sbyte32(opx)) {
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001596 bytes[0] = data;
1597 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
1598 NO_SEG);
1599 offset++;
1600 } else {
1601 out(offset, segment, &data, OUT_ADDRESS, 4,
1602 opx->segment, opx->wrt);
1603 offset += 4;
1604 }
1605 break;
1606
H. Peter Anvind85d2502008-05-04 17:53:31 -07001607 case 0260:
1608 case 0261:
1609 case 0262:
1610 case 0263:
1611 case 0270:
1612 codes += 2;
1613 if (ins->vex_m != 1 || (ins->rex & (REX_W|REX_X|REX_B))) {
1614 bytes[0] = 0xc4;
H. Peter Anvin4d2c38c2008-05-04 23:15:13 -07001615 bytes[1] = ins->vex_m | ((~ins->rex & 7) << 5);
H. Peter Anvind85d2502008-05-04 17:53:31 -07001616 bytes[2] = ((ins->rex & REX_W) << (7-3)) |
H. Peter Anvin4d2c38c2008-05-04 23:15:13 -07001617 ((~ins->drexdst & 15)<< 3) | (ins->vex_wlp & 07);
H. Peter Anvind85d2502008-05-04 17:53:31 -07001618 out(offset, segment, &bytes, OUT_RAWDATA, 3, NO_SEG, NO_SEG);
1619 offset += 3;
1620 } else {
1621 bytes[0] = 0xc5;
H. Peter Anvin4d2c38c2008-05-04 23:15:13 -07001622 bytes[1] = ((~ins->rex & REX_R) << (7-2)) |
1623 ((~ins->drexdst & 15) << 3) | (ins->vex_wlp & 07);
H. Peter Anvind85d2502008-05-04 17:53:31 -07001624 out(offset, segment, &bytes, OUT_RAWDATA, 2, NO_SEG, NO_SEG);
1625 offset += 2;
1626 }
1627 break;
1628
H. Peter Anvine2c80182005-01-15 22:15:51 +00001629 case 0300:
1630 case 0301:
1631 case 0302:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001632 case 0303:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001633 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001634
H. Peter Anvine2c80182005-01-15 22:15:51 +00001635 case 0310:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001636 if (bits == 32 && !has_prefix(ins, PPS_ASIZE, P_A16)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001637 *bytes = 0x67;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001638 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001639 offset += 1;
1640 } else
1641 offset += 0;
1642 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001643
H. Peter Anvine2c80182005-01-15 22:15:51 +00001644 case 0311:
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07001645 if (bits != 32 && !has_prefix(ins, PPS_ASIZE, P_A32)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001646 *bytes = 0x67;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001647 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001648 offset += 1;
1649 } else
1650 offset += 0;
1651 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001652
H. Peter Anvine2c80182005-01-15 22:15:51 +00001653 case 0312:
1654 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001655
Keith Kaniosb7a89542007-04-12 02:40:54 +00001656 case 0313:
1657 ins->rex = 0;
1658 break;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07001659
H. Peter Anvin23440102007-11-12 21:02:33 -08001660 case 0314:
1661 case 0315:
1662 case 0316:
1663 case 0317:
1664 break;
1665
H. Peter Anvine2c80182005-01-15 22:15:51 +00001666 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001667 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001668 *bytes = 0x66;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001669 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001670 offset += 1;
1671 } else
1672 offset += 0;
1673 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001674
H. Peter Anvine2c80182005-01-15 22:15:51 +00001675 case 0321:
1676 if (bits == 16) {
1677 *bytes = 0x66;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001678 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001679 offset += 1;
1680 } else
1681 offset += 0;
1682 break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001683
H. Peter Anvine2c80182005-01-15 22:15:51 +00001684 case 0322:
H. Peter Anvin70653092007-10-19 14:42:29 -07001685 case 0323:
1686 break;
1687
Keith Kaniosb7a89542007-04-12 02:40:54 +00001688 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001689 ins->rex |= REX_W;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001690 break;
H. Peter Anvin70653092007-10-19 14:42:29 -07001691
H. Peter Anvine2c80182005-01-15 22:15:51 +00001692 case 0330:
1693 *bytes = *codes++ ^ condval[ins->condition];
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001694 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001695 offset += 1;
1696 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001697
H. Peter Anvine2c80182005-01-15 22:15:51 +00001698 case 0331:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001699 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001700
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001701 case 0332:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001702 case 0333:
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001703 *bytes = c - 0332 + 0xF2;
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 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001707
Keith Kanios48af1772007-08-17 07:37:52 +00001708 case 0334:
1709 if (ins->rex & REX_R) {
1710 *bytes = 0xF0;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001711 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
Keith Kanios48af1772007-08-17 07:37:52 +00001712 offset += 1;
1713 }
1714 ins->rex &= ~(REX_L|REX_R);
1715 break;
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001716
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001717 case 0335:
1718 break;
1719
H. Peter Anvin962e3052008-08-28 17:47:16 -07001720 case 0336:
1721 case 0337:
1722 break;
1723
H. Peter Anvine2c80182005-01-15 22:15:51 +00001724 case 0340:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001725 if (ins->oprs[0].segment != NO_SEG)
1726 errfunc(ERR_PANIC, "non-constant BSS size in pass two");
1727 else {
H. Peter Anvin428fd672007-11-15 10:25:52 -08001728 int64_t size = ins->oprs[0].offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001729 if (size > 0)
1730 out(offset, segment, NULL,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001731 OUT_RESERVE, size, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001732 offset += size;
1733 }
1734 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001735
H. Peter Anvinfff5a472008-05-20 09:46:24 -07001736 case 0360:
1737 break;
1738
1739 case 0361:
1740 bytes[0] = 0x66;
1741 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1742 offset += 1;
1743 break;
1744
1745 case 0362:
1746 case 0363:
1747 bytes[0] = c - 0362 + 0xf2;
1748 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
1749 offset += 1;
1750 break;
1751
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001752 case 0364:
1753 case 0365:
1754 break;
1755
Keith Kanios48af1772007-08-17 07:37:52 +00001756 case 0366:
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001757 case 0367:
1758 *bytes = c - 0366 + 0x66;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001759 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
Keith Kanios48af1772007-08-17 07:37:52 +00001760 offset += 1;
1761 break;
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001762
H. Peter Anvine2c80182005-01-15 22:15:51 +00001763 case 0370:
1764 case 0371:
1765 case 0372:
1766 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001767
H. Peter Anvine2c80182005-01-15 22:15:51 +00001768 case 0373:
1769 *bytes = bits == 16 ? 3 : 5;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001770 out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001771 offset += 1;
1772 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001773
H. Peter Anvine2c80182005-01-15 22:15:51 +00001774 default: /* can't do it by 'case' statements */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001775 if (c >= 0100 && c <= 0277) { /* it's an EA */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001776 ea ea_data;
1777 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001778 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001779 uint8_t *p;
1780 int32_t s;
H. Peter Anvin70653092007-10-19 14:42:29 -07001781
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001782 if (c <= 0177) {
1783 /* pick rfield from operand b */
1784 rflags = regflag(&ins->oprs[c & 7]);
H. Peter Anvina4835d42008-05-20 14:21:29 -07001785 rfield = nasm_regvals[ins->oprs[c & 7].basereg];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001786 } else {
1787 /* rfield is constant */
1788 rflags = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001789 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001790 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001791
1792 if (!process_ea
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001793 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07001794 ins->addr_size, rfield, rflags)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001795 errfunc(ERR_NONFATAL, "invalid effective address");
1796 }
H. Peter Anvin70653092007-10-19 14:42:29 -07001797
Charles Crayne7e975552007-11-03 22:06:13 -07001798
H. Peter Anvine2c80182005-01-15 22:15:51 +00001799 p = bytes;
1800 *p++ = ea_data.modrm;
1801 if (ea_data.sib_present)
1802 *p++ = ea_data.sib;
1803
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001804 /* DREX suffixes come between the SIB and the displacement */
1805 if (ins->rex & REX_D) {
1806 *p++ =
1807 (ins->drexdst << 4) |
1808 (ins->rex & REX_OC ? 0x08 : 0) |
1809 (ins->rex & (REX_R|REX_X|REX_B));
1810 ins->rex = 0;
1811 }
1812
H. Peter Anvine2c80182005-01-15 22:15:51 +00001813 s = p - bytes;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001814 out(offset, segment, bytes, OUT_RAWDATA, s, NO_SEG, NO_SEG);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001815
1816 switch (ea_data.bytes) {
1817 case 0:
1818 break;
1819 case 1:
1820 if (ins->oprs[(c >> 3) & 7].segment != NO_SEG) {
1821 data = ins->oprs[(c >> 3) & 7].offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001822 out(offset, segment, &data, OUT_ADDRESS, 1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001823 ins->oprs[(c >> 3) & 7].segment,
1824 ins->oprs[(c >> 3) & 7].wrt);
1825 } else {
1826 *bytes = ins->oprs[(c >> 3) & 7].offset;
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001827 out(offset, segment, bytes, OUT_RAWDATA, 1,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001828 NO_SEG, NO_SEG);
1829 }
1830 s++;
1831 break;
H. Peter Anvin70653092007-10-19 14:42:29 -07001832 case 8:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001833 case 2:
1834 case 4:
1835 data = ins->oprs[(c >> 3) & 7].offset;
Charles Crayne7e975552007-11-03 22:06:13 -07001836 warn_overflow(ea_data.bytes, data);
H. Peter Anvind0b0d282007-09-28 17:17:20 -07001837 out(offset, segment, &data,
H. Peter Anvin34f6fb02007-11-09 14:44:02 -08001838 ea_data.rip ? OUT_REL4ADR : OUT_ADDRESS,
1839 ea_data.bytes,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001840 ins->oprs[(c >> 3) & 7].segment,
1841 ins->oprs[(c >> 3) & 7].wrt);
1842 s += ea_data.bytes;
1843 break;
1844 }
1845 offset += s;
H. Peter Anvin839eca22007-10-29 23:12:47 -07001846 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001847 errfunc(ERR_PANIC, "internal instruction table corrupt"
1848 ": instruction code 0x%02X given", c);
H. Peter Anvin839eca22007-10-29 23:12:47 -07001849 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001850 }
H. Peter Anvin839eca22007-10-29 23:12:47 -07001851 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001852}
1853
H. Peter Anvin0ec60e62007-07-07 01:59:52 +00001854static int32_t regflag(const operand * o)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001855{
1856 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1857 errfunc(ERR_PANIC, "invalid operand passed to regflag()");
1858 }
H. Peter Anvina4835d42008-05-20 14:21:29 -07001859 return nasm_reg_flags[o->basereg];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001860}
1861
H. Peter Anvin5b0e3ec2007-07-07 02:01:08 +00001862static int32_t regval(const operand * o)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001863{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001864 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1865 errfunc(ERR_PANIC, "invalid operand passed to regval()");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001866 }
H. Peter Anvina4835d42008-05-20 14:21:29 -07001867 return nasm_regvals[o->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001868}
1869
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001870static int op_rexflags(const operand * o, int mask)
1871{
1872 int32_t flags;
1873 int val;
1874
1875 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1876 errfunc(ERR_PANIC, "invalid operand passed to op_rexflags()");
1877 }
1878
H. Peter Anvina4835d42008-05-20 14:21:29 -07001879 flags = nasm_reg_flags[o->basereg];
1880 val = nasm_regvals[o->basereg];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001881
1882 return rexflags(val, flags, mask);
1883}
1884
1885static int rexflags(int val, int32_t flags, int mask)
1886{
1887 int rex = 0;
1888
1889 if (val >= 8)
1890 rex |= REX_B|REX_X|REX_R;
1891 if (flags & BITS64)
1892 rex |= REX_W;
1893 if (!(REG_HIGH & ~flags)) /* AH, CH, DH, BH */
1894 rex |= REX_H;
1895 else if (!(REG8 & ~flags) && val >= 4) /* SPL, BPL, SIL, DIL */
1896 rex |= REX_P;
1897
1898 return rex & mask;
1899}
1900
H. Peter Anvin3360d792007-09-11 04:16:57 +00001901static int matches(const struct itemplate *itemp, insn * instruction, int bits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001902{
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001903 int i, size[MAX_OPERANDS], asize, oprs, ret;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001904
1905 ret = 100;
1906
1907 /*
1908 * Check the opcode
1909 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001910 if (itemp->opcode != instruction->opcode)
1911 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001912
1913 /*
1914 * Count the operands
1915 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001916 if (itemp->operands != instruction->operands)
1917 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001918
1919 /*
1920 * Check that no spurious colons or TOs are present
1921 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001922 for (i = 0; i < itemp->operands; i++)
1923 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON | TO))
1924 return 0;
H. Peter Anvin70653092007-10-19 14:42:29 -07001925
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001926 /*
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001927 * Process size flags
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001928 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001929 if (itemp->flags & IF_ARMASK) {
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001930 memset(size, 0, sizeof size);
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001931
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001932 i = ((itemp->flags & IF_ARMASK) >> IF_ARSHFT) - 1;
1933
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001934 switch (itemp->flags & IF_SMASK) {
1935 case IF_SB:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001936 size[i] = BITS8;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001937 break;
1938 case IF_SW:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001939 size[i] = BITS16;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001940 break;
1941 case IF_SD:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001942 size[i] = BITS32;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001943 break;
1944 case IF_SQ:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001945 size[i] = BITS64;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001946 break;
H. Peter Anvin41c9f6f2007-09-18 13:01:32 -07001947 case IF_SO:
1948 size[i] = BITS128;
1949 break;
H. Peter Anvindfb91802008-05-20 11:43:53 -07001950 case IF_SY:
1951 size[i] = BITS256;
1952 break;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001953 case IF_SZ:
1954 switch (bits) {
1955 case 16:
1956 size[i] = BITS16;
1957 break;
1958 case 32:
1959 size[i] = BITS32;
1960 break;
1961 case 64:
1962 size[i] = BITS64;
1963 break;
1964 }
1965 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001966 default:
1967 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001968 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001969 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001970 asize = 0;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001971 switch (itemp->flags & IF_SMASK) {
1972 case IF_SB:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001973 asize = BITS8;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001974 break;
1975 case IF_SW:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001976 asize = BITS16;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001977 break;
1978 case IF_SD:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001979 asize = BITS32;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001980 break;
1981 case IF_SQ:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001982 asize = BITS64;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001983 break;
H. Peter Anvin41c9f6f2007-09-18 13:01:32 -07001984 case IF_SO:
1985 asize = BITS128;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001986 break;
H. Peter Anvindfb91802008-05-20 11:43:53 -07001987 case IF_SY:
1988 asize = BITS256;
1989 break;
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07001990 case IF_SZ:
1991 switch (bits) {
1992 case 16:
1993 asize = BITS16;
1994 break;
1995 case 32:
1996 asize = BITS32;
1997 break;
1998 case 64:
1999 asize = BITS64;
2000 break;
2001 }
H. Peter Anvin41c9f6f2007-09-18 13:01:32 -07002002 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002003 default:
2004 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002005 }
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07002006 for (i = 0; i < MAX_OPERANDS; i++)
2007 size[i] = asize;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002008 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002009
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002010 /*
2011 * Check that the operand flags all match up
2012 */
2013 for (i = 0; i < itemp->operands; i++) {
2014 int32_t type = instruction->oprs[i].type;
2015 if (!(type & SIZE_MASK))
2016 type |= size[i];
H. Peter Anvind85d2502008-05-04 17:53:31 -07002017
H. Peter Anvin32cd4c22008-04-04 13:34:53 -07002018 if (itemp->opd[i] & SAME_AS) {
2019 int j = itemp->opd[i] & ~SAME_AS;
2020 if (type != instruction->oprs[j].type ||
2021 instruction->oprs[i].basereg != instruction->oprs[j].basereg)
2022 return 0;
2023 } else if (itemp->opd[i] & ~type ||
2024 ((itemp->opd[i] & SIZE_MASK) &&
2025 ((itemp->opd[i] ^ type) & SIZE_MASK))) {
2026 if ((itemp->opd[i] & ~type & ~SIZE_MASK) ||
2027 (type & SIZE_MASK))
2028 return 0;
2029 else
2030 return 1;
2031 }
2032 }
2033
2034 /*
2035 * Check operand sizes
2036 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002037 if (itemp->flags & (IF_SM | IF_SM2)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002038 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
2039 asize = 0;
2040 for (i = 0; i < oprs; i++) {
2041 if ((asize = itemp->opd[i] & SIZE_MASK) != 0) {
2042 int j;
2043 for (j = 0; j < oprs; j++)
2044 size[j] = asize;
2045 break;
2046 }
2047 }
H. Peter Anvinef7468f2002-04-30 20:57:59 +00002048 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002049 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002050 }
2051
Keith Kaniosb7a89542007-04-12 02:40:54 +00002052 for (i = 0; i < itemp->operands; i++) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002053 if (!(itemp->opd[i] & SIZE_MASK) &&
2054 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvine2c80182005-01-15 22:15:51 +00002055 return 2;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002056 }
2057
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002058 /*
2059 * Check template is okay at the set cpu level
2060 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002061 if (((itemp->flags & IF_PLEVEL) > cpu))
H. Peter Anvine2c80182005-01-15 22:15:51 +00002062 return 3;
H. Peter Anvin70653092007-10-19 14:42:29 -07002063
Keith Kaniosb7a89542007-04-12 02:40:54 +00002064 /*
2065 * Check if instruction is available in long mode
2066 */
2067 if ((itemp->flags & IF_NOLONG) && (bits == 64))
2068 return 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002069
H. Peter Anvinaf535c12002-04-30 20:59:21 +00002070 /*
2071 * Check if special handling needed for Jumps
2072 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002073 if ((uint8_t)(itemp->code[0]) >= 0370)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002074 return 99;
2075
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002076 return ret;
2077}
2078
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002079static ea *process_ea(operand * input, ea * output, int bits,
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07002080 int addrbits, int rfield, int32_t rflags)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002081{
H. Peter Anvin1c3277b2008-07-19 21:38:56 -07002082 bool forw_ref = !!(input->opflags & OPFLAG_FORWARD);
2083
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002084 output->rip = false;
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00002085
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002086 /* REX flags for the rfield operand */
2087 output->rex |= rexflags(rfield, rflags, REX_R|REX_P|REX_W|REX_H);
2088
Keith Kaniosb7a89542007-04-12 02:40:54 +00002089 if (!(REGISTER & ~input->type)) { /* register direct */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002090 int i;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002091 int32_t f;
2092
2093 if (input->basereg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002094 || input->basereg >= REG_ENUM_LIMIT)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002095 return NULL;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002096 f = regflag(input);
H. Peter Anvina4835d42008-05-20 14:21:29 -07002097 i = nasm_regvals[input->basereg];
Keith Kaniosb7a89542007-04-12 02:40:54 +00002098
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002099 if (REG_EA & ~f)
2100 return NULL; /* Invalid EA register */
H. Peter Anvin70653092007-10-19 14:42:29 -07002101
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002102 output->rex |= op_rexflags(input, REX_B|REX_P|REX_W|REX_H);
2103
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002104 output->sib_present = false; /* no SIB necessary */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002105 output->bytes = 0; /* no offset necessary either */
2106 output->modrm = 0xC0 | ((rfield & 7) << 3) | (i & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002107 } else { /* it's a memory reference */
2108 if (input->basereg == -1
2109 && (input->indexreg == -1 || input->scale == 0)) {
2110 /* it's a pure offset */
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002111 if (bits == 64 && (~input->type & IP_REL)) {
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002112 int scale, index, base;
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002113 output->sib_present = true;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002114 scale = 0;
2115 index = 4;
2116 base = 5;
2117 output->sib = (scale << 6) | (index << 3) | base;
2118 output->bytes = 4;
2119 output->modrm = 4 | ((rfield & 7) << 3);
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002120 output->rip = false;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002121 } else {
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002122 output->sib_present = false;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002123 output->bytes = (addrbits != 16 ? 4 : 2);
2124 output->modrm = (addrbits != 16 ? 5 : 6) | ((rfield & 7) << 3);
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002125 output->rip = bits == 64;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00002126 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00002127 } else { /* it's an indirection */
2128 int i = input->indexreg, b = input->basereg, s = input->scale;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002129 int32_t o = input->offset, seg = input->segment;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002130 int hb = input->hintbase, ht = input->hinttype;
2131 int t;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002132 int it, bt;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002133 int32_t ix, bx; /* register flags */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002134
H. Peter Anvine2c80182005-01-15 22:15:51 +00002135 if (s == 0)
2136 i = -1; /* make this easy, at least */
H. Peter Anvin70653092007-10-19 14:42:29 -07002137
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002138 if (i >= EXPR_REG_START && i < REG_ENUM_LIMIT) {
H. Peter Anvina4835d42008-05-20 14:21:29 -07002139 it = nasm_regvals[i];
2140 ix = nasm_reg_flags[i];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002141 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00002142 it = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002143 ix = 0;
2144 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002145
H. Peter Anvinb0c54622007-10-28 23:21:46 -07002146 if (b >= EXPR_REG_START && b < REG_ENUM_LIMIT) {
H. Peter Anvina4835d42008-05-20 14:21:29 -07002147 bt = nasm_regvals[b];
2148 bx = nasm_reg_flags[b];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002149 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00002150 bt = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002151 bx = 0;
2152 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002153
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002154 /* check for a 32/64-bit memory reference... */
2155 if ((ix|bx) & (BITS32|BITS64)) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00002156 /* it must be a 32/64-bit memory reference. Firstly we have
2157 * to check that all registers involved are type E/Rxx. */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002158 int32_t sok = BITS32|BITS64;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002159
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002160 if (it != -1) {
2161 if (!(REG64 & ~ix) || !(REG32 & ~ix))
2162 sok &= ix;
2163 else
2164 return NULL;
2165 }
2166
2167 if (bt != -1) {
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00002168 if (REG_GPR & ~bx)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002169 return NULL; /* Invalid register */
H. Peter Anvina57e8d42007-05-30 03:44:02 +00002170 if (~sok & bx & SIZE_MASK)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002171 return NULL; /* Invalid size */
H. Peter Anvinb0c54622007-10-28 23:21:46 -07002172 sok &= bx;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002173 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002174
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002175 /* While we're here, ensure the user didn't specify
2176 WORD or QWORD. */
2177 if (input->disp_size == 16 || input->disp_size == 64)
2178 return NULL;
2179
2180 if (addrbits == 16 ||
2181 (addrbits == 32 && !(sok & BITS32)) ||
2182 (addrbits == 64 && !(sok & BITS64)))
2183 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002184
Keith Kaniosb7a89542007-04-12 02:40:54 +00002185 /* now reorganize base/index */
2186 if (s == 1 && bt != it && bt != -1 && it != -1 &&
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002187 ((hb == b && ht == EAH_NOTBASE)
2188 || (hb == i && ht == EAH_MAKEBASE))) {
2189 /* swap if hints say so */
2190 t = bt, bt = it, it = t;
2191 t = bx, bx = ix, ix = t;
2192 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00002193 if (bt == it) /* convert EAX+2*EAX to 3*EAX */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002194 bt = -1, bx = 0, s++;
2195 if (bt == -1 && s == 1 && !(hb == it && ht == EAH_NOTBASE)) {
2196 /* make single reg base, unless hint */
2197 bt = it, bx = ix, it = -1, ix = 0;
2198 }
H. Peter Anvinf5843c62007-09-10 18:59:26 +00002199 if (((s == 2 && it != REG_NUM_ESP
H. Peter Anvine2c80182005-01-15 22:15:51 +00002200 && !(input->eaflags & EAF_TIMESTWO)) || s == 3
Keith Kaniosb7a89542007-04-12 02:40:54 +00002201 || s == 5 || s == 9) && bt == -1)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002202 bt = it, bx = ix, s--; /* convert 3*EAX to EAX+2*EAX */
Keith Kanios48af1772007-08-17 07:37:52 +00002203 if (it == -1 && (bt & 7) != REG_NUM_ESP
H. Peter Anvine2c80182005-01-15 22:15:51 +00002204 && (input->eaflags & EAF_TIMESTWO))
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002205 it = bt, ix = bx, bt = -1, bx = 0, s = 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002206 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
Keith Kanios48af1772007-08-17 07:37:52 +00002207 if (s == 1 && it == REG_NUM_ESP) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002208 /* swap ESP into base if scale is 1 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002209 t = it, it = bt, bt = t;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002210 t = ix, ix = bx, bx = t;
2211 }
Keith Kanios48af1772007-08-17 07:37:52 +00002212 if (it == REG_NUM_ESP
Keith Kaniosb7a89542007-04-12 02:40:54 +00002213 || (s != 1 && s != 2 && s != 4 && s != 8 && it != -1))
H. Peter Anvine2c80182005-01-15 22:15:51 +00002214 return NULL; /* wrong, for various reasons */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002215
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002216 output->rex |= rexflags(it, ix, REX_X);
2217 output->rex |= rexflags(bt, bx, REX_B);
Keith Kaniosb7a89542007-04-12 02:40:54 +00002218
Keith Kanios48af1772007-08-17 07:37:52 +00002219 if (it == -1 && (bt & 7) != REG_NUM_ESP) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002220 /* no SIB needed */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002221 int mod, rm;
H. Peter Anvin70653092007-10-19 14:42:29 -07002222
Keith Kaniosb7a89542007-04-12 02:40:54 +00002223 if (bt == -1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002224 rm = 5;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002225 mod = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002226 } else {
2227 rm = (bt & 7);
Keith Kanios48af1772007-08-17 07:37:52 +00002228 if (rm != REG_NUM_EBP && o == 0 &&
Keith Kaniosb7a89542007-04-12 02:40:54 +00002229 seg == NO_SEG && !forw_ref &&
2230 !(input->eaflags &
2231 (EAF_BYTEOFFS | EAF_WORDOFFS)))
2232 mod = 0;
2233 else if (input->eaflags & EAF_BYTEOFFS ||
2234 (o >= -128 && o <= 127 && seg == NO_SEG
2235 && !forw_ref
2236 && !(input->eaflags & EAF_WORDOFFS)))
2237 mod = 1;
2238 else
2239 mod = 2;
2240 }
H. Peter Anvinea838272002-04-30 20:51:53 +00002241
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002242 output->sib_present = false;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002243 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
2244 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002245 } else {
2246 /* we need a SIB */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002247 int mod, scale, index, base;
H. Peter Anvin70653092007-10-19 14:42:29 -07002248
Keith Kaniosb7a89542007-04-12 02:40:54 +00002249 if (it == -1)
2250 index = 4, s = 1;
2251 else
2252 index = (it & 7);
H. Peter Anvin70653092007-10-19 14:42:29 -07002253
H. Peter Anvine2c80182005-01-15 22:15:51 +00002254 switch (s) {
2255 case 1:
2256 scale = 0;
2257 break;
2258 case 2:
2259 scale = 1;
2260 break;
2261 case 4:
2262 scale = 2;
2263 break;
2264 case 8:
2265 scale = 3;
2266 break;
2267 default: /* then what the smeg is it? */
2268 return NULL; /* panic */
2269 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002270
Keith Kaniosb7a89542007-04-12 02:40:54 +00002271 if (bt == -1) {
2272 base = 5;
2273 mod = 0;
2274 } else {
2275 base = (bt & 7);
Keith Kanios48af1772007-08-17 07:37:52 +00002276 if (base != REG_NUM_EBP && o == 0 &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00002277 seg == NO_SEG && !forw_ref &&
2278 !(input->eaflags &
Keith Kaniosb7a89542007-04-12 02:40:54 +00002279 (EAF_BYTEOFFS | EAF_WORDOFFS)))
2280 mod = 0;
2281 else if (input->eaflags & EAF_BYTEOFFS ||
2282 (o >= -128 && o <= 127 && seg == NO_SEG
2283 && !forw_ref
2284 && !(input->eaflags & EAF_WORDOFFS)))
2285 mod = 1;
2286 else
2287 mod = 2;
2288 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002289
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002290 output->sib_present = true;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002291 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
2292 output->modrm = (mod << 6) | ((rfield & 7) << 3) | 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002293 output->sib = (scale << 6) | (index << 3) | base;
2294 }
2295 } else { /* it's 16-bit */
2296 int mod, rm;
H. Peter Anvin70653092007-10-19 14:42:29 -07002297
Keith Kaniosb7a89542007-04-12 02:40:54 +00002298 /* check for 64-bit long mode */
2299 if (addrbits == 64)
2300 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002301
H. Peter Anvine2c80182005-01-15 22:15:51 +00002302 /* check all registers are BX, BP, SI or DI */
2303 if ((b != -1 && b != R_BP && b != R_BX && b != R_SI
2304 && b != R_DI) || (i != -1 && i != R_BP && i != R_BX
2305 && i != R_SI && i != R_DI))
2306 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002307
Keith Kaniosb7a89542007-04-12 02:40:54 +00002308 /* ensure the user didn't specify DWORD/QWORD */
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002309 if (input->disp_size == 32 || input->disp_size == 64)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002310 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002311
H. Peter Anvine2c80182005-01-15 22:15:51 +00002312 if (s != 1 && i != -1)
2313 return NULL; /* no can do, in 16-bit EA */
2314 if (b == -1 && i != -1) {
2315 int tmp = b;
2316 b = i;
2317 i = tmp;
2318 } /* swap */
2319 if ((b == R_SI || b == R_DI) && i != -1) {
2320 int tmp = b;
2321 b = i;
2322 i = tmp;
2323 }
2324 /* have BX/BP as base, SI/DI index */
2325 if (b == i)
2326 return NULL; /* shouldn't ever happen, in theory */
2327 if (i != -1 && b != -1 &&
2328 (i == R_BP || i == R_BX || b == R_SI || b == R_DI))
2329 return NULL; /* invalid combinations */
2330 if (b == -1) /* pure offset: handled above */
2331 return NULL; /* so if it gets to here, panic! */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002332
H. Peter Anvine2c80182005-01-15 22:15:51 +00002333 rm = -1;
2334 if (i != -1)
2335 switch (i * 256 + b) {
2336 case R_SI * 256 + R_BX:
2337 rm = 0;
2338 break;
2339 case R_DI * 256 + R_BX:
2340 rm = 1;
2341 break;
2342 case R_SI * 256 + R_BP:
2343 rm = 2;
2344 break;
2345 case R_DI * 256 + R_BP:
2346 rm = 3;
2347 break;
2348 } else
2349 switch (b) {
2350 case R_SI:
2351 rm = 4;
2352 break;
2353 case R_DI:
2354 rm = 5;
2355 break;
2356 case R_BP:
2357 rm = 6;
2358 break;
2359 case R_BX:
2360 rm = 7;
2361 break;
2362 }
2363 if (rm == -1) /* can't happen, in theory */
2364 return NULL; /* so panic if it does */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002365
H. Peter Anvine2c80182005-01-15 22:15:51 +00002366 if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
2367 !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
2368 mod = 0;
2369 else if (input->eaflags & EAF_BYTEOFFS ||
2370 (o >= -128 && o <= 127 && seg == NO_SEG
2371 && !forw_ref
2372 && !(input->eaflags & EAF_WORDOFFS)))
2373 mod = 1;
2374 else
2375 mod = 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002376
H. Peter Anvin6867acc2007-10-10 14:58:45 -07002377 output->sib_present = false; /* no SIB - it's 16-bit */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002378 output->bytes = mod; /* bytes of offset needed */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002379 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002380 }
2381 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002382 }
H. Peter Anvin70653092007-10-19 14:42:29 -07002383
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002384 output->size = 1 + output->sib_present + output->bytes;
2385 return output;
2386}
2387
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002388static void add_asp(insn *ins, int addrbits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002389{
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002390 int j, valid;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002391 int defdisp;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002392
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002393 valid = (addrbits == 64) ? 64|32 : 32|16;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002394
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002395 switch (ins->prefixes[PPS_ASIZE]) {
2396 case P_A16:
2397 valid &= 16;
2398 break;
2399 case P_A32:
2400 valid &= 32;
2401 break;
2402 case P_A64:
2403 valid &= 64;
2404 break;
2405 case P_ASP:
2406 valid &= (addrbits == 32) ? 16 : 32;
2407 break;
2408 default:
2409 break;
2410 }
2411
2412 for (j = 0; j < ins->operands; j++) {
2413 if (!(MEMORY & ~ins->oprs[j].type)) {
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002414 int32_t i, b;
H. Peter Anvin70653092007-10-19 14:42:29 -07002415
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002416 /* Verify as Register */
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002417 if (ins->oprs[j].indexreg < EXPR_REG_START
2418 || ins->oprs[j].indexreg >= REG_ENUM_LIMIT)
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002419 i = 0;
2420 else
H. Peter Anvina4835d42008-05-20 14:21:29 -07002421 i = nasm_reg_flags[ins->oprs[j].indexreg];
H. Peter Anvin70653092007-10-19 14:42:29 -07002422
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002423 /* Verify as Register */
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002424 if (ins->oprs[j].basereg < EXPR_REG_START
2425 || ins->oprs[j].basereg >= REG_ENUM_LIMIT)
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002426 b = 0;
2427 else
H. Peter Anvina4835d42008-05-20 14:21:29 -07002428 b = nasm_reg_flags[ins->oprs[j].basereg];
H. Peter Anvin70653092007-10-19 14:42:29 -07002429
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002430 if (ins->oprs[j].scale == 0)
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002431 i = 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002432
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002433 if (!i && !b) {
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002434 int ds = ins->oprs[j].disp_size;
2435 if ((addrbits != 64 && ds > 8) ||
2436 (addrbits == 64 && ds == 16))
2437 valid &= ds;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002438 } else {
2439 if (!(REG16 & ~b))
2440 valid &= 16;
2441 if (!(REG32 & ~b))
2442 valid &= 32;
2443 if (!(REG64 & ~b))
2444 valid &= 64;
H. Peter Anvin70653092007-10-19 14:42:29 -07002445
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002446 if (!(REG16 & ~i))
2447 valid &= 16;
2448 if (!(REG32 & ~i))
2449 valid &= 32;
2450 if (!(REG64 & ~i))
2451 valid &= 64;
2452 }
2453 }
2454 }
2455
2456 if (valid & addrbits) {
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002457 ins->addr_size = addrbits;
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002458 } else if (valid & ((addrbits == 32) ? 16 : 32)) {
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002459 /* Add an address size prefix */
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002460 enum prefixes pref = (addrbits == 32) ? P_A16 : P_A32;
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002461 ins->prefixes[PPS_ASIZE] = pref;
2462 ins->addr_size = (addrbits == 32) ? 16 : 32;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002463 } else {
H. Peter Anvinc5b9ce02007-09-22 21:49:51 -07002464 /* Impossible... */
2465 errfunc(ERR_NONFATAL, "impossible combination of address sizes");
H. Peter Anvinde4b89b2007-10-01 15:41:25 -07002466 ins->addr_size = addrbits; /* Error recovery */
2467 }
2468
2469 defdisp = ins->addr_size == 16 ? 16 : 32;
2470
2471 for (j = 0; j < ins->operands; j++) {
2472 if (!(MEM_OFFS & ~ins->oprs[j].type) &&
2473 (ins->oprs[j].disp_size ? ins->oprs[j].disp_size : defdisp)
2474 != ins->addr_size) {
2475 /* mem_offs sizes must match the address size; if not,
2476 strip the MEM_OFFS bit and match only EA instructions */
2477 ins->oprs[j].type &= ~(MEM_OFFS & ~MEMORY);
2478 }
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002479 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002480}