bugfix.s
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:14k
源码类别:

VxWorks

开发平台:

C/C++

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