static char *parse_operands (char *, const char *);
static void swap_operands (void);
static void swap_2_operands (int, int);
+static enum flag_code i386_addressing_mode (void);
static void optimize_imm (void);
static void optimize_disp (void);
static const insn_template *match_template (char);
i.types[1].bitfield.byte = 1;
/* Ignore the suffix. */
i.suffix = 0;
- if (base_regnum >= 4
- && !(i.op[1].regs->reg_flags & RegRex))
+ if (base_regnum >= 4)
{
- /* Handle SP, BP, SI and DI registers. */
+ /* Handle SP, BP, SI, DI and R12-R15 registers. */
if (i.types[1].bitfield.word)
j = 16;
else if (i.types[1].bitfield.dword)
break;
}
- /* Address size prefix will turn Disp64/Disp32/Disp16 operand
- into Disp32/Disp16/Disp32 operand. */
- if (i.prefix[ADDR_PREFIX] != 0)
- {
- /* There should be only one Disp operand. */
- switch (flag_code)
- {
- case CODE_16BIT:
- for (j = 0; j < MAX_OPERANDS; j++)
- {
- if (operand_types[j].bitfield.disp16)
- {
- addr_prefix_disp = j;
- operand_types[j].bitfield.disp32 = 1;
- operand_types[j].bitfield.disp16 = 0;
- break;
- }
- }
+ if (!t->opcode_modifier.jump
+ || t->opcode_modifier.jump == JUMP_ABSOLUTE)
+ {
+ /* There should be only one Disp operand. */
+ for (j = 0; j < MAX_OPERANDS; j++)
+ if (operand_type_check (operand_types[j], disp))
break;
- case CODE_32BIT:
- for (j = 0; j < MAX_OPERANDS; j++)
+ if (j < MAX_OPERANDS)
+ {
+ bfd_boolean override = (i.prefix[ADDR_PREFIX] != 0);
+
+ addr_prefix_disp = j;
+
+ /* Address size prefix will turn Disp64/Disp32S/Disp32/Disp16
+ operand into Disp32/Disp32/Disp16/Disp32 operand. */
+ switch (flag_code)
{
- if (operand_types[j].bitfield.disp32)
+ case CODE_16BIT:
+ override = !override;
+ /* Fall through. */
+ case CODE_32BIT:
+ if (operand_types[j].bitfield.disp32
+ && operand_types[j].bitfield.disp16)
{
- addr_prefix_disp = j;
- operand_types[j].bitfield.disp32 = 0;
- operand_types[j].bitfield.disp16 = 1;
- break;
+ operand_types[j].bitfield.disp16 = override;
+ operand_types[j].bitfield.disp32 = !override;
}
- }
- break;
- case CODE_64BIT:
- for (j = 0; j < MAX_OPERANDS; j++)
- {
- if (operand_types[j].bitfield.disp64)
+ operand_types[j].bitfield.disp32s = 0;
+ operand_types[j].bitfield.disp64 = 0;
+ break;
+
+ case CODE_64BIT:
+ if (operand_types[j].bitfield.disp32s
+ || operand_types[j].bitfield.disp64)
{
- addr_prefix_disp = j;
- operand_types[j].bitfield.disp64 = 0;
- operand_types[j].bitfield.disp32 = 1;
- break;
+ operand_types[j].bitfield.disp64 &= !override;
+ operand_types[j].bitfield.disp32s &= !override;
+ operand_types[j].bitfield.disp32 = override;
}
+ operand_types[j].bitfield.disp16 = 0;
+ break;
}
- break;
}
- }
+ }
/* Force 0x8b encoding for "mov foo@GOT, %eax". */
if (i.reloc[0] == BFD_RELOC_386_GOT32 && t->base_opcode == 0xa0)
return default_seg;
}
+static unsigned int
+flip_code16 (unsigned int code16)
+{
+ gas_assert (i.tm.operands == 1);
+
+ return !(i.prefix[REX_PREFIX] & REX_W)
+ && (code16 ? i.tm.operand_types[0].bitfield.disp32
+ || i.tm.operand_types[0].bitfield.disp32s
+ : i.tm.operand_types[0].bitfield.disp16)
+ ? CODE16 : 0;
+}
+
static void
output_branch (void)
{
{
prefix = 1;
i.prefixes -= 1;
- code16 ^= CODE16;
+ code16 ^= flip_code16(code16);
}
/* Pentium4 branch hints. */
if (i.prefix[SEG_PREFIX] == CS_PREFIX_OPCODE /* not taken */
{
FRAG_APPEND_1_CHAR (DATA_PREFIX_OPCODE);
i.prefixes -= 1;
- code16 ^= CODE16;
+ code16 ^= flip_code16(code16);
}
size = 4;
operand_type_set (&bigdisp, 0);
if (i.jumpabsolute
+ || i.types[this_operand].bitfield.baseindex
|| (current_templates->start->opcode_modifier.jump != JUMP
&& current_templates->start->opcode_modifier.jump != JUMP_DWORD))
{
- bigdisp.bitfield.disp32 = 1;
+ i386_addressing_mode ();
override = (i.prefix[ADDR_PREFIX] != 0);
if (flag_code == CODE_64BIT)
{
bigdisp.bitfield.disp32s = 1;
bigdisp.bitfield.disp64 = 1;
}
+ else
+ bigdisp.bitfield.disp32 = 1;
}
else if ((flag_code == CODE_16BIT) ^ override)
- {
- bigdisp.bitfield.disp32 = 0;
bigdisp.bitfield.disp16 = 1;
- }
+ else
+ bigdisp.bitfield.disp32 = 1;
}
else
{
- /* For PC-relative branches, the width of the displacement
- is dependent upon data size, not address size. */
+ /* For PC-relative branches, the width of the displacement may be
+ dependent upon data size, but is never dependent upon address size.
+ Also make sure to not unintentionally match against a non-PC-relative
+ branch template. */
+ static templates aux_templates;
+ const insn_template *t = current_templates->start;
+ bfd_boolean has_intel64 = FALSE;
+
+ aux_templates.start = t;
+ while (++t < current_templates->end)
+ {
+ if (t->opcode_modifier.jump
+ != current_templates->start->opcode_modifier.jump)
+ break;
+ if (t->opcode_modifier.intel64)
+ has_intel64 = TRUE;
+ }
+ if (t < current_templates->end)
+ {
+ aux_templates.end = t;
+ current_templates = &aux_templates;
+ }
+
override = (i.prefix[DATA_PREFIX] != 0);
if (flag_code == CODE_64BIT)
{
- if (override || i.suffix == WORD_MNEM_SUFFIX)
+ if ((override || i.suffix == WORD_MNEM_SUFFIX)
+ && (!intel64 || !has_intel64))
bigdisp.bitfield.disp16 = 1;
else
- {
- bigdisp.bitfield.disp32 = 1;
- bigdisp.bitfield.disp32s = 1;
- }
+ bigdisp.bitfield.disp32s = 1;
}
else
{
}
#endif
+ if (current_templates->start->opcode_modifier.jump == JUMP_BYTE
+ /* Constants get taken care of by optimize_disp(). */
+ && exp->X_op != O_constant)
+ i.types[this_operand].bitfield.disp8 = 1;
+
/* Check if this is a displacement only operand. */
bigdisp = i.types[this_operand];
bigdisp.bitfield.disp8 = 0;
#define OPTION_MALIGN_BRANCH_BOUNDARY (OPTION_MD_BASE + 27)
#define OPTION_MALIGN_BRANCH_PREFIX_SIZE (OPTION_MD_BASE + 28)
#define OPTION_MALIGN_BRANCH (OPTION_MD_BASE + 29)
+#define OPTION_MBRANCHES_WITH_32B_BOUNDARIES (OPTION_MD_BASE + 30)
struct option md_longopts[] =
{
{"malign-branch-boundary", required_argument, NULL, OPTION_MALIGN_BRANCH_BOUNDARY},
{"malign-branch-prefix-size", required_argument, NULL, OPTION_MALIGN_BRANCH_PREFIX_SIZE},
{"malign-branch", required_argument, NULL, OPTION_MALIGN_BRANCH},
+ {"mbranches-within-32B-boundaries", no_argument, NULL, OPTION_MBRANCHES_WITH_32B_BOUNDARIES},
{"mamd64", no_argument, NULL, OPTION_MAMD64},
{"mintel64", no_argument, NULL, OPTION_MINTEL64},
{NULL, no_argument, NULL, 0}
free (saved);
break;
+ case OPTION_MBRANCHES_WITH_32B_BOUNDARIES:
+ align_branch_power = 5;
+ align_branch_prefix_size = 5;
+ align_branch = (align_branch_jcc_bit
+ | align_branch_fused_bit
+ | align_branch_jmp_bit);
+ break;
+
case OPTION_MAMD64:
intel64 = 0;
break;
-malign-branch-prefix-size=NUM (default: 5)\n\
align branches with NUM prefixes per instruction\n"));
fprintf (stream, _("\
+ -mbranches-within-32B-boundaries\n\
+ align branches within 32 byte boundary\n"));
+ fprintf (stream, _("\
-mamd64 accept only AMD64 ISA [default]\n"));
fprintf (stream, _("\
-mintel64 accept only Intel64 ISA\n"));