lemote-fix.patch 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. diff -Nur binutils-2.20.orig/gas/config/tc-mips.c binutils-2.20/gas/config/tc-mips.c
  2. --- binutils-2.20.orig/gas/config/tc-mips.c 2009-09-22 17:41:00.000000000 +0200
  3. +++ binutils-2.20/gas/config/tc-mips.c 2010-03-06 18:44:16.000000000 +0100
  4. @@ -761,6 +761,15 @@
  5. NUM_FIX_VR4120_CLASSES
  6. };
  7. +/* ...likewise -mfix-loongson2f-jump. */
  8. +static int mips_fix_loongson2f_jump;
  9. +
  10. +/* ...likewise -mfix-loongson2f-nop. */
  11. +static int mips_fix_loongson2f_nop;
  12. +
  13. +/* True if -mfix-loongson2f-nop or -mfix-loongson2f-jump passed */
  14. +static int mips_fix_loongson2f;
  15. +
  16. /* Given two FIX_VR4120_* values X and Y, bit Y of element X is set if
  17. there must be at least one other instruction between an instruction
  18. of type X and an instruction of type Y. */
  19. @@ -1918,6 +1927,8 @@
  20. if (nop_insn.insn_mo == NULL && strcmp (name, "nop") == 0)
  21. {
  22. create_insn (&nop_insn, mips_opcodes + i);
  23. + if (mips_fix_loongson2f_nop)
  24. + nop_insn.insn_opcode = LOONGSON2F_NOP_INSN;
  25. nop_insn.fixed_p = 1;
  26. }
  27. }
  28. @@ -2731,6 +2742,53 @@
  29. return nops;
  30. }
  31. +static void
  32. +macro_build (expressionS *ep, const char *name, const char *fmt, ...);
  33. +
  34. +static void fix_loongson2f_nop(struct mips_cl_insn *ip)
  35. +{
  36. + /* Fix NOP issue: Replace nops by "or at,at,zero" */
  37. + if (strcmp(ip->insn_mo->name, "nop") == 0)
  38. + ip->insn_opcode = LOONGSON2F_NOP_INSN;
  39. +}
  40. +
  41. +static void fix_loongson2f_jump(struct mips_cl_insn *ip)
  42. +{
  43. +
  44. + /* Fix Jump Issue: Eliminate instruction fetch from outside 256M region
  45. + * jr target pc &= 'hffff_ffff_cfff_ffff
  46. + */
  47. + if (strcmp(ip->insn_mo->name, "j") == 0
  48. + || strcmp(ip->insn_mo->name, "jr") == 0
  49. + || strcmp(ip->insn_mo->name, "jalr") == 0)
  50. + {
  51. + int sreg;
  52. + expressionS ep;
  53. +
  54. + if (! mips_opts.at)
  55. + return;
  56. +
  57. + sreg = EXTRACT_OPERAND (RS, *ip);
  58. + if (sreg == ZERO || sreg == KT0 || sreg == KT1 || sreg == ATREG)
  59. + return;
  60. +
  61. + ep.X_op = O_constant;
  62. + ep.X_add_number = 0xcfff0000;
  63. + macro_build (&ep, "lui", "t,u", ATREG, BFD_RELOC_HI16);
  64. + ep.X_add_number = 0xffff;
  65. + macro_build (&ep, "ori", "t,r,i", ATREG, ATREG, BFD_RELOC_LO16);
  66. + macro_build (NULL, "and", "d,v,t", sreg, sreg, ATREG);
  67. + }
  68. +}
  69. +
  70. +static void fix_loongson2f(struct mips_cl_insn *ip)
  71. +{
  72. + if (mips_fix_loongson2f_nop)
  73. + fix_loongson2f_nop(ip);
  74. + if (mips_fix_loongson2f_jump)
  75. + fix_loongson2f_jump(ip);
  76. +}
  77. +
  78. /* Output an instruction. IP is the instruction information.
  79. ADDRESS_EXPR is an operand of the instruction to be used with
  80. RELOC_TYPE. */
  81. @@ -2744,6 +2802,9 @@
  82. bfd_boolean relaxed_branch = FALSE;
  83. segment_info_type *si = seg_info (now_seg);
  84. + if (mips_fix_loongson2f)
  85. + fix_loongson2f(ip);
  86. +
  87. /* Mark instruction labels in mips16 mode. */
  88. mips16_mark_labels ();
  89. @@ -11220,6 +11281,10 @@
  90. OPTION_MNO_7000_HILO_FIX,
  91. OPTION_FIX_24K,
  92. OPTION_NO_FIX_24K,
  93. + OPTION_FIX_LOONGSON2F_JUMP,
  94. + OPTION_NO_FIX_LOONGSON2F_JUMP,
  95. + OPTION_FIX_LOONGSON2F_NOP,
  96. + OPTION_NO_FIX_LOONGSON2F_NOP,
  97. OPTION_FIX_VR4120,
  98. OPTION_NO_FIX_VR4120,
  99. OPTION_FIX_VR4130,
  100. @@ -11308,6 +11373,10 @@
  101. {"mfix7000", no_argument, NULL, OPTION_M7000_HILO_FIX},
  102. {"no-fix-7000", no_argument, NULL, OPTION_MNO_7000_HILO_FIX},
  103. {"mno-fix7000", no_argument, NULL, OPTION_MNO_7000_HILO_FIX},
  104. + {"mfix-loongson2f-jump", no_argument, NULL, OPTION_FIX_LOONGSON2F_JUMP},
  105. + {"mno-fix-loongson2f-jump", no_argument, NULL, OPTION_NO_FIX_LOONGSON2F_JUMP},
  106. + {"mfix-loongson2f-nop", no_argument, NULL, OPTION_FIX_LOONGSON2F_NOP},
  107. + {"mno-fix-loongson2f-nop", no_argument, NULL, OPTION_NO_FIX_LOONGSON2F_NOP},
  108. {"mfix-vr4120", no_argument, NULL, OPTION_FIX_VR4120},
  109. {"mno-fix-vr4120", no_argument, NULL, OPTION_NO_FIX_VR4120},
  110. {"mfix-vr4130", no_argument, NULL, OPTION_FIX_VR4130},
  111. @@ -11575,6 +11644,22 @@
  112. mips_fix_24k = 0;
  113. break;
  114. + case OPTION_FIX_LOONGSON2F_JUMP:
  115. + mips_fix_loongson2f_jump = 1;
  116. + break;
  117. +
  118. + case OPTION_NO_FIX_LOONGSON2F_JUMP:
  119. + mips_fix_loongson2f_jump = 0;
  120. + break;
  121. +
  122. + case OPTION_FIX_LOONGSON2F_NOP:
  123. + mips_fix_loongson2f_nop = 1;
  124. + break;
  125. +
  126. + case OPTION_NO_FIX_LOONGSON2F_NOP:
  127. + mips_fix_loongson2f_nop = 0;
  128. + break;
  129. +
  130. case OPTION_FIX_VR4120:
  131. mips_fix_vr4120 = 1;
  132. break;
  133. @@ -11789,6 +11874,8 @@
  134. return 0;
  135. }
  136. + mips_fix_loongson2f = mips_fix_loongson2f_nop || mips_fix_loongson2f_jump;
  137. +
  138. return 1;
  139. }
  140. @@ -14794,6 +14881,8 @@
  141. mips_handle_align (fragS *fragp)
  142. {
  143. char *p;
  144. + int bytes, size, excess;
  145. + valueT opcode;
  146. if (fragp->fr_type != rs_align_code)
  147. return;
  148. @@ -14801,17 +14890,27 @@
  149. p = fragp->fr_literal + fragp->fr_fix;
  150. if (*p)
  151. {
  152. - int bytes;
  153. + opcode = mips16_nop_insn.insn_opcode;
  154. + size = 2;
  155. + }
  156. + else
  157. + {
  158. + opcode = nop_insn.insn_opcode;
  159. + size = 4;
  160. + }
  161. - bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
  162. - if (bytes & 1)
  163. - {
  164. - *p++ = 0;
  165. - fragp->fr_fix++;
  166. - }
  167. - md_number_to_chars (p, mips16_nop_insn.insn_opcode, 2);
  168. - fragp->fr_var = 2;
  169. + bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
  170. + excess = bytes % size;
  171. + if (excess != 0)
  172. + {
  173. + /* If we're not inserting a whole number of instructions, pad the
  174. + end of the fixed part of the frag with zeros */
  175. + memset (p, 0, excess);
  176. + p += excess;
  177. + fragp->fr_fix += excess;
  178. }
  179. + md_number_to_chars (p, opcode, size);
  180. + fragp->fr_var = size;
  181. }
  182. static void
  183. @@ -15523,6 +15622,8 @@
  184. -mmt generate MT instructions\n\
  185. -mno-mt do not generate MT instructions\n"));
  186. fprintf (stream, _("\
  187. +-mfix-loongson2f-jump work around Loongson2F JUMP instructions\
  188. +-mfix-loongson2f-nop work around Loongson2F NOP errata\n\
  189. -mfix-vr4120 work around certain VR4120 errata\n\
  190. -mfix-vr4130 work around VR4130 mflo/mfhi errata\n\
  191. -mfix-24k insert a nop after ERET and DERET instructions\n\
  192. diff -Nur binutils-2.20.orig/gas/config/tc-mips.h binutils-2.20/gas/config/tc-mips.h
  193. --- binutils-2.20.orig/gas/config/tc-mips.h 2009-09-02 09:24:20.000000000 +0200
  194. +++ binutils-2.20/gas/config/tc-mips.h 2010-03-06 18:44:16.000000000 +0100
  195. @@ -59,7 +59,7 @@
  196. extern void mips_handle_align (struct frag *);
  197. #define HANDLE_ALIGN(fragp) mips_handle_align (fragp)
  198. -#define MAX_MEM_FOR_RS_ALIGN_CODE (1 + 2)
  199. +#define MAX_MEM_FOR_RS_ALIGN_CODE (3 + 4)
  200. struct insn_label_list;
  201. struct mips_segment_info {
  202. diff -Nur binutils-2.20.orig/gas/doc/c-mips.texi binutils-2.20/gas/doc/c-mips.texi
  203. --- binutils-2.20.orig/gas/doc/c-mips.texi 2009-09-28 12:23:57.000000000 +0200
  204. +++ binutils-2.20/gas/doc/c-mips.texi 2010-03-06 18:44:16.000000000 +0100
  205. @@ -172,6 +172,19 @@
  206. Cause nops to be inserted if the read of the destination register
  207. of an mfhi or mflo instruction occurs in the following two instructions.
  208. +@item -mfix-loongson2f-jump
  209. +@itemx -mno-fix-loongson2f-jump
  210. +Eliminate instruction fetch from outside 256M region to work around the
  211. +Loongson2F @samp{jump} instructions. Without it, under extreme cases, kernel
  212. +may crash. The issue has been solved in latest processor batches, but this fix
  213. +has no side effect to them.
  214. +
  215. +@item -mfix-loongson2f-nop
  216. +@itemx -mno-fix-loongson2f-nop
  217. +Replace nops by @code{or at,at,zero} to work around the Loongson2F @samp{nop}
  218. +errata. Without it, under extreme cases, cpu might deadlock. The issue has been
  219. +solved in latest loongson2f batches, but this fix has no side effect to them.
  220. +
  221. @item -mfix-vr4120
  222. @itemx -no-mfix-vr4120
  223. Insert nops to work around certain VR4120 errata. This option is
  224. 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
  225. --- binutils-2.20.orig/gas/testsuite/gas/mips/loongson-2f-2.d 1970-01-01 01:00:00.000000000 +0100
  226. +++ binutils-2.20/gas/testsuite/gas/mips/loongson-2f-2.d 2010-03-06 18:44:16.000000000 +0100
  227. @@ -0,0 +1,18 @@
  228. +#as: -mfix-loongson2f-nop
  229. +#objdump: -M reg-names=numeric -dr
  230. +#name: ST Microelectronics Loongson-2F workarounds of nop issue
  231. +
  232. +.*: file format .*
  233. +
  234. +
  235. +Disassembly of section .text:
  236. +
  237. +00000000 <loongson2f_nop_insn>:
  238. + 0: 00200825 move \$1,\$1
  239. + 4: 00200825 move \$1,\$1
  240. + 8: 00200825 move \$1,\$1
  241. + c: 00200825 move \$1,\$1
  242. + 10: 00200825 move \$1,\$1
  243. + 14: 00200825 move \$1,\$1
  244. + 18: 00200825 move \$1,\$1
  245. + 1c: 00200825 move \$1,\$1
  246. 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
  247. --- binutils-2.20.orig/gas/testsuite/gas/mips/loongson-2f-2.s 1970-01-01 01:00:00.000000000 +0100
  248. +++ binutils-2.20/gas/testsuite/gas/mips/loongson-2f-2.s 2010-03-06 18:44:16.000000000 +0100
  249. @@ -0,0 +1,10 @@
  250. +# Test the work around of the NOP issue of loongson2F
  251. + .text
  252. + .set noreorder
  253. +
  254. + .align 5 # Test _implicit_ nops
  255. +loongson2f_nop_insn:
  256. + nop # Test _explicit_ nops
  257. +
  258. +# align section end to 16-byte boundary for easier testing on multiple targets
  259. + .p2align 4
  260. 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
  261. --- binutils-2.20.orig/gas/testsuite/gas/mips/loongson-2f-3.d 1970-01-01 01:00:00.000000000 +0100
  262. +++ binutils-2.20/gas/testsuite/gas/mips/loongson-2f-3.d 2010-03-06 18:44:16.000000000 +0100
  263. @@ -0,0 +1,35 @@
  264. +#as: -mfix-loongson2f-jump
  265. +#objdump: -M reg-names=numeric -dr
  266. +#name: ST Microelectronics Loongson-2F workarounds of Jump Instruction issue
  267. +
  268. +.*: file format .*
  269. +
  270. +
  271. +Disassembly of section .text:
  272. +
  273. +00000000 <.text>:
  274. + 0: 3c01cfff lui \$1,0xcfff
  275. + 4: 3421ffff ori \$1,\$1,0xffff
  276. + 8: 03c1f024 and \$30,\$30,\$1
  277. + c: 03c00008 jr \$30
  278. + 10: 00000000 nop
  279. +
  280. + 14: 3c01cfff lui \$1,0xcfff
  281. + 18: 3421ffff ori \$1,\$1,0xffff
  282. + 1c: 03e1f824 and \$31,\$31,\$1
  283. + 20: 03e00008 jr \$31
  284. + 24: 00000000 nop
  285. +
  286. + 28: 3c01cfff lui \$1,0xcfff
  287. + 2c: 3421ffff ori \$1,\$1,0xffff
  288. + 30: 03c1f024 and \$30,\$30,\$1
  289. + 34: 03c0f809 jalr \$30
  290. + 38: 00000000 nop
  291. +
  292. + 3c: 00200008 jr \$1
  293. + 40: 00000000 nop
  294. +
  295. + 44: 08000000 j 0x0
  296. + 44: R_MIPS_26 external_label
  297. + 48: 00000000 nop
  298. + 4c: 00000000 nop
  299. 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
  300. --- binutils-2.20.orig/gas/testsuite/gas/mips/loongson-2f-3.s 1970-01-01 01:00:00.000000000 +0100
  301. +++ binutils-2.20/gas/testsuite/gas/mips/loongson-2f-3.s 2010-03-06 18:44:16.000000000 +0100
  302. @@ -0,0 +1,23 @@
  303. +# Test the work around of the Jump instruction Issue of Loongson2F
  304. + .text
  305. + .set noreorder
  306. +
  307. + j $30 # j with register
  308. + nop
  309. +
  310. + jr $31 # jr
  311. + nop
  312. +
  313. + jalr $30 # jalr
  314. + nop
  315. +
  316. + .set noat
  317. + jr $1 # jr with at register and .set annotation
  318. + nop
  319. + .set at
  320. +
  321. + j external_label # j with label
  322. + nop
  323. +
  324. +# align section end to 16-byte boundary for easier testing on multiple targets
  325. + .p2align 4
  326. diff -Nur binutils-2.20.orig/gas/testsuite/gas/mips/mips.exp binutils-2.20/gas/testsuite/gas/mips/mips.exp
  327. --- binutils-2.20.orig/gas/testsuite/gas/mips/mips.exp 2009-09-22 17:41:03.000000000 +0200
  328. +++ binutils-2.20/gas/testsuite/gas/mips/mips.exp 2010-03-06 18:44:16.000000000 +0100
  329. @@ -789,6 +789,8 @@
  330. run_dump_test "loongson-2e"
  331. run_dump_test "loongson-2f"
  332. + run_dump_test "loongson-2f-2"
  333. + run_dump_test "loongson-2f-3"
  334. run_dump_test_arches "octeon" [mips_arch_list_matching octeon]
  335. run_list_test_arches "octeon-ill" "" \
  336. diff -Nur binutils-2.20.orig/include/opcode/mips.h binutils-2.20/include/opcode/mips.h
  337. --- binutils-2.20.orig/include/opcode/mips.h 2009-09-02 09:21:40.000000000 +0200
  338. +++ binutils-2.20/include/opcode/mips.h 2010-03-06 18:44:16.000000000 +0100
  339. @@ -1106,4 +1106,8 @@
  340. extern const struct mips_opcode mips16_opcodes[];
  341. extern const int bfd_mips16_num_opcodes;
  342. +/* Replace the original nops by "or at,at,zero",
  343. + Used to implement -mfix-loongson2f */
  344. +#define LOONGSON2F_NOP_INSN 0x00200825
  345. +
  346. #endif /* _MIPS_H_ */