bugfix.S
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:14k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. |
  2. | bugfix.sa 3.2 1/31/91
  3. |
  4. |
  5. | This file contains workarounds for bugs in the 040
  6. | relating to the Floating-Point Software Package (FPSP)
  7. |
  8. | Fixes for bugs: 1238
  9. |
  10. | Bug: 1238 
  11. |
  12. |
  13. |    /* The following dirty_bit clear should be left in
  14. |     * the handler permanently to improve throughput.
  15. |     * The dirty_bits are located at bits [23:16] in
  16. |     * longword $08 in the busy frame $4x60.  Bit 16
  17. |     * corresponds to FP0, bit 17 corresponds to FP1,
  18. |     * and so on.
  19. |     */
  20. |    if  (E3_exception_just_serviced)   {
  21. |         dirty_bit[cmdreg3b[9:7]] = 0;
  22. |         }
  23. |
  24. |    if  (fsave_format_version != $40)  {goto NOFIX}
  25. |
  26. |    if !(E3_exception_just_serviced)   {goto NOFIX}
  27. |    if  (cupc == 0000000)              {goto NOFIX}
  28. |    if  ((cmdreg1b[15:13] != 000) &&
  29. |         (cmdreg1b[15:10] != 010001))  {goto NOFIX}
  30. |    if (((cmdreg1b[15:13] != 000) || ((cmdreg1b[12:10] != cmdreg2b[9:7]) &&
  31. |       (cmdreg1b[12:10] != cmdreg3b[9:7]))  ) &&
  32. |  ((cmdreg1b[ 9: 7] != cmdreg2b[9:7]) &&
  33. |   (cmdreg1b[ 9: 7] != cmdreg3b[9:7])) )  {goto NOFIX}
  34. |
  35. |    /* Note: for 6d43b or 8d43b, you may want to add the following code
  36. |     * to get better coverage.  (If you do not insert this code, the part
  37. |     * won't lock up; it will simply get the wrong answer.)
  38. |     * Do NOT insert this code for 10d43b or later parts.
  39. |     *
  40. |     *  if (fpiarcu == integer stack return address) {
  41. |     *       cupc = 0000000;
  42. |     *       goto NOFIX;
  43. |     *       }
  44. |     */
  45. |
  46. |    if (cmdreg1b[15:13] != 000)   {goto FIX_OPCLASS2}
  47. |    FIX_OPCLASS0:
  48. |    if (((cmdreg1b[12:10] == cmdreg2b[9:7]) ||
  49. |  (cmdreg1b[ 9: 7] == cmdreg2b[9:7])) &&
  50. | (cmdreg1b[12:10] != cmdreg3b[9:7]) &&
  51. | (cmdreg1b[ 9: 7] != cmdreg3b[9:7]))  {  /* xu conflict only */
  52. | /* We execute the following code if there is an
  53. |    xu conflict and NOT an nu conflict */
  54. |
  55. | /* first save some values on the fsave frame */
  56. | stag_temp     = STAG[fsave_frame];
  57. | cmdreg1b_temp = CMDREG1B[fsave_frame];
  58. | dtag_temp     = DTAG[fsave_frame];
  59. | ete15_temp    = ETE15[fsave_frame];
  60. |
  61. | CUPC[fsave_frame] = 0000000;
  62. | FRESTORE
  63. | FSAVE
  64. |
  65. | /* If the xu instruction is exceptional, we punt.
  66. |  * Otherwise, we would have to include OVFL/UNFL handler
  67. |  * code here to get the correct answer.
  68. |  */
  69. | if (fsave_frame_format == $4060) {goto KILL_PROCESS}
  70. |
  71. | fsave_frame = /* build a long frame of all zeros */
  72. | fsave_frame_format = $4060;  /* label it as long frame */
  73. |
  74. | /* load it with the temps we saved */
  75. | STAG[fsave_frame]     =  stag_temp;
  76. | CMDREG1B[fsave_frame] =  cmdreg1b_temp;
  77. | DTAG[fsave_frame]     =  dtag_temp;
  78. | ETE15[fsave_frame]    =  ete15_temp;
  79. |
  80. | /* Make sure that the cmdreg3b dest reg is not going to
  81. |  * be destroyed by a FMOVEM at the end of all this code.
  82. |  * If it is, you should move the current value of the reg
  83. |  * onto the stack so that the reg will loaded with that value.
  84. |  */
  85. |
  86. | /* All done.  Proceed with the code below */
  87. |    }
  88. |
  89. |    etemp  = FP_reg_[cmdreg1b[12:10]];
  90. |    ete15  = ~ete14;
  91. |    cmdreg1b[15:10] = 010010;
  92. |    clear(bug_flag_procIDxxxx);
  93. |    FRESTORE and return;
  94. |
  95. |
  96. |    FIX_OPCLASS2:
  97. |    if ((cmdreg1b[9:7] == cmdreg2b[9:7]) &&
  98. | (cmdreg1b[9:7] != cmdreg3b[9:7]))  {  /* xu conflict only */
  99. | /* We execute the following code if there is an
  100. |    xu conflict and NOT an nu conflict */
  101. |
  102. | /* first save some values on the fsave frame */
  103. | stag_temp     = STAG[fsave_frame];
  104. | cmdreg1b_temp = CMDREG1B[fsave_frame];
  105. | dtag_temp     = DTAG[fsave_frame];
  106. | ete15_temp    = ETE15[fsave_frame];
  107. | etemp_temp    = ETEMP[fsave_frame];
  108. |
  109. | CUPC[fsave_frame] = 0000000;
  110. | FRESTORE
  111. | FSAVE
  112. |
  113. |
  114. | /* If the xu instruction is exceptional, we punt.
  115. |  * Otherwise, we would have to include OVFL/UNFL handler
  116. |  * code here to get the correct answer.
  117. |  */
  118. | if (fsave_frame_format == $4060) {goto KILL_PROCESS}
  119. |
  120. | fsave_frame = /* build a long frame of all zeros */
  121. | fsave_frame_format = $4060;  /* label it as long frame */
  122. |
  123. | /* load it with the temps we saved */
  124. | STAG[fsave_frame]     =  stag_temp;
  125. | CMDREG1B[fsave_frame] =  cmdreg1b_temp;
  126. | DTAG[fsave_frame]     =  dtag_temp;
  127. | ETE15[fsave_frame]    =  ete15_temp;
  128. | ETEMP[fsave_frame]    =  etemp_temp;
  129. |
  130. | /* Make sure that the cmdreg3b dest reg is not going to
  131. |  * be destroyed by a FMOVEM at the end of all this code.
  132. |  * If it is, you should move the current value of the reg
  133. |  * onto the stack so that the reg will loaded with that value.
  134. |  */
  135. |
  136. | /* All done.  Proceed with the code below */
  137. |    }
  138. |
  139. |    if (etemp_exponent == min_sgl)   etemp_exponent = min_dbl;
  140. |    if (etemp_exponent == max_sgl)   etemp_exponent = max_dbl;
  141. |    cmdreg1b[15:10] = 010101;
  142. |    clear(bug_flag_procIDxxxx);
  143. |    FRESTORE and return;
  144. |
  145. |
  146. |    NOFIX:
  147. |    clear(bug_flag_procIDxxxx);
  148. |    FRESTORE and return;
  149. |
  150. | Copyright (C) Motorola, Inc. 1990
  151. | All Rights Reserved
  152. |
  153. | THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA 
  154. | The copyright notice above does not evidence any  
  155. | actual or intended publication of such source code.
  156. |BUGFIX    idnt    2,1 | Motorola 040 Floating Point Software Package
  157. |section 8
  158. .include "fpsp.h"
  159. |xref fpsp_fmt_error
  160. .global b1238_fix
  161. b1238_fix:
  162. |
  163. | This code is entered only on completion of the handling of an 
  164. | nu-generated ovfl, unfl, or inex exception.  If the version 
  165. | number of the fsave is not $40, this handler is not necessary.
  166. | Simply branch to fix_done and exit normally.
  167. |
  168. cmpib #VER_40,4(%a7)
  169. bne fix_done
  170. |
  171. | Test for cu_savepc equal to zero.  If not, this is not a bug
  172. | #1238 case.
  173. |
  174. moveb CU_SAVEPC(%a6),%d0
  175. andib #0xFE,%d0
  176. beq  fix_done |if zero, this is not bug #1238
  177. |
  178. | Test the register conflict aspect.  If opclass0, check for
  179. | cu src equal to xu dest or equal to nu dest.  If so, go to 
  180. | op0.  Else, or if opclass2, check for cu dest equal to
  181. | xu dest or equal to nu dest.  If so, go to tst_opcl.  Else,
  182. | exit, it is not the bug case.
  183. |
  184. | Check for opclass 0.  If not, go and check for opclass 2 and sgl.
  185. |
  186. movew CMDREG1B(%a6),%d0
  187. andiw #0xE000,%d0 |strip all but opclass
  188. bne op2sgl |not opclass 0, check op2
  189. |
  190. | Check for cu and nu register conflict.  If one exists, this takes
  191. | priority over a cu and xu conflict. 
  192. |
  193. bfextu CMDREG1B(%a6){#3:#3},%d0 |get 1st src 
  194. bfextu CMDREG3B(%a6){#6:#3},%d1 |get 3rd dest
  195. cmpb %d0,%d1
  196. beqs op0 |if equal, continue bugfix
  197. |
  198. | Check for cu dest equal to nu dest.  If so, go and fix the 
  199. | bug condition.  Otherwise, exit.
  200. |
  201. bfextu CMDREG1B(%a6){#6:#3},%d0 |get 1st dest 
  202. cmpb %d0,%d1 |cmp 1st dest with 3rd dest
  203. beqs op0 |if equal, continue bugfix
  204. |
  205. | Check for cu and xu register conflict.
  206. |
  207. bfextu CMDREG2B(%a6){#6:#3},%d1 |get 2nd dest
  208. cmpb %d0,%d1 |cmp 1st dest with 2nd dest
  209. beqs op0_xu |if equal, continue bugfix
  210. bfextu CMDREG1B(%a6){#3:#3},%d0 |get 1st src 
  211. cmpb %d0,%d1 |cmp 1st src with 2nd dest
  212. beq op0_xu
  213. bne fix_done |if the reg checks fail, exit
  214. |
  215. | We have the opclass 0 situation.
  216. |
  217. op0:
  218. bfextu CMDREG1B(%a6){#3:#3},%d0 |get source register no
  219. movel #7,%d1
  220. subl %d0,%d1
  221. clrl %d0
  222. bsetl %d1,%d0
  223. fmovemx %d0,ETEMP(%a6) |load source to ETEMP
  224. moveb #0x12,%d0
  225. bfins %d0,CMDREG1B(%a6){#0:#6} |opclass 2, extended
  226. |
  227. | Set ETEMP exponent bit 15 as the opposite of ete14
  228. |
  229. btst #6,ETEMP_EX(%a6) |check etemp exponent bit 14
  230. beq setete15
  231. bclr #etemp15_bit,STAG(%a6)
  232. bra finish
  233. setete15:
  234. bset #etemp15_bit,STAG(%a6)
  235. bra finish
  236. |
  237. | We have the case in which a conflict exists between the cu src or
  238. | dest and the dest of the xu.  We must clear the instruction in 
  239. | the cu and restore the state, allowing the instruction in the
  240. | xu to complete.  Remember, the instruction in the nu
  241. | was exceptional, and was completed by the appropriate handler.
  242. | If the result of the xu instruction is not exceptional, we can
  243. | restore the instruction from the cu to the frame and continue
  244. | processing the original exception.  If the result is also
  245. | exceptional, we choose to kill the process.
  246. |
  247. | Items saved from the stack:
  248. |
  249. | $3c stag     - L_SCR1
  250. | $40 cmdreg1b - L_SCR2
  251. | $44 dtag     - L_SCR3
  252. |
  253. | The cu savepc is set to zero, and the frame is restored to the
  254. | fpu.
  255. |
  256. op0_xu:
  257. movel STAG(%a6),L_SCR1(%a6)
  258. movel CMDREG1B(%a6),L_SCR2(%a6)
  259. movel DTAG(%a6),L_SCR3(%a6)
  260. andil #0xe0000000,L_SCR3(%a6)
  261. moveb #0,CU_SAVEPC(%a6)
  262. movel (%a7)+,%d1 |save return address from bsr
  263. frestore (%a7)+
  264. fsave -(%a7)
  265. |
  266. | Check if the instruction which just completed was exceptional.
  267. cmpw #0x4060,(%a7)
  268. beq op0_xb
  269. | It is necessary to isolate the result of the instruction in the
  270. | xu if it is to fp0 - fp3 and write that value to the USER_FPn
  271. | locations on the stack.  The correct destination register is in 
  272. | cmdreg2b.
  273. |
  274. bfextu CMDREG2B(%a6){#6:#3},%d0 |get dest register no
  275. cmpil #3,%d0
  276. bgts op0_xi
  277. beqs op0_fp3
  278. cmpil #1,%d0
  279. blts op0_fp0
  280. beqs op0_fp1
  281. op0_fp2:
  282. fmovemx %fp2-%fp2,USER_FP2(%a6)
  283. bras op0_xi
  284. op0_fp1:
  285. fmovemx %fp1-%fp1,USER_FP1(%a6)
  286. bras op0_xi
  287. op0_fp0:
  288. fmovemx %fp0-%fp0,USER_FP0(%a6)
  289. bras op0_xi
  290. op0_fp3:
  291. fmovemx %fp3-%fp3,USER_FP3(%a6)
  292. |
  293. | The frame returned is idle.  We must build a busy frame to hold
  294. | the cu state information and setup etemp.
  295. |
  296. op0_xi:
  297. movel #22,%d0 |clear 23 lwords
  298. clrl (%a7)
  299. op0_loop:
  300. clrl -(%a7)
  301. dbf %d0,op0_loop
  302. movel #0x40600000,-(%a7)
  303. movel L_SCR1(%a6),STAG(%a6)
  304. movel L_SCR2(%a6),CMDREG1B(%a6)
  305. movel L_SCR3(%a6),DTAG(%a6)
  306. moveb #0x6,CU_SAVEPC(%a6)
  307. movel %d1,-(%a7) |return bsr return address
  308. bfextu CMDREG1B(%a6){#3:#3},%d0 |get source register no
  309. movel #7,%d1
  310. subl %d0,%d1
  311. clrl %d0
  312. bsetl %d1,%d0
  313. fmovemx %d0,ETEMP(%a6) |load source to ETEMP
  314. moveb #0x12,%d0
  315. bfins %d0,CMDREG1B(%a6){#0:#6} |opclass 2, extended
  316. |
  317. | Set ETEMP exponent bit 15 as the opposite of ete14
  318. |
  319. btst #6,ETEMP_EX(%a6) |check etemp exponent bit 14
  320. beq op0_sete15
  321. bclr #etemp15_bit,STAG(%a6)
  322. bra finish
  323. op0_sete15:
  324. bset #etemp15_bit,STAG(%a6)
  325. bra finish
  326. |
  327. | The frame returned is busy.  It is not possible to reconstruct
  328. | the code sequence to allow completion.  We will jump to 
  329. | fpsp_fmt_error and allow the kernel to kill the process.
  330. |
  331. op0_xb:
  332. jmp fpsp_fmt_error
  333. |
  334. | Check for opclass 2 and single size.  If not both, exit.
  335. |
  336. op2sgl:
  337. movew CMDREG1B(%a6),%d0
  338. andiw #0xFC00,%d0 |strip all but opclass and size
  339. cmpiw #0x4400,%d0 |test for opclass 2 and size=sgl
  340. bne fix_done |if not, it is not bug 1238
  341. |
  342. | Check for cu dest equal to nu dest or equal to xu dest, with 
  343. | a cu and nu conflict taking priority an nu conflict.  If either,
  344. | go and fix the bug condition.  Otherwise, exit.
  345. |
  346. bfextu CMDREG1B(%a6){#6:#3},%d0 |get 1st dest 
  347. bfextu CMDREG3B(%a6){#6:#3},%d1 |get 3rd dest
  348. cmpb %d0,%d1 |cmp 1st dest with 3rd dest
  349. beq op2_com |if equal, continue bugfix
  350. bfextu CMDREG2B(%a6){#6:#3},%d1 |get 2nd dest 
  351. cmpb %d0,%d1 |cmp 1st dest with 2nd dest
  352. bne fix_done |if the reg checks fail, exit
  353. |
  354. | We have the case in which a conflict exists between the cu src or
  355. | dest and the dest of the xu.  We must clear the instruction in 
  356. | the cu and restore the state, allowing the instruction in the
  357. | xu to complete.  Remember, the instruction in the nu
  358. | was exceptional, and was completed by the appropriate handler.
  359. | If the result of the xu instruction is not exceptional, we can
  360. | restore the instruction from the cu to the frame and continue
  361. | processing the original exception.  If the result is also
  362. | exceptional, we choose to kill the process.
  363. |
  364. | Items saved from the stack:
  365. |
  366. | $3c stag     - L_SCR1
  367. | $40 cmdreg1b - L_SCR2
  368. | $44 dtag     - L_SCR3
  369. | etemp        - FP_SCR2
  370. |
  371. | The cu savepc is set to zero, and the frame is restored to the
  372. | fpu.
  373. |
  374. op2_xu:
  375. movel STAG(%a6),L_SCR1(%a6)
  376. movel CMDREG1B(%a6),L_SCR2(%a6)
  377. movel DTAG(%a6),L_SCR3(%a6)
  378. andil #0xe0000000,L_SCR3(%a6)
  379. moveb #0,CU_SAVEPC(%a6)
  380. movel ETEMP(%a6),FP_SCR2(%a6)
  381. movel ETEMP_HI(%a6),FP_SCR2+4(%a6)
  382. movel ETEMP_LO(%a6),FP_SCR2+8(%a6)
  383. movel (%a7)+,%d1 |save return address from bsr
  384. frestore (%a7)+
  385. fsave -(%a7)
  386. |
  387. | Check if the instruction which just completed was exceptional.
  388. cmpw #0x4060,(%a7)
  389. beq op2_xb
  390. | It is necessary to isolate the result of the instruction in the
  391. | xu if it is to fp0 - fp3 and write that value to the USER_FPn
  392. | locations on the stack.  The correct destination register is in 
  393. | cmdreg2b.
  394. |
  395. bfextu CMDREG2B(%a6){#6:#3},%d0 |get dest register no
  396. cmpil #3,%d0
  397. bgts op2_xi
  398. beqs op2_fp3
  399. cmpil #1,%d0
  400. blts op2_fp0
  401. beqs op2_fp1
  402. op2_fp2:
  403. fmovemx %fp2-%fp2,USER_FP2(%a6)
  404. bras op2_xi
  405. op2_fp1:
  406. fmovemx %fp1-%fp1,USER_FP1(%a6)
  407. bras op2_xi
  408. op2_fp0:
  409. fmovemx %fp0-%fp0,USER_FP0(%a6)
  410. bras op2_xi
  411. op2_fp3:
  412. fmovemx %fp3-%fp3,USER_FP3(%a6)
  413. |
  414. | The frame returned is idle.  We must build a busy frame to hold
  415. | the cu state information and fix up etemp.
  416. |
  417. op2_xi:
  418. movel #22,%d0 |clear 23 lwords
  419. clrl (%a7)
  420. op2_loop:
  421. clrl -(%a7)
  422. dbf %d0,op2_loop
  423. movel #0x40600000,-(%a7)
  424. movel L_SCR1(%a6),STAG(%a6)
  425. movel L_SCR2(%a6),CMDREG1B(%a6)
  426. movel L_SCR3(%a6),DTAG(%a6)
  427. moveb #0x6,CU_SAVEPC(%a6)
  428. movel FP_SCR2(%a6),ETEMP(%a6)
  429. movel FP_SCR2+4(%a6),ETEMP_HI(%a6)
  430. movel FP_SCR2+8(%a6),ETEMP_LO(%a6)
  431. movel %d1,-(%a7)
  432. bra op2_com
  433. |
  434. | We have the opclass 2 single source situation.
  435. |
  436. op2_com:
  437. moveb #0x15,%d0
  438. bfins %d0,CMDREG1B(%a6){#0:#6} |opclass 2, double
  439. cmpw #0x407F,ETEMP_EX(%a6) |single +max
  440. bnes case2
  441. movew #0x43FF,ETEMP_EX(%a6) |to double +max
  442. bra finish
  443. case2:
  444. cmpw #0xC07F,ETEMP_EX(%a6) |single -max
  445. bnes case3
  446. movew #0xC3FF,ETEMP_EX(%a6) |to double -max
  447. bra finish
  448. case3:
  449. cmpw #0x3F80,ETEMP_EX(%a6) |single +min
  450. bnes case4
  451. movew #0x3C00,ETEMP_EX(%a6) |to double +min
  452. bra finish
  453. case4:
  454. cmpw #0xBF80,ETEMP_EX(%a6) |single -min
  455. bne fix_done
  456. movew #0xBC00,ETEMP_EX(%a6) |to double -min
  457. bra finish
  458. |
  459. | The frame returned is busy.  It is not possible to reconstruct
  460. | the code sequence to allow completion.  fpsp_fmt_error causes
  461. | an fline illegal instruction to be executed.
  462. |
  463. | You should replace the jump to fpsp_fmt_error with a jump
  464. | to the entry point used to kill a process. 
  465. |
  466. op2_xb:
  467. jmp fpsp_fmt_error
  468. |
  469. | Enter here if the case is not of the situations affected by
  470. | bug #1238, or if the fix is completed, and exit.
  471. |
  472. finish:
  473. fix_done:
  474. rts
  475. |end