bugfix.S 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  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. |
  268. cmpw #0x4060,(%a7)
  269. beq op0_xb
  270. |
  271. | It is necessary to isolate the result of the instruction in the
  272. | xu if it is to fp0 - fp3 and write that value to the USER_FPn
  273. | locations on the stack. The correct destination register is in
  274. | cmdreg2b.
  275. |
  276. bfextu CMDREG2B(%a6){#6:#3},%d0 |get dest register no
  277. cmpil #3,%d0
  278. bgts op0_xi
  279. beqs op0_fp3
  280. cmpil #1,%d0
  281. blts op0_fp0
  282. beqs op0_fp1
  283. op0_fp2:
  284. fmovemx %fp2-%fp2,USER_FP2(%a6)
  285. bras op0_xi
  286. op0_fp1:
  287. fmovemx %fp1-%fp1,USER_FP1(%a6)
  288. bras op0_xi
  289. op0_fp0:
  290. fmovemx %fp0-%fp0,USER_FP0(%a6)
  291. bras op0_xi
  292. op0_fp3:
  293. fmovemx %fp3-%fp3,USER_FP3(%a6)
  294. |
  295. | The frame returned is idle. We must build a busy frame to hold
  296. | the cu state information and setup etemp.
  297. |
  298. op0_xi:
  299. movel #22,%d0 |clear 23 lwords
  300. clrl (%a7)
  301. op0_loop:
  302. clrl -(%a7)
  303. dbf %d0,op0_loop
  304. movel #0x40600000,-(%a7)
  305. movel L_SCR1(%a6),STAG(%a6)
  306. movel L_SCR2(%a6),CMDREG1B(%a6)
  307. movel L_SCR3(%a6),DTAG(%a6)
  308. moveb #0x6,CU_SAVEPC(%a6)
  309. movel %d1,-(%a7) |return bsr return address
  310. bfextu CMDREG1B(%a6){#3:#3},%d0 |get source register no
  311. movel #7,%d1
  312. subl %d0,%d1
  313. clrl %d0
  314. bsetl %d1,%d0
  315. fmovemx %d0,ETEMP(%a6) |load source to ETEMP
  316. moveb #0x12,%d0
  317. bfins %d0,CMDREG1B(%a6){#0:#6} |opclass 2, extended
  318. |
  319. | Set ETEMP exponent bit 15 as the opposite of ete14
  320. |
  321. btst #6,ETEMP_EX(%a6) |check etemp exponent bit 14
  322. beq op0_sete15
  323. bclr #etemp15_bit,STAG(%a6)
  324. bra finish
  325. op0_sete15:
  326. bset #etemp15_bit,STAG(%a6)
  327. bra finish
  328. |
  329. | The frame returned is busy. It is not possible to reconstruct
  330. | the code sequence to allow completion. We will jump to
  331. | fpsp_fmt_error and allow the kernel to kill the process.
  332. |
  333. op0_xb:
  334. jmp fpsp_fmt_error
  335. |
  336. | Check for opclass 2 and single size. If not both, exit.
  337. |
  338. op2sgl:
  339. movew CMDREG1B(%a6),%d0
  340. andiw #0xFC00,%d0 |strip all but opclass and size
  341. cmpiw #0x4400,%d0 |test for opclass 2 and size=sgl
  342. bne fix_done |if not, it is not bug 1238
  343. |
  344. | Check for cu dest equal to nu dest or equal to xu dest, with
  345. | a cu and nu conflict taking priority an nu conflict. If either,
  346. | go and fix the bug condition. Otherwise, exit.
  347. |
  348. bfextu CMDREG1B(%a6){#6:#3},%d0 |get 1st dest
  349. bfextu CMDREG3B(%a6){#6:#3},%d1 |get 3rd dest
  350. cmpb %d0,%d1 |cmp 1st dest with 3rd dest
  351. beq op2_com |if equal, continue bugfix
  352. bfextu CMDREG2B(%a6){#6:#3},%d1 |get 2nd dest
  353. cmpb %d0,%d1 |cmp 1st dest with 2nd dest
  354. bne fix_done |if the reg checks fail, exit
  355. |
  356. | We have the case in which a conflict exists between the cu src or
  357. | dest and the dest of the xu. We must clear the instruction in
  358. | the cu and restore the state, allowing the instruction in the
  359. | xu to complete. Remember, the instruction in the nu
  360. | was exceptional, and was completed by the appropriate handler.
  361. | If the result of the xu instruction is not exceptional, we can
  362. | restore the instruction from the cu to the frame and continue
  363. | processing the original exception. If the result is also
  364. | exceptional, we choose to kill the process.
  365. |
  366. | Items saved from the stack:
  367. |
  368. | $3c stag - L_SCR1
  369. | $40 cmdreg1b - L_SCR2
  370. | $44 dtag - L_SCR3
  371. | etemp - FP_SCR2
  372. |
  373. | The cu savepc is set to zero, and the frame is restored to the
  374. | fpu.
  375. |
  376. op2_xu:
  377. movel STAG(%a6),L_SCR1(%a6)
  378. movel CMDREG1B(%a6),L_SCR2(%a6)
  379. movel DTAG(%a6),L_SCR3(%a6)
  380. andil #0xe0000000,L_SCR3(%a6)
  381. moveb #0,CU_SAVEPC(%a6)
  382. movel ETEMP(%a6),FP_SCR2(%a6)
  383. movel ETEMP_HI(%a6),FP_SCR2+4(%a6)
  384. movel ETEMP_LO(%a6),FP_SCR2+8(%a6)
  385. movel (%a7)+,%d1 |save return address from bsr
  386. frestore (%a7)+
  387. fsave -(%a7)
  388. |
  389. | Check if the instruction which just completed was exceptional.
  390. |
  391. cmpw #0x4060,(%a7)
  392. beq op2_xb
  393. |
  394. | It is necessary to isolate the result of the instruction in the
  395. | xu if it is to fp0 - fp3 and write that value to the USER_FPn
  396. | locations on the stack. The correct destination register is in
  397. | cmdreg2b.
  398. |
  399. bfextu CMDREG2B(%a6){#6:#3},%d0 |get dest register no
  400. cmpil #3,%d0
  401. bgts op2_xi
  402. beqs op2_fp3
  403. cmpil #1,%d0
  404. blts op2_fp0
  405. beqs op2_fp1
  406. op2_fp2:
  407. fmovemx %fp2-%fp2,USER_FP2(%a6)
  408. bras op2_xi
  409. op2_fp1:
  410. fmovemx %fp1-%fp1,USER_FP1(%a6)
  411. bras op2_xi
  412. op2_fp0:
  413. fmovemx %fp0-%fp0,USER_FP0(%a6)
  414. bras op2_xi
  415. op2_fp3:
  416. fmovemx %fp3-%fp3,USER_FP3(%a6)
  417. |
  418. | The frame returned is idle. We must build a busy frame to hold
  419. | the cu state information and fix up etemp.
  420. |
  421. op2_xi:
  422. movel #22,%d0 |clear 23 lwords
  423. clrl (%a7)
  424. op2_loop:
  425. clrl -(%a7)
  426. dbf %d0,op2_loop
  427. movel #0x40600000,-(%a7)
  428. movel L_SCR1(%a6),STAG(%a6)
  429. movel L_SCR2(%a6),CMDREG1B(%a6)
  430. movel L_SCR3(%a6),DTAG(%a6)
  431. moveb #0x6,CU_SAVEPC(%a6)
  432. movel FP_SCR2(%a6),ETEMP(%a6)
  433. movel FP_SCR2+4(%a6),ETEMP_HI(%a6)
  434. movel FP_SCR2+8(%a6),ETEMP_LO(%a6)
  435. movel %d1,-(%a7)
  436. bra op2_com
  437. |
  438. | We have the opclass 2 single source situation.
  439. |
  440. op2_com:
  441. moveb #0x15,%d0
  442. bfins %d0,CMDREG1B(%a6){#0:#6} |opclass 2, double
  443. cmpw #0x407F,ETEMP_EX(%a6) |single +max
  444. bnes case2
  445. movew #0x43FF,ETEMP_EX(%a6) |to double +max
  446. bra finish
  447. case2:
  448. cmpw #0xC07F,ETEMP_EX(%a6) |single -max
  449. bnes case3
  450. movew #0xC3FF,ETEMP_EX(%a6) |to double -max
  451. bra finish
  452. case3:
  453. cmpw #0x3F80,ETEMP_EX(%a6) |single +min
  454. bnes case4
  455. movew #0x3C00,ETEMP_EX(%a6) |to double +min
  456. bra finish
  457. case4:
  458. cmpw #0xBF80,ETEMP_EX(%a6) |single -min
  459. bne fix_done
  460. movew #0xBC00,ETEMP_EX(%a6) |to double -min
  461. bra finish
  462. |
  463. | The frame returned is busy. It is not possible to reconstruct
  464. | the code sequence to allow completion. fpsp_fmt_error causes
  465. | an fline illegal instruction to be executed.
  466. |
  467. | You should replace the jump to fpsp_fmt_error with a jump
  468. | to the entry point used to kill a process.
  469. |
  470. op2_xb:
  471. jmp fpsp_fmt_error
  472. |
  473. | Enter here if the case is not of the situations affected by
  474. | bug #1238, or if the fix is completed, and exit.
  475. |
  476. finish:
  477. fix_done:
  478. rts
  479. |end