static ea *process_ea(operand * input, ea * output, int addrbits,
int rfield, int32_t rflags, int forw_ref)
{
-
- int rip = FALSE; /* Used for RIP-relative addressing */
- output->rip = 0;
-
+ output->rip = FALSE;
+
/* REX flags for the rfield operand */
output->rex |= rexflags(rfield, rflags, REX_R|REX_P|REX_W|REX_H);
output->bytes = 0; /* no offset necessary either */
output->modrm = 0xC0 | ((rfield & 7) << 3) | (i & 7);
} else { /* it's a memory reference */
-
if (input->basereg == -1
&& (input->indexreg == -1 || input->scale == 0)) {
/* it's a pure offset */
if (input->addr_size)
addrbits = input->addr_size;
- if (addrbits == 64) {
+
+ if (globalbits == 64 && (~input->type & IP_REL)) {
int scale, index, base;
output->sib_present = TRUE;
scale = 0;
output->sib = (scale << 6) | (index << 3) | base;
output->bytes = 4;
output->modrm = 4 | ((rfield & 7) << 3);
+ output->rip = FALSE;
} else {
output->sib_present = FALSE;
output->bytes = (addrbits != 16 ? 4 : 2);
output->modrm = (addrbits != 16 ? 5 : 6) | ((rfield & 7) << 3);
+ output->rip = globalbits == 64;
}
} else { /* it's an indirection */
int i = input->indexreg, b = input->basereg, s = input->scale;
}
if (bt != -1) {
- if ((REG_GPR & ~bx) && (IP_REG & ~bx))
+ if (REG_GPR & ~bx)
return NULL; /* Invalid register */
if (~sok & bx & SIZE_MASK)
return NULL; /* Invalid size */
sok &= ~bx;
- if (!(IP_REG & ~bx)) {
- bt = b = -1;
- rip = TRUE;
- }
}
/* While we're here, ensure the user didn't specify WORD. */
output->modrm = (mod << 6) | ((rfield & 7) << 3) | 4;
output->sib = (scale << 6) | (index << 3) | base;
}
-
- /* Process RIP-relative Addressing */
- if (rip) {
- if (globalbits != 64 ||
- (output->modrm & 0xC7) != 0x05)
- return NULL;
- output->rip = TRUE;
- } else {
- output->rip = FALSE;
- /* Actual Disp32 needs blank SIB on x64 */
- if (globalbits == 64 &&
- !(output->sib_present) &&
- ((output->modrm & 0xC7) == 0x05)) {
- output->sib_present = TRUE;
- /* RM Field = 4 (forward to Base of SIB) */
- output->modrm--;
- /* Index = 4 (none), Base = 5 */
- output->sib = (4 << 3) | 5;
- }
- }
} else { /* it's 16-bit */
int mod, rm;
}
op->addr_size = 0;
+ op->eaflags = 0;
if (asize == 16) {
/*
if (rm == 5 && mod == 0) {
if (segsize == 64) {
- op->basereg = R_RIP;
+ op->eaflags |= EAF_REL;
op->segment |= SEG_RELATIVE;
mod = 2; /* fake disp32 */
- } else {
- op->basereg = -1;
- if (segsize != 32)
- op->addr_size = 32;
- mod = 2; /* fake disp32 */
}
+
+ if (asize != 64)
+ op->addr_size = asize;
+
+ op->basereg = -1;
+ mod = 2; /* fake disp32 */
}
if (rm == 4) { /* process SIB */
op->basereg = rd_reg64[base | ((rex & REX_B) ? 8 : 0)];
else
op->basereg = rd_reg32[base | ((rex & REX_B) ? 8 : 0)];
+
+ if (segsize != 32)
+ op->addr_size = 32;
}
switch (mod) {
ins.oprs[i].addr_size == 32 ? "dword " :
ins.oprs[i].addr_size == 16 ? "word " :
""));
+ if (ins.oprs[i].eaflags & EAF_REL)
+ slen += snprintf(output + slen, outbufsize - slen, "rel ");
if (segover) {
slen +=
snprintf(output + slen, outbufsize - slen, "%s:",
} else if (ins.oprs[i].segment & SEG_DISP32) {
char *prefix = "";
int32_t offset = ins.oprs[i].offset;
- if (ins.oprs[i].basereg == R_RIP) {
- prefix = ":";
- } else if (offset < 0) {
+ if (offset < 0) {
offset = -offset;
prefix = "-";
} else {
int tasm_compatible_mode = FALSE;
int pass0;
int maxbits = 0;
+int globalrel = 0;
static char inname[FILENAME_MAX];
static char outname[FILENAME_MAX];
* 6: NEAR
* 7: SHORT
*
- * Bits 8-11: modifiers
+ * Bits 8-11 modifiers
* 8: TO
* 9: COLON
* 10: STRICT
*
* With MEMORY:
* 16: MEM_OFFS (this is a simple offset)
+ * 17: IP_REL (IP-relative offset)
*
* With IMMEDIATE:
* 16: UNITY (1)
* 20: REG_CDT (CRx, DRx, TRx)
* 21: REG_GPR (integer register)
* 22: REG_SREG
- * 23: IP_REG (RIP or EIP)
+ * 23: IP_REG (RIP or EIP) [unused]
* 24: FPUREG
* 25: MMXREG
* 26: XMMREG
#define REG_RDX 0x00249008L
#define REG_HIGH 0x00289001L /* high regs: AH, CH, DH, BH */
-/* special type of EA */
-#define MEM_OFFS 0x00214000L /* simple [address] offset */
+/* special types of EAs */
+#define MEM_OFFS 0x00214000L /* simple [address] offset - absolute! */
+#define IP_REL 0x00224000L /* IP-relative offset */
/* special type of immediate operand */
#define UNITY 0x00012000L /* for shift/rotate instructions */
};
enum { /* special EA flags */
- EAF_BYTEOFFS = 1, /* force offset part to byte size */
- EAF_WORDOFFS = 2, /* force offset part to [d]word size */
- EAF_TIMESTWO = 4 /* really do EAX*2 not EAX+EAX */
+ EAF_BYTEOFFS = 1, /* force offset part to byte size */
+ EAF_WORDOFFS = 2, /* force offset part to [d]word size */
+ EAF_TIMESTWO = 4, /* really do EAX*2 not EAX+EAX */
+ EAF_REL = 8, /* IP-relative addressing */
+ EAF_ABS = 16, /* non-IP-relative addressing */
+ EAF_SEGOVER = 32 /* segment override present */
};
enum { /* values for `hinttype' */
#define elements(x) ( sizeof(x) / sizeof(*(x)) )
-extern int tasm_compatible_mode;
+/*
+ * -----
+ * Global modes
+ * -----
+ */
/*
* This declaration passes the "pass" number to all other modules
* 2 = pass 2
*/
-extern int pass0; /* this is globally known */
+extern int pass0;
+
+extern int tasm_compatible_mode;
extern int optimizing;
-extern int globalbits; /* this is globally known */
-extern int maxbits; /* this is globally known */
+extern int globalbits; /* 16, 32 or 64-bit mode */
+extern int globalrel; /* default to relative addressing? */
+extern int maxbits; /* max bits supported by output */
#endif
#include "insns.h" /* For MAX_KEYWORD */
int globalbits = 0; /* defined in nasm.h, works better here for ASM+DISASM */
-
static efunc nasm_malloc_error;
#ifdef LOGALLOC
*/
#include "names.c"
static const char *special_names[] = {
- "byte", "dword", "far", "long", "near", "nosplit", "qword",
+ "abs", "byte", "dword", "far", "long", "near", "nosplit", "qword", "rel",
"short", "strict", "to", "tword", "word"
};
static const char *prefix_names[] = {
#include "regflags.c" /* List of register flags */
enum { /* special tokens */
- S_BYTE, S_DWORD, S_FAR, S_LONG, S_NEAR, S_NOSPLIT, S_QWORD,
+ S_ABS, S_BYTE, S_DWORD, S_FAR, S_LONG, S_NEAR, S_NOSPLIT, S_QWORD, S_REL,
S_SHORT, S_STRICT, S_TO, S_TWORD, S_WORD
};
if (i == '[' || i == '&') { /* memory reference */
mref = TRUE;
bracket = (i == '[');
- i = stdscan(NULL, &tokval);
- if (i == TOKEN_SPECIAL) { /* check for address size override */
+ while ((i = stdscan(NULL, &tokval)) == TOKEN_SPECIAL) {
+ /* check for address directives */
if (tasm_compatible_mode) {
switch ((int)tokval.t_integer) {
/* For TASM compatibility a size override inside the
case S_NOSPLIT:
result->oprs[operand].eaflags |= EAF_TIMESTWO;
break;
+ case S_REL:
+ result->oprs[operand].eaflags |= EAF_REL;
+ break;
+ case S_ABS:
+ result->oprs[operand].eaflags |= EAF_ABS;
+ break;
case S_BYTE:
result->oprs[operand].eaflags |= EAF_BYTEOFFS;
break;
result->oprs[operand].addr_size = 32;
result->oprs[operand].eaflags |= EAF_WORDOFFS;
break;
+ case S_QWORD:
+ result->oprs[operand].addr_size = 64;
+ result->oprs[operand].eaflags |= EAF_WORDOFFS;
+ break;
default:
error(ERR_NONFATAL, "invalid size specification in"
" effective address");
}
}
- i = stdscan(NULL, &tokval);
}
} else { /* immediate operand, or register */
mref = FALSE;
else if (result->nprefix == MAXPREFIX)
error(ERR_NONFATAL,
"instruction has more than %d prefixes", MAXPREFIX);
- else
+ else {
result->prefixes[result->nprefix++] = value->type;
+ result->oprs[operand].eaflags |= EAF_SEGOVER;
+ }
i = stdscan(NULL, &tokval); /* then skip the colon */
if (i == TOKEN_SPECIAL) { /* another check for size override */
case S_LONG:
result->oprs[operand].addr_size = 32;
break;
+ case S_QWORD:
+ result->oprs[operand].addr_size = 64;
+ break;
default:
error(ERR_NONFATAL, "invalid size specification in"
" effective address");
}
result->oprs[operand].type |= MEMORY;
- if (b == -1 && (i == -1 || s == 0))
- result->oprs[operand].type |= MEM_OFFS;
+
+ if (b == -1 && (i == -1 || s == 0)) {
+ int is_rel = globalbits == 64 &&
+ !(result->oprs[operand].eaflags & EAF_ABS) &&
+ ((globalrel &&
+ !(result->oprs[operand].eaflags & EAF_SEGOVER)) ||
+ (result->oprs[operand].eaflags & EAF_REL));
+
+ result->oprs[operand].type |= is_rel ? IP_REL : MEM_OFFS;
+ }
result->oprs[operand].basereg = b;
result->oprs[operand].indexreg = i;
result->oprs[operand].scale = s;
# SSE registers
xmm0-15 XMMREG xmmreg 0
-
-# Special registers
-eip REG_EIP eipreg 0
-rip REG_RIP ripreg 0