mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-25 13:27:26 +08:00
include:
* xtensa-config.h (XCHAL_HAVE_WIDE_BRANCHES): New. gas: * config/tc-xtensa.c (op_placement_info_struct): Delete single, single_size, widest, and widest_size fields. Add narrowest_slot. (xg_emit_insn_to_buf): Remove fmt parameter and compute it here. Use xg_get_single_slot to find the slot. (finish_vinsn): Use emit_single_op instead of bundle_single_op. (bundle_single_op): Rename this to.... (bundle_tinsn): ...this function, which builds a vliw_insn but does not call finish_vinsn. (emit_single_op): Use bundle_tinsn instead of bundle_single_op. (relax_frag_immed): Get num_slots from cur_vinsn. (convert_frag_narrow): Update call to xg_emit_insn_to_buf. (convert_frag_immed): Likewise. Also, get num_slots from cur_vinsn. (init_op_placement_info_table): Set narrowest_slot field. Remove code for deleted fields. (xg_get_single_size): Return narrowest_size field, not single_size. (xg_get_single_format): Return narrowest field, not single. (xg_get_single_slot): New. (tinsn_to_insnbuf): Rewrite to use tinsn_to_slotbuf. * config/xtensa-relax.c (widen_spec_list): Add wide branch relaxations. (transition_applies): Check wide branch option availability.
This commit is contained in:
@ -1,3 +1,27 @@
|
|||||||
|
2005-12-30 Sterling Augustine <sterling@tensilica.com>
|
||||||
|
Bob Wilson <bob.wilson@acm.org>
|
||||||
|
|
||||||
|
* config/tc-xtensa.c (op_placement_info_struct): Delete single,
|
||||||
|
single_size, widest, and widest_size fields. Add narrowest_slot.
|
||||||
|
(xg_emit_insn_to_buf): Remove fmt parameter and compute it here.
|
||||||
|
Use xg_get_single_slot to find the slot.
|
||||||
|
(finish_vinsn): Use emit_single_op instead of bundle_single_op.
|
||||||
|
(bundle_single_op): Rename this to....
|
||||||
|
(bundle_tinsn): ...this function, which builds a vliw_insn but does
|
||||||
|
not call finish_vinsn.
|
||||||
|
(emit_single_op): Use bundle_tinsn instead of bundle_single_op.
|
||||||
|
(relax_frag_immed): Get num_slots from cur_vinsn.
|
||||||
|
(convert_frag_narrow): Update call to xg_emit_insn_to_buf.
|
||||||
|
(convert_frag_immed): Likewise. Also, get num_slots from cur_vinsn.
|
||||||
|
(init_op_placement_info_table): Set narrowest_slot field. Remove
|
||||||
|
code for deleted fields.
|
||||||
|
(xg_get_single_size): Return narrowest_size field, not single_size.
|
||||||
|
(xg_get_single_format): Return narrowest field, not single.
|
||||||
|
(xg_get_single_slot): New.
|
||||||
|
(tinsn_to_insnbuf): Rewrite to use tinsn_to_slotbuf.
|
||||||
|
* config/xtensa-relax.c (widen_spec_list): Add wide branch relaxations.
|
||||||
|
(transition_applies): Check wide branch option availability.
|
||||||
|
|
||||||
2005-12-29 Sterling Augustine <sterling@tensilica.com>
|
2005-12-29 Sterling Augustine <sterling@tensilica.com>
|
||||||
|
|
||||||
* config/tc-xtensa.h (MAX_MEM_FOR_RS_ALIGN_CODE): Define.
|
* config/tc-xtensa.h (MAX_MEM_FOR_RS_ALIGN_CODE): Define.
|
||||||
|
@ -327,15 +327,9 @@ typedef struct op_placement_info_struct
|
|||||||
restrictive is the opcode that fits only one slot in one
|
restrictive is the opcode that fits only one slot in one
|
||||||
format. */
|
format. */
|
||||||
int issuef;
|
int issuef;
|
||||||
/* The single format (i.e., if the op can live in a bundle by itself),
|
|
||||||
narrowest format, and widest format the op can be bundled in
|
|
||||||
and their sizes: */
|
|
||||||
xtensa_format single;
|
|
||||||
xtensa_format narrowest;
|
xtensa_format narrowest;
|
||||||
xtensa_format widest;
|
|
||||||
char narrowest_size;
|
char narrowest_size;
|
||||||
char widest_size;
|
char narrowest_slot;
|
||||||
char single_size;
|
|
||||||
|
|
||||||
/* formats is a bitfield with the Nth bit set
|
/* formats is a bitfield with the Nth bit set
|
||||||
if the opcode fits in the Nth xtensa_format. */
|
if the opcode fits in the Nth xtensa_format. */
|
||||||
@ -484,6 +478,7 @@ static void init_op_placement_info_table (void);
|
|||||||
extern bfd_boolean opcode_fits_format_slot (xtensa_opcode, xtensa_format, int);
|
extern bfd_boolean opcode_fits_format_slot (xtensa_opcode, xtensa_format, int);
|
||||||
static int xg_get_single_size (xtensa_opcode);
|
static int xg_get_single_size (xtensa_opcode);
|
||||||
static xtensa_format xg_get_single_format (xtensa_opcode);
|
static xtensa_format xg_get_single_format (xtensa_opcode);
|
||||||
|
static int xg_get_single_slot (xtensa_opcode);
|
||||||
|
|
||||||
/* TInsn and IStack functions. */
|
/* TInsn and IStack functions. */
|
||||||
|
|
||||||
@ -4189,7 +4184,6 @@ xg_add_opcode_fix (TInsn *tinsn,
|
|||||||
|
|
||||||
static bfd_boolean
|
static bfd_boolean
|
||||||
xg_emit_insn_to_buf (TInsn *tinsn,
|
xg_emit_insn_to_buf (TInsn *tinsn,
|
||||||
xtensa_format fmt,
|
|
||||||
char *buf,
|
char *buf,
|
||||||
fragS *fragP,
|
fragS *fragP,
|
||||||
offsetT offset,
|
offsetT offset,
|
||||||
@ -4198,6 +4192,7 @@ xg_emit_insn_to_buf (TInsn *tinsn,
|
|||||||
static xtensa_insnbuf insnbuf = NULL;
|
static xtensa_insnbuf insnbuf = NULL;
|
||||||
bfd_boolean has_symbolic_immed = FALSE;
|
bfd_boolean has_symbolic_immed = FALSE;
|
||||||
bfd_boolean ok = TRUE;
|
bfd_boolean ok = TRUE;
|
||||||
|
|
||||||
if (!insnbuf)
|
if (!insnbuf)
|
||||||
insnbuf = xtensa_insnbuf_alloc (xtensa_default_isa);
|
insnbuf = xtensa_insnbuf_alloc (xtensa_default_isa);
|
||||||
|
|
||||||
@ -4205,10 +4200,12 @@ xg_emit_insn_to_buf (TInsn *tinsn,
|
|||||||
if (has_symbolic_immed && build_fix)
|
if (has_symbolic_immed && build_fix)
|
||||||
{
|
{
|
||||||
/* Add a fixup. */
|
/* Add a fixup. */
|
||||||
|
xtensa_format fmt = xg_get_single_format (tinsn->opcode);
|
||||||
|
int slot = xg_get_single_slot (tinsn->opcode);
|
||||||
int opnum = get_relaxable_immed (tinsn->opcode);
|
int opnum = get_relaxable_immed (tinsn->opcode);
|
||||||
expressionS *exp = &tinsn->tok[opnum];
|
expressionS *exp = &tinsn->tok[opnum];
|
||||||
|
|
||||||
if (!xg_add_opcode_fix (tinsn, opnum, fmt, 0, exp, fragP, offset))
|
if (!xg_add_opcode_fix (tinsn, opnum, fmt, slot, exp, fragP, offset))
|
||||||
ok = FALSE;
|
ok = FALSE;
|
||||||
}
|
}
|
||||||
fragP->tc_frag_data.is_insn = TRUE;
|
fragP->tc_frag_data.is_insn = TRUE;
|
||||||
@ -5937,7 +5934,6 @@ resources_conflict (vliw_insn *vinsn)
|
|||||||
|
|
||||||
static bfd_boolean find_vinsn_conflicts (vliw_insn *);
|
static bfd_boolean find_vinsn_conflicts (vliw_insn *);
|
||||||
static xtensa_format xg_find_narrowest_format (vliw_insn *);
|
static xtensa_format xg_find_narrowest_format (vliw_insn *);
|
||||||
static void bundle_single_op (TInsn *);
|
|
||||||
static void xg_assemble_vliw_tokens (vliw_insn *);
|
static void xg_assemble_vliw_tokens (vliw_insn *);
|
||||||
|
|
||||||
|
|
||||||
@ -6065,7 +6061,7 @@ finish_vinsn (vliw_insn *vinsn)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bundle_single_op (&slotstack.insn[slotstack.ninsn - 1]);
|
emit_single_op (&slotstack.insn[slotstack.ninsn - 1]);
|
||||||
if (vinsn->format == XTENSA_UNDEFINED)
|
if (vinsn->format == XTENSA_UNDEFINED)
|
||||||
vinsn->slots[i].opcode = xtensa_nop_opcode;
|
vinsn->slots[i].opcode = xtensa_nop_opcode;
|
||||||
else
|
else
|
||||||
@ -6529,40 +6525,28 @@ relaxation_requirements (vliw_insn *vinsn)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bundle_single_op (TInsn *orig_insn)
|
bundle_tinsn (TInsn *tinsn, vliw_insn *vinsn)
|
||||||
{
|
{
|
||||||
xtensa_isa isa = xtensa_default_isa;
|
xtensa_isa isa = xtensa_default_isa;
|
||||||
vliw_insn v;
|
int slot, chosen_slot;
|
||||||
int slot;
|
|
||||||
|
|
||||||
xg_init_vinsn (&v);
|
vinsn->format = xg_get_single_format (tinsn->opcode);
|
||||||
v.format = op_placement_table[orig_insn->opcode].narrowest;
|
assert (vinsn->format != XTENSA_UNDEFINED);
|
||||||
assert (v.format != XTENSA_UNDEFINED);
|
vinsn->num_slots = xtensa_format_num_slots (isa, vinsn->format);
|
||||||
v.num_slots = xtensa_format_num_slots (isa, v.format);
|
|
||||||
|
|
||||||
for (slot = 0;
|
chosen_slot = xg_get_single_slot (tinsn->opcode);
|
||||||
!opcode_fits_format_slot (orig_insn->opcode, v.format, slot);
|
for (slot = 0; slot < vinsn->num_slots; slot++)
|
||||||
slot++)
|
|
||||||
{
|
{
|
||||||
v.slots[slot].opcode =
|
if (slot == chosen_slot)
|
||||||
xtensa_format_slot_nop_opcode (isa, v.format, slot);
|
vinsn->slots[slot] = *tinsn;
|
||||||
v.slots[slot].ntok = 0;
|
else
|
||||||
v.slots[slot].insn_type = ITYPE_INSN;
|
|
||||||
}
|
|
||||||
|
|
||||||
v.slots[slot] = *orig_insn;
|
|
||||||
slot++;
|
|
||||||
|
|
||||||
for ( ; slot < v.num_slots; slot++)
|
|
||||||
{
|
{
|
||||||
v.slots[slot].opcode =
|
vinsn->slots[slot].opcode =
|
||||||
xtensa_format_slot_nop_opcode (isa, v.format, slot);
|
xtensa_format_slot_nop_opcode (isa, vinsn->format, slot);
|
||||||
v.slots[slot].ntok = 0;
|
vinsn->slots[slot].ntok = 0;
|
||||||
v.slots[slot].insn_type = ITYPE_INSN;
|
vinsn->slots[slot].insn_type = ITYPE_INSN;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
finish_vinsn (&v);
|
|
||||||
xg_free_vinsn (&v);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -6612,11 +6596,17 @@ emit_single_op (TInsn *orig_insn)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ITYPE_INSN:
|
case ITYPE_INSN:
|
||||||
|
{
|
||||||
|
vliw_insn v;
|
||||||
if (lit_sym)
|
if (lit_sym)
|
||||||
xg_resolve_literals (insn, lit_sym);
|
xg_resolve_literals (insn, lit_sym);
|
||||||
if (label_sym)
|
if (label_sym)
|
||||||
xg_resolve_labels (insn, label_sym);
|
xg_resolve_labels (insn, label_sym);
|
||||||
bundle_single_op (insn);
|
xg_init_vinsn (&v);
|
||||||
|
bundle_tinsn (insn, &v);
|
||||||
|
finish_vinsn (&v);
|
||||||
|
xg_free_vinsn (&v);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert (0);
|
assert (0);
|
||||||
@ -8818,7 +8808,7 @@ relax_frag_immed (segT segP,
|
|||||||
|
|
||||||
xg_clear_vinsn (&cur_vinsn);
|
xg_clear_vinsn (&cur_vinsn);
|
||||||
vinsn_from_chars (&cur_vinsn, fragP->fr_opcode);
|
vinsn_from_chars (&cur_vinsn, fragP->fr_opcode);
|
||||||
if (xtensa_format_num_slots (isa, fmt) > 1)
|
if (cur_vinsn.num_slots > 1)
|
||||||
wide_insn = TRUE;
|
wide_insn = TRUE;
|
||||||
|
|
||||||
tinsn = cur_vinsn.slots[slot];
|
tinsn = cur_vinsn.slots[slot];
|
||||||
@ -9076,7 +9066,6 @@ static void
|
|||||||
convert_frag_narrow (segT segP, fragS *fragP, xtensa_format fmt, int slot)
|
convert_frag_narrow (segT segP, fragS *fragP, xtensa_format fmt, int slot)
|
||||||
{
|
{
|
||||||
TInsn tinsn, single_target;
|
TInsn tinsn, single_target;
|
||||||
xtensa_format single_fmt;
|
|
||||||
int size, old_size, diff;
|
int size, old_size, diff;
|
||||||
offsetT frag_offset;
|
offsetT frag_offset;
|
||||||
|
|
||||||
@ -9119,10 +9108,8 @@ convert_frag_narrow (segT segP, fragS *fragP, xtensa_format fmt, int slot)
|
|||||||
}
|
}
|
||||||
|
|
||||||
size = xg_get_single_size (single_target.opcode);
|
size = xg_get_single_size (single_target.opcode);
|
||||||
single_fmt = xg_get_single_format (single_target.opcode);
|
xg_emit_insn_to_buf (&single_target, fragP->fr_opcode, fragP,
|
||||||
|
frag_offset, TRUE);
|
||||||
xg_emit_insn_to_buf (&single_target, single_fmt, fragP->fr_opcode,
|
|
||||||
fragP, frag_offset, TRUE);
|
|
||||||
|
|
||||||
diff = size - old_size;
|
diff = size - old_size;
|
||||||
assert (diff >= 0);
|
assert (diff >= 0);
|
||||||
@ -9183,7 +9170,7 @@ convert_frag_immed (segT segP,
|
|||||||
xg_clear_vinsn (&cur_vinsn);
|
xg_clear_vinsn (&cur_vinsn);
|
||||||
|
|
||||||
vinsn_from_chars (&cur_vinsn, fr_opcode);
|
vinsn_from_chars (&cur_vinsn, fr_opcode);
|
||||||
if (xtensa_format_num_slots (isa, fmt) > 1)
|
if (cur_vinsn.num_slots > 1)
|
||||||
wide_insn = TRUE;
|
wide_insn = TRUE;
|
||||||
|
|
||||||
orig_tinsn = cur_vinsn.slots[slot];
|
orig_tinsn = cur_vinsn.slots[slot];
|
||||||
@ -9363,22 +9350,16 @@ convert_frag_immed (segT segP,
|
|||||||
size = xtensa_format_length (isa, fmt);
|
size = xtensa_format_length (isa, fmt);
|
||||||
if (!opcode_fits_format_slot (tinsn->opcode, fmt, slot))
|
if (!opcode_fits_format_slot (tinsn->opcode, fmt, slot))
|
||||||
{
|
{
|
||||||
xtensa_format single_fmt =
|
|
||||||
xg_get_single_format (tinsn->opcode);
|
|
||||||
|
|
||||||
xg_emit_insn_to_buf
|
xg_emit_insn_to_buf
|
||||||
(tinsn, single_fmt, immed_instr + size, fragP,
|
(tinsn, immed_instr + size, fragP,
|
||||||
immed_instr - fragP->fr_literal + size, TRUE);
|
immed_instr - fragP->fr_literal + size, TRUE);
|
||||||
size += xg_get_single_size (tinsn->opcode);
|
size += xg_get_single_size (tinsn->opcode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xtensa_format single_format;
|
|
||||||
size = xg_get_single_size (tinsn->opcode);
|
size = xg_get_single_size (tinsn->opcode);
|
||||||
single_format = xg_get_single_format (tinsn->opcode);
|
xg_emit_insn_to_buf (tinsn, immed_instr, fragP,
|
||||||
xg_emit_insn_to_buf (tinsn, single_format, immed_instr,
|
|
||||||
fragP,
|
|
||||||
immed_instr - fragP->fr_literal, TRUE);
|
immed_instr - fragP->fr_literal, TRUE);
|
||||||
}
|
}
|
||||||
immed_instr += size;
|
immed_instr += size;
|
||||||
@ -10848,12 +10829,9 @@ init_op_placement_info_table (void)
|
|||||||
/* FIXME: Make tinsn allocation dynamic. */
|
/* FIXME: Make tinsn allocation dynamic. */
|
||||||
if (xtensa_opcode_num_operands (isa, opcode) >= MAX_INSN_ARGS)
|
if (xtensa_opcode_num_operands (isa, opcode) >= MAX_INSN_ARGS)
|
||||||
as_fatal (_("too many operands in instruction"));
|
as_fatal (_("too many operands in instruction"));
|
||||||
opi->single = XTENSA_UNDEFINED;
|
|
||||||
opi->single_size = 0;
|
|
||||||
opi->widest = XTENSA_UNDEFINED;
|
|
||||||
opi->widest_size = 0;
|
|
||||||
opi->narrowest = XTENSA_UNDEFINED;
|
opi->narrowest = XTENSA_UNDEFINED;
|
||||||
opi->narrowest_size = 0x7F;
|
opi->narrowest_size = 0x7F;
|
||||||
|
opi->narrowest_slot = 0;
|
||||||
opi->formats = 0;
|
opi->formats = 0;
|
||||||
opi->num_formats = 0;
|
opi->num_formats = 0;
|
||||||
opi->issuef = 0;
|
opi->issuef = 0;
|
||||||
@ -10873,20 +10851,7 @@ init_op_placement_info_table (void)
|
|||||||
{
|
{
|
||||||
opi->narrowest = fmt;
|
opi->narrowest = fmt;
|
||||||
opi->narrowest_size = fmt_length;
|
opi->narrowest_size = fmt_length;
|
||||||
}
|
opi->narrowest_slot = slot;
|
||||||
if (fmt_length > opi->widest_size)
|
|
||||||
{
|
|
||||||
opi->widest = fmt;
|
|
||||||
opi->widest_size = fmt_length;
|
|
||||||
}
|
|
||||||
if (xtensa_format_num_slots (isa, fmt) == 1)
|
|
||||||
{
|
|
||||||
if (opi->single_size == 0
|
|
||||||
|| fmt_length < opi->single_size)
|
|
||||||
{
|
|
||||||
opi->single = fmt;
|
|
||||||
opi->single_size = fmt_length;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -10910,15 +10875,21 @@ opcode_fits_format_slot (xtensa_opcode opcode, xtensa_format fmt, int slot)
|
|||||||
static int
|
static int
|
||||||
xg_get_single_size (xtensa_opcode opcode)
|
xg_get_single_size (xtensa_opcode opcode)
|
||||||
{
|
{
|
||||||
assert (op_placement_table[opcode].single != XTENSA_UNDEFINED);
|
return op_placement_table[opcode].narrowest_size;
|
||||||
return op_placement_table[opcode].single_size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static xtensa_format
|
static xtensa_format
|
||||||
xg_get_single_format (xtensa_opcode opcode)
|
xg_get_single_format (xtensa_opcode opcode)
|
||||||
{
|
{
|
||||||
return op_placement_table[opcode].single;
|
return op_placement_table[opcode].narrowest;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
xg_get_single_slot (xtensa_opcode opcode)
|
||||||
|
{
|
||||||
|
return op_placement_table[opcode].narrowest_slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -11121,92 +11092,13 @@ tinsn_has_complex_operands (const TInsn *insn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Convert the constant operands in the tinsn to insnbuf.
|
/* Encode a TInsn opcode and its constant operands into slotbuf.
|
||||||
Return TRUE if there is a symbol in the immediate field.
|
Return TRUE if there is a symbol in the immediate field. This
|
||||||
|
function assumes that:
|
||||||
Before this is called,
|
1) The number of operands are correct.
|
||||||
1) the number of operands are correct
|
2) The insn_type is ITYPE_INSN.
|
||||||
2) the tinsn is a ITYPE_INSN
|
3) The opcode can be encoded in the specified format and slot.
|
||||||
3) ONLY the relaxable_ is built
|
4) Operands are either O_constant or O_symbol, and all constants fit. */
|
||||||
4) All operands are O_constant, O_symbol. All constants fit
|
|
||||||
The return value tells whether there are any remaining O_symbols. */
|
|
||||||
|
|
||||||
static bfd_boolean
|
|
||||||
tinsn_to_insnbuf (TInsn *tinsn, xtensa_insnbuf insnbuf)
|
|
||||||
{
|
|
||||||
static xtensa_insnbuf slotbuf = 0;
|
|
||||||
xtensa_isa isa = xtensa_default_isa;
|
|
||||||
xtensa_opcode opcode = tinsn->opcode;
|
|
||||||
xtensa_format fmt = xg_get_single_format (opcode);
|
|
||||||
bfd_boolean has_fixup = FALSE;
|
|
||||||
int noperands = xtensa_opcode_num_operands (isa, opcode);
|
|
||||||
int i;
|
|
||||||
uint32 opnd_value;
|
|
||||||
char *file_name;
|
|
||||||
unsigned line;
|
|
||||||
|
|
||||||
if (!slotbuf)
|
|
||||||
slotbuf = xtensa_insnbuf_alloc (isa);
|
|
||||||
|
|
||||||
assert (tinsn->insn_type == ITYPE_INSN);
|
|
||||||
if (noperands != tinsn->ntok)
|
|
||||||
as_fatal (_("operand number mismatch"));
|
|
||||||
|
|
||||||
if (xtensa_opcode_encode (isa, fmt, 0, slotbuf, opcode))
|
|
||||||
as_fatal (_("cannot encode opcode"));
|
|
||||||
|
|
||||||
for (i = 0; i < noperands; ++i)
|
|
||||||
{
|
|
||||||
expressionS *expr = &tinsn->tok[i];
|
|
||||||
switch (expr->X_op)
|
|
||||||
{
|
|
||||||
case O_register:
|
|
||||||
if (xtensa_operand_is_visible (isa, opcode, i) == 0)
|
|
||||||
break;
|
|
||||||
/* The register number has already been checked in
|
|
||||||
expression_maybe_register, so we don't need to check here. */
|
|
||||||
opnd_value = expr->X_add_number;
|
|
||||||
(void) xtensa_operand_encode (isa, opcode, i, &opnd_value);
|
|
||||||
xtensa_operand_set_field (isa, opcode, i, fmt, 0,
|
|
||||||
slotbuf, opnd_value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case O_constant:
|
|
||||||
if (xtensa_operand_is_visible (isa, opcode, i) == 0)
|
|
||||||
break;
|
|
||||||
as_where (&file_name, &line);
|
|
||||||
/* It is a constant and we called this function,
|
|
||||||
then we have to try to fit it. */
|
|
||||||
xtensa_insnbuf_set_operand (slotbuf, fmt, 0, opcode, i,
|
|
||||||
expr->X_add_number, file_name, line);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
has_fixup = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
xtensa_format_encode (isa, fmt, insnbuf);
|
|
||||||
xtensa_format_set_slot (isa, fmt, 0, insnbuf, slotbuf);
|
|
||||||
|
|
||||||
return has_fixup;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Convert the constant operands in the tinsn to slotbuf.
|
|
||||||
Return TRUE if there is a symbol in the immediate field.
|
|
||||||
(Eventually this should replace tinsn_to_insnbuf.) */
|
|
||||||
|
|
||||||
/* Before this is called,
|
|
||||||
1) the number of operands are correct
|
|
||||||
2) the tinsn is a ITYPE_INSN
|
|
||||||
3) ONLY the relaxable_ is built
|
|
||||||
4) All operands are
|
|
||||||
O_constant, O_symbol
|
|
||||||
All constants fit
|
|
||||||
|
|
||||||
The return value tells whether there are any remaining O_symbols. */
|
|
||||||
|
|
||||||
static bfd_boolean
|
static bfd_boolean
|
||||||
tinsn_to_slotbuf (xtensa_format fmt,
|
tinsn_to_slotbuf (xtensa_format fmt,
|
||||||
@ -11274,6 +11166,44 @@ tinsn_to_slotbuf (xtensa_format fmt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Encode a single TInsn into an insnbuf. If the opcode can only be encoded
|
||||||
|
into a multi-slot instruction, fill the other slots with NOPs.
|
||||||
|
Return TRUE if there is a symbol in the immediate field. See also the
|
||||||
|
assumptions listed for tinsn_to_slotbuf. */
|
||||||
|
|
||||||
|
static bfd_boolean
|
||||||
|
tinsn_to_insnbuf (TInsn *tinsn, xtensa_insnbuf insnbuf)
|
||||||
|
{
|
||||||
|
static xtensa_insnbuf slotbuf = 0;
|
||||||
|
static vliw_insn vinsn;
|
||||||
|
xtensa_isa isa = xtensa_default_isa;
|
||||||
|
bfd_boolean has_fixup = FALSE;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!slotbuf)
|
||||||
|
{
|
||||||
|
slotbuf = xtensa_insnbuf_alloc (isa);
|
||||||
|
xg_init_vinsn (&vinsn);
|
||||||
|
}
|
||||||
|
|
||||||
|
xg_clear_vinsn (&vinsn);
|
||||||
|
|
||||||
|
bundle_tinsn (tinsn, &vinsn);
|
||||||
|
|
||||||
|
xtensa_format_encode (isa, vinsn.format, insnbuf);
|
||||||
|
|
||||||
|
for (i = 0; i < vinsn.num_slots; i++)
|
||||||
|
{
|
||||||
|
/* Only one slot may have a fix-up because the rest contains NOPs. */
|
||||||
|
has_fixup |=
|
||||||
|
tinsn_to_slotbuf (vinsn.format, i, &vinsn.slots[i], vinsn.slotbuf[i]);
|
||||||
|
xtensa_format_set_slot (isa, vinsn.format, i, insnbuf, vinsn.slotbuf[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return has_fixup;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Check the instruction arguments. Return TRUE on failure. */
|
/* Check the instruction arguments. Return TRUE on failure. */
|
||||||
|
|
||||||
static bfd_boolean
|
static bfd_boolean
|
||||||
|
@ -339,13 +339,55 @@ static string_pattern_pair widen_spec_list[] =
|
|||||||
"addi %as, %as, 1;" /* density -> addi.n %as, %as, 1 */
|
"addi %as, %as, 1;" /* density -> addi.n %as, %as, 1 */
|
||||||
"LABEL0"},
|
"LABEL0"},
|
||||||
|
|
||||||
|
/* Relaxing to wide branches. Order is important here. With wide
|
||||||
|
branches, there is more than one correct relaxation for an
|
||||||
|
out-of-range branch. Put the wide branch relaxations first in the
|
||||||
|
table since they are more efficient than the branch-around
|
||||||
|
relaxations. */
|
||||||
|
|
||||||
|
{"beqz %as,%label ? IsaUseWideBranches", "beqz.w18 %as,%label"},
|
||||||
|
{"bnez %as,%label ? IsaUseWideBranches", "bnez.w18 %as,%label"},
|
||||||
|
{"bgez %as,%label ? IsaUseWideBranches", "bgez.w18 %as,%label"},
|
||||||
|
{"bltz %as,%label ? IsaUseWideBranches", "bltz.w18 %as,%label"},
|
||||||
|
{"beqi %as,%imm,%label ? IsaUseWideBranches", "beqi.w18 %as,%imm,%label"},
|
||||||
|
{"bnei %as,%imm,%label ? IsaUseWideBranches", "bnei.w18 %as,%imm,%label"},
|
||||||
|
{"bgei %as,%imm,%label ? IsaUseWideBranches", "bgei.w18 %as,%imm,%label"},
|
||||||
|
{"blti %as,%imm,%label ? IsaUseWideBranches", "blti.w18 %as,%imm,%label"},
|
||||||
|
{"bgeui %as,%imm,%label ? IsaUseWideBranches", "bgeui.w18 %as,%imm,%label"},
|
||||||
|
{"bltui %as,%imm,%label ? IsaUseWideBranches", "bltui.w18 %as,%imm,%label"},
|
||||||
|
{"bbci %as,%imm,%label ? IsaUseWideBranches", "bbci.w18 %as,%imm,%label"},
|
||||||
|
{"bbsi %as,%imm,%label ? IsaUseWideBranches", "bbsi.w18 %as,%imm,%label"},
|
||||||
|
{"beq %as,%at,%label ? IsaUseWideBranches", "beq.w18 %as,%at,%label"},
|
||||||
|
{"bne %as,%at,%label ? IsaUseWideBranches", "bne.w18 %as,%at,%label"},
|
||||||
|
{"bge %as,%at,%label ? IsaUseWideBranches", "bge.w18 %as,%at,%label"},
|
||||||
|
{"blt %as,%at,%label ? IsaUseWideBranches", "blt.w18 %as,%at,%label"},
|
||||||
|
{"bgeu %as,%at,%label ? IsaUseWideBranches", "bgeu.w18 %as,%at,%label"},
|
||||||
|
{"bltu %as,%at,%label ? IsaUseWideBranches", "bltu.w18 %as,%at,%label"},
|
||||||
|
{"bany %as,%at,%label ? IsaUseWideBranches", "bany.w18 %as,%at,%label"},
|
||||||
|
{"bnone %as,%at,%label ? IsaUseWideBranches", "bnone.w18 %as,%at,%label"},
|
||||||
|
{"ball %as,%at,%label ? IsaUseWideBranches", "ball.w18 %as,%at,%label"},
|
||||||
|
{"bnall %as,%at,%label ? IsaUseWideBranches", "bnall.w18 %as,%at,%label"},
|
||||||
|
{"bbc %as,%at,%label ? IsaUseWideBranches", "bbc.w18 %as,%at,%label"},
|
||||||
|
{"bbs %as,%at,%label ? IsaUseWideBranches", "bbs.w18 %as,%at,%label"},
|
||||||
|
|
||||||
|
/* Widening branch comparisons eq/ne to zero. Prefer relaxing to narrow
|
||||||
|
branches if the density option is available. */
|
||||||
{"beqz %as,%label ? IsaUseDensityInstruction", "bnez.n %as,%LABEL0;j %label;LABEL0"},
|
{"beqz %as,%label ? IsaUseDensityInstruction", "bnez.n %as,%LABEL0;j %label;LABEL0"},
|
||||||
{"bnez %as,%label ? IsaUseDensityInstruction", "beqz.n %as,%LABEL0;j %label;LABEL0"},
|
{"bnez %as,%label ? IsaUseDensityInstruction", "beqz.n %as,%LABEL0;j %label;LABEL0"},
|
||||||
{"beqz %as,%label", "bnez %as,%LABEL0;j %label;LABEL0"},
|
{"beqz %as,%label", "bnez %as,%LABEL0;j %label;LABEL0"},
|
||||||
{"bnez %as,%label", "beqz %as,%LABEL0;j %label;LABEL0"},
|
{"bnez %as,%label", "beqz %as,%LABEL0;j %label;LABEL0"},
|
||||||
|
|
||||||
|
/* Widening expect-taken branches. */
|
||||||
{"beqzt %as,%label ? IsaUsePredictedBranches", "bnez %as,%LABEL0;j %label;LABEL0"},
|
{"beqzt %as,%label ? IsaUsePredictedBranches", "bnez %as,%LABEL0;j %label;LABEL0"},
|
||||||
{"bnezt %as,%label ? IsaUsePredictedBranches", "beqz %as,%LABEL0;j %label;LABEL0"},
|
{"bnezt %as,%label ? IsaUsePredictedBranches", "beqz %as,%LABEL0;j %label;LABEL0"},
|
||||||
|
{"beqt %as,%at,%label ? IsaUsePredictedBranches", "bne %as,%at,%LABEL0;j %label;LABEL0"},
|
||||||
|
{"bnet %as,%at,%label ? IsaUsePredictedBranches", "beq %as,%at,%LABEL0;j %label;LABEL0"},
|
||||||
|
|
||||||
|
/* Widening branches from the Xtensa boolean option. */
|
||||||
|
{"bt %bs,%label ? IsaUseBooleans", "bf %bs,%LABEL0;j %label;LABEL0"},
|
||||||
|
{"bf %bs,%label ? IsaUseBooleans", "bt %bs,%LABEL0;j %label;LABEL0"},
|
||||||
|
|
||||||
|
/* Other branch-around-jump widenings. */
|
||||||
{"bgez %as,%label", "bltz %as,%LABEL0;j %label;LABEL0"},
|
{"bgez %as,%label", "bltz %as,%LABEL0;j %label;LABEL0"},
|
||||||
{"bltz %as,%label", "bgez %as,%LABEL0;j %label;LABEL0"},
|
{"bltz %as,%label", "bgez %as,%LABEL0;j %label;LABEL0"},
|
||||||
{"beqi %as,%imm,%label", "bnei %as,%imm,%LABEL0;j %label;LABEL0"},
|
{"beqi %as,%imm,%label", "bnei %as,%imm,%LABEL0;j %label;LABEL0"},
|
||||||
@ -358,17 +400,11 @@ static string_pattern_pair widen_spec_list[] =
|
|||||||
{"bbsi %as,%imm,%label", "bbci %as,%imm,%LABEL0;j %label;LABEL0"},
|
{"bbsi %as,%imm,%label", "bbci %as,%imm,%LABEL0;j %label;LABEL0"},
|
||||||
{"beq %as,%at,%label", "bne %as,%at,%LABEL0;j %label;LABEL0"},
|
{"beq %as,%at,%label", "bne %as,%at,%LABEL0;j %label;LABEL0"},
|
||||||
{"bne %as,%at,%label", "beq %as,%at,%LABEL0;j %label;LABEL0"},
|
{"bne %as,%at,%label", "beq %as,%at,%LABEL0;j %label;LABEL0"},
|
||||||
{"beqt %as,%at,%label ? IsaUsePredictedBranches", "bne %as,%at,%LABEL0;j %label;LABEL0"},
|
|
||||||
{"bnet %as,%at,%label ? IsaUsePredictedBranches", "beq %as,%at,%LABEL0;j %label;LABEL0"},
|
|
||||||
{"bge %as,%at,%label", "blt %as,%at,%LABEL0;j %label;LABEL0"},
|
{"bge %as,%at,%label", "blt %as,%at,%LABEL0;j %label;LABEL0"},
|
||||||
{"blt %as,%at,%label", "bge %as,%at,%LABEL0;j %label;LABEL0"},
|
{"blt %as,%at,%label", "bge %as,%at,%LABEL0;j %label;LABEL0"},
|
||||||
{"bgeu %as,%at,%label", "bltu %as,%at,%LABEL0;j %label;LABEL0"},
|
{"bgeu %as,%at,%label", "bltu %as,%at,%LABEL0;j %label;LABEL0"},
|
||||||
{"bltu %as,%at,%label", "bgeu %as,%at,%LABEL0;j %label;LABEL0"},
|
{"bltu %as,%at,%label", "bgeu %as,%at,%LABEL0;j %label;LABEL0"},
|
||||||
{"bany %as,%at,%label", "bnone %as,%at,%LABEL0;j %label;LABEL0"},
|
{"bany %as,%at,%label", "bnone %as,%at,%LABEL0;j %label;LABEL0"},
|
||||||
|
|
||||||
{"bt %bs,%label ? IsaUseBooleans", "bf %bs,%LABEL0;j %label;LABEL0"},
|
|
||||||
{"bf %bs,%label ? IsaUseBooleans", "bt %bs,%LABEL0;j %label;LABEL0"},
|
|
||||||
|
|
||||||
{"bnone %as,%at,%label", "bany %as,%at,%LABEL0;j %label;LABEL0"},
|
{"bnone %as,%at,%label", "bany %as,%at,%LABEL0;j %label;LABEL0"},
|
||||||
{"ball %as,%at,%label", "bnall %as,%at,%LABEL0;j %label;LABEL0"},
|
{"ball %as,%at,%label", "bnall %as,%at,%LABEL0;j %label;LABEL0"},
|
||||||
{"bnall %as,%at,%label", "ball %as,%at,%LABEL0;j %label;LABEL0"},
|
{"bnall %as,%at,%label", "ball %as,%at,%LABEL0;j %label;LABEL0"},
|
||||||
@ -1489,6 +1525,8 @@ transition_applies (insn_pattern *initial_insn,
|
|||||||
option_available = (XCHAL_HAVE_CONST16 == 1);
|
option_available = (XCHAL_HAVE_CONST16 == 1);
|
||||||
else if (!strcmp (option_name, "Loops"))
|
else if (!strcmp (option_name, "Loops"))
|
||||||
option_available = (XCHAL_HAVE_LOOPS == 1);
|
option_available = (XCHAL_HAVE_LOOPS == 1);
|
||||||
|
else if (!strcmp (option_name, "WideBranches"))
|
||||||
|
option_available = (XCHAL_HAVE_WIDE_BRANCHES == 1);
|
||||||
else if (!strcmp (option_name, "PredictedBranches"))
|
else if (!strcmp (option_name, "PredictedBranches"))
|
||||||
option_available = (XCHAL_HAVE_PREDICTED_BRANCHES == 1);
|
option_available = (XCHAL_HAVE_PREDICTED_BRANCHES == 1);
|
||||||
else if (!strcmp (option_name, "Booleans"))
|
else if (!strcmp (option_name, "Booleans"))
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
2005-12-30 Bob Wilson <bob.wilson@acm.org>
|
||||||
|
|
||||||
|
* xtensa-config.h (XCHAL_HAVE_WIDE_BRANCHES): New.
|
||||||
|
|
||||||
2005-12-16 Nathan Sidwell <nathan@codesourcery.com>
|
2005-12-16 Nathan Sidwell <nathan@codesourcery.com>
|
||||||
|
|
||||||
Second part of ms1 to mt renaming.
|
Second part of ms1 to mt renaming.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Xtensa configuration settings.
|
/* Xtensa configuration settings.
|
||||||
Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
|
Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||||
Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica.
|
Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
@ -90,6 +90,9 @@
|
|||||||
#undef XCHAL_HAVE_WINDOWED
|
#undef XCHAL_HAVE_WINDOWED
|
||||||
#define XCHAL_HAVE_WINDOWED 1
|
#define XCHAL_HAVE_WINDOWED 1
|
||||||
|
|
||||||
|
#undef XCHAL_HAVE_WIDE_BRANCHES
|
||||||
|
#define XCHAL_HAVE_WIDE_BRANCHES 0
|
||||||
|
|
||||||
#undef XCHAL_HAVE_PREDICTED_BRANCHES
|
#undef XCHAL_HAVE_PREDICTED_BRANCHES
|
||||||
#define XCHAL_HAVE_PREDICTED_BRANCHES 0
|
#define XCHAL_HAVE_PREDICTED_BRANCHES 0
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user