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

VxWorks

开发平台:

C/C++

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