/* tc-xtensa.c -- Assemble Xtensa instructions.
- Copyright 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+ Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
bfd_boolean density_supported = XCHAL_HAVE_DENSITY;
bfd_boolean absolute_literals_supported = XSHAL_USE_ABSOLUTE_LITERALS;
-/* Maximum width we would pad an unreachable frag to get alignment. */
-#define UNREACHABLE_MAX_WIDTH 8
-
static vliw_insn cur_vinsn;
unsigned xtensa_num_pipe_stages;
/* vliw_insn functions. */
static void xg_init_vinsn (vliw_insn *);
+static void xg_copy_vinsn (vliw_insn *, vliw_insn *);
static void xg_clear_vinsn (vliw_insn *);
static bfd_boolean vinsn_has_specific_opcodes (vliw_insn *);
static void xg_free_vinsn (vliw_insn *);
static xtensa_opcode xtensa_retw_n_opcode;
static xtensa_opcode xtensa_rsr_lcount_opcode;
static xtensa_opcode xtensa_waiti_opcode;
+static int config_max_slots = 0;
\f
/* Command-line Options. */
{
bfd_reloc_code_real_type reloc;
segT t = expression (tok);
+
if (t == absolute_section
&& xtensa_operand_is_PCrelative (isa, opc, opnd) == 1)
{
gas_assert (insn->insn_type == ITYPE_INSN);
for (i = 0; i < n; ++i)
{
- const expressionS *expr = &insn->tok[i];
+ const expressionS *exp = &insn->tok[i];
+
if (xtensa_operand_is_register (isa, insn->opcode, i) == 1)
continue;
- switch (expr->X_op)
+ switch (exp->X_op)
{
case O_register:
case O_constant:
- if (xg_check_operand (expr->X_add_number, insn->opcode, i))
+ if (xg_check_operand (exp->X_add_number, insn->opcode, i))
return FALSE;
break;
for (i = 0; i < n; ++i)
{
- const expressionS *expr = &insn->tok[i];
+ const expressionS *exp = &insn->tok[i];
+
if (xtensa_operand_is_register (isa, insn->opcode, i) == 1)
continue;
- switch (expr->X_op)
+ switch (exp->X_op)
{
case O_register:
case O_constant:
- if (xg_check_operand (expr->X_add_number, insn->opcode, i))
+ if (xg_check_operand (exp->X_add_number, insn->opcode, i))
return FALSE;
break;
/* If it is a weak symbol or a symbol in a different section,
it cannot be known to fit at assembly time. */
- if (S_IS_WEAK (expr->X_add_symbol)
- || S_GET_SEGMENT (expr->X_add_symbol) != pc_seg)
+ if (S_IS_WEAK (exp->X_add_symbol)
+ || S_GET_SEGMENT (exp->X_add_symbol) != pc_seg)
{
/* For a direct call with --no-longcalls, be optimistic and
assume it will be in range. If the symbol is weak and
symbols even if longcalls is not enabled. */
if (is_direct_call_opcode (insn->opcode)
&& ! pc_frag->tc_frag_data.use_longcalls
- && (! S_IS_WEAK (expr->X_add_symbol)
- || S_IS_DEFINED (expr->X_add_symbol)))
+ && (! S_IS_WEAK (exp->X_add_symbol)
+ || S_IS_DEFINED (exp->X_add_symbol)))
return TRUE;
return FALSE;
}
- symbolP = expr->X_add_symbol;
+ symbolP = exp->X_add_symbol;
sym_frag = symbol_get_frag (symbolP);
- target = S_GET_VALUE (symbolP) + expr->X_add_number;
+ target = S_GET_VALUE (symbolP) + exp->X_add_number;
pc = pc_frag->fr_address + pc_offset;
/* If frag has yet to be reached on this pass, assume it
/* Check to see if it fits. */
for (i = stack_size; i < istack->ninsn; i++)
{
- TInsn *insn = &istack->insn[i];
+ TInsn *tinsn = &istack->insn[i];
- if (insn->insn_type == ITYPE_INSN
- && !tinsn_has_symbolic_operands (insn)
- && !xg_immeds_fit (insn))
+ if (tinsn->insn_type == ITYPE_INSN
+ && !tinsn_has_symbolic_operands (tinsn)
+ && !xg_immeds_fit (tinsn))
{
istack->ninsn = stack_size;
return FALSE;
int opnum,
xtensa_format fmt,
int slot,
- expressionS *expr,
+ expressionS *exp,
fragS *fragP,
offsetT offset)
{
}
else if (opcode == xtensa_const16_opcode)
{
- if (expr->X_op == O_lo16)
+ if (exp->X_op == O_lo16)
{
reloc = encode_reloc (slot);
- expr->X_op = O_symbol;
+ exp->X_op = O_symbol;
}
- else if (expr->X_op == O_hi16)
+ else if (exp->X_op == O_hi16)
{
reloc = encode_alt_reloc (slot);
- expr->X_op = O_symbol;
+ exp->X_op = O_symbol;
}
}
/* Handle erroneous "@h" and "@l" expressions here before they propagate
into the symbol table where the generic portions of the assembler
won't know what to do with them. */
- if (expr->X_op == O_lo16 || expr->X_op == O_hi16)
+ if (exp->X_op == O_lo16 || exp->X_op == O_hi16)
{
as_bad (_("invalid expression for operand %i of '%s'"),
opnum + 1, xtensa_opcode_name (xtensa_default_isa, opcode));
}
fmt_length = xtensa_format_length (xtensa_default_isa, fmt);
- the_fix = fix_new_exp (fragP, offset, fmt_length, expr,
+ the_fix = fix_new_exp (fragP, offset, fmt_length, exp,
howto->pc_relative, reloc);
the_fix->fx_no_overflow = 1;
- the_fix->tc_fix_data.X_add_symbol = expr->X_add_symbol;
- the_fix->tc_fix_data.X_add_number = expr->X_add_number;
+ the_fix->tc_fix_data.X_add_symbol = exp->X_add_symbol;
+ the_fix->tc_fix_data.X_add_number = exp->X_add_number;
the_fix->tc_fix_data.slot = slot;
return TRUE;
be accompanied by major changes to make use of that data.
In any event, we can tell that we are expanding from a single-slot
- three-byte format to a wider one with the logic below. */
+ format to a wider one with the logic below. */
- if (fmt_size <= 3 && fragP->tc_frag_data.text_expansion[0] != 3)
- return 3 + fragP->tc_frag_data.text_expansion[0];
- else
- return 3;
+ int i;
+ int relaxed_size = fmt_size + fragP->tc_frag_data.text_expansion[0];
+
+ for (i = 0; i < xtensa_isa_num_formats (isa); i++)
+ {
+ if (relaxed_size == xtensa_format_length (isa, i))
+ return relaxed_size;
+ }
+
+ return 3;
}
if (fragP->tc_frag_data.slot_subtypes[0] == RELAX_NARROW)
segT current_section = now_seg;
int current_subsec = now_subseg;
xtensa_isa isa;
+ int i;
xtensa_default_isa = xtensa_isa_init (0, 0);
isa = xtensa_default_isa;
subseg_set (current_section, current_subsec);
- xg_init_vinsn (&cur_vinsn);
-
xtensa_addi_opcode = xtensa_opcode_lookup (isa, "addi");
xtensa_addmi_opcode = xtensa_opcode_lookup (isa, "addmi");
xtensa_call0_opcode = xtensa_opcode_lookup (isa, "call0");
xtensa_rsr_lcount_opcode = xtensa_opcode_lookup (isa, "rsr.lcount");
xtensa_waiti_opcode = xtensa_opcode_lookup (isa, "waiti");
+ for (i = 0; i < xtensa_isa_num_formats (isa); i++)
+ {
+ int format_slots = xtensa_format_num_slots (isa, i);
+ if (format_slots > config_max_slots)
+ config_max_slots = format_slots;
+ }
+
+ xg_init_vinsn (&cur_vinsn);
+
xtensa_num_pipe_stages = xtensa_isa_num_pipe_stages (isa);
init_op_placement_info_table ();
bfd_boolean
xtensa_fix_adjustable (fixS *fixP)
{
- /* An offset is not allowed in combination with the difference of two
- symbols, but that cannot be easily detected after a local symbol
- has been adjusted to a (section+offset) form. Return 0 so that such
- an fix will not be adjusted. */
- if (fixP->fx_subsy && fixP->fx_addsy && fixP->fx_offset
- && relaxable_section (S_GET_SEGMENT (fixP->fx_subsy)))
- return 0;
-
/* We need the symbol name for the VTABLE entries. */
if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
|| fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
break;
}
- /* An offset is only allowed when it results from adjusting a
- local symbol into a section-relative offset. If the offset
- came from the original expression, tc_fix_adjustable will have
- prevented the fix from being converted to a section-relative
- form so that we can flag the error here. */
- if (fixP->fx_offset != 0 && !symbol_section_p (fixP->fx_addsy))
- as_bad_where (fixP->fx_file, fixP->fx_line,
- _("cannot represent subtraction with an offset"));
-
val = (S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset
- S_GET_VALUE (fixP->fx_subsy));
xtensa_isa isa = xtensa_default_isa;
xtensa_format format;
- vliw_insn v_copy = *vinsn;
xtensa_opcode nop_opcode = xtensa_nop_opcode;
if (vinsn->num_slots == 1)
for (format = 0; format < xtensa_isa_num_formats (isa); format++)
{
- v_copy = *vinsn;
+ vliw_insn v_copy;
+ xg_copy_vinsn (&v_copy, vinsn);
if (xtensa_format_num_slots (isa, format) == v_copy.num_slots)
{
int slot;
}
if (fit == v_copy.num_slots)
{
- *vinsn = v_copy;
+ xg_copy_vinsn (vinsn, &v_copy);
xtensa_format_encode (isa, format, vinsn->insnbuf);
vinsn->format = format;
break;
int slot;
int total_expansion = 0;
- for (slot = 0; slot < MAX_SLOTS; slot++)
+ for (slot = 0; slot < config_max_slots; slot++)
total_expansion += fragP->tc_frag_data.text_expansion[slot];
return total_expansion;
{
gas_assert (finish_frag);
frag_var (rs_machine_dependent,
- UNREACHABLE_MAX_WIDTH, UNREACHABLE_MAX_WIDTH,
+ xtensa_fetch_width, xtensa_fetch_width,
RELAX_UNREACHABLE,
frag_now->fr_symbol, frag_now->fr_offset, NULL);
xtensa_set_frag_assembly_state (frag_now);
{
gas_assert (finish_frag);
frag_var (rs_machine_dependent,
- UNREACHABLE_MAX_WIDTH, UNREACHABLE_MAX_WIDTH,
+ xtensa_fetch_width, xtensa_fetch_width,
RELAX_MAYBE_UNREACHABLE,
frag_now->fr_symbol, frag_now->fr_offset, NULL);
xtensa_set_frag_assembly_state (frag_now);
static bfd_boolean
is_narrow_branch_guaranteed_in_range (fragS *fragP, TInsn *tinsn)
{
- const expressionS *expr = &tinsn->tok[1];
- symbolS *symbolP = expr->X_add_symbol;
- offsetT max_distance = expr->X_add_number;
+ const expressionS *exp = &tinsn->tok[1];
+ symbolS *symbolP = exp->X_add_symbol;
+ offsetT max_distance = exp->X_add_number;
fragS *target_frag;
- if (expr->X_op != O_symbol)
+ if (exp->X_op != O_symbol)
return FALSE;
target_frag = symbol_get_frag (symbolP);
for (expr_sym = expr_symbols; expr_sym;
expr_sym = symbol_get_tc (expr_sym)->next_expr_symbol)
{
- expressionS *expr = symbol_get_value_expression (expr_sym);
+ expressionS *exp = symbol_get_value_expression (expr_sym);
- if (expr->X_op == O_subtract)
+ if (exp->X_op == O_subtract)
{
- symbolS *left = expr->X_add_symbol;
- symbolS *right = expr->X_op_symbol;
+ symbolS *left = exp->X_add_symbol;
+ symbolS *right = exp->X_op_symbol;
/* Difference of two symbols not in the same section
are handled with relocations in the linker. */
{
fragS *start;
fragS *end;
+ fragS *walk;
if (symbol_get_frag (left)->fr_address
<= symbol_get_frag (right)->fr_address)
start = symbol_get_frag (right);
end = symbol_get_frag (left);
}
+
+ if (start->tc_frag_data.no_transform_end != NULL)
+ walk = start->tc_frag_data.no_transform_end;
+ else
+ walk = start;
do
{
- start->tc_frag_data.is_no_transform = 1;
- start = start->fr_next;
+ walk->tc_frag_data.is_no_transform = 1;
+ walk = walk->fr_next;
}
- while (start && start->fr_address < end->fr_address);
+ while (walk && walk->fr_address < end->fr_address);
+
+ start->tc_frag_data.no_transform_end = walk;
}
}
}
static bfd_boolean
is_empty_loop (const TInsn *insn, fragS *fragP)
{
- const expressionS *expr;
+ const expressionS *exp;
symbolS *symbolP;
fragS *next_fragP;
if (insn->ntok <= LOOP_IMMED_OPN)
return FALSE;
- expr = &insn->tok[LOOP_IMMED_OPN];
+ exp = &insn->tok[LOOP_IMMED_OPN];
- if (expr->X_op != O_symbol)
+ if (exp->X_op != O_symbol)
return FALSE;
- symbolP = expr->X_add_symbol;
+ symbolP = exp->X_add_symbol;
if (!symbolP)
return FALSE;
static bfd_boolean
is_local_forward_loop (const TInsn *insn, fragS *fragP)
{
- const expressionS *expr;
+ const expressionS *exp;
symbolS *symbolP;
fragS *next_fragP;
if (insn->ntok <= LOOP_IMMED_OPN)
return FALSE;
- expr = &insn->tok[LOOP_IMMED_OPN];
+ exp = &insn->tok[LOOP_IMMED_OPN];
- if (expr->X_op != O_symbol)
+ if (exp->X_op != O_symbol)
return FALSE;
- symbolP = expr->X_add_symbol;
+ symbolP = exp->X_add_symbol;
if (!symbolP)
return FALSE;
{
if (target_size <= 4)
return 2;
- gas_assert (target_size == 8);
- return 3;
+
+ if (target_size <= 8)
+ return 3;
+
+ if (target_size <= 16)
+ return 4;
+
+ if (target_size <= 32)
+ return 5;
+
+ if (target_size <= 64)
+ return 6;
+
+ if (target_size <= 128)
+ return 7;
+
+ if (target_size <= 256)
+ return 8;
+
+ if (target_size <= 512)
+ return 9;
+
+ if (target_size <= 1024)
+ return 10;
+
+ gas_assert (0);
+ return 0;
}
static int
branch_align_power (segT sec)
{
- /* If the Xtensa processor has a fetch width of 8 bytes, and the section
- is aligned to at least an 8-byte boundary, then a branch target need
- only fit within an 8-byte aligned block of memory to avoid a stall.
- Otherwise, try to fit branch targets within 4-byte aligned blocks
- (which may be insufficient, e.g., if the section has no alignment, but
- it's good enough). */
- if (xtensa_fetch_width == 8)
- {
- if (get_recorded_alignment (sec) >= 3)
- return 3;
- }
- else
- gas_assert (xtensa_fetch_width == 4);
+ /* If the Xtensa processor has a fetch width of X, and
+ the section is aligned to at least that boundary, then a branch
+ target need only fit within that aligned block of memory to avoid
+ a stall. Otherwise, try to fit branch targets within 4-byte
+ aligned blocks (which may be insufficient, e.g., if the section
+ has no alignment, but it's good enough). */
+ int fetch_align = get_text_align_power(xtensa_fetch_width);
+ int sec_align = get_recorded_alignment (sec);
+
+ if (sec_align >= fetch_align)
+ return fetch_align;
return 2;
}
{
if (this_frag->fr_subtype == RELAX_UNREACHABLE)
{
- gas_assert (opt_diff <= UNREACHABLE_MAX_WIDTH);
+ gas_assert (opt_diff <= (signed) xtensa_fetch_width);
return opt_diff;
}
return 0;
/* The idea: widen everything you can to get a target or loop aligned,
then start using NOPs.
- When we must have a NOP, here is a table of how we decide
- (so you don't have to fight through the control flow below):
-
wide_nops = the number of wide NOPs available for aligning
narrow_nops = the number of narrow NOPs available for aligning
(a subset of wide_nops)
widens = the number of narrow instructions that should be widened
- Desired wide narrow
- Diff nop nop widens
- 1 0 0 1
- 2 0 1 0
- 3a 1 0 0
- b 0 1 1 (case 3a makes this case unnecessary)
- 4a 1 0 1
- b 0 2 0
- c 0 1 2 (case 4a makes this case unnecessary)
- 5a 1 0 2
- b 1 1 0
- c 0 2 1 (case 5b makes this case unnecessary)
- 6a 2 0 0
- b 1 0 3
- c 0 1 4 (case 6b makes this case unnecessary)
- d 1 1 1 (case 6a makes this case unnecessary)
- e 0 2 2 (case 6a makes this case unnecessary)
- f 0 3 0 (case 6a makes this case unnecessary)
- 7a 1 0 4
- b 2 0 1
- c 1 1 2 (case 7b makes this case unnecessary)
- d 0 1 5 (case 7a makes this case unnecessary)
- e 0 2 3 (case 7b makes this case unnecessary)
- f 0 3 1 (case 7b makes this case unnecessary)
- g 1 2 1 (case 7b makes this case unnecessary)
*/
static long
int num_widens,
int desired_diff)
{
+ int nops_needed;
+ int nop_bytes;
+ int extra_bytes;
int bytes_short = desired_diff - num_widens;
- gas_assert (desired_diff >= 0 && desired_diff < 8);
+ gas_assert (desired_diff >= 0
+ && desired_diff < (signed) xtensa_fetch_width);
if (desired_diff == 0)
return 0;
/* From here we will need at least one NOP to get an alignment.
However, we may not be able to align at all, in which case,
don't widen. */
- if (this_frag->fr_subtype == RELAX_FILL_NOP)
+ nops_needed = desired_diff / 3;
+
+ /* If there aren't enough nops, don't widen. */
+ if (nops_needed > wide_nops)
+ return 0;
+
+ /* First try it with all wide nops. */
+ nop_bytes = nops_needed * 3;
+ extra_bytes = desired_diff - nop_bytes;
+
+ if (nop_bytes + num_widens >= desired_diff)
{
- switch (desired_diff)
- {
- case 1:
- return 0;
- case 2:
- if (!this_frag->tc_frag_data.is_no_density && narrow_nops == 1)
- return 2; /* case 2 */
- return 0;
- case 3:
- if (wide_nops > 1)
- return 0;
- else
- return 3; /* case 3a */
- case 4:
- if (num_widens >= 1 && wide_nops == 1)
- return 3; /* case 4a */
- if (!this_frag->tc_frag_data.is_no_density && narrow_nops == 2)
- return 2; /* case 4b */
- return 0;
- case 5:
- if (num_widens >= 2 && wide_nops == 1)
- return 3; /* case 5a */
- /* We will need two nops. Are there enough nops
- between here and the align target? */
- if (wide_nops < 2 || narrow_nops == 0)
- return 0;
- /* Are there other nops closer that can serve instead? */
- if (wide_nops > 2 && narrow_nops > 1)
- return 0;
- /* Take the density one first, because there might not be
- another density one available. */
- if (!this_frag->tc_frag_data.is_no_density)
- return 2; /* case 5b narrow */
- else
- return 3; /* case 5b wide */
- return 0;
- case 6:
- if (wide_nops == 2)
- return 3; /* case 6a */
- else if (num_widens >= 3 && wide_nops == 1)
- return 3; /* case 6b */
- return 0;
- case 7:
- if (wide_nops == 1 && num_widens >= 4)
- return 3; /* case 7a */
- else if (wide_nops == 2 && num_widens >= 1)
- return 3; /* case 7b */
- return 0;
- default:
- gas_assert (0);
- }
+ if (this_frag->fr_subtype == RELAX_FILL_NOP)
+ return 3;
+ else if (num_widens == extra_bytes)
+ return 1;
+ return 0;
}
- else
+
+ /* Add a narrow nop. */
+ nops_needed++;
+ nop_bytes += 2;
+ extra_bytes -= 2;
+ if (narrow_nops == 0 || nops_needed > wide_nops)
+ return 0;
+
+ if (nop_bytes + num_widens >= desired_diff && extra_bytes >= 0)
{
- /* We will need a NOP no matter what, but should we widen
- this instruction to help?
+ if (this_frag->fr_subtype == RELAX_FILL_NOP)
+ return !this_frag->tc_frag_data.is_no_density ? 2 : 3;
+ else if (num_widens == extra_bytes)
+ return 1;
+ return 0;
+ }
- This is a RELAX_NARROW frag. */
- switch (desired_diff)
- {
- case 1:
- gas_assert (0);
- return 0;
- case 2:
- case 3:
- return 0;
- case 4:
- if (wide_nops >= 1 && num_widens == 1)
- return 1; /* case 4a */
- return 0;
- case 5:
- if (wide_nops >= 1 && num_widens == 2)
- return 1; /* case 5a */
- return 0;
- case 6:
- if (wide_nops >= 2)
- return 0; /* case 6a */
- else if (wide_nops >= 1 && num_widens == 3)
- return 1; /* case 6b */
- return 0;
- case 7:
- if (wide_nops >= 1 && num_widens == 4)
- return 1; /* case 7a */
- else if (wide_nops >= 2 && num_widens == 1)
- return 1; /* case 7b */
- return 0;
- default:
- gas_assert (0);
- return 0;
- }
+ /* Replace a wide nop with a narrow nop--we can get here if
+ extra_bytes was negative in the previous conditional. */
+ if (narrow_nops == 1)
+ return 0;
+ nop_bytes--;
+ extra_bytes++;
+ if (nop_bytes + num_widens >= desired_diff)
+ {
+ if (this_frag->fr_subtype == RELAX_FILL_NOP)
+ return !this_frag->tc_frag_data.is_no_density ? 2 : 3;
+ else if (num_widens == extra_bytes)
+ return 1;
+ return 0;
}
- gas_assert (0);
+
+ /* If we can't satisfy any of the above cases, then we can't align
+ using padding or fill nops. */
return 0;
}
for (lit = literal_syms; lit; lit = lit->next)
{
symbolS *lit_sym = lit->sym;
- segT dest_seg = symbol_get_frag (lit_sym)->tc_frag_data.lit_seg;
- if (dest_seg)
- S_SET_SEGMENT (lit_sym, dest_seg);
+ segT dseg = symbol_get_frag (lit_sym)->tc_frag_data.lit_seg;
+ if (dseg)
+ S_SET_SEGMENT (lit_sym, dseg);
}
}
for (i = 0; i < noperands; i++)
{
- expressionS *expr = &tinsn->tok[i];
+ expressionS *exp = &tinsn->tok[i];
int rc;
unsigned line;
char *file_name;
uint32 opnd_value;
- switch (expr->X_op)
+ switch (exp->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;
+ opnd_value = exp->X_add_number;
(void) xtensa_operand_encode (isa, opcode, i, &opnd_value);
rc = xtensa_operand_set_field (isa, opcode, i, fmt, slot, slotbuf,
opnd_value);
/* It is a constant and we called this function
then we have to try to fit it. */
xtensa_insnbuf_set_operand (slotbuf, fmt, slot, opcode, i,
- expr->X_add_number, file_name, line);
+ exp->X_add_number, file_name, line);
break;
default:
if (v->insnbuf == NULL)
as_fatal (_("out of memory"));
- for (i = 0; i < MAX_SLOTS; i++)
+ for (i = 0; i < config_max_slots; i++)
{
v->slotbuf[i] = xtensa_insnbuf_alloc (isa);
if (v->slotbuf[i] == NULL)
{
int i;
- memset (v, 0, offsetof (vliw_insn, insnbuf));
+ memset (v, 0, offsetof (vliw_insn, slots)
+ + sizeof(TInsn) * config_max_slots);
v->format = XTENSA_UNDEFINED;
v->num_slots = 0;
if (xt_saved_debug_type != DEBUG_NONE)
debug_type = xt_saved_debug_type;
- for (i = 0; i < MAX_SLOTS; i++)
+ for (i = 0; i < config_max_slots; i++)
v->slots[i].opcode = XTENSA_UNDEFINED;
}
+static void
+xg_copy_vinsn (vliw_insn *dst, vliw_insn *src)
+{
+ memcpy (dst, src,
+ offsetof(vliw_insn, slots) + src->num_slots * sizeof(TInsn));
+ dst->insnbuf = src->insnbuf;
+ memcpy (dst->slotbuf, src->slotbuf, src->num_slots * sizeof(xtensa_insnbuf));
+}
+
+
static bfd_boolean
vinsn_has_specific_opcodes (vliw_insn *v)
{
{
int i;
xtensa_insnbuf_free (xtensa_default_isa, v->insnbuf);
- for (i = 0; i < MAX_SLOTS; i++)
+ for (i = 0; i < config_max_slots; i++)
xtensa_insnbuf_free (xtensa_default_isa, v->slotbuf[i]);
}
for (i = 0; i < noperands; i++)
{
- expressionS* expr = &tinsn->tok[i];
- switch (expr->X_op)
+ expressionS* exp = &tinsn->tok[i];
+ switch (exp->X_op)
{
case O_symbol:
case O_lo16:
|| tinsn->is_specific_opcode
|| !xg_is_relaxable_insn (tinsn, 0))
{
- xg_add_opcode_fix (tinsn, i, fmt, slot, expr, fragP,
+ xg_add_opcode_fix (tinsn, i, fmt, slot, exp, fragP,
frag_offset - fragP->fr_literal);
}
else
{
- if (expr->X_op != O_symbol)
+ if (exp->X_op != O_symbol)
as_bad (_("invalid operand"));
- tinsn->symbol = expr->X_add_symbol;
- tinsn->offset = expr->X_add_number;
+ tinsn->symbol = exp->X_add_symbol;
+ tinsn->offset = exp->X_add_number;
}
}
else