123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362 |
- diff -Nur binutils-2.20.orig/gas/config/tc-mips.c binutils-2.20/gas/config/tc-mips.c
- --- binutils-2.20.orig/gas/config/tc-mips.c 2009-09-22 17:41:00.000000000 +0200
- +++ binutils-2.20/gas/config/tc-mips.c 2010-03-06 18:44:16.000000000 +0100
- @@ -761,6 +761,15 @@
- NUM_FIX_VR4120_CLASSES
- };
-
- +/* ...likewise -mfix-loongson2f-jump. */
- +static int mips_fix_loongson2f_jump;
- +
- +/* ...likewise -mfix-loongson2f-nop. */
- +static int mips_fix_loongson2f_nop;
- +
- +/* True if -mfix-loongson2f-nop or -mfix-loongson2f-jump passed */
- +static int mips_fix_loongson2f;
- +
- /* Given two FIX_VR4120_* values X and Y, bit Y of element X is set if
- there must be at least one other instruction between an instruction
- of type X and an instruction of type Y. */
- @@ -1918,6 +1927,8 @@
- if (nop_insn.insn_mo == NULL && strcmp (name, "nop") == 0)
- {
- create_insn (&nop_insn, mips_opcodes + i);
- + if (mips_fix_loongson2f_nop)
- + nop_insn.insn_opcode = LOONGSON2F_NOP_INSN;
- nop_insn.fixed_p = 1;
- }
- }
- @@ -2731,6 +2742,53 @@
- return nops;
- }
-
- +static void
- +macro_build (expressionS *ep, const char *name, const char *fmt, ...);
- +
- +static void fix_loongson2f_nop(struct mips_cl_insn *ip)
- +{
- + /* Fix NOP issue: Replace nops by "or at,at,zero" */
- + if (strcmp(ip->insn_mo->name, "nop") == 0)
- + ip->insn_opcode = LOONGSON2F_NOP_INSN;
- +}
- +
- +static void fix_loongson2f_jump(struct mips_cl_insn *ip)
- +{
- +
- + /* Fix Jump Issue: Eliminate instruction fetch from outside 256M region
- + * jr target pc &= 'hffff_ffff_cfff_ffff
- + */
- + if (strcmp(ip->insn_mo->name, "j") == 0
- + || strcmp(ip->insn_mo->name, "jr") == 0
- + || strcmp(ip->insn_mo->name, "jalr") == 0)
- + {
- + int sreg;
- + expressionS ep;
- +
- + if (! mips_opts.at)
- + return;
- +
- + sreg = EXTRACT_OPERAND (RS, *ip);
- + if (sreg == ZERO || sreg == KT0 || sreg == KT1 || sreg == ATREG)
- + return;
- +
- + ep.X_op = O_constant;
- + ep.X_add_number = 0xcfff0000;
- + macro_build (&ep, "lui", "t,u", ATREG, BFD_RELOC_HI16);
- + ep.X_add_number = 0xffff;
- + macro_build (&ep, "ori", "t,r,i", ATREG, ATREG, BFD_RELOC_LO16);
- + macro_build (NULL, "and", "d,v,t", sreg, sreg, ATREG);
- + }
- +}
- +
- +static void fix_loongson2f(struct mips_cl_insn *ip)
- +{
- + if (mips_fix_loongson2f_nop)
- + fix_loongson2f_nop(ip);
- + if (mips_fix_loongson2f_jump)
- + fix_loongson2f_jump(ip);
- +}
- +
- /* Output an instruction. IP is the instruction information.
- ADDRESS_EXPR is an operand of the instruction to be used with
- RELOC_TYPE. */
- @@ -2744,6 +2802,9 @@
- bfd_boolean relaxed_branch = FALSE;
- segment_info_type *si = seg_info (now_seg);
-
- + if (mips_fix_loongson2f)
- + fix_loongson2f(ip);
- +
- /* Mark instruction labels in mips16 mode. */
- mips16_mark_labels ();
-
- @@ -11220,6 +11281,10 @@
- OPTION_MNO_7000_HILO_FIX,
- OPTION_FIX_24K,
- OPTION_NO_FIX_24K,
- + OPTION_FIX_LOONGSON2F_JUMP,
- + OPTION_NO_FIX_LOONGSON2F_JUMP,
- + OPTION_FIX_LOONGSON2F_NOP,
- + OPTION_NO_FIX_LOONGSON2F_NOP,
- OPTION_FIX_VR4120,
- OPTION_NO_FIX_VR4120,
- OPTION_FIX_VR4130,
- @@ -11308,6 +11373,10 @@
- {"mfix7000", no_argument, NULL, OPTION_M7000_HILO_FIX},
- {"no-fix-7000", no_argument, NULL, OPTION_MNO_7000_HILO_FIX},
- {"mno-fix7000", no_argument, NULL, OPTION_MNO_7000_HILO_FIX},
- + {"mfix-loongson2f-jump", no_argument, NULL, OPTION_FIX_LOONGSON2F_JUMP},
- + {"mno-fix-loongson2f-jump", no_argument, NULL, OPTION_NO_FIX_LOONGSON2F_JUMP},
- + {"mfix-loongson2f-nop", no_argument, NULL, OPTION_FIX_LOONGSON2F_NOP},
- + {"mno-fix-loongson2f-nop", no_argument, NULL, OPTION_NO_FIX_LOONGSON2F_NOP},
- {"mfix-vr4120", no_argument, NULL, OPTION_FIX_VR4120},
- {"mno-fix-vr4120", no_argument, NULL, OPTION_NO_FIX_VR4120},
- {"mfix-vr4130", no_argument, NULL, OPTION_FIX_VR4130},
- @@ -11575,6 +11644,22 @@
- mips_fix_24k = 0;
- break;
-
- + case OPTION_FIX_LOONGSON2F_JUMP:
- + mips_fix_loongson2f_jump = 1;
- + break;
- +
- + case OPTION_NO_FIX_LOONGSON2F_JUMP:
- + mips_fix_loongson2f_jump = 0;
- + break;
- +
- + case OPTION_FIX_LOONGSON2F_NOP:
- + mips_fix_loongson2f_nop = 1;
- + break;
- +
- + case OPTION_NO_FIX_LOONGSON2F_NOP:
- + mips_fix_loongson2f_nop = 0;
- + break;
- +
- case OPTION_FIX_VR4120:
- mips_fix_vr4120 = 1;
- break;
- @@ -11789,6 +11874,8 @@
- return 0;
- }
-
- + mips_fix_loongson2f = mips_fix_loongson2f_nop || mips_fix_loongson2f_jump;
- +
- return 1;
- }
-
- @@ -14794,6 +14881,8 @@
- mips_handle_align (fragS *fragp)
- {
- char *p;
- + int bytes, size, excess;
- + valueT opcode;
-
- if (fragp->fr_type != rs_align_code)
- return;
- @@ -14801,17 +14890,27 @@
- p = fragp->fr_literal + fragp->fr_fix;
- if (*p)
- {
- - int bytes;
- + opcode = mips16_nop_insn.insn_opcode;
- + size = 2;
- + }
- + else
- + {
- + opcode = nop_insn.insn_opcode;
- + size = 4;
- + }
-
- - bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
- - if (bytes & 1)
- - {
- - *p++ = 0;
- - fragp->fr_fix++;
- - }
- - md_number_to_chars (p, mips16_nop_insn.insn_opcode, 2);
- - fragp->fr_var = 2;
- + bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
- + excess = bytes % size;
- + if (excess != 0)
- + {
- + /* If we're not inserting a whole number of instructions, pad the
- + end of the fixed part of the frag with zeros */
- + memset (p, 0, excess);
- + p += excess;
- + fragp->fr_fix += excess;
- }
- + md_number_to_chars (p, opcode, size);
- + fragp->fr_var = size;
- }
-
- static void
- @@ -15523,6 +15622,8 @@
- -mmt generate MT instructions\n\
- -mno-mt do not generate MT instructions\n"));
- fprintf (stream, _("\
- +-mfix-loongson2f-jump work around Loongson2F JUMP instructions\
- +-mfix-loongson2f-nop work around Loongson2F NOP errata\n\
- -mfix-vr4120 work around certain VR4120 errata\n\
- -mfix-vr4130 work around VR4130 mflo/mfhi errata\n\
- -mfix-24k insert a nop after ERET and DERET instructions\n\
- diff -Nur binutils-2.20.orig/gas/config/tc-mips.h binutils-2.20/gas/config/tc-mips.h
- --- binutils-2.20.orig/gas/config/tc-mips.h 2009-09-02 09:24:20.000000000 +0200
- +++ binutils-2.20/gas/config/tc-mips.h 2010-03-06 18:44:16.000000000 +0100
- @@ -59,7 +59,7 @@
- extern void mips_handle_align (struct frag *);
- #define HANDLE_ALIGN(fragp) mips_handle_align (fragp)
-
- -#define MAX_MEM_FOR_RS_ALIGN_CODE (1 + 2)
- +#define MAX_MEM_FOR_RS_ALIGN_CODE (3 + 4)
-
- struct insn_label_list;
- struct mips_segment_info {
- diff -Nur binutils-2.20.orig/gas/doc/c-mips.texi binutils-2.20/gas/doc/c-mips.texi
- --- binutils-2.20.orig/gas/doc/c-mips.texi 2009-09-28 12:23:57.000000000 +0200
- +++ binutils-2.20/gas/doc/c-mips.texi 2010-03-06 18:44:16.000000000 +0100
- @@ -172,6 +172,19 @@
- Cause nops to be inserted if the read of the destination register
- of an mfhi or mflo instruction occurs in the following two instructions.
-
- +@item -mfix-loongson2f-jump
- +@itemx -mno-fix-loongson2f-jump
- +Eliminate instruction fetch from outside 256M region to work around the
- +Loongson2F @samp{jump} instructions. Without it, under extreme cases, kernel
- +may crash. The issue has been solved in latest processor batches, but this fix
- +has no side effect to them.
- +
- +@item -mfix-loongson2f-nop
- +@itemx -mno-fix-loongson2f-nop
- +Replace nops by @code{or at,at,zero} to work around the Loongson2F @samp{nop}
- +errata. Without it, under extreme cases, cpu might deadlock. The issue has been
- +solved in latest loongson2f batches, but this fix has no side effect to them.
- +
- @item -mfix-vr4120
- @itemx -no-mfix-vr4120
- Insert nops to work around certain VR4120 errata. This option is
- diff -Nur binutils-2.20.orig/gas/testsuite/gas/mips/loongson-2f-2.d binutils-2.20/gas/testsuite/gas/mips/loongson-2f-2.d
- --- binutils-2.20.orig/gas/testsuite/gas/mips/loongson-2f-2.d 1970-01-01 01:00:00.000000000 +0100
- +++ binutils-2.20/gas/testsuite/gas/mips/loongson-2f-2.d 2010-03-06 18:44:16.000000000 +0100
- @@ -0,0 +1,18 @@
- +#as: -mfix-loongson2f-nop
- +#objdump: -M reg-names=numeric -dr
- +#name: ST Microelectronics Loongson-2F workarounds of nop issue
- +
- +.*: file format .*
- +
- +
- +Disassembly of section .text:
- +
- +00000000 <loongson2f_nop_insn>:
- + 0: 00200825 move \$1,\$1
- + 4: 00200825 move \$1,\$1
- + 8: 00200825 move \$1,\$1
- + c: 00200825 move \$1,\$1
- + 10: 00200825 move \$1,\$1
- + 14: 00200825 move \$1,\$1
- + 18: 00200825 move \$1,\$1
- + 1c: 00200825 move \$1,\$1
- diff -Nur binutils-2.20.orig/gas/testsuite/gas/mips/loongson-2f-2.s binutils-2.20/gas/testsuite/gas/mips/loongson-2f-2.s
- --- binutils-2.20.orig/gas/testsuite/gas/mips/loongson-2f-2.s 1970-01-01 01:00:00.000000000 +0100
- +++ binutils-2.20/gas/testsuite/gas/mips/loongson-2f-2.s 2010-03-06 18:44:16.000000000 +0100
- @@ -0,0 +1,10 @@
- +# Test the work around of the NOP issue of loongson2F
- + .text
- + .set noreorder
- +
- + .align 5 # Test _implicit_ nops
- +loongson2f_nop_insn:
- + nop # Test _explicit_ nops
- +
- +# align section end to 16-byte boundary for easier testing on multiple targets
- + .p2align 4
- diff -Nur binutils-2.20.orig/gas/testsuite/gas/mips/loongson-2f-3.d binutils-2.20/gas/testsuite/gas/mips/loongson-2f-3.d
- --- binutils-2.20.orig/gas/testsuite/gas/mips/loongson-2f-3.d 1970-01-01 01:00:00.000000000 +0100
- +++ binutils-2.20/gas/testsuite/gas/mips/loongson-2f-3.d 2010-03-06 18:44:16.000000000 +0100
- @@ -0,0 +1,35 @@
- +#as: -mfix-loongson2f-jump
- +#objdump: -M reg-names=numeric -dr
- +#name: ST Microelectronics Loongson-2F workarounds of Jump Instruction issue
- +
- +.*: file format .*
- +
- +
- +Disassembly of section .text:
- +
- +00000000 <.text>:
- + 0: 3c01cfff lui \$1,0xcfff
- + 4: 3421ffff ori \$1,\$1,0xffff
- + 8: 03c1f024 and \$30,\$30,\$1
- + c: 03c00008 jr \$30
- + 10: 00000000 nop
- +
- + 14: 3c01cfff lui \$1,0xcfff
- + 18: 3421ffff ori \$1,\$1,0xffff
- + 1c: 03e1f824 and \$31,\$31,\$1
- + 20: 03e00008 jr \$31
- + 24: 00000000 nop
- +
- + 28: 3c01cfff lui \$1,0xcfff
- + 2c: 3421ffff ori \$1,\$1,0xffff
- + 30: 03c1f024 and \$30,\$30,\$1
- + 34: 03c0f809 jalr \$30
- + 38: 00000000 nop
- +
- + 3c: 00200008 jr \$1
- + 40: 00000000 nop
- +
- + 44: 08000000 j 0x0
- + 44: R_MIPS_26 external_label
- + 48: 00000000 nop
- + 4c: 00000000 nop
- diff -Nur binutils-2.20.orig/gas/testsuite/gas/mips/loongson-2f-3.s binutils-2.20/gas/testsuite/gas/mips/loongson-2f-3.s
- --- binutils-2.20.orig/gas/testsuite/gas/mips/loongson-2f-3.s 1970-01-01 01:00:00.000000000 +0100
- +++ binutils-2.20/gas/testsuite/gas/mips/loongson-2f-3.s 2010-03-06 18:44:16.000000000 +0100
- @@ -0,0 +1,23 @@
- +# Test the work around of the Jump instruction Issue of Loongson2F
- + .text
- + .set noreorder
- +
- + j $30 # j with register
- + nop
- +
- + jr $31 # jr
- + nop
- +
- + jalr $30 # jalr
- + nop
- +
- + .set noat
- + jr $1 # jr with at register and .set annotation
- + nop
- + .set at
- +
- + j external_label # j with label
- + nop
- +
- +# align section end to 16-byte boundary for easier testing on multiple targets
- + .p2align 4
- diff -Nur binutils-2.20.orig/gas/testsuite/gas/mips/mips.exp binutils-2.20/gas/testsuite/gas/mips/mips.exp
- --- binutils-2.20.orig/gas/testsuite/gas/mips/mips.exp 2009-09-22 17:41:03.000000000 +0200
- +++ binutils-2.20/gas/testsuite/gas/mips/mips.exp 2010-03-06 18:44:16.000000000 +0100
- @@ -789,6 +789,8 @@
-
- run_dump_test "loongson-2e"
- run_dump_test "loongson-2f"
- + run_dump_test "loongson-2f-2"
- + run_dump_test "loongson-2f-3"
-
- run_dump_test_arches "octeon" [mips_arch_list_matching octeon]
- run_list_test_arches "octeon-ill" "" \
- diff -Nur binutils-2.20.orig/include/opcode/mips.h binutils-2.20/include/opcode/mips.h
- --- binutils-2.20.orig/include/opcode/mips.h 2009-09-02 09:21:40.000000000 +0200
- +++ binutils-2.20/include/opcode/mips.h 2010-03-06 18:44:16.000000000 +0100
- @@ -1106,4 +1106,8 @@
- extern const struct mips_opcode mips16_opcodes[];
- extern const int bfd_mips16_num_opcodes;
-
- +/* Replace the original nops by "or at,at,zero",
- + Used to implement -mfix-loongson2f */
- +#define LOONGSON2F_NOP_INSN 0x00200825
- +
- #endif /* _MIPS_H_ */
|