|
@@ -0,0 +1,362 @@
|
|
|
+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_ */
|