/* Table of relaxations for Xtensa assembly.
- Copyright 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2003-2015 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
GAS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
+ the Free Software Foundation; either version 3, or (at your option)
any later version.
GAS is distributed in the hope that it will be useful,
addi.n a4, 0x1010
=> addi a4, 0x1010
=> addmi a4, 0x1010
- => addmi a4, 0x1000, addi a4, 0x10. */
+ => addmi a4, 0x1000, addi a4, 0x10.
+
+ See the comments in xg_assembly_relax for some important details
+ regarding how these chains must be built. */
static string_pattern_pair widen_spec_list[] =
{
{"bnez %as,%label ? IsaUseDensityInstruction", "beqz.n %as,%LABEL;j %label;LABEL"},
{"beqz %as,%label", "bnez %as,%LABEL;j %label;LABEL"},
{"bnez %as,%label", "beqz %as,%LABEL;j %label;LABEL"},
+ {"WIDE.beqz %as,%label ? IsaUseDensityInstruction", "bnez.n %as,%LABEL;j %label;LABEL"},
+ {"WIDE.bnez %as,%label ? IsaUseDensityInstruction", "beqz.n %as,%LABEL;j %label;LABEL"},
+ {"WIDE.beqz %as,%label", "bnez %as,%LABEL;j %label;LABEL"},
+ {"WIDE.bnez %as,%label", "beqz %as,%LABEL;j %label;LABEL"},
/* Widening expect-taken branches. */
{"beqzt %as,%label ? IsaUsePredictedBranches", "bnez %as,%LABEL;j %label;LABEL"},
{"bbc %as,%at,%label", "bbs %as,%at,%LABEL;j %label;LABEL"},
{"bbs %as,%at,%label", "bbc %as,%at,%LABEL;j %label;LABEL"},
+ {"WIDE.bgez %as,%label", "bltz %as,%LABEL;j %label;LABEL"},
+ {"WIDE.bltz %as,%label", "bgez %as,%LABEL;j %label;LABEL"},
+ {"WIDE.beqi %as,%imm,%label", "bnei %as,%imm,%LABEL;j %label;LABEL"},
+ {"WIDE.bnei %as,%imm,%label", "beqi %as,%imm,%LABEL;j %label;LABEL"},
+ {"WIDE.bgei %as,%imm,%label", "blti %as,%imm,%LABEL;j %label;LABEL"},
+ {"WIDE.blti %as,%imm,%label", "bgei %as,%imm,%LABEL;j %label;LABEL"},
+ {"WIDE.bgeui %as,%imm,%label", "bltui %as,%imm,%LABEL;j %label;LABEL"},
+ {"WIDE.bltui %as,%imm,%label", "bgeui %as,%imm,%LABEL;j %label;LABEL"},
+ {"WIDE.bbci %as,%imm,%label", "bbsi %as,%imm,%LABEL;j %label;LABEL"},
+ {"WIDE.bbsi %as,%imm,%label", "bbci %as,%imm,%LABEL;j %label;LABEL"},
+ {"WIDE.beq %as,%at,%label", "bne %as,%at,%LABEL;j %label;LABEL"},
+ {"WIDE.bne %as,%at,%label", "beq %as,%at,%LABEL;j %label;LABEL"},
+ {"WIDE.bge %as,%at,%label", "blt %as,%at,%LABEL;j %label;LABEL"},
+ {"WIDE.blt %as,%at,%label", "bge %as,%at,%LABEL;j %label;LABEL"},
+ {"WIDE.bgeu %as,%at,%label", "bltu %as,%at,%LABEL;j %label;LABEL"},
+ {"WIDE.bltu %as,%at,%label", "bgeu %as,%at,%LABEL;j %label;LABEL"},
+ {"WIDE.bany %as,%at,%label", "bnone %as,%at,%LABEL;j %label;LABEL"},
+ {"WIDE.bnone %as,%at,%label", "bany %as,%at,%LABEL;j %label;LABEL"},
+ {"WIDE.ball %as,%at,%label", "bnall %as,%at,%LABEL;j %label;LABEL"},
+ {"WIDE.bnall %as,%at,%label", "ball %as,%at,%LABEL;j %label;LABEL"},
+ {"WIDE.bbc %as,%at,%label", "bbs %as,%at,%LABEL;j %label;LABEL"},
+ {"WIDE.bbs %as,%at,%label", "bbc %as,%at,%LABEL;j %label;LABEL"},
+
/* Expanding calls with literals. */
{"call0 %label,%ar0 ? IsaUseL32R",
"LITERAL %label; l32r a0,%LITERAL; callx0 a0,%ar0"},
{"call8 %label,%ar8 ? IsaUseConst16",
"const16 a8,HI16U(%label); const16 a8,LOW16U(%label); callx8 a8,%ar8"},
{"call12 %label,%ar12 ? IsaUseConst16",
- "const16 a12,HI16U(%label); const16 a12,LOW16U(%label); callx12 a12,%ar12"}
+ "const16 a12,HI16U(%label); const16 a12,LOW16U(%label); callx12 a12,%ar12"},
+
+ /* Expanding j.l with literals. */
+ {"j %label ? FREEREG ? IsaUseL32R",
+ "LITERAL %label; l32r FREEREG,%LITERAL; jx FREEREG"},
+ /* Expanding j.l with const16. */
+ {"j %label ? FREEREG ? IsaUseConst16",
+ "const16 FREEREG,HI16U(%label); const16 FREEREG,LOW16U(%label); jx FREEREG"},
};
#define WIDEN_COUNT (sizeof (widen_spec_list) / sizeof (string_pattern_pair))
TransitionList *tl = (TransitionList *) xmalloc (sizeof (TransitionList));
TransitionList *prev;
TransitionList **t_p;
- assert (tt != NULL);
- assert (opcode < tt->num_opcodes);
+ gas_assert (tt != NULL);
+ gas_assert (opcode < tt->num_opcodes);
prev = tt->table[opcode];
tl->rule = t;
static void
-append_literal_op (BuildInstr *bi, unsigned op1)
+append_literal_op (BuildInstr *bi, unsigned op1, unsigned src_op)
{
BuildOp *b_op = (BuildOp *) xmalloc (sizeof (BuildOp));
b_op->op_num = op1;
b_op->typ = OP_LITERAL;
- b_op->op_data = 0;
+ b_op->op_data = src_op;
b_op->next = NULL;
append_op (bi, b_op);
}
static unsigned
op_get_constant (const opname_map_e *m1)
{
- assert (m1->operand_name == NULL);
+ gas_assert (m1->operand_name == NULL);
return m1->constant_value;
}
else if (!strcmp (option_name, "Loops"))
option_available = (XCHAL_HAVE_LOOPS == 1);
else if (!strcmp (option_name, "WideBranches"))
- option_available = (XCHAL_HAVE_WIDE_BRANCHES == 1);
+ option_available
+ = (XCHAL_HAVE_WIDE_BRANCHES == 1 && produce_flix == FLIX_ALL);
else if (!strcmp (option_name, "PredictedBranches"))
- option_available = (XCHAL_HAVE_PREDICTED_BRANCHES == 1);
+ option_available
+ = (XCHAL_HAVE_PREDICTED_BRANCHES == 1
+ && produce_flix == FLIX_ALL);
else if (!strcmp (option_name, "Booleans"))
option_available = (XCHAL_HAVE_BOOLEANS == 1);
else
TransitionRule *tr = NULL;
xtensa_opcode opcode;
xtensa_isa isa = xtensa_default_isa;
+ BuildInstr *literal_bi;
opname_map_e *op1;
opname_map_e *op2;
precond_e *precond;
insn_repl_e *r;
- opcode = xtensa_opcode_lookup (isa, initial_insn->t.opcode_name);
+ if (!wide_branch_opcode (initial_insn->t.opcode_name, ".w18", &opcode)
+ && !wide_branch_opcode (initial_insn->t.opcode_name, ".w15", &opcode))
+ opcode = xtensa_opcode_lookup (isa, initial_insn->t.opcode_name);
+
if (opcode == XTENSA_UNDEFINED)
{
/* It is OK to not be able to translate some of these opcodes. */
can be used before they are defined. Also there are a number of
special operands (e.g., HI24S). */
+ literal_bi = NULL;
for (r = replace_insns->head; r != NULL; r = r->next)
{
BuildInstr *bi;
bi->typ = INSTR_LITERAL_DEF;
if (operand_count != 1)
as_fatal (_("expected one operand for generated literal"));
+ literal_bi = bi;
}
else if (strcmp (opcode_name, "LABEL") == 0)
{
if (op_is_constant (op))
append_constant_op (bi, op->operand_num, op_get_constant (op));
else if (strcmp (op->operand_name, "%LITERAL") == 0)
- append_literal_op (bi, op->operand_num);
+ {
+ if (! literal_bi || ! literal_bi->ops || literal_bi->ops->next)
+ as_fatal (_("opcode '%s': cannot find literal definition"),
+ opcode_name);
+ append_literal_op (bi, op->operand_num,
+ literal_bi->ops->op_data);
+ }
else if (strcmp (op->operand_name, "%LABEL") == 0)
append_label_op (bi, op->operand_num);
else if (op->operand_name[0] == 'a'
opcode_name, op->operand_name, to_string);
append_field_op (bi, op->operand_num, orig_op->operand_num);
}
+ else if (strcmp (op->operand_name, "FREEREG") == 0)
+ {
+ append_user_fn_field_op (bi, op->operand_num, OP_FREEREG, 0);
+ }
else if (parse_special_fn (op->operand_name,
&fn_name, &operand_arg_name))
{