unsigned int prefixes;
unsigned char prefix[MAX_PREFIXES];
+ /* The operand to a branch insn indicates an absolute branch. */
+ bfd_boolean jumpabsolute;
+
/* Has MMX register operands. */
bfd_boolean has_regmmx;
{
unsigned int j, match = MATCH_STRAIGHT;
- /* Don't check jump instructions. */
+ /* Don't check non-absolute jump instructions. */
if (t->opcode_modifier.jump
- || t->opcode_modifier.jumpbyte
- || t->opcode_modifier.jumpdword
- || t->opcode_modifier.jumpintersegment)
+ && t->opcode_modifier.jump != JUMP_ABSOLUTE)
return match;
/* Check memory and accumulator operand size. */
{
if (i.types[j].bitfield.class != Reg
&& i.types[j].bitfield.class != RegSIMD
- && t->operand_types[j].bitfield.anysize)
+ && t->opcode_modifier.anysize)
continue;
if (t->operand_types[j].bitfield.class == Reg
{
i386_operand_type temp = overlap;
- temp.bitfield.jumpabsolute = 0;
temp.bitfield.unspecified = 0;
temp.bitfield.byte = 0;
temp.bitfield.word = 0;
if (operand_type_all_zero (&temp))
goto mismatch;
- if (given.bitfield.baseindex == overlap.bitfield.baseindex
- && given.bitfield.jumpabsolute == overlap.bitfield.jumpabsolute)
+ if (given.bitfield.baseindex == overlap.bitfield.baseindex)
return 1;
mismatch:
{ OPERAND_TYPE_FLOATREG, "FReg" },
{ OPERAND_TYPE_FLOATACC, "FAcc" },
{ OPERAND_TYPE_SREG, "SReg" },
- { OPERAND_TYPE_JUMPABSOLUTE, "Jump Absolute" },
{ OPERAND_TYPE_REGMMX, "rMMX" },
{ OPERAND_TYPE_REGXMM, "rXMM" },
{ OPERAND_TYPE_REGYMM, "rYMM" },
{ OPERAND_TYPE_REGZMM, "rZMM" },
{ OPERAND_TYPE_REGMASK, "Mask reg" },
- { OPERAND_TYPE_ESSEG, "es" },
};
static void
{
expressionS *exp;
- if ((i.tm.cpu_flags.bitfield.cpusse3 || i.tm.cpu_flags.bitfield.cpusvme)
- && i.operands > 0)
- {
- /* MONITOR/MWAIT as well as SVME instructions have 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 (register_number (i.op[x].regs) != 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;
- }
-
- if (i.tm.cpu_flags.bitfield.cpumwaitx && i.operands > 0)
- {
- /* MONITORX/MWAITX instructions have 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;
-
- if (i.operands != 3)
- abort();
-
- for (x = 0; x < 2; x++)
- if (register_number (i.op[x].regs) != x)
- goto bad_register_operand;
-
- /* Check for third operand for mwaitx/monitorx insn. */
- if (register_number (i.op[x].regs)
- != (x + (i.tm.extension_opcode == 0xfb)))
- {
-bad_register_operand:
- 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
}
/* Check string instruction segment overrides. */
- if (i.tm.opcode_modifier.isstring && i.mem_operands != 0)
+ if (i.tm.opcode_modifier.isstring >= IS_STRING_ES_OP0)
{
+ gas_assert (i.mem_operands);
if (!check_string ())
return;
i.disp_operands = 0;
i.imm_operands = 0;
}
- if ((i.tm.opcode_modifier.jump
- || i.tm.opcode_modifier.jumpbyte
- || i.tm.opcode_modifier.jumpdword)
+ if ((i.tm.opcode_modifier.jump == JUMP
+ || i.tm.opcode_modifier.jump == JUMP_BYTE
+ || i.tm.opcode_modifier.jump == JUMP_DWORD)
&& i.op[0].disps->X_op == O_constant)
{
/* Convert "jmp constant" (and "call constant") to a jump (call) to
}
}
- if (current_templates->start->opcode_modifier.jump
- || current_templates->start->opcode_modifier.jumpbyte)
+ if (current_templates->start->opcode_modifier.jump == JUMP
+ || current_templates->start->opcode_modifier.jump == JUMP_BYTE)
{
/* Check for a branch hint. We allow ",pt" and ",pn" for
predict taken and predict not taken respectively.
if (!size_match)
continue;
+ /* This is intentionally not
+
+ if (i.jumpabsolute != (t->opcode_modifier.jump == JUMP_ABSOLUTE))
+
+ as the case of a missing * on the operand is accepted (perhaps with
+ a warning, issued further down). */
+ if (i.jumpabsolute && t->opcode_modifier.jump != JUMP_ABSOLUTE)
+ {
+ i.error = operand_type_mismatch;
+ continue;
+ }
+
for (j = 0; j < MAX_OPERANDS; j++)
operand_types[j] = t->operand_types[j];
if (!quiet_warnings)
{
if (!intel_syntax
- && (i.types[0].bitfield.jumpabsolute
- != operand_types[0].bitfield.jumpabsolute))
- {
- as_warn (_("indirect %s without `*'"), t->name);
- }
+ && (i.jumpabsolute != (t->opcode_modifier.jump == JUMP_ABSOLUTE)))
+ as_warn (_("indirect %s without `*'"), t->name);
if (t->opcode_modifier.isprefix
&& t->opcode_modifier.ignoresize)
static int
check_string (void)
{
- unsigned int mem_op = i.flags[0] & Operand_Mem ? 0 : 1;
+ unsigned int es_op = i.tm.opcode_modifier.isstring - IS_STRING_ES_OP0;
+ unsigned int op = i.tm.operand_types[0].bitfield.baseindex ? es_op : 0;
- if (i.tm.operand_types[mem_op].bitfield.esseg)
+ if (i.seg[op] != NULL && i.seg[op] != &es)
{
- if (i.seg[0] != NULL && i.seg[0] != &es)
- {
- as_bad (_("`%s' operand %d must use `%ses' segment"),
- i.tm.name,
- intel_syntax ? i.tm.operands - mem_op : mem_op + 1,
- register_prefix);
- return 0;
- }
- /* There's only ever one segment override allowed per instruction.
- This instruction possibly has a legal segment override on the
- second operand, so copy the segment to where non-string
- instructions store it, allowing common code. */
- i.seg[0] = i.seg[1];
- }
- else if (i.tm.operand_types[mem_op + 1].bitfield.esseg)
- {
- if (i.seg[1] != NULL && i.seg[1] != &es)
- {
- as_bad (_("`%s' operand %d must use `%ses' segment"),
- i.tm.name,
- intel_syntax ? i.tm.operands - mem_op - 1 : mem_op + 2,
- register_prefix);
- return 0;
- }
+ as_bad (_("`%s' operand %u must use `%ses' segment"),
+ i.tm.name,
+ intel_syntax ? i.tm.operands - es_op : es_op + 1,
+ register_prefix);
+ return 0;
}
+
+ /* There's only ever one segment override allowed per instruction.
+ This instruction possibly has a legal segment override on the
+ second operand, so copy the segment to where non-string
+ instructions store it, allowing common code. */
+ i.seg[op] = i.seg[1];
+
return 1;
}
i.suffix = LONG_MNEM_SUFFIX;
else if (i.tm.opcode_modifier.size == SIZE64)
i.suffix = QWORD_MNEM_SUFFIX;
- else if (i.reg_operands)
+ else if (i.reg_operands
+ && (i.operands > 1 || i.types[0].bitfield.class == Reg))
{
/* If there's no instruction mnemonic suffix we try to invent one
- based on register operands. */
+ based on GPR operands. */
if (!i.suffix)
{
/* We take i.suffix from the last register operand specified,
else if (i.tm.opcode_modifier.defaultsize
&& !i.suffix
/* exclude fldenv/frstor/fsave/fstenv */
- && i.tm.opcode_modifier.no_ssuf)
+ && i.tm.opcode_modifier.no_ssuf
+ /* exclude sysret */
+ && i.tm.base_opcode != 0x0f07)
{
- if (stackop_size == LONG_MNEM_SUFFIX
- && i.tm.base_opcode == 0xcf)
+ i.suffix = stackop_size;
+ if (stackop_size == LONG_MNEM_SUFFIX)
{
/* stackop_size is set to LONG_MNEM_SUFFIX for the
.code16gcc directive to support 16-bit mode with
32-bit address. For IRET without a suffix, generate
16-bit IRET (opcode 0xcf) to return from an interrupt
handler. */
- i.suffix = WORD_MNEM_SUFFIX;
- as_warn (_("generating 16-bit `iret' for .code16gcc directive"));
+ if (i.tm.base_opcode == 0xcf)
+ {
+ i.suffix = WORD_MNEM_SUFFIX;
+ as_warn (_("generating 16-bit `iret' for .code16gcc directive"));
+ }
+ /* Warn about changed behavior for segment register push/pop. */
+ else if ((i.tm.base_opcode | 1) == 0x07)
+ as_warn (_("generating 32-bit `%s', unlike earlier gas versions"),
+ i.tm.name);
}
- else
- i.suffix = stackop_size;
}
else if (intel_syntax
&& !i.suffix
- && (i.tm.operand_types[0].bitfield.jumpabsolute
- || i.tm.opcode_modifier.jumpbyte
- || i.tm.opcode_modifier.jumpintersegment
+ && (i.tm.opcode_modifier.jump == JUMP_ABSOLUTE
+ || i.tm.opcode_modifier.jump == JUMP_BYTE
+ || i.tm.opcode_modifier.jump == JUMP_INTERSEGMENT
|| (i.tm.base_opcode == 0x0f01 /* [ls][gi]dt */
&& i.tm.extension_opcode <= 3)))
{
if (i.reg_operands > 0
&& i.types[0].bitfield.class == Reg
&& i.tm.opcode_modifier.addrprefixopreg
- && (i.tm.opcode_modifier.immext
+ && (i.tm.operand_types[0].bitfield.instance == Accum
|| i.operands == 1))
{
/* The address size override prefix changes the size of the
&& !is_any_vex_encoding (&i.tm)
&& ((i.suffix == LONG_MNEM_SUFFIX) == (flag_code == CODE_16BIT)
|| (flag_code == CODE_64BIT
- && i.tm.opcode_modifier.jumpbyte)))
+ && i.tm.opcode_modifier.jump == JUMP_BYTE)))
{
unsigned int prefix = DATA_PREFIX_OPCODE;
- if (i.tm.opcode_modifier.jumpbyte) /* jcxz, loop */
+ if (i.tm.opcode_modifier.jump == JUMP_BYTE) /* jcxz, loop */
prefix = ADDR_PREFIX_OPCODE;
if (!add_prefix (prefix))
if (i.reg_operands != 0
&& i.operands > 1
&& i.tm.opcode_modifier.addrprefixopreg
- && !i.tm.opcode_modifier.immext)
+ && i.tm.operand_types[0].bitfield.instance != Accum)
{
/* Check invalid register operand when the address size override
prefix changes the size of register operands. */
fixS *fixP;
bfd_reloc_code_real_type jump_reloc = i.reloc[0];
- if (i.tm.opcode_modifier.jumpbyte)
+ if (i.tm.opcode_modifier.jump == JUMP_BYTE)
{
/* This is a loop or jecxz type instruction. */
size = 1;
insn_start_off = frag_now_fix ();
/* Output jumps. */
- if (i.tm.opcode_modifier.jump)
+ if (i.tm.opcode_modifier.jump == JUMP)
output_branch ();
- else if (i.tm.opcode_modifier.jumpbyte
- || i.tm.opcode_modifier.jumpdword)
+ else if (i.tm.opcode_modifier.jump == JUMP_BYTE
+ || i.tm.opcode_modifier.jump == JUMP_DWORD)
output_jump ();
- else if (i.tm.opcode_modifier.jumpintersegment)
+ else if (i.tm.opcode_modifier.jump == JUMP_INTERSEGMENT)
output_interseg_jump ();
else
{
}
operand_type_set (&bigdisp, 0);
- if ((i.types[this_operand].bitfield.jumpabsolute)
- || (!current_templates->start->opcode_modifier.jump
- && !current_templates->start->opcode_modifier.jumpdword))
+ if (i.jumpabsolute
+ || (current_templates->start->opcode_modifier.jump != JUMP
+ && current_templates->start->opcode_modifier.jump != JUMP_DWORD))
{
bigdisp.bitfield.disp32 = 1;
override = (i.prefix[ADDR_PREFIX] != 0);
if (current_templates->start->opcode_modifier.repprefixok)
{
- i386_operand_type type = current_templates->end[-1].operand_types[0];
+ int es_op = current_templates->end[-1].opcode_modifier.isstring
+ - IS_STRING_ES_OP0;
+ int op = 0;
- if (!type.bitfield.baseindex
+ if (!current_templates->end[-1].operand_types[0].bitfield.baseindex
|| ((!i.mem_operands != !intel_syntax)
&& current_templates->end[-1].operand_types[1]
.bitfield.baseindex))
- type = current_templates->end[-1].operand_types[1];
- expected_reg = hash_find (reg_hash,
- di_si[addr_mode][type.bitfield.esseg]);
-
+ op = 1;
+ expected_reg = hash_find (reg_hash, di_si[addr_mode][op == es_op]);
}
else
expected_reg = hash_find (reg_hash, bx[addr_mode]);
++op_string;
if (is_space_char (*op_string))
++op_string;
- i.types[this_operand].bitfield.jumpabsolute = 1;
+ i.jumpabsolute = TRUE;
}
/* Check if operand is a register. */
++op_string;
if (is_space_char (*op_string))
++op_string;
- i.types[this_operand].bitfield.jumpabsolute = 1;
+ i.jumpabsolute = TRUE;
}
goto do_memory_reference;
}
else if (*op_string == IMMEDIATE_PREFIX)
{
++op_string;
- if (i.types[this_operand].bitfield.jumpabsolute)
+ if (i.jumpabsolute)
{
as_bad (_("immediate operand illegal with absolute jump"));
return 0;