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

VxWorks

开发平台:

C/C++

  1. /* gen_except.s - Motorola 68040 FP exception detection (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. 01g,21jul93,kdl  added .text (SPR #2372).
  10. 01f,23aug92,jcf  changed bxxx to jxx.
  11. 01e,20aug92,kdl  put in changes from Motorola v3.7 (from FPSP 2.2):
  12.  added workaround for hardware bug #1384.
  13. 01d,26may92,rrr  the tree shuffle
  14. 01c,10jan92,kdl  added modification history; general cleanup.
  15. 01b,16dec91,kdl  put in changes from Motorola v3.6 (from FPSP 2.1):
  16.  add translation of CMDREG1B to CMDREG3B; add check
  17.  for new version number in unimp frame.
  18. 01a,15aug91,kdl  original version, from Motorola FPSP v2.0; added
  19.  missing comment symbols.
  20. */
  21. /*
  22. DESCRIPTION
  23. gen_exceptsa 3.4 4/26/91
  24. __x_gen_except --- FPSP routine to detect reportable exceptions
  25. This routine compares the exception enable byte of the
  26. user_fpcr on the stack with the exception status byte
  27. of the user_fpsr.
  28. Any routine which may report an exceptions must load
  29. the stack frame in memory with the exceptional operand(s).
  30. Priority for exceptions is:
  31. Highest: bsun
  32. snan
  33. operr
  34. ovfl
  35. unfl
  36. dz
  37. inex2
  38. Lowest: inex1
  39. Note: The IEEE standard specifies that inex2 is to be
  40. reported if ovfl occurs and the ovfl enable bit is not
  41. set but the inex2 enable bit is.
  42. Copyright (C) Motorola, Inc. 1990
  43. All Rights Reserved
  44. THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
  45. The copyright notice above does not evidence any
  46. actual or intended publication of such source code.
  47. GEN_EXCEPT    idnt    2,1 Motorola 040 Floating Point Software Package
  48. section 8
  49. NOMANUAL
  50. */
  51. #include "fpsp040E.h"
  52. | xref __x_real_trace
  53. | xref __x_fpsp_done
  54. | xref __x_fpsp_fmt_error
  55. exc_tbl:
  56. .long __x_bsun_exc
  57. .long commonE1
  58. .long commonE1
  59. .long __x_ovfl_unfl
  60. .long __x_ovfl_unfl
  61. .long commonE1
  62. .long commonE3
  63. .long commonE3
  64. .long no_match
  65. .globl __x_gen_except
  66. .text
  67. __x_gen_except:
  68. cmpib #IDLE_SIZE-4,a7@(1) | test for idle frame
  69. jeq  do_check | go handle idle frame
  70. cmpib #UNIMP_40_SIZE-4,a7@(1) | test for orig unimp frame
  71. jeq  unimp_x | go handle unimp frame
  72. cmpib #UNIMP_41_SIZE-4,a7@(1) | test for rev unimp frame
  73. jeq  unimp_x | go handle unimp frame
  74. cmpib #BUSY_SIZE-4,a7@(1) | if size <> 0x60, fmt error
  75. jne  __x_fpsp_fmt_error
  76. lea a7@(BUSY_SIZE+LOCAL_SIZE),a1 | init a1 so fpsp040E.h
  77. | | equates will work
  78. | Fix up the new busy frame with entries from the unimp frame
  79. |
  80. movel a6@(ETEMP_EX),a1@(ETEMP_EX)  | copy etemp from unimp
  81. movel a6@(ETEMP_HI),a1@(ETEMP_HI)  | frame to busy frame
  82. movel a6@(ETEMP_LO),a1@(ETEMP_LO)
  83. movel a6@(CMDREG1B),a1@(CMDREG1B)  | set inst in frame to unimp
  84. movel a6@(CMDREG1B),d0 | fix cmd1b to make it
  85. andl #0x03c30000,d0 | work for cmd3b
  86. bfextu a6@(CMDREG1B){#13:#1},d1 | extract bit 2
  87. lsll #5,d1
  88. swap d1
  89. orl d1,d0 | put it in the right place
  90. bfextu a6@(CMDREG1B){#10:#3},d1 | extract bit 3,4,5
  91. lsll #2,d1
  92. swap d1
  93. orl d1,d0 | put them in the right place
  94. movel d0,a1@(CMDREG3B) | in the busy frame
  95. |
  96. | Or in the FPSR from the emulation with the USER_FPSR on the stack.
  97. |
  98. fmovel FPSR,d0
  99. orl d0,a6@(USER_FPSR)
  100. movel a6@(USER_FPSR),a1@(FPSR_SHADOW) | set exc bits
  101. orl #sx_mask,a1@(E_BYTE)
  102. jra  do_clean
  103. |
  104. | Frame is an unimp frame possible resulting from an fmovel <ea>,fp0
  105. | that caused an exception
  106. |
  107. | a1 is modified to point into the new frame allowing fpsp equates
  108. | to be valid.
  109. |
  110. unimp_x:
  111. cmpib #UNIMP_40_SIZE-4,a7@(1) | test for orig unimp frame
  112. jne  test_rev
  113. lea a7@(UNIMP_40_SIZE+LOCAL_SIZE),a1
  114. jra  unimp_con
  115. test_rev:
  116. cmpib #UNIMP_41_SIZE-4,a7@(1) | test for rev unimp frame
  117. jne  __x_fpsp_fmt_error | if not 0x28 or 0x30
  118. lea a7@(UNIMP_41_SIZE+LOCAL_SIZE),a1
  119. unimp_con:
  120. |
  121. | Fix up the new unimp frame with entries from the old unimp frame
  122. |
  123. movel a6@(CMDREG1B),a1@(CMDREG1B)  | set inst in frame to unimp
  124. |
  125. | Or in the FPSR from the emulation with the USER_FPSR on the stack.
  126. |
  127. fmovel FPSR,d0
  128. orl d0,a6@(USER_FPSR)
  129. jra  do_clean
  130. |
  131. | Frame is idle, so check for exceptions reported through
  132. | USER_FPSR and set the unimp frame accordingly.
  133. | A7 must be incremented to the point before the
  134. | idle fsave vector to the unimp vector.
  135. |
  136. do_check:
  137. addl #4,a7 | point a7 back to unimp frame
  138. |
  139. | Or in the FPSR from the emulation with the USER_FPSR on the stack.
  140. |
  141. fmovel FPSR,d0
  142. orl d0,a6@(USER_FPSR)
  143. |
  144. | On a busy frame, we must clear the nmnexc bits.
  145. |
  146. cmpib #BUSY_SIZE-4,a7@(1) | check frame type
  147. jne  check_fr | if busy, clr nmnexc
  148. clrw a6@(NMNEXC) | clr nmnexc # nmcexc
  149. btst #5,a6@(CMDREG1B) | test for fmovel out
  150. jne  frame_com
  151. movel a6@(USER_FPSR),a6@(FPSR_SHADOW) | set exc bits
  152. orl #sx_mask,a6@(E_BYTE)
  153. jra  frame_com
  154. check_fr:
  155. cmpb #UNIMP_40_SIZE-4,a7@(1)
  156. jeq  frame_com
  157. clrw a6@(NMNEXC)
  158. frame_com:
  159. moveb a6@(fpcr_ENABLE),d0 | get fpcr enable byte
  160. andb a6@(FPSR_EXCEPT),d0 | and in the fpsr exc byte
  161. bfffo d0{#24:#8},d1 | test for first set bit
  162. lea exc_tbl,a0 | load jmp table address
  163. subib #24,d1 | normalize bit offset to 0-8
  164. movel a0@(d1:w:4),a0 | load routine address based
  165. | | based on first enabled exc
  166. jmp a0@ | jump to routine
  167. |
  168. | Bsun is not possible in unimp or unsupp
  169. |
  170. __x_bsun_exc:
  171. jra  do_clean
  172. |
  173. | The typical work to be done to the unimp frame to report an
  174. | exception is to set the E1/E3 byte and clr the U flag.
  175. | commonE1 does this for E1 exceptions, which are snan,
  176. | operr, and dz.  commonE3 does this for E3 exceptions, which
  177. | are inex2 and inex1, and also clears the E1 exception bit
  178. | left over from the unimp exception.
  179. |
  180. commonE1:
  181. bset #E1,a6@(E_BYTE) | set E1 flag
  182. jra  commonE | go clean and exit
  183. commonE3:
  184. tstb a6@(UFLG_TMP) | test flag for unsup/unimp state
  185. jne  unsE3
  186. uniE3:
  187. bset #E3,a6@(E_BYTE) | set E3 flag
  188. bclr #E1,a6@(E_BYTE) | clr E1 from unimp
  189. jra  commonE
  190. unsE3:
  191. tstb a6@(RES_FLG)
  192. jne  unsE3_0
  193. unsE3_1:
  194. bset #E3,a6@(E_BYTE) | set E3 flag
  195. unsE3_0:
  196. bclr #E1,a6@(E_BYTE) | clr E1 flag
  197. movel a6@(CMDREG1B),d0
  198. andl #0x03c30000,d0 | work for cmd3b
  199. bfextu a6@(CMDREG1B){#13:#1},d1 | extract bit 2
  200. lsll #5,d1
  201. swap d1
  202. orl d1,d0 | put it in the right place
  203. bfextu a6@(CMDREG1B){#10:#3},d1 | extract bit 3,4,5
  204. lsll #2,d1
  205. swap d1
  206. orl d1,d0 | put them in the right place
  207. movel d0,a6@(CMDREG3B) | in the busy frame
  208. commonE:
  209. bclr #UFLAG,a6@(T_BYTE) | clr U flag from unimp
  210. jra  do_clean | go clean and exit
  211. |
  212. | No bits in the enable byte match existing exceptions.  Check for
  213. | the case of the ovfl exc without the ovfl enabled, but with
  214. | inex2 enabled.
  215. |
  216. no_match:
  217. btst #__x_inex2_bit,a6@(fpcr_ENABLE) | check for ovfl/inex2 case
  218. jeq  no_exc | if clear, exit
  219. btst #__x_ovfl_bit,a6@(FPSR_EXCEPT)  | now check ovfl
  220. jeq  no_exc | if clear, exit
  221. jra  __x_ovfl_unfl | go to __x_unfl_ovfl to determine if
  222. | | it is an unsupp or unimp exc
  223. | No exceptions are to be reported.  If the instruction was
  224. | unimplemented, no FPU restore is necessary.  If it was
  225. | unsupported, we must perform the restore.
  226. no_exc:
  227. tstb a6@(UFLG_TMP) | test flag for unsupp/unimp state
  228. jeq  uni_no_exc
  229. uns_no_exc:
  230. tstb a6@(RES_FLG) | check if frestore is needed
  231. jne  do_clean  | if clear, no frestore needed
  232. uni_no_exc:
  233. moveml a6@(USER_DA),d0-d1/a0-a1
  234. fmovemx a6@(USER_FP0),fp0-fp3
  235. fmoveml a6@(USER_FPCR),fpcr/fpsr/fpi
  236. unlk a6
  237. jra  finish_up
  238. |
  239. | Unsupported Data Type Handler:
  240. | Ovfl:
  241. |   An fmoveout that results in an overflow is reported this way.
  242. | Unfl:
  243. |   An fmoveout that results in an underflow is reported this way.
  244. |
  245. | Unimplemented Instruction Handler:
  246. | Ovfl:
  247. |   Only scosh, setox, ssinh, stwotox, and scale can set overflow in
  248. |   this manner.
  249. | Unfl:
  250. |   Stwotox, setox, and scale can set underflow in this manner.
  251. |   Any of the other Library Routines such that f(x)=x in which
  252. |   x is an extended denorm can report an underflow exception.
  253. |   It is the responsibility of the exception-causing exception
  254. |   to make sure that WBTEMP is correct.
  255. |
  256. |   The exceptional operand is in FP_SCR1.
  257. |
  258. __x_ovfl_unfl:
  259. tstb a6@(UFLG_TMP) | test flag for unsupp/unimp state
  260. jeq  ofuf_con
  261. |
  262. | The caller was from an unsupported data type trap.  Test if the
  263. | caller set CU_ONLY.  If so, the exceptional operand is expected in
  264. | FPTEMP, rather than WBTEMP.
  265. |
  266. tstb a6@(CU_ONLY) | test if inst is cu-only
  267. jeq  unsE3
  268. | movew #0xfe,a6@(CU_SAVEPC)
  269. clrb a6@(CU_SAVEPC)
  270. bset #E1,a6@(E_BYTE) | set E1 exception flag
  271. movew a6@(ETEMP_EX),a6@(FPTEMP_EX)
  272. movel a6@(ETEMP_HI),a6@(FPTEMP_HI)
  273. movel a6@(ETEMP_LO),a6@(FPTEMP_LO)
  274. bset #fptemp15_bit,a6@(DTAG) | set fpte15
  275. bclr #UFLAG,a6@(T_BYTE) | clr U flag from unimp
  276. jra  do_clean | go clean and exit
  277. ofuf_con:
  278. moveb a7@,a6@(VER_TMP) | save version number
  279. cmpib #BUSY_SIZE-4,a7@(1) | check for busy frame
  280. jeq  busy_fr | if unimp, grow to busy
  281. cmpib #VER_40,a7@ | test for orig unimp frame
  282. jne  try_41 | if not, test for rev frame
  283. moveql #13,d0 | need to zero 14 lwords
  284. jra  ofuf_fin
  285. try_41:
  286. cmpib #VER_41,a7@ | test for rev unimp frame
  287. jne  __x_fpsp_fmt_error | if neither, exit with error
  288. moveql #11,d0 | need to zero 12 lwords
  289. ofuf_fin:
  290. clrl a7@
  291. loop1:
  292. clrl a7@- | clear and dec a7
  293. dbra d0,loop1
  294. moveb a6@(VER_TMP),a7@
  295. moveb #BUSY_SIZE-4,a7@(1) | write busy fmt word.
  296. busy_fr:
  297. movel a6@(FP_SCR1),a6@(WBTEMP_EX) | write
  298. movel a6@(FP_SCR1+4),a6@(WBTEMP_HI) | execptional op to
  299. movel a6@(FP_SCR1+8),a6@(WBTEMP_LO) | wbtemp
  300. bset #E3,a6@(E_BYTE) | set E3 flag
  301. bclr #E1,a6@(E_BYTE) | make sure E1 is clear
  302. bclr #UFLAG,a6@(T_BYTE) | clr U flag
  303. movel a6@(USER_FPSR),a6@(FPSR_SHADOW)
  304. orl #sx_mask,a6@(E_BYTE)
  305. movel a6@(CMDREG1B),d0 | fix cmd1b to make it
  306. andl #0x03c30000,d0 | work for cmd3b
  307. bfextu a6@(CMDREG1B){#13:#1},d1 | extract bit 2
  308. lsll #5,d1
  309. swap d1
  310. orl d1,d0 | put it in the right place
  311. bfextu a6@(CMDREG1B){#10:#3},d1 | extract bit 3,4,5
  312. lsll #2,d1
  313. swap d1
  314. orl d1,d0 | put them in the right place
  315. movel d0,a6@(CMDREG3B) | in the busy frame
  316. |
  317. | Check if the frame to be restored is busy or unimp.
  318. |** NOTE *** Bug fix for errata (0d43b #3)
  319. | If the frame is unimp, we must create a busy frame to
  320. | fix the bug with the nmnexc bits in cases in which they
  321. | are set by a previous instruction and not cleared by
  322. | the save. The frame will be unimp only if the final
  323. | instruction in an emulation routine caused the exception
  324. | by doing an fmovel <ea>,fp0.  The exception operand, in
  325. | internal format, is in fptemp.
  326. |
  327. do_clean:
  328. cmpib #UNIMP_40_SIZE-4,a7@(1)
  329. jne  do_con
  330. moveql #13,d0 | in orig, need to zero 14 lwords
  331. jra  do_build
  332. do_con:
  333. cmpib #UNIMP_41_SIZE-4,a7@(1)
  334. jne  do_restore | frame must be busy
  335. moveql #11,d0 | in rev, need to zero 12 lwords
  336. do_build:
  337. moveb a7@,a6@(VER_TMP)
  338. clrl a7@
  339. loop2:
  340. clrl a7@- | clear and dec a7
  341. dbra d0,loop2
  342. |
  343. | Use a1 as pointer into new frame.  a6 is not correct if an unimp or
  344. | busy frame was created as the result of an exception on the final
  345. | instruction of an emulation routine.
  346. |
  347. | We need to set the nmcexc bits if the exception is E1. Otherwise,
  348. | the exc taken will be inex2.
  349. |
  350. lea a7@(BUSY_SIZE+LOCAL_SIZE),a1 | init a1 for new frame
  351. moveb a6@(VER_TMP),a7@ | write busy fmt word
  352. moveb #BUSY_SIZE-4,a7@(1)
  353. movel a6@(FP_SCR1),a1@(WBTEMP_EX)  | write
  354. movel a6@(FP_SCR1+4),a1@(WBTEMP_HI) | exceptional op to
  355. movel a6@(FP_SCR1+8),a1@(WBTEMP_LO) | wbtemp
  356. | btst #E1,a1@(E_BYTE)
  357. | jeq  do_restore
  358. bfextu a6@(USER_FPSR){#17:#4},d0 | get snan/operr/ovfl/unfl bits
  359. bfins d0,a1@(NMCEXC){#4:#4} | and insert them in nmcexc
  360. movel a6@(USER_FPSR),a1@(FPSR_SHADOW) | set exc bits
  361. orl #sx_mask,a1@(E_BYTE)
  362. do_restore:
  363. moveml a6@(USER_DA),d0-d1/a0-a1
  364. fmovemx a6@(USER_FP0),fp0-fp3
  365. fmoveml a6@(USER_FPCR),fpcr/fpsr/fpi
  366. frestore a7@+
  367. tstb a6@(RES_FLG) | RES_FLG indicates a "continuation" frame
  368. jeq  cont
  369. bsrl bug1384
  370. cont:
  371. unlk a6
  372. |
  373. | If trace mode enabled, then go to trace handler.  This handler
  374. /* | cannot have any fp instructions.  If there are fp inst's and an  */
  375. | exception has been restored into the machine then the exception
  376. | will occur upon execution of the fp inst.  This is not desirable
  377. | in the kernel (supervisor mode).  See MC68040 manual Section 9.3.8.
  378. |
  379. finish_up:
  380. btst #7,a7@ | test T1 in SR
  381. jne  g_trace
  382. btst #6,a7@ | test T0 in SR
  383. jne  g_trace
  384. jra  __x_fpsp_done
  385. |
  386. | Change integer stack to look like trace stack
  387. | The address of the instruction that caused the
  388. | exception is already in the integer stack (is
  389. | the same as the saved friar)
  390. |
  391. | If the current frame is already a 6-word stack then all
  392. | that needs to be done is to change the vector# to TRACE.
  393. | If the frame is only a 4-word stack (meaning we got here
  394. | on an Unsupported data type exception), then we need to grow
  395. | the stack an extra 2 words and get the fpi from the FPU.
  396. |
  397. g_trace:
  398. bftst a7@(EXC_VEC-4){#0:#4}
  399. jne  g_easy
  400. subw #4,sp |  make room
  401. movel a7@(4),a7@
  402. movel a7@(8),a7@(4)
  403. subw #BUSY_SIZE,sp
  404. fsave a7@
  405. fmovel fpi,a7@(BUSY_SIZE+EXC_EA-4)
  406. frestore a7@
  407. addw #BUSY_SIZE,sp
  408. g_easy:
  409. movew #TRACE_VEC,a7@(EXC_VEC-4)
  410. jra  __x_real_trace
  411. |
  412. |
  413. |  This is a work-around for hardware bug 1384.
  414. |
  415. bug1384:
  416. link a5,#0
  417. fsave a7@-
  418. cmpib #0x41,a7@ |  check for correct frame
  419. jeq  frame_41
  420. jgt  nofix |  if more advanced mask, do nada
  421. frame_40:
  422. tstb a7@(1) |  check to see if idle
  423. jne  notidle
  424. idle40:
  425. clrl a7@ |  get rid of old fsave frame
  426.         movel  d1,a6@(USER_D1)  |  save d1
  427. movew #8,d1 |  place unimp frame instead
  428. loop40: clrl a7@-
  429. dbra d1,loop40
  430.         movel  a6@(USER_D1),d1  |  restore d1
  431. movel #0x40280000,a7@-
  432. frestore a7@+
  433. unlk   a5
  434. rts
  435. frame_41:
  436. tstb a7@(1) |  check to see if idle
  437. jne  notidle
  438. idle41:
  439. clrl a7@ |  get rid of old fsave frame
  440.         movel  d1,a6@(USER_D1)  |  save d1
  441. movew #10,d1 |  place unimp frame instead
  442. loop41: clrl a7@-
  443. dbra d1,loop41
  444.         movel  a6@(USER_D1),d1  |  restore d1
  445. movel #0x41300000,a7@-
  446. frestore a7@+
  447. unlk a5
  448. rts
  449. notidle:
  450. bclr #etemp15_bit,a5@(-40) 
  451. frestore a7@+
  452. unlk a5
  453. rts
  454. nofix:
  455. frestore a7@+
  456. unlk a5
  457. rts
  458. | end