gas/
authorRichard Sandiford <rdsandiford@googlemail.com>
Mon, 10 Dec 2007 10:36:00 +0000 (10:36 +0000)
committerRichard Sandiford <rdsandiford@googlemail.com>
Mon, 10 Dec 2007 10:36:00 +0000 (10:36 +0000)
* config/tc-mips.h (mips_nop_opcode): Declare.
(NOP_OPCODE): Define.
(mips_segment_info): New structure.
(TC_SEGMENT_INFO_TYPE): Use it instead of insn_label_list.
* config/tc-mips.c (label_list): Adjust for new TC_SEGMENT_INFO_TYPE.
(mips_record_mips16_mode): New function.
(install_insn): Call it.
(mips_align): Likewise.  Turn the fill argument into an "int *".
Use frag_align_code for code segments if no fill data is given.
(s_align): Adjust call accordingly.
(mips_nop_opcode): New function.
(mips_handle_align): Use the first variable byte to decide which
nop sequence is needed.  Use md_number_to_chars and mips16_nop_insn.

gas/testsuite/
* gas/mips/align2.s, gas/mips/align2.d, gas/mips/align2-el.d: New
tests.
* gas/mips/mips.exp: Run them.

gas/ChangeLog
gas/config/tc-mips.c
gas/config/tc-mips.h
gas/testsuite/ChangeLog
gas/testsuite/gas/mips/align2-el.d [new file with mode: 0644]
gas/testsuite/gas/mips/align2.d [new file with mode: 0644]
gas/testsuite/gas/mips/align2.s [new file with mode: 0644]
gas/testsuite/gas/mips/mips.exp

index f16ae72..f950dba 100644 (file)
@@ -1,3 +1,19 @@
+2007-12-10  Richard Sandiford  <rsandifo@nildram.co.uk>
+
+       * config/tc-mips.h (mips_nop_opcode): Declare.
+       (NOP_OPCODE): Define.
+       (mips_segment_info): New structure.
+       (TC_SEGMENT_INFO_TYPE): Use it instead of insn_label_list.
+       * config/tc-mips.c (label_list): Adjust for new TC_SEGMENT_INFO_TYPE.
+       (mips_record_mips16_mode): New function.
+       (install_insn): Call it.
+       (mips_align): Likewise.  Turn the fill argument into an "int *".
+       Use frag_align_code for code segments if no fill data is given.
+       (s_align): Adjust call accordingly.
+       (mips_nop_opcode): New function.
+       (mips_handle_align): Use the first variable byte to decide which
+       nop sequence is needed.  Use md_number_to_chars and mips16_nop_insn.
+
 2007-12-07  Bob Wilson  <bob.wilson@acm.org>
        
        * config/tc-xtensa.c (O_pcrel): Define.
index 7a88608..f19299e 100644 (file)
@@ -1185,7 +1185,7 @@ struct insn_label_list
 };
 
 static struct insn_label_list *free_insn_labels;
-#define label_list tc_segment_info_data
+#define label_list tc_segment_info_data.labels
 
 static void mips_clear_insn_labels (void);
 
@@ -1310,6 +1310,18 @@ create_insn (struct mips_cl_insn *insn, const struct mips_opcode *mo)
   insn->mips16_absolute_jump_p = 0;
 }
 
+/* Record the current MIPS16 mode in now_seg.  */
+
+static void
+mips_record_mips16_mode (void)
+{
+  segment_info_type *si;
+
+  si = seg_info (now_seg);
+  if (si->tc_segment_info_data.mips16 != mips_opts.mips16)
+    si->tc_segment_info_data.mips16 = mips_opts.mips16;
+}
+
 /* Install INSN at the location specified by its "frag" and "where" fields.  */
 
 static void
@@ -1332,6 +1344,7 @@ install_insn (const struct mips_cl_insn *insn)
        }
       md_number_to_chars (f, insn->insn_opcode, 2);
     }
+  mips_record_mips16_mode ();
 }
 
 /* Move INSN to offset WHERE in FRAG.  Adjust the fixups accordingly
@@ -11994,14 +12007,22 @@ get_symbol (void)
   return p;
 }
 
-/* Align the current frag to a given power of two.  The MIPS assembler
-   also automatically adjusts any preceding label.  */
+/* Align the current frag to a given power of two.  If a particular
+   fill byte should be used, FILL points to an integer that contains
+   that byte, otherwise FILL is null.
+
+   The MIPS assembler also automatically adjusts any preceding
+   label.  */
 
 static void
-mips_align (int to, int fill, symbolS *label)
+mips_align (int to, int *fill, symbolS *label)
 {
   mips_emit_delays ();
-  frag_align (to, fill, 0);
+  mips_record_mips16_mode ();
+  if (fill == NULL && subseg_text_p (now_seg))
+    frag_align_code (to, 0);
+  else
+    frag_align (to, fill ? *fill : 0, 0);
   record_alignment (now_seg, to);
   if (label != NULL)
     {
@@ -12017,8 +12038,7 @@ mips_align (int to, int fill, symbolS *label)
 static void
 s_align (int x ATTRIBUTE_UNUSED)
 {
-  int temp;
-  long temp_fill;
+  int temp, fill_value, *fill_ptr;
   long max_alignment = 28;
 
   /* o Note that the assembler pulls down any immediately preceding label
@@ -12040,17 +12060,18 @@ s_align (int x ATTRIBUTE_UNUSED)
   if (*input_line_pointer == ',')
     {
       ++input_line_pointer;
-      temp_fill = get_absolute_expression ();
+      fill_value = get_absolute_expression ();
+      fill_ptr = &fill_value;
     }
   else
-    temp_fill = 0;
+    fill_ptr = 0;
   if (temp)
     {
       segment_info_type *si = seg_info (now_seg);
       struct insn_label_list *l = si->label_list;
       /* Auto alignment should be switched on by next section change.  */
       auto_align = 1;
-      mips_align (temp, (int) temp_fill, l != NULL ? l->label : NULL);
+      mips_align (temp, fill_ptr, l != NULL ? l->label : NULL);
     }
   else
     {
@@ -14321,36 +14342,40 @@ static procS cur_proc;
 static procS *cur_proc_ptr;
 static int numprocs;
 
-/* Fill in an rs_align_code fragment.  */
+/* Implement NOP_OPCODE.  We encode a MIPS16 nop as "1" and a normal
+   nop as "0".  */
+
+char
+mips_nop_opcode (void)
+{
+  return seg_info (now_seg)->tc_segment_info_data.mips16;
+}
+
+/* Fill in an rs_align_code fragment.  This only needs to do something
+   for MIPS16 code, where 0 is not a nop.  */
 
 void
 mips_handle_align (fragS *fragp)
 {
+  char *p;
+
   if (fragp->fr_type != rs_align_code)
     return;
 
-  if (mips_opts.mips16)
+  p = fragp->fr_literal + fragp->fr_fix;
+  if (*p)
     {
-      static const unsigned char be_nop[] = { 0x65, 0x00 };
-      static const unsigned char le_nop[] = { 0x00, 0x65 };
-
       int bytes;
-      char *p;
 
       bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
-      p = fragp->fr_literal + fragp->fr_fix;
-
       if (bytes & 1)
        {
          *p++ = 0;
          fragp->fr_fix++;
        }
-
-      memcpy (p, (target_big_endian ? be_nop : le_nop), 2);
+      md_number_to_chars (p, mips16_nop_insn.insn_opcode, 2);
       fragp->fr_var = 2;
     }
-
-  /* For mips32, a nop is a zero, which we trivially get by doing nothing.  */
 }
 
 static void
index 74a7e20..171ef7a 100644 (file)
@@ -53,13 +53,20 @@ extern int mips_relax_frag (asection *, struct frag *, long);
 #define md_undefined_symbol(name)      (0)
 #define md_operand(x)
 
+extern char mips_nop_opcode (void);
+#define NOP_OPCODE (mips_nop_opcode ())
+
 extern void mips_handle_align (struct frag *);
 #define HANDLE_ALIGN(fragp)  mips_handle_align (fragp)
 
 #define MAX_MEM_FOR_RS_ALIGN_CODE  (1 + 2)
 
 struct insn_label_list;
-#define TC_SEGMENT_INFO_TYPE struct insn_label_list *
+struct mips_segment_info {
+  struct insn_label_list *labels;
+  unsigned int mips16 : 1;
+};
+#define TC_SEGMENT_INFO_TYPE struct mips_segment_info
 
 /* This field is nonzero if the symbol is the target of a MIPS16 jump.  */
 #define TC_SYMFIELD_TYPE int
index aa5e20c..61450eb 100644 (file)
@@ -1,3 +1,9 @@
+2007-12-10  Richard Sandiford  <rsandifo@nildram.co.uk>
+
+       * gas/mips/align2.s, gas/mips/align2.d, gas/mips/align2-el.d: New
+       tests.
+       * gas/mips/mips.exp: Run them.
+
 2007-12-07  Bob Wilson  <bob.wilson@acm.org>
 
        * gas/xtensa/all.exp: Run new pcrel test.
diff --git a/gas/testsuite/gas/mips/align2-el.d b/gas/testsuite/gas/mips/align2-el.d
new file mode 100644 (file)
index 0000000..1f50774
--- /dev/null
@@ -0,0 +1,42 @@
+# source: align2.s
+# as: -EL
+# objdump: -dr
+
+.* file format .*
+
+Disassembly of section \.text:
+
+00000000 <f1>:
+   0:  4a01            addiu   v0,1
+   2:  6500            nop
+   4:  6500            nop
+   6:  6500            nop
+   8:  4b01            addiu   v1,1
+   a:  6500            nop
+
+0000000c <f2>:
+   c:  24420001        addiu   v0,v0,1
+  10:  24630001        addiu   v1,v1,1
+       \.\.\.
+  20:  24840001        addiu   a0,a0,1
+  24:  00000000        nop
+
+00000028 <f3>:
+  28:  4001            addiu   s0,s0,1
+  2a:  6500            nop
+  2c:  6500            nop
+  2e:  6500            nop
+  30:  6500            nop
+  32:  6500            nop
+  34:  6500            nop
+  36:  6500            nop
+  38:  6500            nop
+  3a:  6500            nop
+  3c:  6500            nop
+  3e:  6500            nop
+
+Disassembly of section \.text\.a:
+
+00000000 <f4>:
+   0:  24a50001        addiu   a1,a1,1
+       \.\.\.
diff --git a/gas/testsuite/gas/mips/align2.d b/gas/testsuite/gas/mips/align2.d
new file mode 100644 (file)
index 0000000..7090cee
--- /dev/null
@@ -0,0 +1,41 @@
+# as: -EB
+# objdump: -dr
+
+.* file format .*
+
+Disassembly of section \.text:
+
+00000000 <f1>:
+   0:  4a01            addiu   v0,1
+   2:  6500            nop
+   4:  6500            nop
+   6:  6500            nop
+   8:  4b01            addiu   v1,1
+   a:  6500            nop
+
+0000000c <f2>:
+   c:  24420001        addiu   v0,v0,1
+  10:  24630001        addiu   v1,v1,1
+       \.\.\.
+  20:  24840001        addiu   a0,a0,1
+  24:  00000000        nop
+
+00000028 <f3>:
+  28:  4001            addiu   s0,s0,1
+  2a:  6500            nop
+  2c:  6500            nop
+  2e:  6500            nop
+  30:  6500            nop
+  32:  6500            nop
+  34:  6500            nop
+  36:  6500            nop
+  38:  6500            nop
+  3a:  6500            nop
+  3c:  6500            nop
+  3e:  6500            nop
+
+Disassembly of section \.text\.a:
+
+00000000 <f4>:
+   0:  24a50001        addiu   a1,a1,1
+       \.\.\.
diff --git a/gas/testsuite/gas/mips/align2.s b/gas/testsuite/gas/mips/align2.s
new file mode 100644 (file)
index 0000000..ab73732
--- /dev/null
@@ -0,0 +1,35 @@
+       .text
+       .align  5
+       .type   f1,@function
+f1:
+       .set    mips16
+       addiu   $2,1
+       .align  3
+       addiu   $3,1
+       .size   f1,.-f1
+
+       .align  2
+       .set    nomips16
+       .type   f2,@function
+f2:
+       addiu   $2,$2,1
+       addiu   $3,$3,1
+       .align  4
+       addiu   $4,$4,1
+       .align  3
+       .size   f2,.-f2
+
+       .set    mips16
+       .type   f3,@function
+f3:
+       addiu   $16,$16,1
+       .align  3
+       .size   f3,.-f3
+
+       .section .text.a,"ax",@progbits
+       .align  4
+       .set    nomips16
+       .type   f4,@function
+f4:
+       addiu   $5,$5,1
+       .size   f4,.-f4
index 5d04f41..dd2eaef 100644 (file)
@@ -786,5 +786,7 @@ if { [istarget mips*-*-vxworks*] } {
 
     run_dump_test "noreorder"
     run_dump_test "align"
+    run_dump_test "align2"
+    run_dump_test "align2-el"
     run_dump_test "odd-float"
 }