This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: [patch] [MIPS] Implement Errata for 24K and 24KE
- From: Catherine Moore <clm at codesourcery dot com>
- To: Catherine Moore <clm at codesourcery dot com>, binutils at sourceware dot org, rdsandiford at googlemail dot com
- Date: Mon, 18 May 2009 17:45:09 -0400
- Subject: Re: [patch] [MIPS] Implement Errata for 24K and 24KE
- References: <49DD1319.7070108@codesourcery.com> <871vs1hr0f.fsf@firetop.home> <4A0213B9.2050605@codesourcery.com> <873abesoik.fsf@firetop.home>
Hi Richard,
I've attached a new patch. It adds the testcases that you asked for along with the other cleanups.
I had trouble with one section -- this first example:
.set noreorder
1: eret
.set reorder
b 1b
insns_between is called only when the the history insn is not in a noreorder block. For this
errata, I think we need to call insns between if we're fixing 24k_errata and 1) the history insn is
a noreorder block or 2) the history insn is in a noreorder block and the following instruction is
not in a noreorder block. For the above example, insns_between was not called for the eret.
Let me know if this patch looks okay.
Thanks,
Catherine
2009-05-18 Catherine Moore <clm@codesourcery.com>
gas/
* config/tc-mips.c (check_for_24k_errata): Remove.
(md_mips_end): Remove call to check_for_24k_errata.
(start_noreorder): Likewise.
(s_change_sec): Likewise.
(s_change_section): Likewise.
(insns_between): Add 24k errata checks.
(nops_for_insn): Add check for 24k errata.
(append_insn): Remove declaration and references to nhdx_24k.
Remove calls to check_for_24k_errata.
gas/testsuite:
* eret.s, eret.d eret.l: Remove.
* eret-1.s, eret-1.d: New.
* eret-2.s, eret-2.d: New.
* eret-3.s, eret-3.d: New.
* mips.exp: Run new tests. Remove old tests.
Richard Sandiford wrote:
One upshot of this is that gas ought to insert nops in the
following situations:
.set noreorder
1: eret
.set reorder
b 1b
1: eret
.set noreorder
b 1b
.set reorder
Index: config/tc-mips.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mips.c,v
retrieving revision 1.406
diff -p -r1.406 tc-mips.c
*** config/tc-mips.c 22 Apr 2009 11:40:25 -0000 1.406
--- config/tc-mips.c 18 May 2009 21:29:31 -0000
*************** reg_lookup (char **s, unsigned int types
*** 1792,1876 ****
return reg >= 0;
}
- #define INSN_ERET 0x42000018
- #define INSN_DERET 0x4200001f
-
- /* Implement the ERET/DERET Errata for MIPS 24k.
-
- If an ERET/DERET is encountered in a noreorder block,
- warn if the ERET/DERET is followed by a branch instruction.
- Also warn if the ERET/DERET is the last instruction in the
- noreorder block.
-
- IF an ERET/DERET is in a reorder block and is followed by a
- branch instruction, insert a nop. */
-
- static void
- check_for_24k_errata (struct mips_cl_insn *insn, int eret_ndx)
- {
- bfd_boolean next_insn_is_branch = FALSE;
-
- /* eret_ndx will be -1 for the last instruction in a section
- and the ERET/DERET will be in insn, not history. */
- if (insn
- && eret_ndx == -1
- && (insn->insn_opcode == INSN_ERET
- || insn->insn_opcode == INSN_DERET)
- && insn->noreorder_p)
- {
- as_warn (_("ERET and DERET must be followed by a NOP on the 24K."));
- return;
- }
-
- if (history[eret_ndx].insn_opcode != INSN_ERET
- && history[eret_ndx].insn_opcode != INSN_DERET)
- return;
-
- if (!insn)
- {
- if (history[eret_ndx].noreorder_p)
- as_warn (_("ERET and DERET must be followed by a NOP on the 24K."));
- return;
- }
-
- next_insn_is_branch = ((insn->insn_opcode == INSN_ERET)
- || (insn->insn_opcode == INSN_DERET)
- || (insn->insn_mo->pinfo
- & (INSN_UNCOND_BRANCH_DELAY
- | INSN_COND_BRANCH_DELAY
- | INSN_COND_BRANCH_LIKELY)));
-
- if (next_insn_is_branch && history[eret_ndx].noreorder_p)
- {
- as_warn (_("ERET and DERET must be followed by a NOP on the 24K."));
- return;
- }
-
- /* Emit nop if the next instruction is a branch. */
- if (next_insn_is_branch)
- {
- long nop_where, br_where;
- struct frag *nop_frag, *br_frag;
- struct mips_cl_insn br_insn, nop_insn;
-
- emit_nop ();
-
- nop_insn = history[eret_ndx - 1];
- nop_frag = history[eret_ndx - 1].frag;
- nop_where = history[eret_ndx - 1].where;
-
- br_insn = history[eret_ndx];
- br_frag = history[eret_ndx].frag;
- br_where = history[eret_ndx].where;
-
- move_insn (&nop_insn, br_frag, br_where);
- move_insn (&br_insn, nop_frag, nop_where);
-
- history[eret_ndx-1] = br_insn;
- history[eret_ndx] = nop_insn;
- }
- }
-
/* Return TRUE if opcode MO is valid on the currently selected ISA and
architecture. If EXPANSIONP is TRUE then this check is done while
expanding a macro. Use is_opcode_valid_16 for MIPS16 opcodes. */
--- 1792,1797 ----
*************** md_begin (void)
*** 2156,2164 ****
void
md_mips_end (void)
{
- if (mips_fix_24k)
- check_for_24k_errata ((struct mips_cl_insn *) &history[0], -1);
-
if (! ECOFF_DEBUGGING)
md_obj_end ();
}
--- 2077,2082 ----
*************** classify_vr4120_insn (const char *name)
*** 2536,2541 ****
--- 2454,2462 ----
return NUM_FIX_VR4120_CLASSES;
}
+ #define INSN_ERET 0x42000018
+ #define INSN_DERET 0x4200001f
+
/* Return the number of instructions that must separate INSN1 and INSN2,
where INSN1 is the earlier instruction. Return the worst-case value
for any INSN2 if INSN2 is null. */
*************** insns_between (const struct mips_cl_insn
*** 2573,2578 ****
--- 2494,2522 ----
&& INSN2_USES_REG (EXTRACT_OPERAND (RD, *insn1), MIPS_GR_REG))
return 2;
+ /* If we're working around 24K errata, one instruction is required
+ if an ERET or DERET is followed by a branch instruction. */
+ if (mips_fix_24k)
+ {
+ if (insn1 != NULL
+ && (insn1->insn_opcode == INSN_ERET
+ || insn1->insn_opcode == INSN_DERET)
+ && insn2 == NULL)
+ return 1;
+
+ if ((insn1 != NULL)
+ && (insn2 != NULL)
+ && (insn1->insn_opcode == INSN_ERET
+ || insn1->insn_opcode == INSN_DERET)
+ && ((insn2->insn_opcode == INSN_ERET)
+ || (insn2->insn_opcode == INSN_DERET)
+ || ((insn2->insn_mo->pinfo
+ & (INSN_UNCOND_BRANCH_DELAY
+ | INSN_COND_BRANCH_DELAY
+ | INSN_COND_BRANCH_LIKELY)))))
+ return 1;
+ }
+
/* If working around VR4120 errata, check for combinations that need
a single intervening instruction. */
if (mips_fix_vr4120)
*************** nops_for_insn (const struct mips_cl_insn
*** 2714,2720 ****
nops = 0;
for (i = 0; i < MAX_DELAY_NOPS; i++)
! if (!history[i].noreorder_p)
{
tmp_nops = insns_between (history + i, insn) - i;
if (tmp_nops > nops)
--- 2658,2665 ----
nops = 0;
for (i = 0; i < MAX_DELAY_NOPS; i++)
! if (!history[i].noreorder_p
! || (mips_fix_24k && insn && !insn->noreorder_p))
{
tmp_nops = insns_between (history + i, insn) - i;
if (tmp_nops > nops)
*************** append_insn (struct mips_cl_insn *ip, ex
*** 2790,2796 ****
bfd_reloc_code_real_type *reloc_type)
{
unsigned long prev_pinfo, pinfo;
- int hndx_24k = 0;
relax_stateT prev_insn_frag_type = 0;
bfd_boolean relaxed_branch = FALSE;
segment_info_type *si = seg_info (now_seg);
--- 2735,2740 ----
*************** append_insn (struct mips_cl_insn *ip, ex
*** 3348,3355 ****
slot, and bump the destination address. */
insert_into_history (0, 1, ip);
emit_nop ();
- if (mips_fix_24k)
- hndx_24k++;
}
if (mips_relax.sequence)
--- 3292,3297 ----
*************** append_insn (struct mips_cl_insn *ip, ex
*** 3390,3400 ****
insn information. */
if (pinfo & INSN_UNCOND_BRANCH_DELAY)
{
- /* Check for eret/deret before clearing history. */
- if (mips_fix_24k)
- check_for_24k_errata (
- (struct mips_cl_insn *) &history[hndx_24k],
- hndx_24k+1);
mips_no_prev_insn ();
}
}
--- 3332,3337 ----
*************** append_insn (struct mips_cl_insn *ip, ex
*** 3406,3413 ****
the next instruction. */
insert_into_history (0, 1, ip);
emit_nop ();
- if (mips_fix_24k)
- hndx_24k++;
}
else
insert_into_history (0, 1, ip);
--- 3343,3348 ----
*************** append_insn (struct mips_cl_insn *ip, ex
*** 3415,3424 ****
else
insert_into_history (0, 1, ip);
- if (mips_fix_24k)
- check_for_24k_errata ((struct mips_cl_insn *) &history[hndx_24k],
- hndx_24k+1);
-
/* We just output an insn, so the next one doesn't have a label. */
mips_clear_insn_labels ();
}
--- 3350,3355 ----
*************** start_noreorder (void)
*** 3505,3512 ****
static void
end_noreorder (void)
{
- if (mips_fix_24k)
- check_for_24k_errata (NULL, 0);
mips_opts.noreorder--;
if (mips_opts.noreorder == 0 && prev_nop_frag != NULL)
--- 3436,3441 ----
*************** s_change_sec (int sec)
*** 12589,12597 ****
mips_emit_delays ();
- if (mips_fix_24k)
- check_for_24k_errata ((struct mips_cl_insn *) &history[0], -1);
-
switch (sec)
{
case 't':
--- 12518,12523 ----
*************** s_change_section (int ignore ATTRIBUTE_U
*** 12650,12658 ****
if (!IS_ELF)
return;
- if (mips_fix_24k)
- check_for_24k_errata ((struct mips_cl_insn *) &history[0], -1);
-
section_name = input_line_pointer;
c = get_symbol_end ();
if (c)
--- 12576,12581 ----
Index: testsuite/gas/mips/eret-1.d
===================================================================
RCS file: testsuite/gas/mips/eret-1.d
diff -N testsuite/gas/mips/eret-1.d
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/gas/mips/eret-1.d 18 May 2009 21:29:31 -0000
***************
*** 0 ****
--- 1,41 ----
+ #objdump: -d
+ #name: MIPS eret-1 disassembly
+ #as: -mfix-24k -march=24kc --no-warn
+
+ .*\.o: file format .*mips.*
+
+ Disassembly of section \.text:
+
+ 00000000 <\.text>:
+ 0: 240c0000 li t4,0
+ 4: 42000018 eret
+ 8: 00000000 nop
+ c: 10000003 b 0x1c
+ 10: 00000000 nop
+ 14: 240a0003 li t2,3
+ 18: 42000018 eret
+ 1c: 24040000 li a0,0
+ 20: 4200001f deret
+ 24: 00000000 nop
+ 28: 116afffa beq t3,t2,0x14
+ 2c: 00000000 nop
+ 30: 4200001f deret
+ 34: 00000000 nop
+ 38: 42000018 eret
+ 3c: 00000000 nop
+ 40: 42000018 eret
+ 44: 00000000 nop
+ 48: 1000fff4 b 0x1c
+ 4c: 00000000 nop
+ 50: 240c0004 li t4,4
+ 54: 4200001f deret
+ 58: 240c0003 li t4,3
+ 5c: 42000018 eret
+ 60: 10000005 b 0x78
+ 64: 240c0003 li t4,3
+ 68: 42000018 eret
+ 6c: 00000000 nop
+ 70: 10000001 b 0x78
+ 74: 240c0003 li t4,3
+ 78: 240c0003 li t4,3
+ 7c: 42000018 eret
Index: testsuite/gas/mips/eret-1.s
===================================================================
RCS file: testsuite/gas/mips/eret-1.s
diff -N testsuite/gas/mips/eret-1.s
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/gas/mips/eret-1.s 18 May 2009 21:29:31 -0000
***************
*** 0 ****
--- 1,27 ----
+ .text
+ li $t4, 0
+ eret
+ b 2f
+ 1: li $t2, 3
+ eret
+ 2: li $a0, 0
+ deret
+ beq $t3,$t2,1b
+ deret
+ eret
+ eret
+ b 2b
+
+ .set noreorder
+ li $t4, 4
+ deret
+ li $t4, 3
+ eret
+ b 1f
+ li $t4, 3
+ eret
+ nop
+ b 1f
+ li $t4, 3
+ 1: li $t4, 3
+ eret
Index: testsuite/gas/mips/eret-2.d
===================================================================
RCS file: testsuite/gas/mips/eret-2.d
diff -N testsuite/gas/mips/eret-2.d
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/gas/mips/eret-2.d 18 May 2009 21:29:31 -0000
***************
*** 0 ****
--- 1,16 ----
+ #objdump: -d
+ #name: MIPS eret-2 disassembly
+ #as: -mfix-24k -march=24kc --no-warn
+
+ .*\.o: file format .*mips.*
+
+ Disassembly of section \.text:
+
+ 00000000 <\.text>:
+ 0: 42000018 eret
+ 4: 00000000 nop
+ 8: 1000fffd b 0x0
+ c: 00000000 nop
+ 10: 42000018 eret
+ 14: 00000000 nop
+ 18: 1000fffd b 0x10
Index: testsuite/gas/mips/eret-2.s
===================================================================
RCS file: testsuite/gas/mips/eret-2.s
diff -N testsuite/gas/mips/eret-2.s
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/gas/mips/eret-2.s 18 May 2009 21:29:31 -0000
***************
*** 0 ****
--- 1,9 ----
+ .set noreorder
+ 1: eret
+ .set reorder
+ b 1b
+
+ 1: eret
+ .set noreorder
+ b 1b
+ .set reorder
Index: testsuite/gas/mips/eret-3.d
===================================================================
RCS file: testsuite/gas/mips/eret-3.d
diff -N testsuite/gas/mips/eret-3.d
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/gas/mips/eret-3.d 18 May 2009 21:29:31 -0000
***************
*** 0 ****
--- 1,18 ----
+ #objdump: -d
+ #name: MIPS eret-3 disassembly
+ #as: -mfix-24k -march=24kc --no-warn
+
+ .*\.o: file format .*mips.*
+
+ Disassembly of section \.text:
+
+ 00000000 <foo>:
+ 0: 42000018 eret
+ 4: 00000000 nop
+
+ 00000008 <bar>:
+ 8: 10800002 beqz a0,14 <bar\+0xc>
+ c: 00000000 nop
+ 10: aca40000 sw a0,0\(a1\)
+ 14: 03e00008 jr ra
+ 18: 00000000 nop
Index: testsuite/gas/mips/eret-3.s
===================================================================
RCS file: testsuite/gas/mips/eret-3.s
diff -N testsuite/gas/mips/eret-3.s
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/gas/mips/eret-3.s 18 May 2009 21:29:31 -0000
***************
*** 0 ****
--- 1,14 ----
+ .globl foo
+ .ent foo
+ foo:
+ eret
+ .end foo
+
+ .globl bar
+ .ent bar
+ bar:
+ beq $4,$0,1f
+ sw $4,0($5)
+ 1:
+ jr $31
+ .end bar
Index: testsuite/gas/mips/eret.d
===================================================================
RCS file: testsuite/gas/mips/eret.d
diff -N testsuite/gas/mips/eret.d
*** testsuite/gas/mips/eret.d 9 Apr 2009 15:55:59 -0000 1.1
--- /dev/null 1 Jan 1970 00:00:00 -0000
***************
*** 1,41 ****
- #objdump: -d
- #name: MIPS eret disassembly
- #as: -mfix-24k -march=24kc --no-warn
-
- .*\.o: file format .*mips.*
-
- Disassembly of section \.text:
-
- 00000000 <\.text>:
- 0: 240c0000 li t4,0
- 4: 42000018 eret
- 8: 00000000 nop
- c: 10000003 b 0x1c
- 10: 00000000 nop
- 14: 240a0003 li t2,3
- 18: 42000018 eret
- 1c: 24040000 li a0,0
- 20: 4200001f deret
- 24: 00000000 nop
- 28: 116afffa beq t3,t2,0x14
- 2c: 00000000 nop
- 30: 4200001f deret
- 34: 00000000 nop
- 38: 42000018 eret
- 3c: 00000000 nop
- 40: 42000018 eret
- 44: 00000000 nop
- 48: 1000fff4 b 0x1c
- 4c: 00000000 nop
- 50: 240c0004 li t4,4
- 54: 4200001f deret
- 58: 240c0003 li t4,3
- 5c: 42000018 eret
- 60: 10000005 b 0x78
- 64: 240c0003 li t4,3
- 68: 42000018 eret
- 6c: 00000000 nop
- 70: 10000001 b 0x78
- 74: 240c0003 li t4,3
- 78: 240c0003 li t4,3
- 7c: 42000018 eret
--- 0 ----
Index: testsuite/gas/mips/eret.l
===================================================================
RCS file: testsuite/gas/mips/eret.l
diff -N testsuite/gas/mips/eret.l
*** testsuite/gas/mips/eret.l 9 Apr 2009 15:55:59 -0000 1.1
--- /dev/null 1 Jan 1970 00:00:00 -0000
***************
*** 1,3 ****
- .*\.s: Assembler messages:
- .*\.s:20: Warning: ERET and DERET must be followed by a NOP on the 24K\.
- .*\.s:27: Warning: ERET and DERET must be followed by a NOP on the 24K\.
--- 0 ----
Index: testsuite/gas/mips/eret.s
===================================================================
RCS file: testsuite/gas/mips/eret.s
diff -N testsuite/gas/mips/eret.s
*** testsuite/gas/mips/eret.s 9 Apr 2009 15:55:59 -0000 1.1
--- /dev/null 1 Jan 1970 00:00:00 -0000
***************
*** 1,27 ****
- .text
- li $t4, 0
- eret
- b 2f
- 1: li $t2, 3
- eret
- 2: li $a0, 0
- deret
- beq $t3,$t2,1b
- deret
- eret
- eret
- b 2b
-
- .set noreorder
- li $t4, 4
- deret
- li $t4, 3
- eret
- b 1f
- li $t4, 3
- eret
- nop
- b 1f
- li $t4, 3
- 1: li $t4, 3
- eret
--- 0 ----
Index: testsuite/gas/mips/mips.exp
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/mips/mips.exp,v
retrieving revision 1.150
diff -p -r1.150 mips.exp
*** testsuite/gas/mips/mips.exp 9 Apr 2009 15:55:59 -0000 1.150
--- testsuite/gas/mips/mips.exp 18 May 2009 21:29:31 -0000
*************** if { [istarget mips*-*-vxworks*] } {
*** 436,443 ****
} else {
run_dump_test "jal"
}
! run_dump_test "eret"
! run_list_test "eret" "-mfix-24k -march=24kc" "MIPS eret warnings"
if $elf { run_dump_test "jal-svr4pic" }
if $elf { run_dump_test "jal-xgot" }
--- 436,444 ----
} else {
run_dump_test "jal"
}
! run_dump_test "eret-1"
! run_dump_test "eret-2"
! run_dump_test "eret-3"
if $elf { run_dump_test "jal-svr4pic" }
if $elf { run_dump_test "jal-xgot" }