Back to home page

LXR

 
 

    


0001 |
0002 |   x_operr.sa 3.5 7/1/91
0003 |
0004 |   fpsp_operr --- FPSP handler for operand error exception
0005 |
0006 |   See 68040 User's Manual pp. 9-44f
0007 |
0008 | Note 1: For trap disabled 040 does the following:
0009 | If the dest is a fp reg, then an extended precision non_signaling
0010 | NAN is stored in the dest reg.  If the dest format is b, w, or l and
0011 | the source op is a NAN, then garbage is stored as the result (actually
0012 | the upper 32 bits of the mantissa are sent to the integer unit). If
0013 | the dest format is integer (b, w, l) and the operr is caused by
0014 | integer overflow, or the source op is inf, then the result stored is
0015 | garbage.
0016 | There are three cases in which operr is incorrectly signaled on the
0017 | 040.  This occurs for move_out of format b, w, or l for the largest
0018 | negative integer (-2^7 for b, -2^15 for w, -2^31 for l).
0019 |
0020 |     On opclass = 011 fmove.(b,w,l) that causes a conversion
0021 |     overflow -> OPERR, the exponent in wbte (and fpte) is:
0022 |       byte    56 - (62 - exp)
0023 |       word    48 - (62 - exp)
0024 |       long    32 - (62 - exp)
0025 |
0026 |           where exp = (true exp) - 1
0027 |
0028 |  So, wbtemp and fptemp will contain the following on erroneously
0029 |     signalled operr:
0030 |           fpts = 1
0031 |           fpte = $4000  (15 bit externally)
0032 |       byte    fptm = $ffffffff ffffff80
0033 |       word    fptm = $ffffffff ffff8000
0034 |       long    fptm = $ffffffff 80000000
0035 |
0036 | Note 2: For trap enabled 040 does the following:
0037 | If the inst is move_out, then same as Note 1.
0038 | If the inst is not move_out, the dest is not modified.
0039 | The exceptional operand is not defined for integer overflow
0040 | during a move_out.
0041 |
0042 
0043 |       Copyright (C) Motorola, Inc. 1990
0044 |           All Rights Reserved
0045 |
0046 |       For details on the license for this file, please see the
0047 |       file, README, in this same directory.
0048 
0049 X_OPERR:    |idnt    2,1 | Motorola 040 Floating Point Software Package
0050 
0051     |section    8
0052 
0053 #include "fpsp.h"
0054 
0055     |xref   mem_write
0056     |xref   real_operr
0057     |xref   real_inex
0058     |xref   get_fline
0059     |xref   fpsp_done
0060     |xref   reg_dest
0061 
0062     .global fpsp_operr
0063 fpsp_operr:
0064 |
0065     link        %a6,#-LOCAL_SIZE
0066     fsave       -(%a7)
0067     moveml      %d0-%d1/%a0-%a1,USER_DA(%a6)
0068     fmovemx %fp0-%fp3,USER_FP0(%a6)
0069     fmoveml %fpcr/%fpsr/%fpiar,USER_FPCR(%a6)
0070 
0071 |
0072 | Check if this is an opclass 3 instruction.
0073 |  If so, fall through, else branch to operr_end
0074 |
0075     btstb   #TFLAG,T_BYTE(%a6)
0076     beqs    operr_end
0077 
0078 |
0079 | If the destination size is B,W,or L, the operr must be
0080 | handled here.
0081 |
0082     movel   CMDREG1B(%a6),%d0
0083     bfextu  %d0{#3:#3},%d0  |0=long, 4=word, 6=byte
0084     cmpib   #0,%d0      |determine size; check long
0085     beq operr_long
0086     cmpib   #4,%d0      |check word
0087     beq operr_word
0088     cmpib   #6,%d0      |check byte
0089     beq operr_byte
0090 
0091 |
0092 | The size is not B,W,or L, so the operr is handled by the
0093 | kernel handler.  Set the operr bits and clean up, leaving
0094 | only the integer exception frame on the stack, and the
0095 | fpu in the original exceptional state.
0096 |
0097 operr_end:
0098     bsetb       #operr_bit,FPSR_EXCEPT(%a6)
0099     bsetb       #aiop_bit,FPSR_AEXCEPT(%a6)
0100 
0101     moveml      USER_DA(%a6),%d0-%d1/%a0-%a1
0102     fmovemx USER_FP0(%a6),%fp0-%fp3
0103     fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
0104     frestore    (%a7)+
0105     unlk        %a6
0106     bral        real_operr
0107 
0108 operr_long:
0109     moveql  #4,%d1      |write size to d1
0110     moveb   STAG(%a6),%d0   |test stag for nan
0111     andib   #0xe0,%d0       |clr all but tag
0112     cmpib   #0x60,%d0       |check for nan
0113     beq operr_nan
0114     cmpil   #0x80000000,FPTEMP_LO(%a6) |test if ls lword is special
0115     bnes    chklerr     |if not equal, check for incorrect operr
0116     bsr check_upper |check if exp and ms mant are special
0117     tstl    %d0
0118     bnes    chklerr     |if d0 is true, check for incorrect operr
0119     movel   #0x80000000,%d0 |store special case result
0120     bsr operr_store
0121     bra not_enabled |clean and exit
0122 |
0123 |   CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
0124 |
0125 chklerr:
0126     movew   FPTEMP_EX(%a6),%d0
0127     andw    #0x7FFF,%d0 |ignore sign bit
0128     cmpw    #0x3FFE,%d0 |this is the only possible exponent value
0129     bnes    chklerr2
0130 fixlong:
0131     movel   FPTEMP_LO(%a6),%d0
0132     bsr operr_store
0133     bra not_enabled
0134 chklerr2:
0135     movew   FPTEMP_EX(%a6),%d0
0136     andw    #0x7FFF,%d0 |ignore sign bit
0137     cmpw    #0x4000,%d0
0138     bcc store_max   |exponent out of range
0139 
0140     movel   FPTEMP_LO(%a6),%d0
0141     andl    #0x7FFF0000,%d0 |look for all 1's on bits 30-16
0142     cmpl    #0x7FFF0000,%d0
0143     beqs    fixlong
0144 
0145     tstl    FPTEMP_LO(%a6)
0146     bpls    chklepos
0147     cmpl    #0xFFFFFFFF,FPTEMP_HI(%a6)
0148     beqs    fixlong
0149     bra store_max
0150 chklepos:
0151     tstl    FPTEMP_HI(%a6)
0152     beqs    fixlong
0153     bra store_max
0154 
0155 operr_word:
0156     moveql  #2,%d1      |write size to d1
0157     moveb   STAG(%a6),%d0   |test stag for nan
0158     andib   #0xe0,%d0       |clr all but tag
0159     cmpib   #0x60,%d0       |check for nan
0160     beq operr_nan
0161     cmpil   #0xffff8000,FPTEMP_LO(%a6) |test if ls lword is special
0162     bnes    chkwerr     |if not equal, check for incorrect operr
0163     bsr check_upper |check if exp and ms mant are special
0164     tstl    %d0
0165     bnes    chkwerr     |if d0 is true, check for incorrect operr
0166     movel   #0x80000000,%d0 |store special case result
0167     bsr operr_store
0168     bra not_enabled |clean and exit
0169 |
0170 |   CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
0171 |
0172 chkwerr:
0173     movew   FPTEMP_EX(%a6),%d0
0174     andw    #0x7FFF,%d0 |ignore sign bit
0175     cmpw    #0x3FFE,%d0 |this is the only possible exponent value
0176     bnes    store_max
0177     movel   FPTEMP_LO(%a6),%d0
0178     swap    %d0
0179     bsr operr_store
0180     bra not_enabled
0181 
0182 operr_byte:
0183     moveql  #1,%d1      |write size to d1
0184     moveb   STAG(%a6),%d0   |test stag for nan
0185     andib   #0xe0,%d0       |clr all but tag
0186     cmpib   #0x60,%d0       |check for nan
0187     beqs    operr_nan
0188     cmpil   #0xffffff80,FPTEMP_LO(%a6) |test if ls lword is special
0189     bnes    chkberr     |if not equal, check for incorrect operr
0190     bsr check_upper |check if exp and ms mant are special
0191     tstl    %d0
0192     bnes    chkberr     |if d0 is true, check for incorrect operr
0193     movel   #0x80000000,%d0 |store special case result
0194     bsr operr_store
0195     bra not_enabled |clean and exit
0196 |
0197 |   CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
0198 |
0199 chkberr:
0200     movew   FPTEMP_EX(%a6),%d0
0201     andw    #0x7FFF,%d0 |ignore sign bit
0202     cmpw    #0x3FFE,%d0 |this is the only possible exponent value
0203     bnes    store_max
0204     movel   FPTEMP_LO(%a6),%d0
0205     asll    #8,%d0
0206     swap    %d0
0207     bsr operr_store
0208     bra not_enabled
0209 
0210 |
0211 | This operr condition is not of the special case.  Set operr
0212 | and aiop and write the portion of the nan to memory for the
0213 | given size.
0214 |
0215 operr_nan:
0216     orl #opaop_mask,USER_FPSR(%a6) |set operr & aiop
0217 
0218     movel   ETEMP_HI(%a6),%d0   |output will be from upper 32 bits
0219     bsr operr_store
0220     bra end_operr
0221 |
0222 | Store_max loads the max pos or negative for the size, sets
0223 | the operr and aiop bits, and clears inex and ainex, incorrectly
0224 | set by the 040.
0225 |
0226 store_max:
0227     orl #opaop_mask,USER_FPSR(%a6) |set operr & aiop
0228     bclrb   #inex2_bit,FPSR_EXCEPT(%a6)
0229     bclrb   #ainex_bit,FPSR_AEXCEPT(%a6)
0230     fmovel  #0,%FPSR
0231 
0232     tstw    FPTEMP_EX(%a6)  |check sign
0233     blts    load_neg
0234     movel   #0x7fffffff,%d0
0235     bsr operr_store
0236     bra end_operr
0237 load_neg:
0238     movel   #0x80000000,%d0
0239     bsr operr_store
0240     bra end_operr
0241 
0242 |
0243 | This routine stores the data in d0, for the given size in d1,
0244 | to memory or data register as required.  A read of the fline
0245 | is required to determine the destination.
0246 |
0247 operr_store:
0248     movel   %d0,L_SCR1(%a6) |move write data to L_SCR1
0249     movel   %d1,-(%a7)  |save register size
0250     bsrl    get_fline   |fline returned in d0
0251     movel   (%a7)+,%d1
0252     bftst   %d0{#26:#3}     |if mode is zero, dest is Dn
0253     bnes    dest_mem
0254 |
0255 | Destination is Dn.  Get register number from d0. Data is on
0256 | the stack at (a7). D1 has size: 1=byte,2=word,4=long/single
0257 |
0258     andil   #7,%d0      |isolate register number
0259     cmpil   #4,%d1
0260     beqs    op_long     |the most frequent case
0261     cmpil   #2,%d1
0262     bnes    op_con
0263     orl #8,%d0
0264     bras    op_con
0265 op_long:
0266     orl #0x10,%d0
0267 op_con:
0268     movel   %d0,%d1     |format size:reg for reg_dest
0269     bral    reg_dest    |call to reg_dest returns to caller
0270 |               ;of operr_store
0271 |
0272 | Destination is memory.  Get <ea> from integer exception frame
0273 | and call mem_write.
0274 |
0275 dest_mem:
0276     leal    L_SCR1(%a6),%a0 |put ptr to write data in a0
0277     movel   EXC_EA(%a6),%a1 |put user destination address in a1
0278     movel   %d1,%d0     |put size in d0
0279     bsrl    mem_write
0280     rts
0281 |
0282 | Check the exponent for $c000 and the upper 32 bits of the
0283 | mantissa for $ffffffff.  If both are true, return d0 clr
0284 | and store the lower n bits of the least lword of FPTEMP
0285 | to d0 for write out.  If not, it is a real operr, and set d0.
0286 |
0287 check_upper:
0288     cmpil   #0xffffffff,FPTEMP_HI(%a6) |check if first byte is all 1's
0289     bnes    true_operr  |if not all 1's then was true operr
0290     cmpiw   #0xc000,FPTEMP_EX(%a6) |check if incorrectly signalled
0291     beqs    not_true_operr  |branch if not true operr
0292     cmpiw   #0xbfff,FPTEMP_EX(%a6) |check if incorrectly signalled
0293     beqs    not_true_operr  |branch if not true operr
0294 true_operr:
0295     movel   #1,%d0      |signal real operr
0296     rts
0297 not_true_operr:
0298     clrl    %d0     |signal no real operr
0299     rts
0300 
0301 |
0302 | End_operr tests for operr enabled.  If not, it cleans up the stack
0303 | and does an rte.  If enabled, it cleans up the stack and branches
0304 | to the kernel operr handler with only the integer exception
0305 | frame on the stack and the fpu in the original exceptional state
0306 | with correct data written to the destination.
0307 |
0308 end_operr:
0309     btstb       #operr_bit,FPCR_ENABLE(%a6)
0310     beqs        not_enabled
0311 enabled:
0312     moveml      USER_DA(%a6),%d0-%d1/%a0-%a1
0313     fmovemx USER_FP0(%a6),%fp0-%fp3
0314     fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
0315     frestore    (%a7)+
0316     unlk        %a6
0317     bral        real_operr
0318 
0319 not_enabled:
0320 |
0321 | It is possible to have either inex2 or inex1 exceptions with the
0322 | operr.  If the inex enable bit is set in the FPCR, and either
0323 | inex2 or inex1 occurred, we must clean up and branch to the
0324 | real inex handler.
0325 |
0326 ck_inex:
0327     moveb   FPCR_ENABLE(%a6),%d0
0328     andb    FPSR_EXCEPT(%a6),%d0
0329     andib   #0x3,%d0
0330     beq operr_exit
0331 |
0332 | Inexact enabled and reported, and we must take an inexact exception.
0333 |
0334 take_inex:
0335     moveb       #INEX_VEC,EXC_VEC+1(%a6)
0336     movel       USER_FPSR(%a6),FPSR_SHADOW(%a6)
0337     orl     #sx_mask,E_BYTE(%a6)
0338     moveml      USER_DA(%a6),%d0-%d1/%a0-%a1
0339     fmovemx USER_FP0(%a6),%fp0-%fp3
0340     fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
0341     frestore    (%a7)+
0342     unlk        %a6
0343     bral        real_inex
0344 |
0345 | Since operr is only an E1 exception, there is no need to frestore
0346 | any state back to the fpu.
0347 |
0348 operr_exit:
0349     moveml      USER_DA(%a6),%d0-%d1/%a0-%a1
0350     fmovemx USER_FP0(%a6),%fp0-%fp3
0351     fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
0352     unlk        %a6
0353     bral        fpsp_done
0354 
0355     |end