2008-11-04 Sterling Augustine <sterling@tensilica.com>
authorBob Wilson <bob.wilson@acm.org>
Tue, 4 Nov 2008 23:11:02 +0000 (23:11 +0000)
committerBob Wilson <bob.wilson@acm.org>
Tue, 4 Nov 2008 23:11:02 +0000 (23:11 +0000)
* 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.

gas/ChangeLog
gas/config/tc-xtensa.c
gas/config/tc-xtensa.h
gas/config/xtensa-istack.h
gas/config/xtensa-relax.c
gas/config/xtensa-relax.h
gas/testsuite/ChangeLog
gas/testsuite/gas/xtensa/all.exp
gas/testsuite/gas/xtensa/jlong.d [new file with mode: 0644]
gas/testsuite/gas/xtensa/jlong.s [new file with mode: 0644]

index b58eadc575238f12734109bc1cd32a2b1aa2815f..72df07b68eade635e3fbd7d1b08af8a94472aa7a 100644 (file)
@@ -1,3 +1,21 @@
+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-10-31  Alan Modra  <amodra@bigpond.net.au>
 
        * po/id.po: Update.
index b6c35ecd33c2b2ccdaba1d4db7fd02fd2189e26e..92e796c64653745f8307e4efc7149e2a59f0130a 100644 (file)
@@ -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)
        {
index dbb5267102f4a170610efb0040e8b9c8fd40d342..91607aff61af7bb07f0a2540c9fd60ec60730c60 100644 (file)
@@ -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];
index 71d9114c5f2f2b123425d52332d2f89617bf0f0d..3b5b7c27a0564fb27a89f07688e9a6a022ba8354 100644 (file)
@@ -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;
index 8f49afab51afae41700a689cc98a2d515ed2bc0c..5de7dd28c55361dd7abaf27f57c0db6cc76ab90c 100644 (file)
@@ -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))
            {
index 14898c913465266f0b874b6f6a17798610bb8126..6cb8fcc989f2f81bcd870245ff94c2d3e6eed632 100644 (file)
@@ -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
 };
 
index 51209ecc1191e3ad33af45501feac6a99ae1208d..871913471d8151751dbfcace1b2dca1b5d399816 100644 (file)
@@ -1,3 +1,9 @@
+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.
+
 2008-11-03  H.J. Lu  <hongjiu.lu@intel.com>
 
        * gas/i386/intel.s: Add tests for cmovpe and cmovpo.
index 85c071608df27e4ff758f22cbcbcd90d98a7f67b..b7fb4d742975908db867a3a0c1dc65a2e8c5856b 100644 (file)
@@ -81,6 +81,7 @@ if [istarget xtensa*-*-*] then {
     run_dump_test "short_branch_offset"
     run_dump_test "pcrel"
     run_dump_test "weak-call"
+    run_dump_test "jlong"
 }
 
 if [info exists errorInfo] then {
diff --git a/gas/testsuite/gas/xtensa/jlong.d b/gas/testsuite/gas/xtensa/jlong.d
new file mode 100644 (file)
index 0000000..ee7331f
--- /dev/null
@@ -0,0 +1,18 @@
+#as: 
+#objdump: -d -j .text.1 -j .text.2
+#name: long jump relaxation
+
+.*: +file format .*xtensa.*
+
+Disassembly of section \.text\.1:
+
+00000000 <\.text\.1>:
+# Skip instructions to load a8 since they will vary depending on whether
+# the Xtensa configuration uses L32R or Const16.
+#...
+  .*:  .*      jx      a8
+Disassembly of section \.text\.2:
+
+00000000 <\.text\.2>:
+   0:  .*      j       .*
+#...
diff --git a/gas/testsuite/gas/xtensa/jlong.s b/gas/testsuite/gas/xtensa/jlong.s
new file mode 100644 (file)
index 0000000..9c52c09
--- /dev/null
@@ -0,0 +1,7 @@
+       .section .text.1
+       j.l     .Lfar, a8
+       .section .text.2
+.Lfar:
+       j.l     .Lnear, a9
+       .word   0
+.Lnear:
This page took 0.038125 seconds and 4 git commands to generate.