/* 1 if support old (<= 2.8.1) versions of gcc. */
static int old_gcc = OLDGCC_COMPAT;
+/* 1 if pseudo registers are permitted. */
+static int allow_pseudo_reg = 0;
+
/* 1 if register prefix % not required. */
static int allow_naked_reg = 0;
CPU_VMX_FLAGS },
{ ".smx", PROCESSOR_UNKNOWN,
CPU_SMX_FLAGS },
+ { ".xsave", PROCESSOR_UNKNOWN,
+ CPU_XSAVE_FLAGS },
{ ".3dnow", PROCESSOR_UNKNOWN,
CPU_3DNOW_FLAGS },
{ ".3dnowa", PROCESSOR_UNKNOWN,
}
static INLINE int
-uints_all_zero (const unsigned int *x, unsigned int size)
+operand_type_all_zero (const union i386_operand_type *x)
{
- switch (size)
+ switch (ARRAY_SIZE(x->array))
{
case 3:
- if (x[2])
+ if (x->array[2])
return 0;
case 2:
- if (x[1])
+ if (x->array[1])
return 0;
case 1:
- return !x[0];
+ return !x->array[0];
default:
abort ();
}
}
static INLINE void
-uints_set (unsigned int *x, unsigned int v, unsigned int size)
+operand_type_set (union i386_operand_type *x, unsigned int v)
{
- switch (size)
+ switch (ARRAY_SIZE(x->array))
{
case 3:
- x[2] = v;
+ x->array[2] = v;
case 2:
- x[1] = v;
+ x->array[1] = v;
case 1:
- x[0] = v;
+ x->array[0] = v;
break;
default:
abort ();
}
static INLINE int
-uints_equal (const unsigned int *x, const unsigned int *y,
- unsigned int size)
+operand_type_equal (const union i386_operand_type *x,
+ const union i386_operand_type *y)
{
- switch (size)
+ switch (ARRAY_SIZE(x->array))
+ {
+ case 3:
+ if (x->array[2] != y->array[2])
+ return 0;
+ case 2:
+ if (x->array[1] != y->array[1])
+ return 0;
+ case 1:
+ return x->array[0] == y->array[0];
+ break;
+ default:
+ abort ();
+ }
+}
+
+static INLINE int
+cpu_flags_all_zero (const union i386_cpu_flags *x)
+{
+ switch (ARRAY_SIZE(x->array))
{
case 3:
- if (x[2] != y [2])
+ if (x->array[2])
return 0;
case 2:
- if (x[1] != y [1])
+ if (x->array[1])
return 0;
case 1:
- return x[0] == y [0];
+ return !x->array[0];
+ default:
+ abort ();
+ }
+}
+
+static INLINE void
+cpu_flags_set (union i386_cpu_flags *x, unsigned int v)
+{
+ switch (ARRAY_SIZE(x->array))
+ {
+ case 3:
+ x->array[2] = v;
+ case 2:
+ x->array[1] = v;
+ case 1:
+ x->array[0] = v;
break;
default:
abort ();
}
}
-#define UINTS_ALL_ZERO(x) \
- uints_all_zero ((x).array, ARRAY_SIZE ((x).array))
-#define UINTS_SET(x, v) \
- uints_set ((x).array, v, ARRAY_SIZE ((x).array))
-#define UINTS_CLEAR(x) \
- uints_set ((x).array, 0, ARRAY_SIZE ((x).array))
-#define UINTS_EQUAL(x, y) \
- uints_equal ((x).array, (y).array, ARRAY_SIZE ((x).array))
+static INLINE int
+cpu_flags_equal (const union i386_cpu_flags *x,
+ const union i386_cpu_flags *y)
+{
+ switch (ARRAY_SIZE(x->array))
+ {
+ case 3:
+ if (x->array[2] != y->array[2])
+ return 0;
+ case 2:
+ if (x->array[1] != y->array[1])
+ return 0;
+ case 1:
+ return x->array[0] == y->array[0];
+ break;
+ default:
+ abort ();
+ }
+}
static INLINE int
cpu_flags_check_cpu64 (i386_cpu_flags f)
x.bitfield.cpu64 = 0;
x.bitfield.cpuno64 = 0;
- if (UINTS_ALL_ZERO (x))
+ if (cpu_flags_all_zero (&x))
overlap |= 1;
else
{
cpu.bitfield.cpu64 = 0;
cpu.bitfield.cpuno64 = 0;
cpu = cpu_flags_and (x, cpu);
- overlap |= UINTS_ALL_ZERO (cpu) ? 0 : 1;
+ overlap |= cpu_flags_all_zero (&cpu) ? 0 : 1;
}
return overlap;
}
static const i386_operand_type acc32 = OPERAND_TYPE_ACC32;
static const i386_operand_type acc64 = OPERAND_TYPE_ACC64;
static const i386_operand_type control = OPERAND_TYPE_CONTROL;
+static const i386_operand_type inoutportreg
+ = OPERAND_TYPE_INOUTPORTREG;
static const i386_operand_type reg16_inoutportreg
= OPERAND_TYPE_REG16_INOUTPORTREG;
static const i386_operand_type disp16 = OPERAND_TYPE_DISP16;
temp.bitfield.qword = 0;
temp.bitfield.tbyte = 0;
temp.bitfield.xmmword = 0;
- if (UINTS_ALL_ZERO (temp))
+ if (operand_type_all_zero (&temp))
return 0;
return (given.bitfield.baseindex == overlap.bitfield.baseindex
{
i386_operand_type t;
- UINTS_CLEAR (t);
+ operand_type_set (&t, 0);
t.bitfield.imm64 = 1;
if (cpu_arch_tune != PROCESSOR_I486 && num == 1)
flags = cpu_flags_or (cpu_arch_flags,
cpu_arch[i].flags);
- if (!UINTS_EQUAL (flags, cpu_arch_flags))
+ if (!cpu_flags_equal (&flags, &cpu_arch_flags))
{
if (cpu_sub_arch_name)
{
char *name = cpu_sub_arch_name;
cpu_sub_arch_name = concat (name,
cpu_arch[i].name,
- NULL);
+ (const char *) NULL);
free (name);
}
else
return 1;
}
+static void
+process_immext (void)
+{
+ expressionS *exp;
+
+ if (i.tm.cpu_flags.bitfield.cpusse3 && i.operands > 0)
+ {
+ /* SSE3 Instructions have the fixed operands with an opcode
+ suffix which is coded in the same place as an 8-bit immediate
+ field would be. Here we check those operands and remove them
+ afterwards. */
+ unsigned int x;
+
+ for (x = 0; x < i.operands; x++)
+ if (i.op[x].regs->reg_num != x)
+ as_bad (_("can't use register '%s%s' as operand %d in '%s'."),
+ register_prefix, i.op[x].regs->reg_name, x + 1,
+ i.tm.name);
+
+ i.operands = 0;
+ }
+
+ /* These AMD 3DNow! and SSE2 Instructions have an opcode suffix
+ which is coded in the same place as an 8-bit immediate field
+ would be. Here we fake an 8-bit immediate operand from the
+ opcode suffix stored in tm.extension_opcode.
+
+ SSE5 also uses this encoding, for some of its 3 argument
+ instructions. */
+
+ assert (i.imm_operands == 0
+ && (i.operands <= 2
+ || (i.tm.cpu_flags.bitfield.cpusse5
+ && i.operands <= 3)));
+
+ exp = &im_expressions[i.imm_operands++];
+ i.op[i.operands].imms = exp;
+ i.types[i.operands] = imm8;
+ i.operands++;
+ exp->X_op = O_constant;
+ exp->X_add_number = i.tm.extension_opcode;
+ i.tm.extension_opcode = None;
+}
+
/* This is the guts of the machine-dependent assembler. LINE points to a
machine dependent instruction. This function is supposed to emit
the frags/bytes it assembles to. */
void
-md_assemble (line)
- char *line;
+md_assemble (char *line)
{
unsigned int j;
char mnemonic[MAX_MNEM_SIZE];
i.reg_operands--;
if (i.tm.opcode_modifier.immext)
- {
- expressionS *exp;
-
- if (i.tm.cpu_flags.bitfield.cpusse3 && i.operands > 0)
- {
- /* Streaming SIMD extensions 3 Instructions have the fixed
- operands with an opcode suffix which is coded in the same
- place as an 8-bit immediate field would be. Here we check
- those operands and remove them afterwards. */
- unsigned int x;
-
- for (x = 0; x < i.operands; x++)
- if (i.op[x].regs->reg_num != x)
- as_bad (_("can't use register '%s%s' as operand %d in '%s'."),
- register_prefix,
- i.op[x].regs->reg_name,
- x + 1,
- i.tm.name);
- i.operands = 0;
- }
-
- /* These AMD 3DNow! and Intel Katmai New Instructions have an
- opcode suffix which is coded in the same place as an 8-bit
- immediate field would be. Here we fake an 8-bit immediate
- operand from the opcode suffix stored in tm.extension_opcode.
- SSE5 also uses this encoding, for some of its 3 argument
- instructions. */
-
- assert (i.imm_operands == 0
- && (i.operands <= 2
- || (i.tm.cpu_flags.bitfield.cpusse5
- && i.operands <= 3)));
-
- exp = &im_expressions[i.imm_operands++];
- i.op[i.operands].imms = exp;
- UINTS_CLEAR (i.types[i.operands]);
- i.types[i.operands].bitfield.imm8 = 1;
- i.operands++;
- exp->X_op = O_constant;
- exp->X_add_number = i.tm.extension_opcode;
- i.tm.extension_opcode = None;
- }
+ process_immext ();
/* For insns with operands there are more diddles to do to the opcode. */
if (i.operands)
i386_operand_type mask, allowed;
const template *t;
- UINTS_CLEAR (mask);
- UINTS_CLEAR (allowed);
+ operand_type_set (&mask, 0);
+ operand_type_set (&allowed, 0);
for (t = current_templates->start;
t < current_templates->end;
break;
}
allowed = operand_type_and (mask, allowed);
- if (!UINTS_ALL_ZERO (allowed))
+ if (!operand_type_all_zero (&allowed))
i.types[op] = operand_type_and (i.types[op], mask);
}
break;
|| t->extension_opcode != 1 /* cmpxchg8b */))
continue;
+ /* In general, don't allow 32-bit operands on pre-386. */
+ else if (i.suffix == LONG_MNEM_SUFFIX
+ && !cpu_arch_flags.bitfield.cpui386
+ && (intel_syntax
+ ? (!t->opcode_modifier.ignoresize
+ && !intel_float_operand (t->name))
+ : intel_float_operand (t->name) != 2)
+ && ((!operand_types[0].bitfield.regmmx
+ && !operand_types[0].bitfield.regxmm)
+ || (!operand_types[t->operands > 1].bitfield.regmmx
+ && !!operand_types[t->operands > 1].bitfield.regxmm)))
+ continue;
+
/* Do not verify operands when there are none. */
else
{
zero-extend %eax to %rax. */
if (flag_code == CODE_64BIT
&& t->base_opcode == 0x90
- && UINTS_EQUAL (i.types [0], acc32)
- && UINTS_EQUAL (i.types [1], acc32))
+ && operand_type_equal (&i.types [0], &acc32)
+ && operand_type_equal (&i.types [1], &acc32))
continue;
case 3:
case 4:
if (! (i.operands == 2
&& i.tm.base_opcode == 0x90
&& i.tm.extension_opcode == None
- && UINTS_EQUAL (i.types [0], acc64)
- && UINTS_EQUAL (i.types [1], acc64))
+ && operand_type_equal (&i.types [0], &acc64)
+ && operand_type_equal (&i.types [1], &acc64))
&& ! (i.operands == 1
&& i.tm.base_opcode == 0xfc7
&& i.tm.extension_opcode == 1
|| overlap.bitfield.imm32
|| overlap.bitfield.imm32s
|| overlap.bitfield.imm64)
- && !UINTS_EQUAL (overlap, imm8)
- && !UINTS_EQUAL (overlap, imm8s)
- && !UINTS_EQUAL (overlap, imm16)
- && !UINTS_EQUAL (overlap, imm32)
- && !UINTS_EQUAL (overlap, imm32s)
- && !UINTS_EQUAL (overlap, imm64))
+ && !operand_type_equal (&overlap, &imm8)
+ && !operand_type_equal (&overlap, &imm8s)
+ && !operand_type_equal (&overlap, &imm16)
+ && !operand_type_equal (&overlap, &imm32)
+ && !operand_type_equal (&overlap, &imm32s)
+ && !operand_type_equal (&overlap, &imm64))
{
if (i.suffix)
{
i386_operand_type temp;
- UINTS_CLEAR (temp);
+ operand_type_set (&temp, 0);
if (i.suffix == BYTE_MNEM_SUFFIX)
{
temp.bitfield.imm8 = overlap.bitfield.imm8;
temp.bitfield.imm32 = overlap.bitfield.imm32;
overlap = temp;
}
- else if (UINTS_EQUAL (overlap, imm16_32_32s)
- || UINTS_EQUAL (overlap, imm16_32)
- || UINTS_EQUAL (overlap, imm16_32s))
+ else if (operand_type_equal (&overlap, &imm16_32_32s)
+ || operand_type_equal (&overlap, &imm16_32)
+ || operand_type_equal (&overlap, &imm16_32s))
{
- UINTS_CLEAR (overlap);
if ((flag_code == CODE_16BIT) ^ (i.prefix[DATA_PREFIX] != 0))
- overlap.bitfield.imm16 = 1;
+ overlap = imm16;
else
- overlap.bitfield.imm32s = 1;
+ overlap = imm32s;
}
- if (!UINTS_EQUAL (overlap, imm8)
- && !UINTS_EQUAL (overlap, imm8s)
- && !UINTS_EQUAL (overlap, imm16)
- && !UINTS_EQUAL (overlap, imm32)
- && !UINTS_EQUAL (overlap, imm32s)
- && !UINTS_EQUAL (overlap, imm64))
+ if (!operand_type_equal (&overlap, &imm8)
+ && !operand_type_equal (&overlap, &imm8s)
+ && !operand_type_equal (&overlap, &imm16)
+ && !operand_type_equal (&overlap, &imm32)
+ && !operand_type_equal (&overlap, &imm32s)
+ && !operand_type_equal (&overlap, &imm64))
{
as_bad (_("no instruction mnemonic suffix given; "
"can't determine immediate size"));
&& i.op[0].regs->reg_flags == i.op[3].regs->reg_flags)
{
/* Clear the arguments that are stored in drex. */
- UINTS_CLEAR (i.types[0]);
- UINTS_CLEAR (i.types[3]);
+ operand_type_set (&i.types[0], 0);
+ operand_type_set (&i.types[3], 0);
i.reg_operands -= 2;
/* There are two different ways to encode a 4 operand
&& i.op[0].regs->reg_flags == i.op[3].regs->reg_flags)
{
/* clear the arguments that are stored in drex */
- UINTS_CLEAR (i.types[0]);
- UINTS_CLEAR (i.types[3]);
+ operand_type_set (&i.types[0], 0);
+ operand_type_set (&i.types[3], 0);
i.reg_operands -= 2;
/* Specify the modrm encoding for memory addressing. Include
&& i.op[0].regs->reg_flags == i.op[3].regs->reg_flags)
{
/* Clear the arguments that are stored in drex. */
- UINTS_CLEAR (i.types[0]);
- UINTS_CLEAR (i.types[3]);
+ operand_type_set (&i.types[0], 0);
+ operand_type_set (&i.types[3], 0);
i.reg_operands -= 2;
/* Specify the modrm encoding for memory addressing. Include
&& i.op[2].regs->reg_flags == i.op[3].regs->reg_flags)
{
/* clear the arguments that are stored in drex */
- UINTS_CLEAR (i.types[2]);
- UINTS_CLEAR (i.types[3]);
+ operand_type_set (&i.types[2], 0);
+ operand_type_set (&i.types[3], 0);
i.reg_operands -= 2;
/* There are two different ways to encode a 4 operand
&& i.op[2].regs->reg_flags == i.op[3].regs->reg_flags)
{
/* Clear the arguments that are stored in drex. */
- UINTS_CLEAR (i.types[2]);
- UINTS_CLEAR (i.types[3]);
+ operand_type_set (&i.types[2], 0);
+ operand_type_set (&i.types[3], 0);
i.reg_operands -= 2;
/* Specify the modrm encoding and remember the register
&& i.op[2].regs->reg_flags == i.op[3].regs->reg_flags)
{
/* clear the arguments that are stored in drex */
- UINTS_CLEAR (i.types[2]);
- UINTS_CLEAR (i.types[3]);
+ operand_type_set (&i.types[2], 0);
+ operand_type_set (&i.types[3], 0);
i.reg_operands -= 2;
/* Specify the modrm encoding and remember the register
&& i.op[0].regs->reg_flags == i.op[3].regs->reg_flags)
{
/* clear the arguments that are stored in drex */
- UINTS_CLEAR (i.types[0]);
- UINTS_CLEAR (i.types[3]);
+ operand_type_set (&i.types[0], 0);
+ operand_type_set (&i.types[3], 0);
i.reg_operands -= 2;
/* Specify the modrm encoding and remember the register
&& i.types[2].bitfield.regxmm != 0)
{
/* Clear the arguments that are stored in drex. */
- UINTS_CLEAR (i.types[2]);
+ operand_type_set (&i.types[2], 0);
i.reg_operands--;
/* Specify the modrm encoding and remember the register
&& i.types[2].bitfield.regxmm != 0)
{
/* Clear the arguments that are stored in drex. */
- UINTS_CLEAR (i.types[2]);
+ operand_type_set (&i.types[2], 0);
i.reg_operands--;
/* Specify the modrm encoding and remember the register
&& i.types[2].bitfield.regxmm != 0)
{
/* Clear the arguments that are stored in drex. */
- UINTS_CLEAR (i.types[2]);
+ operand_type_set (&i.types[2], 0);
i.reg_operands--;
/* Specify the modrm encoding and remember the register
&& i.types[3].bitfield.regxmm != 0)
{
/* clear the arguments that are stored in drex */
- UINTS_CLEAR (i.types[3]);
+ operand_type_set (&i.types[3], 0);
i.reg_operands--;
/* Specify the modrm encoding and remember the register
&& operand_type_check (i.types[3], imm) != 0)
{
/* clear the arguments that are stored in drex */
- UINTS_CLEAR (i.types[2]);
+ operand_type_set (&i.types[2], 0);
i.reg_operands--;
/* Specify the modrm encoding and remember the register
unsigned int j;
/* The first operand is implicit and must be xmm0. */
- assert (i.reg_operands && UINTS_EQUAL (i.types[0], regxmm));
+ assert (i.reg_operands
+ && operand_type_equal (&i.types[0], ®xmm));
if (i.op[0].regs->reg_num != 0)
{
if (intel_syntax)
&& operand_type_check (i.types[op], disp))
{
i386_operand_type temp;
- UINTS_CLEAR (temp);
+ operand_type_set (&temp, 0);
temp.bitfield.disp8 = i.types[op].bitfield.disp8;
i.types[op] = temp;
if (i.prefix[ADDR_PREFIX] == 0)
expressionS *exp;
i386_operand_type types;
- UINTS_SET (types, ~0);
+ operand_type_set (&types, ~0);
if (i.imm_operands == MAX_IMMEDIATE_OPERANDS)
{
return 0;
}
- UINTS_CLEAR (bigdisp);
+ operand_type_set (&bigdisp, 0);
if ((i.types[this_operand].bitfield.jumpabsolute)
|| (!current_templates->start->opcode_modifier.jump
&& !current_templates->start->opcode_modifier.jumpdword))
bigdisp.bitfield.disp32 = 0;
bigdisp.bitfield.disp32s = 0;
bigdisp.bitfield.disp64 = 0;
- if (UINTS_ALL_ZERO (bigdisp))
+ if (operand_type_all_zero (&bigdisp))
i.types[this_operand] = operand_type_and (i.types[this_operand],
types);
/* Special case for (%dx) while doing input/output op. */
if (i.base_reg
- && UINTS_EQUAL (i.base_reg->reg_type, reg16_inoutportreg)
+ && operand_type_equal (&i.base_reg->reg_type,
+ ®16_inoutportreg)
&& i.index_reg == 0
&& i.log2_scale_factor == 0
&& i.seg[i.mem_operands] == 0
&& !operand_type_check (i.types[this_operand], disp))
{
- UINTS_CLEAR (i.types[this_operand]);
- i.types[this_operand].bitfield.inoutportreg = 1;
+ i.types[this_operand] = inoutportreg;
return 1;
}
}
}
+ if (r == NULL || allow_pseudo_reg)
+ return r;
+
+ if (operand_type_all_zero (&r->reg_type))
+ return (const reg_entry *) NULL;
+
+ if ((r->reg_type.bitfield.reg32
+ || r->reg_type.bitfield.sreg3
+ || r->reg_type.bitfield.control
+ || r->reg_type.bitfield.debug
+ || r->reg_type.bitfield.test)
+ && !cpu_arch_flags.bitfield.cpui386)
+ return (const reg_entry *) NULL;
+
+ if (r->reg_type.bitfield.regmmx && !cpu_arch_flags.bitfield.cpummx)
+ return (const reg_entry *) NULL;
+
+ if (r->reg_type.bitfield.regxmm && !cpu_arch_flags.bitfield.cpusse)
+ return (const reg_entry *) NULL;
+
/* Don't allow fake index register unless allow_index_reg isn't 0. */
- if (r != NULL
- && !allow_index_reg
+ if (!allow_index_reg
&& (r->reg_num == RegEiz || r->reg_num == RegRiz))
return (const reg_entry *) NULL;
- if (r != NULL
- && ((r->reg_flags & (RegRex64 | RegRex))
- || r->reg_type.bitfield.reg64)
+ if (((r->reg_flags & (RegRex64 | RegRex))
+ || r->reg_type.bitfield.reg64)
&& (!cpu_arch_flags.bitfield.cpulm
- || !UINTS_EQUAL (r->reg_type, control))
+ || !operand_type_equal (&r->reg_type, &control))
&& flag_code != CODE_64BIT)
return (const reg_entry *) NULL;
+ if (r->reg_type.bitfield.sreg3 && r->reg_num == RegFlat && !intel_syntax)
+ return (const reg_entry *) NULL;
+
return r;
}
i386_cpu_flags flags;
flags = cpu_flags_or (cpu_arch_flags,
cpu_arch[i].flags);
- if (!UINTS_EQUAL (flags, cpu_arch_flags))
+ if (!cpu_flags_equal (&flags, &cpu_arch_flags))
{
if (cpu_sub_arch_name)
{
char *name = cpu_sub_arch_name;
cpu_sub_arch_name = concat (name,
cpu_arch[i].name,
- NULL);
+ (const char *) NULL);
free (name);
}
else
generic32, generic64\n\
EXTENSION is combination of:\n\
mmx, sse, sse2, sse3, ssse3, sse4.1, sse4.2, sse4,\n\
- vmx, smx, 3dnow, 3dnowa, sse4a, sse5, svme, abm,\n\
- padlock\n"));
+ vmx, smx, xsave, 3dnow, 3dnowa, sse4a, sse5, svme,\n\
+ abm, padlock\n"));
fprintf (stream, _("\
-mtune=CPU optimize for CPU, CPU is one of:\n\
i8086, i186, i286, i386, i486, pentium, pentiumpro,\n\
if (!strcmp (default_arch, "x86_64"))
{
set_code_flag (CODE_64BIT);
- if (UINTS_ALL_ZERO (cpu_arch_isa_flags))
+ if (cpu_flags_all_zero (&cpu_arch_isa_flags))
{
cpu_arch_isa_flags.bitfield.cpui186 = 1;
cpu_arch_isa_flags.bitfield.cpui286 = 1;
cpu_arch_isa_flags.bitfield.cpusse = 1;
cpu_arch_isa_flags.bitfield.cpusse2 = 1;
}
- if (UINTS_ALL_ZERO (cpu_arch_tune_flags))
+ if (cpu_flags_all_zero (&cpu_arch_tune_flags))
{
cpu_arch_tune_flags.bitfield.cpui186 = 1;
cpu_arch_tune_flags.bitfield.cpui286 = 1;
else if (!strcmp (default_arch, "i386"))
{
set_code_flag (CODE_32BIT);
- if (UINTS_ALL_ZERO (cpu_arch_isa_flags))
+ if (cpu_flags_all_zero (&cpu_arch_isa_flags))
{
cpu_arch_isa_flags.bitfield.cpui186 = 1;
cpu_arch_isa_flags.bitfield.cpui286 = 1;
cpu_arch_isa_flags.bitfield.cpui386 = 1;
}
- if (UINTS_ALL_ZERO (cpu_arch_tune_flags))
+ if (cpu_flags_all_zero (&cpu_arch_tune_flags))
{
cpu_arch_tune_flags.bitfield.cpui186 = 1;
cpu_arch_tune_flags.bitfield.cpui286 = 1;
/* Constant and OFFSET expressions are handled by i386_immediate. */
else if ((intel_parser.op_modifier & (1 << T_OFFSET))
|| intel_parser.reg == NULL)
- ret = i386_immediate (intel_parser.disp);
+ {
+ if (i.mem_operands < 2 && i.seg[i.mem_operands])
+ {
+ if (!(intel_parser.op_modifier & (1 << T_OFFSET)))
+ as_warn (_("Segment override ignored"));
+ i.seg[i.mem_operands] = NULL;
+ }
+ ret = i386_immediate (intel_parser.disp);
+ }
if (intel_parser.next_operand && this_operand >= MAX_OPERANDS - 1)
ret = 0;
else if (prev_token.code == T_WORD)
{
- if (current_templates->start->name[0] == 'l'
- && current_templates->start->name[2] == 's'
- && current_templates->start->name[3] == 0)
+ if ((current_templates->start->name[0] == 'l'
+ && current_templates->start->name[2] == 's'
+ && current_templates->start->name[3] == 0)
+ || current_templates->start->base_opcode == 0x62 /* bound */)
suffix = BYTE_MNEM_SUFFIX; /* so it will cause an error */
else if (intel_parser.got_a_float == 2) /* "fi..." */
suffix = SHORT_MNEM_SUFFIX;
else if (prev_token.code == T_DWORD)
{
- if (current_templates->start->name[0] == 'l'
- && current_templates->start->name[2] == 's'
- && current_templates->start->name[3] == 0)
+ if ((current_templates->start->name[0] == 'l'
+ && current_templates->start->name[2] == 's'
+ && current_templates->start->name[3] == 0)
+ || current_templates->start->base_opcode == 0x62 /* bound */)
suffix = WORD_MNEM_SUFFIX;
else if (flag_code == CODE_16BIT
&& (current_templates->start->opcode_modifier.jump
else if (prev_token.code == T_QWORD)
{
- if (intel_parser.got_a_float == 1) /* "f..." */
+ if (current_templates->start->base_opcode == 0x62 /* bound */
+ || intel_parser.got_a_float == 1) /* "f..." */
suffix = LONG_MNEM_SUFFIX;
else
- suffix = QWORD_MNEM_SUFFIX;
+ suffix = QWORD_MNEM_SUFFIX;
i.types[this_operand].bitfield.qword = 1;
}
reg->reg_name);
return 0;
}
+ else if (i.mem_operands >= 2)
+ as_warn (_("Segment override ignored"));
else if (i.seg[i.mem_operands])
as_warn (_("Extra segment override ignored"));
else
}
}
+ else if (reg->reg_type.bitfield.sreg3 && reg->reg_num == RegFlat)
+ {
+ as_bad (_("cannot use `FLAT' here"));
+ return 0;
+ }
+
/* Not a segment register. Check for register scaling. */
else if (cur_token.code == '*')
{
strcat (new_token.str, " FLAT:");
}
- /* ??? This is not mentioned in the MASM grammar. */
- else if (strcasecmp (new_token.str, "FLAT") == 0)
- {
- new_token.code = T_OFFSET;
- if (*q == ':')
- strcat (new_token.str, ":");
- else
- as_bad (_("`:' expected"));
- }
-
else
new_token.code = T_ID;
}
prev_token.str = NULL;
}
-int
-tc_x86_regname_to_dw2regnum (char *regname)
-{
- unsigned int regnum;
- unsigned int regnames_count;
- static const char *const regnames_32[] =
- {
- "eax", "ecx", "edx", "ebx",
- "esp", "ebp", "esi", "edi",
- "eip", "eflags", NULL,
- "st0", "st1", "st2", "st3",
- "st4", "st5", "st6", "st7",
- NULL, NULL,
- "xmm0", "xmm1", "xmm2", "xmm3",
- "xmm4", "xmm5", "xmm6", "xmm7",
- "mm0", "mm1", "mm2", "mm3",
- "mm4", "mm5", "mm6", "mm7",
- "fcw", "fsw", "mxcsr",
- "es", "cs", "ss", "ds", "fs", "gs", NULL, NULL,
- "tr", "ldtr"
- };
- static const char *const regnames_64[] =
- {
- "rax", "rdx", "rcx", "rbx",
- "rsi", "rdi", "rbp", "rsp",
- "r8", "r9", "r10", "r11",
- "r12", "r13", "r14", "r15",
- "rip",
- "xmm0", "xmm1", "xmm2", "xmm3",
- "xmm4", "xmm5", "xmm6", "xmm7",
- "xmm8", "xmm9", "xmm10", "xmm11",
- "xmm12", "xmm13", "xmm14", "xmm15",
- "st0", "st1", "st2", "st3",
- "st4", "st5", "st6", "st7",
- "mm0", "mm1", "mm2", "mm3",
- "mm4", "mm5", "mm6", "mm7",
- "rflags",
- "es", "cs", "ss", "ds", "fs", "gs", NULL, NULL,
- "fs.base", "gs.base", NULL, NULL,
- "tr", "ldtr",
- "mxcsr", "fcw", "fsw"
- };
- const char *const *regnames;
+void
+tc_x86_parse_to_dw2regnum (expressionS *exp)
+{
+ int saved_naked_reg;
+ char saved_register_dot;
- if (flag_code == CODE_64BIT)
- {
- regnames = regnames_64;
- regnames_count = ARRAY_SIZE (regnames_64);
- }
- else
+ saved_naked_reg = allow_naked_reg;
+ allow_naked_reg = 1;
+ saved_register_dot = register_chars['.'];
+ register_chars['.'] = '.';
+ allow_pseudo_reg = 1;
+ expression_and_evaluate (exp);
+ allow_pseudo_reg = 0;
+ register_chars['.'] = saved_register_dot;
+ allow_naked_reg = saved_naked_reg;
+
+ if (exp->X_op == O_register && exp->X_add_number >= 0)
{
- regnames = regnames_32;
- regnames_count = ARRAY_SIZE (regnames_32);
+ if ((addressT) exp->X_add_number < i386_regtab_size)
+ {
+ exp->X_op = O_constant;
+ exp->X_add_number = i386_regtab[exp->X_add_number]
+ .dw2_regnum[flag_code >> 1];
+ }
+ else
+ exp->X_op = O_illegal;
}
-
- for (regnum = 0; regnum < regnames_count; regnum++)
- if (regnames[regnum] != NULL
- && strcmp (regname, regnames[regnum]) == 0)
- return regnum;
-
- return -1;
}
void
tc_x86_frame_initial_instructions (void)
{
- static unsigned int sp_regno;
+ static unsigned int sp_regno[2];
- if (!sp_regno)
- sp_regno = tc_x86_regname_to_dw2regnum (flag_code == CODE_64BIT
- ? "rsp" : "esp");
+ if (!sp_regno[flag_code >> 1])
+ {
+ char *saved_input = input_line_pointer;
+ char sp[][4] = {"esp", "rsp"};
+ expressionS exp;
+
+ input_line_pointer = sp[flag_code >> 1];
+ tc_x86_parse_to_dw2regnum (&exp);
+ assert (exp.X_op == O_constant);
+ sp_regno[flag_code >> 1] = exp.X_add_number;
+ input_line_pointer = saved_input;
+ }
- cfi_add_CFA_def_cfa (sp_regno, -x86_cie_data_alignment);
+ cfi_add_CFA_def_cfa (sp_regno[flag_code >> 1], -x86_cie_data_alignment);
cfi_add_CFA_offset (x86_dwarf2_return_column, x86_cie_data_alignment);
}