static xtensa_opcode xtensa_movi_opcode;
static xtensa_opcode xtensa_movi_n_opcode;
static xtensa_opcode xtensa_isync_opcode;
+static xtensa_opcode xtensa_j_opcode;
static xtensa_opcode xtensa_jx_opcode;
static xtensa_opcode xtensa_l32r_opcode;
static xtensa_opcode xtensa_loop_opcode;
/* The routine xg_instruction_matches_option_term must return TRUE
when a given option term is true. The meaning of all of the option
- terms is given interpretation by this function. This is needed when
- an option depends on the state of a directive, but there are no such
- options in use right now. */
+ terms is given interpretation by this function. */
static bfd_boolean
-xg_instruction_matches_option_term (TInsn *insn ATTRIBUTE_UNUSED,
- const ReqOrOption *option)
+xg_instruction_matches_option_term (TInsn *insn, const ReqOrOption *option)
{
if (strcmp (option->option_name, "realnop") == 0
|| strncmp (option->option_name, "IsaUse", 6) == 0)
relaxation table. There's no need to reevaluate them now. */
return TRUE;
}
+ else if (strcmp (option->option_name, "FREEREG") == 0)
+ return insn->extra_arg.X_op == O_register;
else
{
as_fatal (_("internal error: unknown option name '%s'"),
assert (op_data < insn->ntok);
copy_expr (&targ->tok[op_num], &insn->tok[op_data]);
break;
+ case OP_FREEREG:
+ if (insn->extra_arg.X_op != O_register)
+ return FALSE;
+ copy_expr (&targ->tok[op_num], &insn->extra_arg);
+ break;
case OP_LITERAL:
sym = get_special_literal_symbol ();
set_expr_symbol_offset (&targ->tok[op_num], sym, 0);
if (insn->tok[op_data].X_op == O_tlsfunc
|| insn->tok[op_data].X_op == O_tlsarg)
- copy_expr (&targ->tls_reloc, &insn->tok[op_data]);
+ copy_expr (&targ->extra_arg, &insn->tok[op_data]);
break;
case OP_LABEL:
sym = get_special_label_symbol ();
xtensa_movi_opcode = xtensa_opcode_lookup (isa, "movi");
xtensa_movi_n_opcode = xtensa_opcode_lookup (isa, "movi.n");
xtensa_isync_opcode = xtensa_opcode_lookup (isa, "isync");
+ xtensa_j_opcode = xtensa_opcode_lookup (isa, "j");
xtensa_jx_opcode = xtensa_opcode_lookup (isa, "jx");
xtensa_l32r_opcode = xtensa_opcode_lookup (isa, "l32r");
xtensa_loop_opcode = xtensa_opcode_lookup (isa, "loop");
{
bfd_reloc_code_real_type reloc;
char *old_input_line_pointer;
- expressionS *tok = &orig_insn.tls_reloc;
+ expressionS *tok = &orig_insn.extra_arg;
segT t;
old_input_line_pointer = input_line_pointer;
}
}
+ /* Special case: Check for "j.l" psuedo op. */
+ if (orig_insn.opcode == XTENSA_UNDEFINED
+ && strncasecmp (opname, "j.l", 3) == 0)
+ {
+ if (num_args != 2)
+ as_bad (_("wrong number of operands for '%s'"), opname);
+ else
+ {
+ char *old_input_line_pointer;
+ expressionS *tok = &orig_insn.extra_arg;
+
+ old_input_line_pointer = input_line_pointer;
+ input_line_pointer = arg_strings[num_args - 1];
+
+ expression_maybe_register (xtensa_jx_opcode, 0, tok);
+ input_line_pointer = old_input_line_pointer;
+
+ num_args -= 1;
+ orig_insn.opcode = xtensa_j_opcode;
+ }
+ }
+
if (orig_insn.opcode == XTENSA_UNDEFINED)
{
xtensa_format fmt = xtensa_format_lookup (isa, opname);
frag_now->tc_frag_data.literal_frags[slot] = tinsn->literal_frag;
if (tinsn->literal_space != 0)
xg_assemble_literal_space (tinsn->literal_space, slot);
+ frag_now->tc_frag_data.free_reg[slot] = tinsn->extra_arg;
if (tinsn->subtype == RELAX_NARROW)
assert (vinsn->num_slots == 1);
fragP->tc_frag_data.slot_symbols[slot],
fragP->tc_frag_data.slot_offsets[slot]);
}
+ tinsn->extra_arg = fragP->tc_frag_data.free_reg[slot];
}
for (slot = 0; slot < vinsn->num_slots; slot++)
{
TInsn *tinsn = &vinsn->slots[slot];
- expressionS *tls_reloc = &tinsn->tls_reloc;
+ expressionS *extra_arg = &tinsn->extra_arg;
bfd_boolean tinsn_has_fixup =
tinsn_to_slotbuf (vinsn->format, slot, tinsn,
vinsn->slotbuf[slot]);
xtensa_format_set_slot (isa, fmt, slot,
insnbuf, vinsn->slotbuf[slot]);
- if (tls_reloc->X_op != O_illegal)
+ if (extra_arg->X_op != O_illegal && extra_arg->X_op != O_register)
{
if (vinsn->num_slots != 1)
as_bad (_("TLS relocation not allowed in FLIX bundle"));
else
fix_new (fragP, frag_offset - fragP->fr_literal,
xtensa_format_length (isa, fmt),
- tls_reloc->X_add_symbol, tls_reloc->X_add_number,
- FALSE, map_operator_to_reloc (tls_reloc->X_op, FALSE));
+ extra_arg->X_add_symbol, extra_arg->X_add_number,
+ FALSE, map_operator_to_reloc (extra_arg->X_op, FALSE));
}
if (tinsn_has_fixup)
{
{"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))
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))
{