skeleton.S 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  1. |
  2. | skeleton.sa 3.2 4/26/91
  3. |
  4. | This file contains code that is system dependent and will
  5. | need to be modified to install the FPSP.
  6. |
  7. | Each entry point for exception 'xxxx' begins with a 'jmp fpsp_xxxx'.
  8. | Put any target system specific handling that must be done immediately
  9. | before the jump instruction. If there no handling necessary, then
  10. | the 'fpsp_xxxx' handler entry point should be placed in the exception
  11. | table so that the 'jmp' can be eliminated. If the FPSP determines that the
  12. | exception is one that must be reported then there will be a
  13. | return from the package by a 'jmp real_xxxx'. At that point
  14. | the machine state will be identical to the state before
  15. | the FPSP was entered. In particular, whatever condition
  16. | that caused the exception will still be pending when the FPSP
  17. | package returns. Thus, there will be system specific code
  18. | to handle the exception.
  19. |
  20. | If the exception was completely handled by the package, then
  21. | the return will be via a 'jmp fpsp_done'. Unless there is
  22. | OS specific work to be done (such as handling a context switch or
  23. | interrupt) the user program can be resumed via 'rte'.
  24. |
  25. | In the following skeleton code, some typical 'real_xxxx' handling
  26. | code is shown. This code may need to be moved to an appropriate
  27. | place in the target system, or rewritten.
  28. |
  29. | Copyright (C) Motorola, Inc. 1990
  30. | All Rights Reserved
  31. |
  32. | For details on the license for this file, please see the
  33. | file, README, in this same directory.
  34. |
  35. | Modified for Linux-1.3.x by Jes Sorensen (jds@kom.auc.dk)
  36. |
  37. #include <linux/linkage.h>
  38. #include <asm/entry.h>
  39. #include <asm/asm-offsets.h>
  40. |SKELETON idnt 2,1 | Motorola 040 Floating Point Software Package
  41. |section 15
  42. |
  43. | The following counters are used for standalone testing
  44. |
  45. |section 8
  46. #include "fpsp.h"
  47. |xref b1238_fix
  48. |
  49. | Divide by Zero exception
  50. |
  51. | All dz exceptions are 'real', hence no fpsp_dz entry point.
  52. |
  53. .global dz
  54. .global real_dz
  55. dz:
  56. real_dz:
  57. link %a6,#-LOCAL_SIZE
  58. fsave -(%sp)
  59. bclrb #E1,E_BYTE(%a6)
  60. frestore (%sp)+
  61. unlk %a6
  62. SAVE_ALL_INT
  63. GET_CURRENT(%d0)
  64. movel %sp,%sp@- | stack frame pointer argument
  65. bsrl trap_c
  66. addql #4,%sp
  67. bral ret_from_exception
  68. |
  69. | Inexact exception
  70. |
  71. | All inexact exceptions are real, but the 'real' handler
  72. | will probably want to clear the pending exception.
  73. | The provided code will clear the E3 exception (if pending),
  74. | otherwise clear the E1 exception. The frestore is not really
  75. | necessary for E1 exceptions.
  76. |
  77. | Code following the 'inex' label is to handle bug #1232. In this
  78. | bug, if an E1 snan, ovfl, or unfl occurred, and the process was
  79. | swapped out before taking the exception, the exception taken on
  80. | return was inex, rather than the correct exception. The snan, ovfl,
  81. | and unfl exception to be taken must not have been enabled. The
  82. | fix is to check for E1, and the existence of one of snan, ovfl,
  83. | or unfl bits set in the fpsr. If any of these are set, branch
  84. | to the appropriate handler for the exception in the fpsr. Note
  85. | that this fix is only for d43b parts, and is skipped if the
  86. | version number is not $40.
  87. |
  88. |
  89. .global real_inex
  90. .global inex
  91. inex:
  92. link %a6,#-LOCAL_SIZE
  93. fsave -(%sp)
  94. cmpib #VER_40,(%sp) |test version number
  95. bnes not_fmt40
  96. fmovel %fpsr,-(%sp)
  97. btstb #E1,E_BYTE(%a6) |test for E1 set
  98. beqs not_b1232
  99. btstb #snan_bit,2(%sp) |test for snan
  100. beq inex_ckofl
  101. addl #4,%sp
  102. frestore (%sp)+
  103. unlk %a6
  104. bra snan
  105. inex_ckofl:
  106. btstb #ovfl_bit,2(%sp) |test for ovfl
  107. beq inex_ckufl
  108. addl #4,%sp
  109. frestore (%sp)+
  110. unlk %a6
  111. bra ovfl
  112. inex_ckufl:
  113. btstb #unfl_bit,2(%sp) |test for unfl
  114. beq not_b1232
  115. addl #4,%sp
  116. frestore (%sp)+
  117. unlk %a6
  118. bra unfl
  119. |
  120. | We do not have the bug 1232 case. Clean up the stack and call
  121. | real_inex.
  122. |
  123. not_b1232:
  124. addl #4,%sp
  125. frestore (%sp)+
  126. unlk %a6
  127. real_inex:
  128. link %a6,#-LOCAL_SIZE
  129. fsave -(%sp)
  130. not_fmt40:
  131. bclrb #E3,E_BYTE(%a6) |clear and test E3 flag
  132. beqs inex_cke1
  133. |
  134. | Clear dirty bit on dest resister in the frame before branching
  135. | to b1238_fix.
  136. |
  137. moveml %d0/%d1,USER_DA(%a6)
  138. bfextu CMDREG1B(%a6){#6:#3},%d0 |get dest reg no
  139. bclrb %d0,FPR_DIRTY_BITS(%a6) |clr dest dirty bit
  140. bsrl b1238_fix |test for bug1238 case
  141. moveml USER_DA(%a6),%d0/%d1
  142. bras inex_done
  143. inex_cke1:
  144. bclrb #E1,E_BYTE(%a6)
  145. inex_done:
  146. frestore (%sp)+
  147. unlk %a6
  148. SAVE_ALL_INT
  149. GET_CURRENT(%d0)
  150. movel %sp,%sp@- | stack frame pointer argument
  151. bsrl trap_c
  152. addql #4,%sp
  153. bral ret_from_exception
  154. |
  155. | Overflow exception
  156. |
  157. |xref fpsp_ovfl
  158. .global real_ovfl
  159. .global ovfl
  160. ovfl:
  161. jmp fpsp_ovfl
  162. real_ovfl:
  163. link %a6,#-LOCAL_SIZE
  164. fsave -(%sp)
  165. bclrb #E3,E_BYTE(%a6) |clear and test E3 flag
  166. bnes ovfl_done
  167. bclrb #E1,E_BYTE(%a6)
  168. ovfl_done:
  169. frestore (%sp)+
  170. unlk %a6
  171. SAVE_ALL_INT
  172. GET_CURRENT(%d0)
  173. movel %sp,%sp@- | stack frame pointer argument
  174. bsrl trap_c
  175. addql #4,%sp
  176. bral ret_from_exception
  177. |
  178. | Underflow exception
  179. |
  180. |xref fpsp_unfl
  181. .global real_unfl
  182. .global unfl
  183. unfl:
  184. jmp fpsp_unfl
  185. real_unfl:
  186. link %a6,#-LOCAL_SIZE
  187. fsave -(%sp)
  188. bclrb #E3,E_BYTE(%a6) |clear and test E3 flag
  189. bnes unfl_done
  190. bclrb #E1,E_BYTE(%a6)
  191. unfl_done:
  192. frestore (%sp)+
  193. unlk %a6
  194. SAVE_ALL_INT
  195. GET_CURRENT(%d0)
  196. movel %sp,%sp@- | stack frame pointer argument
  197. bsrl trap_c
  198. addql #4,%sp
  199. bral ret_from_exception
  200. |
  201. | Signalling NAN exception
  202. |
  203. |xref fpsp_snan
  204. .global real_snan
  205. .global snan
  206. snan:
  207. jmp fpsp_snan
  208. real_snan:
  209. link %a6,#-LOCAL_SIZE
  210. fsave -(%sp)
  211. bclrb #E1,E_BYTE(%a6) |snan is always an E1 exception
  212. frestore (%sp)+
  213. unlk %a6
  214. SAVE_ALL_INT
  215. GET_CURRENT(%d0)
  216. movel %sp,%sp@- | stack frame pointer argument
  217. bsrl trap_c
  218. addql #4,%sp
  219. bral ret_from_exception
  220. |
  221. | Operand Error exception
  222. |
  223. |xref fpsp_operr
  224. .global real_operr
  225. .global operr
  226. operr:
  227. jmp fpsp_operr
  228. real_operr:
  229. link %a6,#-LOCAL_SIZE
  230. fsave -(%sp)
  231. bclrb #E1,E_BYTE(%a6) |operr is always an E1 exception
  232. frestore (%sp)+
  233. unlk %a6
  234. SAVE_ALL_INT
  235. GET_CURRENT(%d0)
  236. movel %sp,%sp@- | stack frame pointer argument
  237. bsrl trap_c
  238. addql #4,%sp
  239. bral ret_from_exception
  240. |
  241. | BSUN exception
  242. |
  243. | This sample handler simply clears the nan bit in the FPSR.
  244. |
  245. |xref fpsp_bsun
  246. .global real_bsun
  247. .global bsun
  248. bsun:
  249. jmp fpsp_bsun
  250. real_bsun:
  251. link %a6,#-LOCAL_SIZE
  252. fsave -(%sp)
  253. bclrb #E1,E_BYTE(%a6) |bsun is always an E1 exception
  254. fmovel %FPSR,-(%sp)
  255. bclrb #nan_bit,(%sp)
  256. fmovel (%sp)+,%FPSR
  257. frestore (%sp)+
  258. unlk %a6
  259. SAVE_ALL_INT
  260. GET_CURRENT(%d0)
  261. movel %sp,%sp@- | stack frame pointer argument
  262. bsrl trap_c
  263. addql #4,%sp
  264. bral ret_from_exception
  265. |
  266. | F-line exception
  267. |
  268. | A 'real' F-line exception is one that the FPSP isn't supposed to
  269. | handle. E.g. an instruction with a co-processor ID that is not 1.
  270. |
  271. |
  272. |xref fpsp_fline
  273. .global real_fline
  274. .global fline
  275. fline:
  276. jmp fpsp_fline
  277. real_fline:
  278. SAVE_ALL_INT
  279. GET_CURRENT(%d0)
  280. movel %sp,%sp@- | stack frame pointer argument
  281. bsrl trap_c
  282. addql #4,%sp
  283. bral ret_from_exception
  284. |
  285. | Unsupported data type exception
  286. |
  287. |xref fpsp_unsupp
  288. .global real_unsupp
  289. .global unsupp
  290. unsupp:
  291. jmp fpsp_unsupp
  292. real_unsupp:
  293. link %a6,#-LOCAL_SIZE
  294. fsave -(%sp)
  295. bclrb #E1,E_BYTE(%a6) |unsupp is always an E1 exception
  296. frestore (%sp)+
  297. unlk %a6
  298. SAVE_ALL_INT
  299. GET_CURRENT(%d0)
  300. movel %sp,%sp@- | stack frame pointer argument
  301. bsrl trap_c
  302. addql #4,%sp
  303. bral ret_from_exception
  304. |
  305. | Trace exception
  306. |
  307. .global real_trace
  308. real_trace:
  309. |
  310. bral trap
  311. |
  312. | fpsp_fmt_error --- exit point for frame format error
  313. |
  314. | The fpu stack frame does not match the frames existing
  315. | or planned at the time of this writing. The fpsp is
  316. | unable to handle frame sizes not in the following
  317. | version:size pairs:
  318. |
  319. | {4060, 4160} - busy frame
  320. | {4028, 4130} - unimp frame
  321. | {4000, 4100} - idle frame
  322. |
  323. | This entry point simply holds an f-line illegal value.
  324. | Replace this with a call to your kernel panic code or
  325. | code to handle future revisions of the fpu.
  326. |
  327. .global fpsp_fmt_error
  328. fpsp_fmt_error:
  329. .long 0xf27f0000 |f-line illegal
  330. |
  331. | fpsp_done --- FPSP exit point
  332. |
  333. | The exception has been handled by the package and we are ready
  334. | to return to user mode, but there may be OS specific code
  335. | to execute before we do. If there is, do it now.
  336. |
  337. |
  338. .global fpsp_done
  339. fpsp_done:
  340. btst #0x5,%sp@ | supervisor bit set in saved SR?
  341. beq .Lnotkern
  342. rte
  343. .Lnotkern:
  344. SAVE_ALL_INT
  345. GET_CURRENT(%d0)
  346. | deliver signals, reschedule etc..
  347. jra ret_from_exception
  348. |
  349. | mem_write --- write to user or supervisor address space
  350. |
  351. | Writes to memory while in supervisor mode. copyout accomplishes
  352. | this via a 'moves' instruction. copyout is a UNIX SVR3 (and later) function.
  353. | If you don't have copyout, use the local copy of the function below.
  354. |
  355. | a0 - supervisor source address
  356. | a1 - user destination address
  357. | d0 - number of bytes to write (maximum count is 12)
  358. |
  359. | The supervisor source address is guaranteed to point into the supervisor
  360. | stack. The result is that a UNIX
  361. | process is allowed to sleep as a consequence of a page fault during
  362. | copyout. The probability of a page fault is exceedingly small because
  363. | the 68040 always reads the destination address and thus the page
  364. | faults should have already been handled.
  365. |
  366. | If the EXC_SR shows that the exception was from supervisor space,
  367. | then just do a dumb (and slow) memory move. In a UNIX environment
  368. | there shouldn't be any supervisor mode floating point exceptions.
  369. |
  370. .global mem_write
  371. mem_write:
  372. btstb #5,EXC_SR(%a6) |check for supervisor state
  373. beqs user_write
  374. super_write:
  375. moveb (%a0)+,(%a1)+
  376. subql #1,%d0
  377. bnes super_write
  378. rts
  379. user_write:
  380. movel %d1,-(%sp) |preserve d1 just in case
  381. movel %d0,-(%sp)
  382. movel %a1,-(%sp)
  383. movel %a0,-(%sp)
  384. jsr copyout
  385. addw #12,%sp
  386. movel (%sp)+,%d1
  387. rts
  388. |
  389. | mem_read --- read from user or supervisor address space
  390. |
  391. | Reads from memory while in supervisor mode. copyin accomplishes
  392. | this via a 'moves' instruction. copyin is a UNIX SVR3 (and later) function.
  393. | If you don't have copyin, use the local copy of the function below.
  394. |
  395. | The FPSP calls mem_read to read the original F-line instruction in order
  396. | to extract the data register number when the 'Dn' addressing mode is
  397. | used.
  398. |
  399. |Input:
  400. | a0 - user source address
  401. | a1 - supervisor destination address
  402. | d0 - number of bytes to read (maximum count is 12)
  403. |
  404. | Like mem_write, mem_read always reads with a supervisor
  405. | destination address on the supervisor stack. Also like mem_write,
  406. | the EXC_SR is checked and a simple memory copy is done if reading
  407. | from supervisor space is indicated.
  408. |
  409. .global mem_read
  410. mem_read:
  411. btstb #5,EXC_SR(%a6) |check for supervisor state
  412. beqs user_read
  413. super_read:
  414. moveb (%a0)+,(%a1)+
  415. subql #1,%d0
  416. bnes super_read
  417. rts
  418. user_read:
  419. movel %d1,-(%sp) |preserve d1 just in case
  420. movel %d0,-(%sp)
  421. movel %a1,-(%sp)
  422. movel %a0,-(%sp)
  423. jsr copyin
  424. addw #12,%sp
  425. movel (%sp)+,%d1
  426. rts
  427. |
  428. | Use these routines if your kernel doesn't have copyout/copyin equivalents.
  429. | Assumes that D0/D1/A0/A1 are scratch registers. copyout overwrites DFC,
  430. | and copyin overwrites SFC.
  431. |
  432. copyout:
  433. movel 4(%sp),%a0 | source
  434. movel 8(%sp),%a1 | destination
  435. movel 12(%sp),%d0 | count
  436. subl #1,%d0 | dec count by 1 for dbra
  437. movel #1,%d1
  438. | DFC is already set
  439. | movec %d1,%DFC | set dfc for user data space
  440. moreout:
  441. moveb (%a0)+,%d1 | fetch supervisor byte
  442. out_ea:
  443. movesb %d1,(%a1)+ | write user byte
  444. dbf %d0,moreout
  445. rts
  446. copyin:
  447. movel 4(%sp),%a0 | source
  448. movel 8(%sp),%a1 | destination
  449. movel 12(%sp),%d0 | count
  450. subl #1,%d0 | dec count by 1 for dbra
  451. movel #1,%d1
  452. | SFC is already set
  453. | movec %d1,%SFC | set sfc for user space
  454. morein:
  455. in_ea:
  456. movesb (%a0)+,%d1 | fetch user byte
  457. moveb %d1,(%a1)+ | write supervisor byte
  458. dbf %d0,morein
  459. rts
  460. .section .fixup,#alloc,#execinstr
  461. .even
  462. 1:
  463. jbra fpsp040_die
  464. .section __ex_table,#alloc
  465. .align 4
  466. .long in_ea,1b
  467. .long out_ea,1b
  468. |end