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

嵌入式Linux

开发平台:

Unix_Linux

  1. |
  2. | x_operr.sa 3.5 7/1/91
  3. |
  4. | fpsp_operr --- FPSP handler for operand error exception
  5. |
  6. | See 68040 User's Manual pp. 9-44f
  7. |
  8. | Note 1: For trap disabled 040 does the following:
  9. | If the dest is a fp reg, then an extended precision non_signaling
  10. | NAN is stored in the dest reg.  If the dest format is b, w, or l and
  11. | the source op is a NAN, then garbage is stored as the result (actually
  12. | the upper 32 bits of the mantissa are sent to the integer unit). If
  13. | the dest format is integer (b, w, l) and the operr is caused by
  14. | integer overflow, or the source op is inf, then the result stored is
  15. | garbage.
  16. | There are three cases in which operr is incorrectly signaled on the 
  17. | 040.  This occurs for move_out of format b, w, or l for the largest 
  18. | negative integer (-2^7 for b, -2^15 for w, -2^31 for l).
  19. |
  20. |   On opclass = 011 fmove.(b,w,l) that causes a conversion
  21. |   overflow -> OPERR, the exponent in wbte (and fpte) is:
  22. | byte    56 - (62 - exp)
  23. | word    48 - (62 - exp)
  24. | long    32 - (62 - exp)
  25. |
  26. | where exp = (true exp) - 1
  27. |
  28. |  So, wbtemp and fptemp will contain the following on erroneously
  29. |   signalled operr:
  30. | fpts = 1
  31. | fpte = $4000  (15 bit externally)
  32. | byte fptm = $ffffffff ffffff80
  33. | word fptm = $ffffffff ffff8000
  34. | long fptm = $ffffffff 80000000
  35. |
  36. | Note 2: For trap enabled 040 does the following:
  37. | If the inst is move_out, then same as Note 1.
  38. | If the inst is not move_out, the dest is not modified.
  39. | The exceptional operand is not defined for integer overflow 
  40. | during a move_out.
  41. |
  42. | Copyright (C) Motorola, Inc. 1990
  43. | All Rights Reserved
  44. |
  45. | THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA 
  46. | The copyright notice above does not evidence any  
  47. | actual or intended publication of such source code.
  48. X_OPERR: |idnt    2,1 | Motorola 040 Floating Point Software Package
  49. |section 8
  50. .include "fpsp.h"
  51. |xref mem_write
  52. |xref real_operr
  53. |xref real_inex
  54. |xref get_fline
  55. |xref fpsp_done
  56. |xref reg_dest
  57. .global fpsp_operr
  58. fpsp_operr:
  59. |
  60. link %a6,#-LOCAL_SIZE
  61. fsave -(%a7)
  62. moveml %d0-%d1/%a0-%a1,USER_DA(%a6)
  63. fmovemx %fp0-%fp3,USER_FP0(%a6)
  64. fmoveml %fpcr/%fpsr/%fpiar,USER_FPCR(%a6)
  65. |
  66. | Check if this is an opclass 3 instruction.
  67. |  If so, fall through, else branch to operr_end
  68. |
  69. btstb #TFLAG,T_BYTE(%a6)
  70. beqs operr_end
  71. |
  72. | If the destination size is B,W,or L, the operr must be 
  73. | handled here.
  74. |
  75. movel CMDREG1B(%a6),%d0
  76. bfextu %d0{#3:#3},%d0 |0=long, 4=word, 6=byte
  77. cmpib #0,%d0 |determine size; check long
  78. beq operr_long
  79. cmpib #4,%d0 |check word
  80. beq operr_word
  81. cmpib #6,%d0 |check byte
  82. beq operr_byte
  83. |
  84. | The size is not B,W,or L, so the operr is handled by the 
  85. | kernel handler.  Set the operr bits and clean up, leaving
  86. | only the integer exception frame on the stack, and the 
  87. | fpu in the original exceptional state.
  88. |
  89. operr_end:
  90. bsetb #operr_bit,FPSR_EXCEPT(%a6)
  91. bsetb #aiop_bit,FPSR_AEXCEPT(%a6)
  92. moveml USER_DA(%a6),%d0-%d1/%a0-%a1
  93. fmovemx USER_FP0(%a6),%fp0-%fp3
  94. fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
  95. frestore (%a7)+
  96. unlk %a6
  97. bral real_operr
  98. operr_long:
  99. moveql #4,%d1 |write size to d1
  100. moveb STAG(%a6),%d0 |test stag for nan
  101. andib #0xe0,%d0 |clr all but tag
  102. cmpib #0x60,%d0 |check for nan
  103. beq operr_nan
  104. cmpil #0x80000000,FPTEMP_LO(%a6) |test if ls lword is special
  105. bnes chklerr |if not equal, check for incorrect operr
  106. bsr check_upper |check if exp and ms mant are special
  107. tstl %d0
  108. bnes chklerr |if d0 is true, check for incorrect operr
  109. movel #0x80000000,%d0 |store special case result
  110. bsr operr_store
  111. bra not_enabled |clean and exit
  112. |
  113. | CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
  114. |
  115. chklerr:
  116. movew FPTEMP_EX(%a6),%d0
  117. andw #0x7FFF,%d0 |ignore sign bit
  118. cmpw #0x3FFE,%d0 |this is the only possible exponent value
  119. bnes chklerr2
  120. fixlong:
  121. movel FPTEMP_LO(%a6),%d0
  122. bsr operr_store
  123. bra not_enabled
  124. chklerr2:
  125. movew FPTEMP_EX(%a6),%d0
  126. andw #0x7FFF,%d0 |ignore sign bit
  127. cmpw #0x4000,%d0
  128. bcc store_max |exponent out of range
  129. movel FPTEMP_LO(%a6),%d0
  130. andl #0x7FFF0000,%d0 |look for all 1's on bits 30-16
  131. cmpl #0x7FFF0000,%d0
  132. beqs fixlong
  133. tstl FPTEMP_LO(%a6)
  134. bpls chklepos
  135. cmpl #0xFFFFFFFF,FPTEMP_HI(%a6)
  136. beqs fixlong
  137. bra store_max
  138. chklepos:
  139. tstl FPTEMP_HI(%a6)
  140. beqs fixlong
  141. bra store_max
  142. operr_word:
  143. moveql #2,%d1 |write size to d1
  144. moveb STAG(%a6),%d0 |test stag for nan
  145. andib #0xe0,%d0 |clr all but tag
  146. cmpib #0x60,%d0 |check for nan
  147. beq operr_nan
  148. cmpil #0xffff8000,FPTEMP_LO(%a6) |test if ls lword is special
  149. bnes chkwerr |if not equal, check for incorrect operr
  150. bsr check_upper |check if exp and ms mant are special
  151. tstl %d0
  152. bnes chkwerr |if d0 is true, check for incorrect operr
  153. movel #0x80000000,%d0 |store special case result
  154. bsr operr_store
  155. bra not_enabled |clean and exit
  156. |
  157. | CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
  158. |
  159. chkwerr:
  160. movew FPTEMP_EX(%a6),%d0
  161. andw #0x7FFF,%d0 |ignore sign bit
  162. cmpw #0x3FFE,%d0 |this is the only possible exponent value
  163. bnes store_max
  164. movel FPTEMP_LO(%a6),%d0
  165. swap %d0
  166. bsr operr_store
  167. bra not_enabled
  168. operr_byte:
  169. moveql #1,%d1 |write size to d1
  170. moveb STAG(%a6),%d0 |test stag for nan
  171. andib #0xe0,%d0 |clr all but tag
  172. cmpib #0x60,%d0 |check for nan
  173. beqs operr_nan
  174. cmpil #0xffffff80,FPTEMP_LO(%a6) |test if ls lword is special
  175. bnes chkberr |if not equal, check for incorrect operr
  176. bsr check_upper |check if exp and ms mant are special
  177. tstl %d0
  178. bnes chkberr |if d0 is true, check for incorrect operr
  179. movel #0x80000000,%d0 |store special case result
  180. bsr operr_store
  181. bra not_enabled |clean and exit
  182. |
  183. | CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
  184. |
  185. chkberr:
  186. movew FPTEMP_EX(%a6),%d0
  187. andw #0x7FFF,%d0 |ignore sign bit
  188. cmpw #0x3FFE,%d0 |this is the only possible exponent value
  189. bnes store_max
  190. movel FPTEMP_LO(%a6),%d0
  191. asll #8,%d0
  192. swap %d0
  193. bsr operr_store
  194. bra not_enabled
  195. |
  196. | This operr condition is not of the special case.  Set operr
  197. | and aiop and write the portion of the nan to memory for the
  198. | given size.
  199. |
  200. operr_nan:
  201. orl #opaop_mask,USER_FPSR(%a6) |set operr & aiop
  202. movel ETEMP_HI(%a6),%d0 |output will be from upper 32 bits
  203. bsr operr_store
  204. bra end_operr
  205. |
  206. | Store_max loads the max pos or negative for the size, sets
  207. | the operr and aiop bits, and clears inex and ainex, incorrectly
  208. | set by the 040.
  209. |
  210. store_max:
  211. orl #opaop_mask,USER_FPSR(%a6) |set operr & aiop
  212. bclrb #inex2_bit,FPSR_EXCEPT(%a6)
  213. bclrb #ainex_bit,FPSR_AEXCEPT(%a6)
  214. fmovel #0,%FPSR
  215. tstw FPTEMP_EX(%a6) |check sign
  216. blts load_neg
  217. movel #0x7fffffff,%d0
  218. bsr operr_store
  219. bra end_operr
  220. load_neg:
  221. movel #0x80000000,%d0
  222. bsr operr_store
  223. bra end_operr
  224. |
  225. | This routine stores the data in d0, for the given size in d1,
  226. | to memory or data register as required.  A read of the fline
  227. | is required to determine the destination.
  228. |
  229. operr_store:
  230. movel %d0,L_SCR1(%a6) |move write data to L_SCR1
  231. movel %d1,-(%a7) |save register size
  232. bsrl get_fline |fline returned in d0
  233. movel (%a7)+,%d1
  234. bftst %d0{#26:#3} |if mode is zero, dest is Dn
  235. bnes dest_mem
  236. |
  237. | Destination is Dn.  Get register number from d0. Data is on
  238. | the stack at (a7). D1 has size: 1=byte,2=word,4=long/single
  239. |
  240. andil #7,%d0 |isolate register number
  241. cmpil #4,%d1
  242. beqs op_long |the most frequent case
  243. cmpil #2,%d1
  244. bnes op_con
  245. orl #8,%d0
  246. bras op_con
  247. op_long:
  248. orl #0x10,%d0
  249. op_con:
  250. movel %d0,%d1 |format size:reg for reg_dest
  251. bral reg_dest |call to reg_dest returns to caller
  252. | ;of operr_store
  253. |
  254. | Destination is memory.  Get <ea> from integer exception frame
  255. | and call mem_write.
  256. |
  257. dest_mem:
  258. leal L_SCR1(%a6),%a0 |put ptr to write data in a0
  259. movel EXC_EA(%a6),%a1 |put user destination address in a1
  260. movel %d1,%d0 |put size in d0
  261. bsrl mem_write
  262. rts
  263. |
  264. | Check the exponent for $c000 and the upper 32 bits of the 
  265. | mantissa for $ffffffff.  If both are true, return d0 clr
  266. | and store the lower n bits of the least lword of FPTEMP
  267. | to d0 for write out.  If not, it is a real operr, and set d0.
  268. |
  269. check_upper:
  270. cmpil #0xffffffff,FPTEMP_HI(%a6) |check if first byte is all 1's
  271. bnes true_operr |if not all 1's then was true operr
  272. cmpiw #0xc000,FPTEMP_EX(%a6) |check if incorrectly signalled
  273. beqs not_true_operr |branch if not true operr
  274. cmpiw #0xbfff,FPTEMP_EX(%a6) |check if incorrectly signalled
  275. beqs not_true_operr |branch if not true operr
  276. true_operr:
  277. movel #1,%d0 |signal real operr
  278. rts
  279. not_true_operr:
  280. clrl %d0 |signal no real operr
  281. rts
  282. |
  283. | End_operr tests for operr enabled.  If not, it cleans up the stack
  284. | and does an rte.  If enabled, it cleans up the stack and branches
  285. | to the kernel operr handler with only the integer exception
  286. | frame on the stack and the fpu in the original exceptional state
  287. | with correct data written to the destination.
  288. |
  289. end_operr:
  290. btstb #operr_bit,FPCR_ENABLE(%a6)
  291. beqs not_enabled
  292. enabled:
  293. moveml USER_DA(%a6),%d0-%d1/%a0-%a1
  294. fmovemx USER_FP0(%a6),%fp0-%fp3
  295. fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
  296. frestore (%a7)+
  297. unlk %a6
  298. bral real_operr
  299. not_enabled:
  300. |
  301. | It is possible to have either inex2 or inex1 exceptions with the
  302. | operr.  If the inex enable bit is set in the FPCR, and either
  303. | inex2 or inex1 occurred, we must clean up and branch to the
  304. | real inex handler.
  305. |
  306. ck_inex:
  307. moveb FPCR_ENABLE(%a6),%d0
  308. andb FPSR_EXCEPT(%a6),%d0
  309. andib #0x3,%d0
  310. beq operr_exit
  311. |
  312. | Inexact enabled and reported, and we must take an inexact exception.
  313. |
  314. take_inex:
  315. moveb #INEX_VEC,EXC_VEC+1(%a6)
  316. movel USER_FPSR(%a6),FPSR_SHADOW(%a6)
  317. orl #sx_mask,E_BYTE(%a6)
  318. moveml USER_DA(%a6),%d0-%d1/%a0-%a1
  319. fmovemx USER_FP0(%a6),%fp0-%fp3
  320. fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
  321. frestore (%a7)+
  322. unlk %a6
  323. bral real_inex
  324. |
  325. | Since operr is only an E1 exception, there is no need to frestore
  326. | any state back to the fpu.
  327. |
  328. operr_exit:
  329. moveml USER_DA(%a6),%d0-%d1/%a0-%a1
  330. fmovemx USER_FP0(%a6),%fp0-%fp3
  331. fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
  332. unlk %a6
  333. bral fpsp_done
  334. |end