From 742a56fee56f186cb3a033d456cd0e3cd74c0751 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Mon, 10 Dec 2007 10:36:00 +0000 Subject: [PATCH] gas/ * 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 | 16 +++++++ gas/config/tc-mips.c | 69 ++++++++++++++++++++---------- gas/config/tc-mips.h | 9 +++- gas/testsuite/ChangeLog | 6 +++ gas/testsuite/gas/mips/align2-el.d | 42 ++++++++++++++++++ gas/testsuite/gas/mips/align2.d | 41 ++++++++++++++++++ gas/testsuite/gas/mips/align2.s | 35 +++++++++++++++ gas/testsuite/gas/mips/mips.exp | 2 + 8 files changed, 197 insertions(+), 23 deletions(-) create mode 100644 gas/testsuite/gas/mips/align2-el.d create mode 100644 gas/testsuite/gas/mips/align2.d create mode 100644 gas/testsuite/gas/mips/align2.s diff --git a/gas/ChangeLog b/gas/ChangeLog index f16ae7230db..f950dbafee7 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,19 @@ +2007-12-10 Richard Sandiford + + * 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 * config/tc-xtensa.c (O_pcrel): Define. diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index 7a886083aae..f19299e1c30 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 74a7e20c0d0..171ef7a68ff 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 aa5e20c4641..61450ebdd94 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2007-12-10 Richard Sandiford + + * 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 * 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 00000000000..1f50774f4d0 --- /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 : + 0: 4a01 addiu v0,1 + 2: 6500 nop + 4: 6500 nop + 6: 6500 nop + 8: 4b01 addiu v1,1 + a: 6500 nop + +0000000c : + c: 24420001 addiu v0,v0,1 + 10: 24630001 addiu v1,v1,1 + \.\.\. + 20: 24840001 addiu a0,a0,1 + 24: 00000000 nop + +00000028 : + 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 : + 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 00000000000..7090ceeb5c6 --- /dev/null +++ b/gas/testsuite/gas/mips/align2.d @@ -0,0 +1,41 @@ +# as: -EB +# objdump: -dr + +.* file format .* + +Disassembly of section \.text: + +00000000 : + 0: 4a01 addiu v0,1 + 2: 6500 nop + 4: 6500 nop + 6: 6500 nop + 8: 4b01 addiu v1,1 + a: 6500 nop + +0000000c : + c: 24420001 addiu v0,v0,1 + 10: 24630001 addiu v1,v1,1 + \.\.\. + 20: 24840001 addiu a0,a0,1 + 24: 00000000 nop + +00000028 : + 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 : + 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 00000000000..ab7373238ef --- /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 5d04f41101f..dd2eaef6c56 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" } -- 2.30.2