aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gas/ChangeLog16
-rw-r--r--gas/config/tc-mips.c69
-rw-r--r--gas/config/tc-mips.h9
-rw-r--r--gas/testsuite/ChangeLog6
-rw-r--r--gas/testsuite/gas/mips/align2-el.d42
-rw-r--r--gas/testsuite/gas/mips/align2.d41
-rw-r--r--gas/testsuite/gas/mips/align2.s35
-rw-r--r--gas/testsuite/gas/mips/mips.exp2
8 files changed, 197 insertions, 23 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index f16ae72..f950dba 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -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.
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index 7a88608..f19299e 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -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
diff --git a/gas/config/tc-mips.h b/gas/config/tc-mips.h
index 74a7e20..171ef7a 100644
--- a/gas/config/tc-mips.h
+++ b/gas/config/tc-mips.h
@@ -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
diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog
index aa5e20c..61450eb 100644
--- a/gas/testsuite/ChangeLog
+++ b/gas/testsuite/ChangeLog
@@ -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
index 0000000..1f50774
--- /dev/null
+++ b/gas/testsuite/gas/mips/align2-el.d
@@ -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
index 0000000..7090cee
--- /dev/null
+++ b/gas/testsuite/gas/mips/align2.d
@@ -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
index 0000000..ab73732
--- /dev/null
+++ b/gas/testsuite/gas/mips/align2.s
@@ -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
diff --git a/gas/testsuite/gas/mips/mips.exp b/gas/testsuite/gas/mips/mips.exp
index 5d04f41..dd2eaef 100644
--- a/gas/testsuite/gas/mips/mips.exp
+++ b/gas/testsuite/gas/mips/mips.exp
@@ -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"
}