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

嵌入式Linux

开发平台:

Unix_Linux

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