bugfix.S 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  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. | For details on the license for this file, please see the
  154. | file, README, in this same directory.
  155. |BUGFIX idnt 2,1 | Motorola 040 Floating Point Software Package
  156. |section 8
  157. #include "fpsp.h"
  158. |xref fpsp_fmt_error
  159. .global b1238_fix
  160. b1238_fix:
  161. |
  162. | This code is entered only on completion of the handling of an
  163. | nu-generated ovfl, unfl, or inex exception. If the version
  164. | number of the fsave is not $40, this handler is not necessary.
  165. | Simply branch to fix_done and exit normally.
  166. |
  167. cmpib #VER_40,4(%a7)
  168. bne fix_done
  169. |
  170. | Test for cu_savepc equal to zero. If not, this is not a bug
  171. | #1238 case.
  172. |
  173. moveb CU_SAVEPC(%a6),%d0
  174. andib #0xFE,%d0
  175. beq fix_done |if zero, this is not bug #1238
  176. |
  177. | Test the register conflict aspect. If opclass0, check for
  178. | cu src equal to xu dest or equal to nu dest. If so, go to
  179. | op0. Else, or if opclass2, check for cu dest equal to
  180. | xu dest or equal to nu dest. If so, go to tst_opcl. Else,
  181. | exit, it is not the bug case.
  182. |
  183. | Check for opclass 0. If not, go and check for opclass 2 and sgl.
  184. |
  185. movew CMDREG1B(%a6),%d0
  186. andiw #0xE000,%d0 |strip all but opclass
  187. bne op2sgl |not opclass 0, check op2
  188. |
  189. | Check for cu and nu register conflict. If one exists, this takes
  190. | priority over a cu and xu conflict.
  191. |
  192. bfextu CMDREG1B(%a6){#3:#3},%d0 |get 1st src
  193. bfextu CMDREG3B(%a6){#6:#3},%d1 |get 3rd dest
  194. cmpb %d0,%d1
  195. beqs op0 |if equal, continue bugfix
  196. |
  197. | Check for cu dest equal to nu dest. If so, go and fix the
  198. | bug condition. Otherwise, exit.
  199. |
  200. bfextu CMDREG1B(%a6){#6:#3},%d0 |get 1st dest
  201. cmpb %d0,%d1 |cmp 1st dest with 3rd dest
  202. beqs op0 |if equal, continue bugfix
  203. |
  204. | Check for cu and xu register conflict.
  205. |
  206. bfextu CMDREG2B(%a6){#6:#3},%d1 |get 2nd dest
  207. cmpb %d0,%d1 |cmp 1st dest with 2nd dest
  208. beqs op0_xu |if equal, continue bugfix
  209. bfextu CMDREG1B(%a6){#3:#3},%d0 |get 1st src
  210. cmpb %d0,%d1 |cmp 1st src with 2nd dest
  211. beq op0_xu
  212. bne fix_done |if the reg checks fail, exit
  213. |
  214. | We have the opclass 0 situation.
  215. |
  216. op0:
  217. bfextu CMDREG1B(%a6){#3:#3},%d0 |get source register no
  218. movel #7,%d1
  219. subl %d0,%d1
  220. clrl %d0
  221. bsetl %d1,%d0
  222. fmovemx %d0,ETEMP(%a6) |load source to ETEMP
  223. moveb #0x12,%d0
  224. bfins %d0,CMDREG1B(%a6){#0:#6} |opclass 2, extended
  225. |
  226. | Set ETEMP exponent bit 15 as the opposite of ete14
  227. |
  228. btst #6,ETEMP_EX(%a6) |check etemp exponent bit 14
  229. beq setete15
  230. bclr #etemp15_bit,STAG(%a6)
  231. bra finish
  232. setete15:
  233. bset #etemp15_bit,STAG(%a6)
  234. bra finish
  235. |
  236. | We have the case in which a conflict exists between the cu src or
  237. | dest and the dest of the xu. We must clear the instruction in
  238. | the cu and restore the state, allowing the instruction in the
  239. | xu to complete. Remember, the instruction in the nu
  240. | was exceptional, and was completed by the appropriate handler.
  241. | If the result of the xu instruction is not exceptional, we can
  242. | restore the instruction from the cu to the frame and continue
  243. | processing the original exception. If the result is also
  244. | exceptional, we choose to kill the process.
  245. |
  246. | Items saved from the stack:
  247. |
  248. | $3c stag - L_SCR1
  249. | $40 cmdreg1b - L_SCR2
  250. | $44 dtag - L_SCR3
  251. |
  252. | The cu savepc is set to zero, and the frame is restored to the
  253. | fpu.
  254. |
  255. op0_xu:
  256. movel STAG(%a6),L_SCR1(%a6)
  257. movel CMDREG1B(%a6),L_SCR2(%a6)
  258. movel DTAG(%a6),L_SCR3(%a6)
  259. andil #0xe0000000,L_SCR3(%a6)
  260. moveb #0,CU_SAVEPC(%a6)
  261. movel (%a7)+,%d1 |save return address from bsr
  262. frestore (%a7)+
  263. fsave -(%a7)
  264. |
  265. | Check if the instruction which just completed was exceptional.
  266. |
  267. cmpw #0x4060,(%a7)
  268. beq op0_xb
  269. |
  270. | It is necessary to isolate the result of the instruction in the
  271. | xu if it is to fp0 - fp3 and write that value to the USER_FPn
  272. | locations on the stack. The correct destination register is in
  273. | cmdreg2b.
  274. |
  275. bfextu CMDREG2B(%a6){#6:#3},%d0 |get dest register no
  276. cmpil #3,%d0
  277. bgts op0_xi
  278. beqs op0_fp3
  279. cmpil #1,%d0
  280. blts op0_fp0
  281. beqs op0_fp1
  282. op0_fp2:
  283. fmovemx %fp2-%fp2,USER_FP2(%a6)
  284. bras op0_xi
  285. op0_fp1:
  286. fmovemx %fp1-%fp1,USER_FP1(%a6)
  287. bras op0_xi
  288. op0_fp0:
  289. fmovemx %fp0-%fp0,USER_FP0(%a6)
  290. bras op0_xi
  291. op0_fp3:
  292. fmovemx %fp3-%fp3,USER_FP3(%a6)
  293. |
  294. | The frame returned is idle. We must build a busy frame to hold
  295. | the cu state information and setup etemp.
  296. |
  297. op0_xi:
  298. movel #22,%d0 |clear 23 lwords
  299. clrl (%a7)
  300. op0_loop:
  301. clrl -(%a7)
  302. dbf %d0,op0_loop
  303. movel #0x40600000,-(%a7)
  304. movel L_SCR1(%a6),STAG(%a6)
  305. movel L_SCR2(%a6),CMDREG1B(%a6)
  306. movel L_SCR3(%a6),DTAG(%a6)
  307. moveb #0x6,CU_SAVEPC(%a6)
  308. movel %d1,-(%a7) |return bsr return address
  309. bfextu CMDREG1B(%a6){#3:#3},%d0 |get source register no
  310. movel #7,%d1
  311. subl %d0,%d1
  312. clrl %d0
  313. bsetl %d1,%d0
  314. fmovemx %d0,ETEMP(%a6) |load source to ETEMP
  315. moveb #0x12,%d0
  316. bfins %d0,CMDREG1B(%a6){#0:#6} |opclass 2, extended
  317. |
  318. | Set ETEMP exponent bit 15 as the opposite of ete14
  319. |
  320. btst #6,ETEMP_EX(%a6) |check etemp exponent bit 14
  321. beq op0_sete15
  322. bclr #etemp15_bit,STAG(%a6)
  323. bra finish
  324. op0_sete15:
  325. bset #etemp15_bit,STAG(%a6)
  326. bra finish
  327. |
  328. | The frame returned is busy. It is not possible to reconstruct
  329. | the code sequence to allow completion. We will jump to
  330. | fpsp_fmt_error and allow the kernel to kill the process.
  331. |
  332. op0_xb:
  333. jmp fpsp_fmt_error
  334. |
  335. | Check for opclass 2 and single size. If not both, exit.
  336. |
  337. op2sgl:
  338. movew CMDREG1B(%a6),%d0
  339. andiw #0xFC00,%d0 |strip all but opclass and size
  340. cmpiw #0x4400,%d0 |test for opclass 2 and size=sgl
  341. bne fix_done |if not, it is not bug 1238
  342. |
  343. | Check for cu dest equal to nu dest or equal to xu dest, with
  344. | a cu and nu conflict taking priority an nu conflict. If either,
  345. | go and fix the bug condition. Otherwise, exit.
  346. |
  347. bfextu CMDREG1B(%a6){#6:#3},%d0 |get 1st dest
  348. bfextu CMDREG3B(%a6){#6:#3},%d1 |get 3rd dest
  349. cmpb %d0,%d1 |cmp 1st dest with 3rd dest
  350. beq op2_com |if equal, continue bugfix
  351. bfextu CMDREG2B(%a6){#6:#3},%d1 |get 2nd dest
  352. cmpb %d0,%d1 |cmp 1st dest with 2nd dest
  353. bne fix_done |if the reg checks fail, exit
  354. |
  355. | We have the case in which a conflict exists between the cu src or
  356. | dest and the dest of the xu. We must clear the instruction in
  357. | the cu and restore the state, allowing the instruction in the
  358. | xu to complete. Remember, the instruction in the nu
  359. | was exceptional, and was completed by the appropriate handler.
  360. | If the result of the xu instruction is not exceptional, we can
  361. | restore the instruction from the cu to the frame and continue
  362. | processing the original exception. If the result is also
  363. | exceptional, we choose to kill the process.
  364. |
  365. | Items saved from the stack:
  366. |
  367. | $3c stag - L_SCR1
  368. | $40 cmdreg1b - L_SCR2
  369. | $44 dtag - L_SCR3
  370. | etemp - FP_SCR2
  371. |
  372. | The cu savepc is set to zero, and the frame is restored to the
  373. | fpu.
  374. |
  375. op2_xu:
  376. movel STAG(%a6),L_SCR1(%a6)
  377. movel CMDREG1B(%a6),L_SCR2(%a6)
  378. movel DTAG(%a6),L_SCR3(%a6)
  379. andil #0xe0000000,L_SCR3(%a6)
  380. moveb #0,CU_SAVEPC(%a6)
  381. movel ETEMP(%a6),FP_SCR2(%a6)
  382. movel ETEMP_HI(%a6),FP_SCR2+4(%a6)
  383. movel ETEMP_LO(%a6),FP_SCR2+8(%a6)
  384. movel (%a7)+,%d1 |save return address from bsr
  385. frestore (%a7)+
  386. fsave -(%a7)
  387. |
  388. | Check if the instruction which just completed was exceptional.
  389. |
  390. cmpw #0x4060,(%a7)
  391. beq op2_xb
  392. |
  393. | It is necessary to isolate the result of the instruction in the
  394. | xu if it is to fp0 - fp3 and write that value to the USER_FPn
  395. | locations on the stack. The correct destination register is in
  396. | cmdreg2b.
  397. |
  398. bfextu CMDREG2B(%a6){#6:#3},%d0 |get dest register no
  399. cmpil #3,%d0
  400. bgts op2_xi
  401. beqs op2_fp3
  402. cmpil #1,%d0
  403. blts op2_fp0
  404. beqs op2_fp1
  405. op2_fp2:
  406. fmovemx %fp2-%fp2,USER_FP2(%a6)
  407. bras op2_xi
  408. op2_fp1:
  409. fmovemx %fp1-%fp1,USER_FP1(%a6)
  410. bras op2_xi
  411. op2_fp0:
  412. fmovemx %fp0-%fp0,USER_FP0(%a6)
  413. bras op2_xi
  414. op2_fp3:
  415. fmovemx %fp3-%fp3,USER_FP3(%a6)
  416. |
  417. | The frame returned is idle. We must build a busy frame to hold
  418. | the cu state information and fix up etemp.
  419. |
  420. op2_xi:
  421. movel #22,%d0 |clear 23 lwords
  422. clrl (%a7)
  423. op2_loop:
  424. clrl -(%a7)
  425. dbf %d0,op2_loop
  426. movel #0x40600000,-(%a7)
  427. movel L_SCR1(%a6),STAG(%a6)
  428. movel L_SCR2(%a6),CMDREG1B(%a6)
  429. movel L_SCR3(%a6),DTAG(%a6)
  430. moveb #0x6,CU_SAVEPC(%a6)
  431. movel FP_SCR2(%a6),ETEMP(%a6)
  432. movel FP_SCR2+4(%a6),ETEMP_HI(%a6)
  433. movel FP_SCR2+8(%a6),ETEMP_LO(%a6)
  434. movel %d1,-(%a7)
  435. bra op2_com
  436. |
  437. | We have the opclass 2 single source situation.
  438. |
  439. op2_com:
  440. moveb #0x15,%d0
  441. bfins %d0,CMDREG1B(%a6){#0:#6} |opclass 2, double
  442. cmpw #0x407F,ETEMP_EX(%a6) |single +max
  443. bnes case2
  444. movew #0x43FF,ETEMP_EX(%a6) |to double +max
  445. bra finish
  446. case2:
  447. cmpw #0xC07F,ETEMP_EX(%a6) |single -max
  448. bnes case3
  449. movew #0xC3FF,ETEMP_EX(%a6) |to double -max
  450. bra finish
  451. case3:
  452. cmpw #0x3F80,ETEMP_EX(%a6) |single +min
  453. bnes case4
  454. movew #0x3C00,ETEMP_EX(%a6) |to double +min
  455. bra finish
  456. case4:
  457. cmpw #0xBF80,ETEMP_EX(%a6) |single -min
  458. bne fix_done
  459. movew #0xBC00,ETEMP_EX(%a6) |to double -min
  460. bra finish
  461. |
  462. | The frame returned is busy. It is not possible to reconstruct
  463. | the code sequence to allow completion. fpsp_fmt_error causes
  464. | an fline illegal instruction to be executed.
  465. |
  466. | You should replace the jump to fpsp_fmt_error with a jump
  467. | to the entry point used to kill a process.
  468. |
  469. op2_xb:
  470. jmp fpsp_fmt_error
  471. |
  472. | Enter here if the case is not of the situations affected by
  473. | bug #1238, or if the fix is completed, and exit.
  474. |
  475. finish:
  476. fix_done:
  477. rts
  478. |end