x_operr.sa revision 1.1
11.1Smycroft* MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP 21.1Smycroft* M68000 Hi-Performance Microprocessor Division 31.1Smycroft* M68040 Software Package 41.1Smycroft* 51.1Smycroft* M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc. 61.1Smycroft* All rights reserved. 71.1Smycroft* 81.1Smycroft* THE SOFTWARE is provided on an "AS IS" basis and without warranty. 91.1Smycroft* To the maximum extent permitted by applicable law, 101.1Smycroft* MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, 111.1Smycroft* INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A 121.1Smycroft* PARTICULAR PURPOSE and any warranty against infringement with 131.1Smycroft* regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF) 141.1Smycroft* and any accompanying written materials. 151.1Smycroft* 161.1Smycroft* To the maximum extent permitted by applicable law, 171.1Smycroft* IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER 181.1Smycroft* (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS 191.1Smycroft* PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR 201.1Smycroft* OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE 211.1Smycroft* SOFTWARE. Motorola assumes no responsibility for the maintenance 221.1Smycroft* and support of the SOFTWARE. 231.1Smycroft* 241.1Smycroft* You are hereby granted a copyright license to use, modify, and 251.1Smycroft* distribute the SOFTWARE so long as this entire notice is retained 261.1Smycroft* without alteration in any modified and/or redistributed versions, 271.1Smycroft* and that such modified versions are clearly identified as such. 281.1Smycroft* No licenses are granted by implication, estoppel or otherwise 291.1Smycroft* under any patents or trademarks of Motorola, Inc. 301.1Smycroft 311.1Smycroft* 321.1Smycroft* x_operr.sa 3.5 7/1/91 331.1Smycroft* 341.1Smycroft* fpsp_operr --- FPSP handler for operand error exception 351.1Smycroft* 361.1Smycroft* See 68040 User's Manual pp. 9-44f 371.1Smycroft* 381.1Smycroft* Note 1: For trap disabled 040 does the following: 391.1Smycroft* If the dest is a fp reg, then an extended precision non_signaling 401.1Smycroft* NAN is stored in the dest reg. If the dest format is b, w, or l and 411.1Smycroft* the source op is a NAN, then garbage is stored as the result (actually 421.1Smycroft* the upper 32 bits of the mantissa are sent to the integer unit). If 431.1Smycroft* the dest format is integer (b, w, l) and the operr is caused by 441.1Smycroft* integer overflow, or the source op is inf, then the result stored is 451.1Smycroft* garbage. 461.1Smycroft* There are three cases in which operr is incorrectly signaled on the 471.1Smycroft* 040. This occurs for move_out of format b, w, or l for the largest 481.1Smycroft* negative integer (-2^7 for b, -2^15 for w, -2^31 for l). 491.1Smycroft* 501.1Smycroft* On opclass = 011 fmove.(b,w,l) that causes a conversion 511.1Smycroft* overflow -> OPERR, the exponent in wbte (and fpte) is: 521.1Smycroft* byte 56 - (62 - exp) 531.1Smycroft* word 48 - (62 - exp) 541.1Smycroft* long 32 - (62 - exp) 551.1Smycroft* 561.1Smycroft* where exp = (true exp) - 1 571.1Smycroft* 581.1Smycroft* So, wbtemp and fptemp will contain the following on erroneoulsy 591.1Smycroft* signalled operr: 601.1Smycroft* fpts = 1 611.1Smycroft* fpte = $4000 (15 bit externally) 621.1Smycroft* byte fptm = $ffffffff ffffff80 631.1Smycroft* word fptm = $ffffffff ffff8000 641.1Smycroft* long fptm = $ffffffff 80000000 651.1Smycroft* 661.1Smycroft* Note 2: For trap enabled 040 does the following: 671.1Smycroft* If the inst is move_out, then same as Note 1. 681.1Smycroft* If the inst is not move_out, the dest is not modified. 691.1Smycroft* The exceptional operand is not defined for integer overflow 701.1Smycroft* during a move_out. 711.1Smycroft* 721.1Smycroft 731.1SmycroftX_OPERR IDNT 2,1 Motorola 040 Floating Point Software Package 741.1Smycroft 751.1Smycroft section 8 761.1Smycroft 771.1Smycroft include fpsp.h 781.1Smycroft 791.1Smycroft xref mem_write 801.1Smycroft xref real_operr 811.1Smycroft xref real_inex 821.1Smycroft xref get_fline 831.1Smycroft xref fpsp_done 841.1Smycroft xref reg_dest 851.1Smycroft 861.1Smycroft xdef fpsp_operr 871.1Smycroftfpsp_operr: 881.1Smycroft* 891.1Smycroft link a6,#-LOCAL_SIZE 901.1Smycroft fsave -(a7) 911.1Smycroft movem.l d0-d1/a0-a1,USER_DA(a6) 921.1Smycroft fmovem.x fp0-fp3,USER_FP0(a6) 931.1Smycroft fmovem.l fpcr/fpsr/fpiar,USER_FPCR(a6) 941.1Smycroft 951.1Smycroft* 961.1Smycroft* Check if this is an opclass 3 instruction. 971.1Smycroft* If so, fall through, else branch to operr_end 981.1Smycroft* 991.1Smycroft btst.b #TFLAG,T_BYTE(a6) 1001.1Smycroft beq.b operr_end 1011.1Smycroft 1021.1Smycroft* 1031.1Smycroft* If the destination size is B,W,or L, the operr must be 1041.1Smycroft* handled here. 1051.1Smycroft* 1061.1Smycroft move.l CMDREG1B(a6),d0 1071.1Smycroft bfextu d0{3:3},d0 ;0=long, 4=word, 6=byte 1081.1Smycroft cmpi.b #0,d0 ;determine size; check long 1091.1Smycroft beq.w operr_long 1101.1Smycroft cmpi.b #4,d0 ;check word 1111.1Smycroft beq.w operr_word 1121.1Smycroft cmpi.b #6,d0 ;check byte 1131.1Smycroft beq.w operr_byte 1141.1Smycroft 1151.1Smycroft* 1161.1Smycroft* The size is not B,W,or L, so the operr is handled by the 1171.1Smycroft* kernel handler. Set the operr bits and clean up, leaving 1181.1Smycroft* only the integer exception frame on the stack, and the 1191.1Smycroft* fpu in the original exceptional state. 1201.1Smycroft* 1211.1Smycroftoperr_end: 1221.1Smycroft bset.b #operr_bit,FPSR_EXCEPT(a6) 1231.1Smycroft bset.b #aiop_bit,FPSR_AEXCEPT(a6) 1241.1Smycroft 1251.1Smycroft movem.l USER_DA(a6),d0-d1/a0-a1 1261.1Smycroft fmovem.x USER_FP0(a6),fp0-fp3 1271.1Smycroft fmovem.l USER_FPCR(a6),fpcr/fpsr/fpiar 1281.1Smycroft frestore (a7)+ 1291.1Smycroft unlk a6 1301.1Smycroft bra.l real_operr 1311.1Smycroft 1321.1Smycroftoperr_long: 1331.1Smycroft moveq.l #4,d1 ;write size to d1 1341.1Smycroft move.b STAG(a6),d0 ;test stag for nan 1351.1Smycroft andi.b #$e0,d0 ;clr all but tag 1361.1Smycroft cmpi.b #$60,d0 ;check for nan 1371.1Smycroft beq operr_nan 1381.1Smycroft cmpi.l #$80000000,FPTEMP_LO(a6) ;test if ls lword is special 1391.1Smycroft bne.b chklerr ;if not equal, check for incorrect operr 1401.1Smycroft bsr check_upper ;check if exp and ms mant are special 1411.1Smycroft tst.l d0 1421.1Smycroft bne.b chklerr ;if d0 is true, check for incorrect operr 1431.1Smycroft move.l #$80000000,d0 ;store special case result 1441.1Smycroft bsr operr_store 1451.1Smycroft bra.w not_enabled ;clean and exit 1461.1Smycroft* 1471.1Smycroft* CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE 1481.1Smycroft* 1491.1Smycroftchklerr: 1501.1Smycroft move.w FPTEMP_EX(a6),d0 1511.1Smycroft and.w #$7FFF,d0 ;ignore sign bit 1521.1Smycroft cmp.w #$3FFE,d0 ;this is the only possible exponent value 1531.1Smycroft bne.b chklerr2 1541.1Smycroftfixlong: 1551.1Smycroft move.l FPTEMP_LO(a6),d0 1561.1Smycroft bsr operr_store 1571.1Smycroft bra.w not_enabled 1581.1Smycroftchklerr2: 1591.1Smycroft move.w FPTEMP_EX(a6),d0 1601.1Smycroft and.w #$7FFF,d0 ;ignore sign bit 1611.1Smycroft cmp.w #$4000,d0 1621.1Smycroft bhs.w store_max ;exponent out of range 1631.1Smycroft 1641.1Smycroft move.l FPTEMP_LO(a6),d0 1651.1Smycroft and.l #$7FFF0000,d0 ;look for all 1's on bits 30-16 1661.1Smycroft cmp.l #$7FFF0000,d0 1671.1Smycroft beq.b fixlong 1681.1Smycroft 1691.1Smycroft tst.l FPTEMP_LO(a6) 1701.1Smycroft bpl.b chklepos 1711.1Smycroft cmp.l #$FFFFFFFF,FPTEMP_HI(a6) 1721.1Smycroft beq.b fixlong 1731.1Smycroft bra.w store_max 1741.1Smycroftchklepos: 1751.1Smycroft tst.l FPTEMP_HI(a6) 1761.1Smycroft beq.b fixlong 1771.1Smycroft bra.w store_max 1781.1Smycroft 1791.1Smycroftoperr_word: 1801.1Smycroft moveq.l #2,d1 ;write size to d1 1811.1Smycroft move.b STAG(a6),d0 ;test stag for nan 1821.1Smycroft andi.b #$e0,d0 ;clr all but tag 1831.1Smycroft cmpi.b #$60,d0 ;check for nan 1841.1Smycroft beq.w operr_nan 1851.1Smycroft cmpi.l #$ffff8000,FPTEMP_LO(a6) ;test if ls lword is special 1861.1Smycroft bne.b chkwerr ;if not equal, check for incorrect operr 1871.1Smycroft bsr check_upper ;check if exp and ms mant are special 1881.1Smycroft tst.l d0 1891.1Smycroft bne.b chkwerr ;if d0 is true, check for incorrect operr 1901.1Smycroft move.l #$80000000,d0 ;store special case result 1911.1Smycroft bsr operr_store 1921.1Smycroft bra.w not_enabled ;clean and exit 1931.1Smycroft* 1941.1Smycroft* CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE 1951.1Smycroft* 1961.1Smycroftchkwerr: 1971.1Smycroft move.w FPTEMP_EX(a6),d0 1981.1Smycroft and.w #$7FFF,d0 ;ignore sign bit 1991.1Smycroft cmp.w #$3FFE,d0 ;this is the only possible exponent value 2001.1Smycroft bne.b store_max 2011.1Smycroft move.l FPTEMP_LO(a6),d0 2021.1Smycroft swap d0 2031.1Smycroft bsr operr_store 2041.1Smycroft bra.w not_enabled 2051.1Smycroft 2061.1Smycroftoperr_byte: 2071.1Smycroft moveq.l #1,d1 ;write size to d1 2081.1Smycroft move.b STAG(a6),d0 ;test stag for nan 2091.1Smycroft andi.b #$e0,d0 ;clr all but tag 2101.1Smycroft cmpi.b #$60,d0 ;check for nan 2111.1Smycroft beq.b operr_nan 2121.1Smycroft cmpi.l #$ffffff80,FPTEMP_LO(a6) ;test if ls lword is special 2131.1Smycroft bne.b chkberr ;if not equal, check for incorrect operr 2141.1Smycroft bsr check_upper ;check if exp and ms mant are special 2151.1Smycroft tst.l d0 2161.1Smycroft bne.b chkberr ;if d0 is true, check for incorrect operr 2171.1Smycroft move.l #$80000000,d0 ;store special case result 2181.1Smycroft bsr operr_store 2191.1Smycroft bra.w not_enabled ;clean and exit 2201.1Smycroft* 2211.1Smycroft* CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE 2221.1Smycroft* 2231.1Smycroftchkberr: 2241.1Smycroft move.w FPTEMP_EX(a6),d0 2251.1Smycroft and.w #$7FFF,d0 ;ignore sign bit 2261.1Smycroft cmp.w #$3FFE,d0 ;this is the only possible exponent value 2271.1Smycroft bne.b store_max 2281.1Smycroft move.l FPTEMP_LO(a6),d0 2291.1Smycroft asl.l #8,d0 2301.1Smycroft swap d0 2311.1Smycroft bsr operr_store 2321.1Smycroft bra.w not_enabled 2331.1Smycroft 2341.1Smycroft* 2351.1Smycroft* This operr condition is not of the special case. Set operr 2361.1Smycroft* and aiop and write the portion of the nan to memory for the 2371.1Smycroft* given size. 2381.1Smycroft* 2391.1Smycroftoperr_nan: 2401.1Smycroft or.l #opaop_mask,USER_FPSR(a6) ;set operr & aiop 2411.1Smycroft 2421.1Smycroft move.l ETEMP_HI(a6),d0 ;output will be from upper 32 bits 2431.1Smycroft bsr operr_store 2441.1Smycroft bra end_operr 2451.1Smycroft* 2461.1Smycroft* Store_max loads the max pos or negative for the size, sets 2471.1Smycroft* the operr and aiop bits, and clears inex and ainex, incorrectly 2481.1Smycroft* set by the 040. 2491.1Smycroft* 2501.1Smycroftstore_max: 2511.1Smycroft or.l #opaop_mask,USER_FPSR(a6) ;set operr & aiop 2521.1Smycroft bclr.b #inex2_bit,FPSR_EXCEPT(a6) 2531.1Smycroft bclr.b #ainex_bit,FPSR_AEXCEPT(a6) 2541.1Smycroft fmove.l #0,FPSR 2551.1Smycroft 2561.1Smycroft tst.w FPTEMP_EX(a6) ;check sign 2571.1Smycroft blt.b load_neg 2581.1Smycroft move.l #$7fffffff,d0 2591.1Smycroft bsr operr_store 2601.1Smycroft bra end_operr 2611.1Smycroftload_neg: 2621.1Smycroft move.l #$80000000,d0 2631.1Smycroft bsr operr_store 2641.1Smycroft bra end_operr 2651.1Smycroft 2661.1Smycroft* 2671.1Smycroft* This routine stores the data in d0, for the given size in d1, 2681.1Smycroft* to memory or data register as required. A read of the fline 2691.1Smycroft* is required to determine the destination. 2701.1Smycroft* 2711.1Smycroftoperr_store: 2721.1Smycroft move.l d0,L_SCR1(a6) ;move write data to L_SCR1 2731.1Smycroft move.l d1,-(a7) ;save register size 2741.1Smycroft bsr.l get_fline ;fline returned in d0 2751.1Smycroft move.l (a7)+,d1 2761.1Smycroft bftst d0{26:3} ;if mode is zero, dest is Dn 2771.1Smycroft bne.b dest_mem 2781.1Smycroft* 2791.1Smycroft* Destination is Dn. Get register number from d0. Data is on 2801.1Smycroft* the stack at (a7). D1 has size: 1=byte,2=word,4=long/single 2811.1Smycroft* 2821.1Smycroft andi.l #7,d0 ;isolate register number 2831.1Smycroft cmpi.l #4,d1 2841.1Smycroft beq.b op_long ;the most frequent case 2851.1Smycroft cmpi.l #2,d1 2861.1Smycroft bne.b op_con 2871.1Smycroft or.l #8,d0 2881.1Smycroft bra.b op_con 2891.1Smycroftop_long: 2901.1Smycroft or.l #$10,d0 2911.1Smycroftop_con: 2921.1Smycroft move.l d0,d1 ;format size:reg for reg_dest 2931.1Smycroft bra.l reg_dest ;call to reg_dest returns to caller 2941.1Smycroft* ;of operr_store 2951.1Smycroft* 2961.1Smycroft* Destination is memory. Get <ea> from integer exception frame 2971.1Smycroft* and call mem_write. 2981.1Smycroft* 2991.1Smycroftdest_mem: 3001.1Smycroft lea.l L_SCR1(a6),a0 ;put ptr to write data in a0 3011.1Smycroft move.l EXC_EA(a6),a1 ;put user destination address in a1 3021.1Smycroft move.l d1,d0 ;put size in d0 3031.1Smycroft bsr.l mem_write 3041.1Smycroft rts 3051.1Smycroft* 3061.1Smycroft* Check the exponent for $c000 and the upper 32 bits of the 3071.1Smycroft* mantissa for $ffffffff. If both are true, return d0 clr 3081.1Smycroft* and store the lower n bits of the least lword of FPTEMP 3091.1Smycroft* to d0 for write out. If not, it is a real operr, and set d0. 3101.1Smycroft* 3111.1Smycroftcheck_upper: 3121.1Smycroft cmpi.l #$ffffffff,FPTEMP_HI(a6) ;check if first byte is all 1's 3131.1Smycroft bne.b true_operr ;if not all 1's then was true operr 3141.1Smycroft cmpi.w #$c000,FPTEMP_EX(a6) ;check if incorrectly signalled 3151.1Smycroft beq.b not_true_operr ;branch if not true operr 3161.1Smycroft cmpi.w #$bfff,FPTEMP_EX(a6) ;check if incorrectly signalled 3171.1Smycroft beq.b not_true_operr ;branch if not true operr 3181.1Smycrofttrue_operr: 3191.1Smycroft move.l #1,d0 ;signal real operr 3201.1Smycroft rts 3211.1Smycroftnot_true_operr: 3221.1Smycroft clr.l d0 ;signal no real operr 3231.1Smycroft rts 3241.1Smycroft 3251.1Smycroft* 3261.1Smycroft* End_operr tests for operr enabled. If not, it cleans up the stack 3271.1Smycroft* and does an rte. If enabled, it cleans up the stack and branches 3281.1Smycroft* to the kernel operr handler with only the integer exception 3291.1Smycroft* frame on the stack and the fpu in the original exceptional state 3301.1Smycroft* with correct data written to the destination. 3311.1Smycroft* 3321.1Smycroftend_operr: 3331.1Smycroft btst.b #operr_bit,FPCR_ENABLE(a6) 3341.1Smycroft beq.b not_enabled 3351.1Smycroftenabled: 3361.1Smycroft movem.l USER_DA(a6),d0-d1/a0-a1 3371.1Smycroft fmovem.x USER_FP0(a6),fp0-fp3 3381.1Smycroft fmovem.l USER_FPCR(a6),fpcr/fpsr/fpiar 3391.1Smycroft frestore (a7)+ 3401.1Smycroft unlk a6 3411.1Smycroft bra.l real_operr 3421.1Smycroft 3431.1Smycroftnot_enabled: 3441.1Smycroft* 3451.1Smycroft* It is possible to have either inex2 or inex1 exceptions with the 3461.1Smycroft* operr. If the inex enable bit is set in the FPCR, and either 3471.1Smycroft* inex2 or inex1 occured, we must clean up and branch to the 3481.1Smycroft* real inex handler. 3491.1Smycroft* 3501.1Smycroftck_inex: 3511.1Smycroft move.b FPCR_ENABLE(a6),d0 3521.1Smycroft and.b FPSR_EXCEPT(a6),d0 3531.1Smycroft andi.b #$3,d0 3541.1Smycroft beq.w operr_exit 3551.1Smycroft* 3561.1Smycroft* Inexact enabled and reported, and we must take an inexact exception. 3571.1Smycroft* 3581.1Smycrofttake_inex: 3591.1Smycroft move.b #INEX_VEC,EXC_VEC+1(a6) 3601.1Smycroft move.l USER_FPSR(a6),FPSR_SHADOW(a6) 3611.1Smycroft or.l #sx_mask,E_BYTE(a6) 3621.1Smycroft movem.l USER_DA(a6),d0-d1/a0-a1 3631.1Smycroft fmovem.x USER_FP0(a6),fp0-fp3 3641.1Smycroft fmovem.l USER_FPCR(a6),fpcr/fpsr/fpiar 3651.1Smycroft frestore (a7)+ 3661.1Smycroft unlk a6 3671.1Smycroft bra.l real_inex 3681.1Smycroft* 3691.1Smycroft* Since operr is only an E1 exception, there is no need to frestore 3701.1Smycroft* any state back to the fpu. 3711.1Smycroft* 3721.1Smycroftoperr_exit: 3731.1Smycroft movem.l USER_DA(a6),d0-d1/a0-a1 3741.1Smycroft fmovem.x USER_FP0(a6),fp0-fp3 3751.1Smycroft fmovem.l USER_FPCR(a6),fpcr/fpsr/fpiar 3761.1Smycroft unlk a6 3771.1Smycroft bra.l fpsp_done 3781.1Smycroft 3791.1Smycroft end 380