diff options
author | Bob Wilson <bob.wilson@acm.org> | 2008-11-04 23:11:02 +0000 |
---|---|---|
committer | Bob Wilson <bob.wilson@acm.org> | 2008-11-04 23:11:02 +0000 |
commit | 19e8f41aa49baed9fd1f4a154e3611bb19de0442 (patch) | |
tree | 0df808cc4ca68628c4076fe7afd4f7f28a810327 /gas/config | |
parent | d3fd534293b3e22ff1aac0e141bb22e99fbbe3c2 (diff) | |
download | gdb-19e8f41aa49baed9fd1f4a154e3611bb19de0442.zip gdb-19e8f41aa49baed9fd1f4a154e3611bb19de0442.tar.gz gdb-19e8f41aa49baed9fd1f4a154e3611bb19de0442.tar.bz2 |
2008-11-04 Sterling Augustine <sterling@tensilica.com>
* config/tc-xtensa.c (xtensa_j_opcode): New.
(xg_instruction_matches_option_term): Handle "FREEREG" option.
(xg_build_to_insn): Likewise. Update renamed tls_reloc reference.
(md_begin): Initialize xtensa_j_opcode.
(md_assemble): Update renamed tls_reloc reference. Handle "j.l".
(xg_assemble_vliw_tokens): Save free_reg info in the frag.
(tinsn_immed_from_frag): Get free_reg info back out of the frag.
(vinsn_to_insnbuf): Update renamed tls_reloc references.
Distinguish extra argument for "FREEREG" from extra TLS argument.
* config/tc-xtensa.h (struct xtensa_frag_type): Add free_reg field.
* config/xtensa-istack.h (struct tinsn_struct): Rename tls_reloc
field to extra_arg.
* config/xtensa-relax.c (widen_spec_list): Add rules to relax "j.l".
(build_transition): Handle "FREEREG" operand.
* config/xtensa-relax.h (enum op_type): Add OP_FREEREG.
2008-11-04 Bob Wilson <bob.wilson@acm.org>
* gas/xtensa/all.exp: Run jlong test.
* gas/xtensa/jlong.d: New.
* gas/xtensa/jlong.s: New.
Diffstat (limited to 'gas/config')
-rw-r--r-- | gas/config/tc-xtensa.c | 52 | ||||
-rw-r--r-- | gas/config/tc-xtensa.h | 4 | ||||
-rw-r--r-- | gas/config/xtensa-istack.h | 10 | ||||
-rw-r--r-- | gas/config/xtensa-relax.c | 13 | ||||
-rw-r--r-- | gas/config/xtensa-relax.h | 1 |
5 files changed, 67 insertions, 13 deletions
diff --git a/gas/config/tc-xtensa.c b/gas/config/tc-xtensa.c index b6c35ec..92e796c 100644 --- a/gas/config/tc-xtensa.c +++ b/gas/config/tc-xtensa.c @@ -571,6 +571,7 @@ static xtensa_opcode xtensa_extui_opcode; 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; @@ -2730,13 +2731,10 @@ xtensa_insnbuf_get_operand (xtensa_insnbuf slotbuf, /* 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) @@ -2745,6 +2743,8 @@ xg_instruction_matches_option_term (TInsn *insn ATTRIBUTE_UNUSED, 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'"), @@ -3370,12 +3370,17 @@ xg_build_to_insn (TInsn *targ, TInsn *insn, BuildInstr *bi) 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 (); @@ -5103,6 +5108,7 @@ md_begin (void) 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"); @@ -5375,7 +5381,7 @@ md_assemble (char *str) { 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; @@ -5395,6 +5401,28 @@ md_assemble (char *str) } } + /* 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); @@ -6996,6 +7024,7 @@ xg_assemble_vliw_tokens (vliw_insn *vinsn) 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); @@ -11505,6 +11534,7 @@ tinsn_immed_from_frag (TInsn *tinsn, fragS *fragP, int slot) fragP->tc_frag_data.slot_symbols[slot], fragP->tc_frag_data.slot_offsets[slot]); } + tinsn->extra_arg = fragP->tc_frag_data.free_reg[slot]; } @@ -11626,14 +11656,14 @@ vinsn_to_insnbuf (vliw_insn *vinsn, 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")); @@ -11646,8 +11676,8 @@ vinsn_to_insnbuf (vliw_insn *vinsn, 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) { diff --git a/gas/config/tc-xtensa.h b/gas/config/tc-xtensa.h index dbb5267..91607af 100644 --- a/gas/config/tc-xtensa.h +++ b/gas/config/tc-xtensa.h @@ -253,6 +253,10 @@ struct xtensa_frag_type int literal_expansion[MAX_SLOTS]; int unreported_expansion; + /* For slots that have a free register for relaxation, record that + register. */ + expressionS free_reg[MAX_SLOTS]; + /* For text fragments that can generate literals at relax time: */ fragS *literal_frags[MAX_SLOTS]; enum xtensa_relax_statesE slot_subtypes[MAX_SLOTS]; diff --git a/gas/config/xtensa-istack.h b/gas/config/xtensa-istack.h index 71d9114..3b5b7c2 100644 --- a/gas/config/xtensa-istack.h +++ b/gas/config/xtensa-istack.h @@ -49,11 +49,19 @@ typedef struct tinsn_struct bfd_boolean loc_directive_seen; struct dwarf2_line_info debug_line; - expressionS tls_reloc; + /* This field is used for two types of special pseudo ops: + 1. TLS-related operations. Eg: callx8.tls + 2. j.l label, a2 + + For the tls-related operations, it will hold a tls-related opcode + and info to be used in a fixup. For j.l it will hold a + register to be used during relaxation. */ + expressionS extra_arg; /* Filled out by relaxation_requirements: */ enum xtensa_relax_statesE subtype; int literal_space; + /* Filled out by vinsn_to_insnbuf: */ symbolS *symbol; offsetT offset; diff --git a/gas/config/xtensa-relax.c b/gas/config/xtensa-relax.c index 8f49afa..5de7dd2 100644 --- a/gas/config/xtensa-relax.c +++ b/gas/config/xtensa-relax.c @@ -463,7 +463,14 @@ static string_pattern_pair widen_spec_list[] = {"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)) @@ -1793,6 +1800,10 @@ build_transition (insn_pattern *initial_insn, 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)) { diff --git a/gas/config/xtensa-relax.h b/gas/config/xtensa-relax.h index 14898c9..6cb8fcc 100644 --- a/gas/config/xtensa-relax.h +++ b/gas/config/xtensa-relax.h @@ -105,6 +105,7 @@ enum op_type OP_OPERAND_LOW16U, /* Low 16 bits of immed. */ OP_OPERAND_HI16U, /* High 16 bits of immed. */ OP_LITERAL, + OP_FREEREG, OP_LABEL }; |