1*4882a593Smuzhiyun| 2*4882a593Smuzhiyun| get_op.sa 3.6 5/19/92 3*4882a593Smuzhiyun| 4*4882a593Smuzhiyun| get_op.sa 3.5 4/26/91 5*4882a593Smuzhiyun| 6*4882a593Smuzhiyun| Description: This routine is called by the unsupported format/data 7*4882a593Smuzhiyun| type exception handler ('unsupp' - vector 55) and the unimplemented 8*4882a593Smuzhiyun| instruction exception handler ('unimp' - vector 11). 'get_op' 9*4882a593Smuzhiyun| determines the opclass (0, 2, or 3) and branches to the 10*4882a593Smuzhiyun| opclass handler routine. See 68881/2 User's Manual table 4-11 11*4882a593Smuzhiyun| for a description of the opclasses. 12*4882a593Smuzhiyun| 13*4882a593Smuzhiyun| For UNSUPPORTED data/format (exception vector 55) and for 14*4882a593Smuzhiyun| UNIMPLEMENTED instructions (exception vector 11) the following 15*4882a593Smuzhiyun| applies: 16*4882a593Smuzhiyun| 17*4882a593Smuzhiyun| - For unnormalized numbers (opclass 0, 2, or 3) the 18*4882a593Smuzhiyun| number(s) is normalized and the operand type tag is updated. 19*4882a593Smuzhiyun| 20*4882a593Smuzhiyun| - For a packed number (opclass 2) the number is unpacked and the 21*4882a593Smuzhiyun| operand type tag is updated. 22*4882a593Smuzhiyun| 23*4882a593Smuzhiyun| - For denormalized numbers (opclass 0 or 2) the number(s) is not 24*4882a593Smuzhiyun| changed but passed to the next module. The next module for 25*4882a593Smuzhiyun| unimp is do_func, the next module for unsupp is res_func. 26*4882a593Smuzhiyun| 27*4882a593Smuzhiyun| For UNSUPPORTED data/format (exception vector 55) only the 28*4882a593Smuzhiyun| following applies: 29*4882a593Smuzhiyun| 30*4882a593Smuzhiyun| - If there is a move out with a packed number (opclass 3) the 31*4882a593Smuzhiyun| number is packed and written to user memory. For the other 32*4882a593Smuzhiyun| opclasses the number(s) are written back to the fsave stack 33*4882a593Smuzhiyun| and the instruction is then restored back into the '040. The 34*4882a593Smuzhiyun| '040 is then able to complete the instruction. 35*4882a593Smuzhiyun| 36*4882a593Smuzhiyun| For example: 37*4882a593Smuzhiyun| fadd.x fpm,fpn where the fpm contains an unnormalized number. 38*4882a593Smuzhiyun| The '040 takes an unsupported data trap and gets to this 39*4882a593Smuzhiyun| routine. The number is normalized, put back on the stack and 40*4882a593Smuzhiyun| then an frestore is done to restore the instruction back into 41*4882a593Smuzhiyun| the '040. The '040 then re-executes the fadd.x fpm,fpn with 42*4882a593Smuzhiyun| a normalized number in the source and the instruction is 43*4882a593Smuzhiyun| successful. 44*4882a593Smuzhiyun| 45*4882a593Smuzhiyun| Next consider if in the process of normalizing the un- 46*4882a593Smuzhiyun| normalized number it becomes a denormalized number. The 47*4882a593Smuzhiyun| routine which converts the unnorm to a norm (called mk_norm) 48*4882a593Smuzhiyun| detects this and tags the number as a denorm. The routine 49*4882a593Smuzhiyun| res_func sees the denorm tag and converts the denorm to a 50*4882a593Smuzhiyun| norm. The instruction is then restored back into the '040 51*4882a593Smuzhiyun| which re_executes the instruction. 52*4882a593Smuzhiyun| 53*4882a593Smuzhiyun| 54*4882a593Smuzhiyun| Copyright (C) Motorola, Inc. 1990 55*4882a593Smuzhiyun| All Rights Reserved 56*4882a593Smuzhiyun| 57*4882a593Smuzhiyun| For details on the license for this file, please see the 58*4882a593Smuzhiyun| file, README, in this same directory. 59*4882a593Smuzhiyun 60*4882a593SmuzhiyunGET_OP: |idnt 2,1 | Motorola 040 Floating Point Software Package 61*4882a593Smuzhiyun 62*4882a593Smuzhiyun |section 8 63*4882a593Smuzhiyun 64*4882a593Smuzhiyun#include "fpsp.h" 65*4882a593Smuzhiyun 66*4882a593Smuzhiyun .global PIRN,PIRZRM,PIRP 67*4882a593Smuzhiyun .global SMALRN,SMALRZRM,SMALRP 68*4882a593Smuzhiyun .global BIGRN,BIGRZRM,BIGRP 69*4882a593Smuzhiyun 70*4882a593SmuzhiyunPIRN: 71*4882a593Smuzhiyun .long 0x40000000,0xc90fdaa2,0x2168c235 |pi 72*4882a593SmuzhiyunPIRZRM: 73*4882a593Smuzhiyun .long 0x40000000,0xc90fdaa2,0x2168c234 |pi 74*4882a593SmuzhiyunPIRP: 75*4882a593Smuzhiyun .long 0x40000000,0xc90fdaa2,0x2168c235 |pi 76*4882a593Smuzhiyun 77*4882a593Smuzhiyun|round to nearest 78*4882a593SmuzhiyunSMALRN: 79*4882a593Smuzhiyun .long 0x3ffd0000,0x9a209a84,0xfbcff798 |log10(2) 80*4882a593Smuzhiyun .long 0x40000000,0xadf85458,0xa2bb4a9a |e 81*4882a593Smuzhiyun .long 0x3fff0000,0xb8aa3b29,0x5c17f0bc |log2(e) 82*4882a593Smuzhiyun .long 0x3ffd0000,0xde5bd8a9,0x37287195 |log10(e) 83*4882a593Smuzhiyun .long 0x00000000,0x00000000,0x00000000 |0.0 84*4882a593Smuzhiyun| round to zero;round to negative infinity 85*4882a593SmuzhiyunSMALRZRM: 86*4882a593Smuzhiyun .long 0x3ffd0000,0x9a209a84,0xfbcff798 |log10(2) 87*4882a593Smuzhiyun .long 0x40000000,0xadf85458,0xa2bb4a9a |e 88*4882a593Smuzhiyun .long 0x3fff0000,0xb8aa3b29,0x5c17f0bb |log2(e) 89*4882a593Smuzhiyun .long 0x3ffd0000,0xde5bd8a9,0x37287195 |log10(e) 90*4882a593Smuzhiyun .long 0x00000000,0x00000000,0x00000000 |0.0 91*4882a593Smuzhiyun| round to positive infinity 92*4882a593SmuzhiyunSMALRP: 93*4882a593Smuzhiyun .long 0x3ffd0000,0x9a209a84,0xfbcff799 |log10(2) 94*4882a593Smuzhiyun .long 0x40000000,0xadf85458,0xa2bb4a9b |e 95*4882a593Smuzhiyun .long 0x3fff0000,0xb8aa3b29,0x5c17f0bc |log2(e) 96*4882a593Smuzhiyun .long 0x3ffd0000,0xde5bd8a9,0x37287195 |log10(e) 97*4882a593Smuzhiyun .long 0x00000000,0x00000000,0x00000000 |0.0 98*4882a593Smuzhiyun 99*4882a593Smuzhiyun|round to nearest 100*4882a593SmuzhiyunBIGRN: 101*4882a593Smuzhiyun .long 0x3ffe0000,0xb17217f7,0xd1cf79ac |ln(2) 102*4882a593Smuzhiyun .long 0x40000000,0x935d8ddd,0xaaa8ac17 |ln(10) 103*4882a593Smuzhiyun .long 0x3fff0000,0x80000000,0x00000000 |10 ^ 0 104*4882a593Smuzhiyun 105*4882a593Smuzhiyun .global PTENRN 106*4882a593SmuzhiyunPTENRN: 107*4882a593Smuzhiyun .long 0x40020000,0xA0000000,0x00000000 |10 ^ 1 108*4882a593Smuzhiyun .long 0x40050000,0xC8000000,0x00000000 |10 ^ 2 109*4882a593Smuzhiyun .long 0x400C0000,0x9C400000,0x00000000 |10 ^ 4 110*4882a593Smuzhiyun .long 0x40190000,0xBEBC2000,0x00000000 |10 ^ 8 111*4882a593Smuzhiyun .long 0x40340000,0x8E1BC9BF,0x04000000 |10 ^ 16 112*4882a593Smuzhiyun .long 0x40690000,0x9DC5ADA8,0x2B70B59E |10 ^ 32 113*4882a593Smuzhiyun .long 0x40D30000,0xC2781F49,0xFFCFA6D5 |10 ^ 64 114*4882a593Smuzhiyun .long 0x41A80000,0x93BA47C9,0x80E98CE0 |10 ^ 128 115*4882a593Smuzhiyun .long 0x43510000,0xAA7EEBFB,0x9DF9DE8E |10 ^ 256 116*4882a593Smuzhiyun .long 0x46A30000,0xE319A0AE,0xA60E91C7 |10 ^ 512 117*4882a593Smuzhiyun .long 0x4D480000,0xC9767586,0x81750C17 |10 ^ 1024 118*4882a593Smuzhiyun .long 0x5A920000,0x9E8B3B5D,0xC53D5DE5 |10 ^ 2048 119*4882a593Smuzhiyun .long 0x75250000,0xC4605202,0x8A20979B |10 ^ 4096 120*4882a593Smuzhiyun|round to minus infinity 121*4882a593SmuzhiyunBIGRZRM: 122*4882a593Smuzhiyun .long 0x3ffe0000,0xb17217f7,0xd1cf79ab |ln(2) 123*4882a593Smuzhiyun .long 0x40000000,0x935d8ddd,0xaaa8ac16 |ln(10) 124*4882a593Smuzhiyun .long 0x3fff0000,0x80000000,0x00000000 |10 ^ 0 125*4882a593Smuzhiyun 126*4882a593Smuzhiyun .global PTENRM 127*4882a593SmuzhiyunPTENRM: 128*4882a593Smuzhiyun .long 0x40020000,0xA0000000,0x00000000 |10 ^ 1 129*4882a593Smuzhiyun .long 0x40050000,0xC8000000,0x00000000 |10 ^ 2 130*4882a593Smuzhiyun .long 0x400C0000,0x9C400000,0x00000000 |10 ^ 4 131*4882a593Smuzhiyun .long 0x40190000,0xBEBC2000,0x00000000 |10 ^ 8 132*4882a593Smuzhiyun .long 0x40340000,0x8E1BC9BF,0x04000000 |10 ^ 16 133*4882a593Smuzhiyun .long 0x40690000,0x9DC5ADA8,0x2B70B59D |10 ^ 32 134*4882a593Smuzhiyun .long 0x40D30000,0xC2781F49,0xFFCFA6D5 |10 ^ 64 135*4882a593Smuzhiyun .long 0x41A80000,0x93BA47C9,0x80E98CDF |10 ^ 128 136*4882a593Smuzhiyun .long 0x43510000,0xAA7EEBFB,0x9DF9DE8D |10 ^ 256 137*4882a593Smuzhiyun .long 0x46A30000,0xE319A0AE,0xA60E91C6 |10 ^ 512 138*4882a593Smuzhiyun .long 0x4D480000,0xC9767586,0x81750C17 |10 ^ 1024 139*4882a593Smuzhiyun .long 0x5A920000,0x9E8B3B5D,0xC53D5DE5 |10 ^ 2048 140*4882a593Smuzhiyun .long 0x75250000,0xC4605202,0x8A20979A |10 ^ 4096 141*4882a593Smuzhiyun|round to positive infinity 142*4882a593SmuzhiyunBIGRP: 143*4882a593Smuzhiyun .long 0x3ffe0000,0xb17217f7,0xd1cf79ac |ln(2) 144*4882a593Smuzhiyun .long 0x40000000,0x935d8ddd,0xaaa8ac17 |ln(10) 145*4882a593Smuzhiyun .long 0x3fff0000,0x80000000,0x00000000 |10 ^ 0 146*4882a593Smuzhiyun 147*4882a593Smuzhiyun .global PTENRP 148*4882a593SmuzhiyunPTENRP: 149*4882a593Smuzhiyun .long 0x40020000,0xA0000000,0x00000000 |10 ^ 1 150*4882a593Smuzhiyun .long 0x40050000,0xC8000000,0x00000000 |10 ^ 2 151*4882a593Smuzhiyun .long 0x400C0000,0x9C400000,0x00000000 |10 ^ 4 152*4882a593Smuzhiyun .long 0x40190000,0xBEBC2000,0x00000000 |10 ^ 8 153*4882a593Smuzhiyun .long 0x40340000,0x8E1BC9BF,0x04000000 |10 ^ 16 154*4882a593Smuzhiyun .long 0x40690000,0x9DC5ADA8,0x2B70B59E |10 ^ 32 155*4882a593Smuzhiyun .long 0x40D30000,0xC2781F49,0xFFCFA6D6 |10 ^ 64 156*4882a593Smuzhiyun .long 0x41A80000,0x93BA47C9,0x80E98CE0 |10 ^ 128 157*4882a593Smuzhiyun .long 0x43510000,0xAA7EEBFB,0x9DF9DE8E |10 ^ 256 158*4882a593Smuzhiyun .long 0x46A30000,0xE319A0AE,0xA60E91C7 |10 ^ 512 159*4882a593Smuzhiyun .long 0x4D480000,0xC9767586,0x81750C18 |10 ^ 1024 160*4882a593Smuzhiyun .long 0x5A920000,0x9E8B3B5D,0xC53D5DE6 |10 ^ 2048 161*4882a593Smuzhiyun .long 0x75250000,0xC4605202,0x8A20979B |10 ^ 4096 162*4882a593Smuzhiyun 163*4882a593Smuzhiyun |xref nrm_zero 164*4882a593Smuzhiyun |xref decbin 165*4882a593Smuzhiyun |xref round 166*4882a593Smuzhiyun 167*4882a593Smuzhiyun .global get_op 168*4882a593Smuzhiyun .global uns_getop 169*4882a593Smuzhiyun .global uni_getop 170*4882a593Smuzhiyunget_op: 171*4882a593Smuzhiyun clrb DY_MO_FLG(%a6) 172*4882a593Smuzhiyun tstb UFLG_TMP(%a6) |test flag for unsupp/unimp state 173*4882a593Smuzhiyun beq uni_getop 174*4882a593Smuzhiyun 175*4882a593Smuzhiyununs_getop: 176*4882a593Smuzhiyun btstb #direction_bit,CMDREG1B(%a6) 177*4882a593Smuzhiyun bne opclass3 |branch if a fmove out (any kind) 178*4882a593Smuzhiyun btstb #6,CMDREG1B(%a6) 179*4882a593Smuzhiyun beqs uns_notpacked 180*4882a593Smuzhiyun 181*4882a593Smuzhiyun bfextu CMDREG1B(%a6){#3:#3},%d0 182*4882a593Smuzhiyun cmpb #3,%d0 183*4882a593Smuzhiyun beq pack_source |check for a packed src op, branch if so 184*4882a593Smuzhiyununs_notpacked: 185*4882a593Smuzhiyun bsr chk_dy_mo |set the dyadic/monadic flag 186*4882a593Smuzhiyun tstb DY_MO_FLG(%a6) 187*4882a593Smuzhiyun beqs src_op_ck |if monadic, go check src op 188*4882a593Smuzhiyun| ;else, check dst op (fall through) 189*4882a593Smuzhiyun 190*4882a593Smuzhiyun btstb #7,DTAG(%a6) 191*4882a593Smuzhiyun beqs src_op_ck |if dst op is norm, check src op 192*4882a593Smuzhiyun bras dst_ex_dnrm |else, handle destination unnorm/dnrm 193*4882a593Smuzhiyun 194*4882a593Smuzhiyununi_getop: 195*4882a593Smuzhiyun bfextu CMDREG1B(%a6){#0:#6},%d0 |get opclass and src fields 196*4882a593Smuzhiyun cmpil #0x17,%d0 |if op class and size fields are $17, 197*4882a593Smuzhiyun| ;it is FMOVECR; if not, continue 198*4882a593Smuzhiyun| 199*4882a593Smuzhiyun| If the instruction is fmovecr, exit get_op. It is handled 200*4882a593Smuzhiyun| in do_func and smovecr.sa. 201*4882a593Smuzhiyun| 202*4882a593Smuzhiyun bne not_fmovecr |handle fmovecr as an unimplemented inst 203*4882a593Smuzhiyun rts 204*4882a593Smuzhiyun 205*4882a593Smuzhiyunnot_fmovecr: 206*4882a593Smuzhiyun btstb #E1,E_BYTE(%a6) |if set, there is a packed operand 207*4882a593Smuzhiyun bne pack_source |check for packed src op, branch if so 208*4882a593Smuzhiyun 209*4882a593Smuzhiyun| The following lines of are coded to optimize on normalized operands 210*4882a593Smuzhiyun moveb STAG(%a6),%d0 211*4882a593Smuzhiyun orb DTAG(%a6),%d0 |check if either of STAG/DTAG msb set 212*4882a593Smuzhiyun bmis dest_op_ck |if so, some op needs to be fixed 213*4882a593Smuzhiyun rts 214*4882a593Smuzhiyun 215*4882a593Smuzhiyundest_op_ck: 216*4882a593Smuzhiyun btstb #7,DTAG(%a6) |check for unsupported data types in 217*4882a593Smuzhiyun beqs src_op_ck |the destination, if not, check src op 218*4882a593Smuzhiyun bsr chk_dy_mo |set dyadic/monadic flag 219*4882a593Smuzhiyun tstb DY_MO_FLG(%a6) | 220*4882a593Smuzhiyun beqs src_op_ck |if monadic, check src op 221*4882a593Smuzhiyun| 222*4882a593Smuzhiyun| At this point, destination has an extended denorm or unnorm. 223*4882a593Smuzhiyun| 224*4882a593Smuzhiyundst_ex_dnrm: 225*4882a593Smuzhiyun movew FPTEMP_EX(%a6),%d0 |get destination exponent 226*4882a593Smuzhiyun andiw #0x7fff,%d0 |mask sign, check if exp = 0000 227*4882a593Smuzhiyun beqs src_op_ck |if denorm then check source op. 228*4882a593Smuzhiyun| ;denorms are taken care of in res_func 229*4882a593Smuzhiyun| ;(unsupp) or do_func (unimp) 230*4882a593Smuzhiyun| ;else unnorm fall through 231*4882a593Smuzhiyun leal FPTEMP(%a6),%a0 |point a0 to dop - used in mk_norm 232*4882a593Smuzhiyun bsr mk_norm |go normalize - mk_norm returns: 233*4882a593Smuzhiyun| ;L_SCR1{7:5} = operand tag 234*4882a593Smuzhiyun| ; (000 = norm, 100 = denorm) 235*4882a593Smuzhiyun| ;L_SCR1{4} = fpte15 or ete15 236*4882a593Smuzhiyun| ; 0 = exp > $3fff 237*4882a593Smuzhiyun| ; 1 = exp <= $3fff 238*4882a593Smuzhiyun| ;and puts the normalized num back 239*4882a593Smuzhiyun| ;on the fsave stack 240*4882a593Smuzhiyun| 241*4882a593Smuzhiyun moveb L_SCR1(%a6),DTAG(%a6) |write the new tag & fpte15 242*4882a593Smuzhiyun| ;to the fsave stack and fall 243*4882a593Smuzhiyun| ;through to check source operand 244*4882a593Smuzhiyun| 245*4882a593Smuzhiyunsrc_op_ck: 246*4882a593Smuzhiyun btstb #7,STAG(%a6) 247*4882a593Smuzhiyun beq end_getop |check for unsupported data types on the 248*4882a593Smuzhiyun| ;source operand 249*4882a593Smuzhiyun btstb #5,STAG(%a6) 250*4882a593Smuzhiyun bnes src_sd_dnrm |if bit 5 set, handle sgl/dbl denorms 251*4882a593Smuzhiyun| 252*4882a593Smuzhiyun| At this point only unnorms or extended denorms are possible. 253*4882a593Smuzhiyun| 254*4882a593Smuzhiyunsrc_ex_dnrm: 255*4882a593Smuzhiyun movew ETEMP_EX(%a6),%d0 |get source exponent 256*4882a593Smuzhiyun andiw #0x7fff,%d0 |mask sign, check if exp = 0000 257*4882a593Smuzhiyun beq end_getop |if denorm then exit, denorms are 258*4882a593Smuzhiyun| ;handled in do_func 259*4882a593Smuzhiyun leal ETEMP(%a6),%a0 |point a0 to sop - used in mk_norm 260*4882a593Smuzhiyun bsr mk_norm |go normalize - mk_norm returns: 261*4882a593Smuzhiyun| ;L_SCR1{7:5} = operand tag 262*4882a593Smuzhiyun| ; (000 = norm, 100 = denorm) 263*4882a593Smuzhiyun| ;L_SCR1{4} = fpte15 or ete15 264*4882a593Smuzhiyun| ; 0 = exp > $3fff 265*4882a593Smuzhiyun| ; 1 = exp <= $3fff 266*4882a593Smuzhiyun| ;and puts the normalized num back 267*4882a593Smuzhiyun| ;on the fsave stack 268*4882a593Smuzhiyun| 269*4882a593Smuzhiyun moveb L_SCR1(%a6),STAG(%a6) |write the new tag & ete15 270*4882a593Smuzhiyun rts |end_getop 271*4882a593Smuzhiyun 272*4882a593Smuzhiyun| 273*4882a593Smuzhiyun| At this point, only single or double denorms are possible. 274*4882a593Smuzhiyun| If the inst is not fmove, normalize the source. If it is, 275*4882a593Smuzhiyun| do nothing to the input. 276*4882a593Smuzhiyun| 277*4882a593Smuzhiyunsrc_sd_dnrm: 278*4882a593Smuzhiyun btstb #4,CMDREG1B(%a6) |differentiate between sgl/dbl denorm 279*4882a593Smuzhiyun bnes is_double 280*4882a593Smuzhiyunis_single: 281*4882a593Smuzhiyun movew #0x3f81,%d1 |write bias for sgl denorm 282*4882a593Smuzhiyun bras common |goto the common code 283*4882a593Smuzhiyunis_double: 284*4882a593Smuzhiyun movew #0x3c01,%d1 |write the bias for a dbl denorm 285*4882a593Smuzhiyuncommon: 286*4882a593Smuzhiyun btstb #sign_bit,ETEMP_EX(%a6) |grab sign bit of mantissa 287*4882a593Smuzhiyun beqs pos 288*4882a593Smuzhiyun bset #15,%d1 |set sign bit because it is negative 289*4882a593Smuzhiyunpos: 290*4882a593Smuzhiyun movew %d1,ETEMP_EX(%a6) 291*4882a593Smuzhiyun| ;put exponent on stack 292*4882a593Smuzhiyun 293*4882a593Smuzhiyun movew CMDREG1B(%a6),%d1 294*4882a593Smuzhiyun andw #0xe3ff,%d1 |clear out source specifier 295*4882a593Smuzhiyun orw #0x0800,%d1 |set source specifier to extended prec 296*4882a593Smuzhiyun movew %d1,CMDREG1B(%a6) |write back to the command word in stack 297*4882a593Smuzhiyun| ;this is needed to fix unsupp data stack 298*4882a593Smuzhiyun leal ETEMP(%a6),%a0 |point a0 to sop 299*4882a593Smuzhiyun 300*4882a593Smuzhiyun bsr mk_norm |convert sgl/dbl denorm to norm 301*4882a593Smuzhiyun moveb L_SCR1(%a6),STAG(%a6) |put tag into source tag reg - d0 302*4882a593Smuzhiyun rts |end_getop 303*4882a593Smuzhiyun| 304*4882a593Smuzhiyun| At this point, the source is definitely packed, whether 305*4882a593Smuzhiyun| instruction is dyadic or monadic is still unknown 306*4882a593Smuzhiyun| 307*4882a593Smuzhiyunpack_source: 308*4882a593Smuzhiyun movel FPTEMP_LO(%a6),ETEMP(%a6) |write ms part of packed 309*4882a593Smuzhiyun| ;number to etemp slot 310*4882a593Smuzhiyun bsr chk_dy_mo |set dyadic/monadic flag 311*4882a593Smuzhiyun bsr unpack 312*4882a593Smuzhiyun 313*4882a593Smuzhiyun tstb DY_MO_FLG(%a6) 314*4882a593Smuzhiyun beqs end_getop |if monadic, exit 315*4882a593Smuzhiyun| ;else, fix FPTEMP 316*4882a593Smuzhiyunpack_dya: 317*4882a593Smuzhiyun bfextu CMDREG1B(%a6){#6:#3},%d0 |extract dest fp reg 318*4882a593Smuzhiyun movel #7,%d1 319*4882a593Smuzhiyun subl %d0,%d1 320*4882a593Smuzhiyun clrl %d0 321*4882a593Smuzhiyun bsetl %d1,%d0 |set up d0 as a dynamic register mask 322*4882a593Smuzhiyun fmovemx %d0,FPTEMP(%a6) |write to FPTEMP 323*4882a593Smuzhiyun 324*4882a593Smuzhiyun btstb #7,DTAG(%a6) |check dest tag for unnorm or denorm 325*4882a593Smuzhiyun bne dst_ex_dnrm |else, handle the unnorm or ext denorm 326*4882a593Smuzhiyun| 327*4882a593Smuzhiyun| Dest is not denormalized. Check for norm, and set fpte15 328*4882a593Smuzhiyun| accordingly. 329*4882a593Smuzhiyun| 330*4882a593Smuzhiyun moveb DTAG(%a6),%d0 331*4882a593Smuzhiyun andib #0xf0,%d0 |strip to only dtag:fpte15 332*4882a593Smuzhiyun tstb %d0 |check for normalized value 333*4882a593Smuzhiyun bnes end_getop |if inf/nan/zero leave get_op 334*4882a593Smuzhiyun movew FPTEMP_EX(%a6),%d0 335*4882a593Smuzhiyun andiw #0x7fff,%d0 336*4882a593Smuzhiyun cmpiw #0x3fff,%d0 |check if fpte15 needs setting 337*4882a593Smuzhiyun bges end_getop |if >= $3fff, leave fpte15=0 338*4882a593Smuzhiyun orb #0x10,DTAG(%a6) 339*4882a593Smuzhiyun bras end_getop 340*4882a593Smuzhiyun 341*4882a593Smuzhiyun| 342*4882a593Smuzhiyun| At this point, it is either an fmoveout packed, unnorm or denorm 343*4882a593Smuzhiyun| 344*4882a593Smuzhiyunopclass3: 345*4882a593Smuzhiyun clrb DY_MO_FLG(%a6) |set dyadic/monadic flag to monadic 346*4882a593Smuzhiyun bfextu CMDREG1B(%a6){#4:#2},%d0 347*4882a593Smuzhiyun cmpib #3,%d0 348*4882a593Smuzhiyun bne src_ex_dnrm |if not equal, must be unnorm or denorm 349*4882a593Smuzhiyun| ;else it is a packed move out 350*4882a593Smuzhiyun| ;exit 351*4882a593Smuzhiyunend_getop: 352*4882a593Smuzhiyun rts 353*4882a593Smuzhiyun 354*4882a593Smuzhiyun| 355*4882a593Smuzhiyun| Sets the DY_MO_FLG correctly. This is used only on if it is an 356*4882a593Smuzhiyun| unsupported data type exception. Set if dyadic. 357*4882a593Smuzhiyun| 358*4882a593Smuzhiyunchk_dy_mo: 359*4882a593Smuzhiyun movew CMDREG1B(%a6),%d0 360*4882a593Smuzhiyun btstl #5,%d0 |testing extension command word 361*4882a593Smuzhiyun beqs set_mon |if bit 5 = 0 then monadic 362*4882a593Smuzhiyun btstl #4,%d0 |know that bit 5 = 1 363*4882a593Smuzhiyun beqs set_dya |if bit 4 = 0 then dyadic 364*4882a593Smuzhiyun andiw #0x007f,%d0 |get rid of all but extension bits {6:0} 365*4882a593Smuzhiyun cmpiw #0x0038,%d0 |if extension = $38 then fcmp (dyadic) 366*4882a593Smuzhiyun bnes set_mon 367*4882a593Smuzhiyunset_dya: 368*4882a593Smuzhiyun st DY_MO_FLG(%a6) |set the inst flag type to dyadic 369*4882a593Smuzhiyun rts 370*4882a593Smuzhiyunset_mon: 371*4882a593Smuzhiyun clrb DY_MO_FLG(%a6) |set the inst flag type to monadic 372*4882a593Smuzhiyun rts 373*4882a593Smuzhiyun| 374*4882a593Smuzhiyun| MK_NORM 375*4882a593Smuzhiyun| 376*4882a593Smuzhiyun| Normalizes unnormalized numbers, sets tag to norm or denorm, sets unfl 377*4882a593Smuzhiyun| exception if denorm. 378*4882a593Smuzhiyun| 379*4882a593Smuzhiyun| CASE opclass 0x0 unsupp 380*4882a593Smuzhiyun| mk_norm till msb set 381*4882a593Smuzhiyun| set tag = norm 382*4882a593Smuzhiyun| 383*4882a593Smuzhiyun| CASE opclass 0x0 unimp 384*4882a593Smuzhiyun| mk_norm till msb set or exp = 0 385*4882a593Smuzhiyun| if integer bit = 0 386*4882a593Smuzhiyun| tag = denorm 387*4882a593Smuzhiyun| else 388*4882a593Smuzhiyun| tag = norm 389*4882a593Smuzhiyun| 390*4882a593Smuzhiyun| CASE opclass 011 unsupp 391*4882a593Smuzhiyun| mk_norm till msb set or exp = 0 392*4882a593Smuzhiyun| if integer bit = 0 393*4882a593Smuzhiyun| tag = denorm 394*4882a593Smuzhiyun| set unfl_nmcexe = 1 395*4882a593Smuzhiyun| else 396*4882a593Smuzhiyun| tag = norm 397*4882a593Smuzhiyun| 398*4882a593Smuzhiyun| if exp <= $3fff 399*4882a593Smuzhiyun| set ete15 or fpte15 = 1 400*4882a593Smuzhiyun| else set ete15 or fpte15 = 0 401*4882a593Smuzhiyun 402*4882a593Smuzhiyun| input: 403*4882a593Smuzhiyun| a0 = points to operand to be normalized 404*4882a593Smuzhiyun| output: 405*4882a593Smuzhiyun| L_SCR1{7:5} = operand tag (000 = norm, 100 = denorm) 406*4882a593Smuzhiyun| L_SCR1{4} = fpte15 or ete15 (0 = exp > $3fff, 1 = exp <=$3fff) 407*4882a593Smuzhiyun| the normalized operand is placed back on the fsave stack 408*4882a593Smuzhiyunmk_norm: 409*4882a593Smuzhiyun clrl L_SCR1(%a6) 410*4882a593Smuzhiyun bclrb #sign_bit,LOCAL_EX(%a0) 411*4882a593Smuzhiyun sne LOCAL_SGN(%a0) |transform into internal extended format 412*4882a593Smuzhiyun 413*4882a593Smuzhiyun cmpib #0x2c,1+EXC_VEC(%a6) |check if unimp 414*4882a593Smuzhiyun bnes uns_data |branch if unsupp 415*4882a593Smuzhiyun bsr uni_inst |call if unimp (opclass 0x0) 416*4882a593Smuzhiyun bras reload 417*4882a593Smuzhiyununs_data: 418*4882a593Smuzhiyun btstb #direction_bit,CMDREG1B(%a6) |check transfer direction 419*4882a593Smuzhiyun bnes bit_set |branch if set (opclass 011) 420*4882a593Smuzhiyun bsr uns_opx |call if opclass 0x0 421*4882a593Smuzhiyun bras reload 422*4882a593Smuzhiyunbit_set: 423*4882a593Smuzhiyun bsr uns_op3 |opclass 011 424*4882a593Smuzhiyunreload: 425*4882a593Smuzhiyun cmpw #0x3fff,LOCAL_EX(%a0) |if exp > $3fff 426*4882a593Smuzhiyun bgts end_mk | fpte15/ete15 already set to 0 427*4882a593Smuzhiyun bsetb #4,L_SCR1(%a6) |else set fpte15/ete15 to 1 428*4882a593Smuzhiyun| ;calling routine actually sets the 429*4882a593Smuzhiyun| ;value on the stack (along with the 430*4882a593Smuzhiyun| ;tag), since this routine doesn't 431*4882a593Smuzhiyun| ;know if it should set ete15 or fpte15 432*4882a593Smuzhiyun| ;ie, it doesn't know if this is the 433*4882a593Smuzhiyun| ;src op or dest op. 434*4882a593Smuzhiyunend_mk: 435*4882a593Smuzhiyun bfclr LOCAL_SGN(%a0){#0:#8} 436*4882a593Smuzhiyun beqs end_mk_pos 437*4882a593Smuzhiyun bsetb #sign_bit,LOCAL_EX(%a0) |convert back to IEEE format 438*4882a593Smuzhiyunend_mk_pos: 439*4882a593Smuzhiyun rts 440*4882a593Smuzhiyun| 441*4882a593Smuzhiyun| CASE opclass 011 unsupp 442*4882a593Smuzhiyun| 443*4882a593Smuzhiyununs_op3: 444*4882a593Smuzhiyun bsr nrm_zero |normalize till msb = 1 or exp = zero 445*4882a593Smuzhiyun btstb #7,LOCAL_HI(%a0) |if msb = 1 446*4882a593Smuzhiyun bnes no_unfl |then branch 447*4882a593Smuzhiyunset_unfl: 448*4882a593Smuzhiyun orw #dnrm_tag,L_SCR1(%a6) |set denorm tag 449*4882a593Smuzhiyun bsetb #unfl_bit,FPSR_EXCEPT(%a6) |set unfl exception bit 450*4882a593Smuzhiyunno_unfl: 451*4882a593Smuzhiyun rts 452*4882a593Smuzhiyun| 453*4882a593Smuzhiyun| CASE opclass 0x0 unsupp 454*4882a593Smuzhiyun| 455*4882a593Smuzhiyununs_opx: 456*4882a593Smuzhiyun bsr nrm_zero |normalize the number 457*4882a593Smuzhiyun btstb #7,LOCAL_HI(%a0) |check if integer bit (j-bit) is set 458*4882a593Smuzhiyun beqs uns_den |if clear then now have a denorm 459*4882a593Smuzhiyununs_nrm: 460*4882a593Smuzhiyun orb #norm_tag,L_SCR1(%a6) |set tag to norm 461*4882a593Smuzhiyun rts 462*4882a593Smuzhiyununs_den: 463*4882a593Smuzhiyun orb #dnrm_tag,L_SCR1(%a6) |set tag to denorm 464*4882a593Smuzhiyun rts 465*4882a593Smuzhiyun| 466*4882a593Smuzhiyun| CASE opclass 0x0 unimp 467*4882a593Smuzhiyun| 468*4882a593Smuzhiyununi_inst: 469*4882a593Smuzhiyun bsr nrm_zero 470*4882a593Smuzhiyun btstb #7,LOCAL_HI(%a0) |check if integer bit (j-bit) is set 471*4882a593Smuzhiyun beqs uni_den |if clear then now have a denorm 472*4882a593Smuzhiyununi_nrm: 473*4882a593Smuzhiyun orb #norm_tag,L_SCR1(%a6) |set tag to norm 474*4882a593Smuzhiyun rts 475*4882a593Smuzhiyununi_den: 476*4882a593Smuzhiyun orb #dnrm_tag,L_SCR1(%a6) |set tag to denorm 477*4882a593Smuzhiyun rts 478*4882a593Smuzhiyun 479*4882a593Smuzhiyun| 480*4882a593Smuzhiyun| Decimal to binary conversion 481*4882a593Smuzhiyun| 482*4882a593Smuzhiyun| Special cases of inf and NaNs are completed outside of decbin. 483*4882a593Smuzhiyun| If the input is an snan, the snan bit is not set. 484*4882a593Smuzhiyun| 485*4882a593Smuzhiyun| input: 486*4882a593Smuzhiyun| ETEMP(a6) - points to packed decimal string in memory 487*4882a593Smuzhiyun| output: 488*4882a593Smuzhiyun| fp0 - contains packed string converted to extended precision 489*4882a593Smuzhiyun| ETEMP - same as fp0 490*4882a593Smuzhiyununpack: 491*4882a593Smuzhiyun movew CMDREG1B(%a6),%d0 |examine command word, looking for fmove's 492*4882a593Smuzhiyun andw #0x3b,%d0 493*4882a593Smuzhiyun beq move_unpack |special handling for fmove: must set FPSR_CC 494*4882a593Smuzhiyun 495*4882a593Smuzhiyun movew ETEMP(%a6),%d0 |get word with inf information 496*4882a593Smuzhiyun bfextu %d0{#20:#12},%d1 |get exponent into d1 497*4882a593Smuzhiyun cmpiw #0x0fff,%d1 |test for inf or NaN 498*4882a593Smuzhiyun bnes try_zero |if not equal, it is not special 499*4882a593Smuzhiyun bfextu %d0{#17:#3},%d1 |get SE and y bits into d1 500*4882a593Smuzhiyun cmpiw #7,%d1 |SE and y bits must be on for special 501*4882a593Smuzhiyun bnes try_zero |if not on, it is not special 502*4882a593Smuzhiyun|input is of the special cases of inf and NaN 503*4882a593Smuzhiyun tstl ETEMP_HI(%a6) |check ms mantissa 504*4882a593Smuzhiyun bnes fix_nan |if non-zero, it is a NaN 505*4882a593Smuzhiyun tstl ETEMP_LO(%a6) |check ls mantissa 506*4882a593Smuzhiyun bnes fix_nan |if non-zero, it is a NaN 507*4882a593Smuzhiyun bra finish |special already on stack 508*4882a593Smuzhiyunfix_nan: 509*4882a593Smuzhiyun btstb #signan_bit,ETEMP_HI(%a6) |test for snan 510*4882a593Smuzhiyun bne finish 511*4882a593Smuzhiyun orl #snaniop_mask,USER_FPSR(%a6) |always set snan if it is so 512*4882a593Smuzhiyun bra finish 513*4882a593Smuzhiyuntry_zero: 514*4882a593Smuzhiyun movew ETEMP_EX+2(%a6),%d0 |get word 4 515*4882a593Smuzhiyun andiw #0x000f,%d0 |clear all but last ni(y)bble 516*4882a593Smuzhiyun tstw %d0 |check for zero. 517*4882a593Smuzhiyun bne not_spec 518*4882a593Smuzhiyun tstl ETEMP_HI(%a6) |check words 3 and 2 519*4882a593Smuzhiyun bne not_spec 520*4882a593Smuzhiyun tstl ETEMP_LO(%a6) |check words 1 and 0 521*4882a593Smuzhiyun bne not_spec 522*4882a593Smuzhiyun tstl ETEMP(%a6) |test sign of the zero 523*4882a593Smuzhiyun bges pos_zero 524*4882a593Smuzhiyun movel #0x80000000,ETEMP(%a6) |write neg zero to etemp 525*4882a593Smuzhiyun clrl ETEMP_HI(%a6) 526*4882a593Smuzhiyun clrl ETEMP_LO(%a6) 527*4882a593Smuzhiyun bra finish 528*4882a593Smuzhiyunpos_zero: 529*4882a593Smuzhiyun clrl ETEMP(%a6) 530*4882a593Smuzhiyun clrl ETEMP_HI(%a6) 531*4882a593Smuzhiyun clrl ETEMP_LO(%a6) 532*4882a593Smuzhiyun bra finish 533*4882a593Smuzhiyun 534*4882a593Smuzhiyunnot_spec: 535*4882a593Smuzhiyun fmovemx %fp0-%fp1,-(%a7) |save fp0 - decbin returns in it 536*4882a593Smuzhiyun bsr decbin 537*4882a593Smuzhiyun fmovex %fp0,ETEMP(%a6) |put the unpacked sop in the fsave stack 538*4882a593Smuzhiyun fmovemx (%a7)+,%fp0-%fp1 539*4882a593Smuzhiyun fmovel #0,%FPSR |clr fpsr from decbin 540*4882a593Smuzhiyun bra finish 541*4882a593Smuzhiyun 542*4882a593Smuzhiyun| 543*4882a593Smuzhiyun| Special handling for packed move in: Same results as all other 544*4882a593Smuzhiyun| packed cases, but we must set the FPSR condition codes properly. 545*4882a593Smuzhiyun| 546*4882a593Smuzhiyunmove_unpack: 547*4882a593Smuzhiyun movew ETEMP(%a6),%d0 |get word with inf information 548*4882a593Smuzhiyun bfextu %d0{#20:#12},%d1 |get exponent into d1 549*4882a593Smuzhiyun cmpiw #0x0fff,%d1 |test for inf or NaN 550*4882a593Smuzhiyun bnes mtry_zero |if not equal, it is not special 551*4882a593Smuzhiyun bfextu %d0{#17:#3},%d1 |get SE and y bits into d1 552*4882a593Smuzhiyun cmpiw #7,%d1 |SE and y bits must be on for special 553*4882a593Smuzhiyun bnes mtry_zero |if not on, it is not special 554*4882a593Smuzhiyun|input is of the special cases of inf and NaN 555*4882a593Smuzhiyun tstl ETEMP_HI(%a6) |check ms mantissa 556*4882a593Smuzhiyun bnes mfix_nan |if non-zero, it is a NaN 557*4882a593Smuzhiyun tstl ETEMP_LO(%a6) |check ls mantissa 558*4882a593Smuzhiyun bnes mfix_nan |if non-zero, it is a NaN 559*4882a593Smuzhiyun|input is inf 560*4882a593Smuzhiyun orl #inf_mask,USER_FPSR(%a6) |set I bit 561*4882a593Smuzhiyun tstl ETEMP(%a6) |check sign 562*4882a593Smuzhiyun bge finish 563*4882a593Smuzhiyun orl #neg_mask,USER_FPSR(%a6) |set N bit 564*4882a593Smuzhiyun bra finish |special already on stack 565*4882a593Smuzhiyunmfix_nan: 566*4882a593Smuzhiyun orl #nan_mask,USER_FPSR(%a6) |set NaN bit 567*4882a593Smuzhiyun moveb #nan_tag,STAG(%a6) |set stag to NaN 568*4882a593Smuzhiyun btstb #signan_bit,ETEMP_HI(%a6) |test for snan 569*4882a593Smuzhiyun bnes mn_snan 570*4882a593Smuzhiyun orl #snaniop_mask,USER_FPSR(%a6) |set snan bit 571*4882a593Smuzhiyun btstb #snan_bit,FPCR_ENABLE(%a6) |test for snan enabled 572*4882a593Smuzhiyun bnes mn_snan 573*4882a593Smuzhiyun bsetb #signan_bit,ETEMP_HI(%a6) |force snans to qnans 574*4882a593Smuzhiyunmn_snan: 575*4882a593Smuzhiyun tstl ETEMP(%a6) |check for sign 576*4882a593Smuzhiyun bge finish |if clr, go on 577*4882a593Smuzhiyun orl #neg_mask,USER_FPSR(%a6) |set N bit 578*4882a593Smuzhiyun bra finish 579*4882a593Smuzhiyun 580*4882a593Smuzhiyunmtry_zero: 581*4882a593Smuzhiyun movew ETEMP_EX+2(%a6),%d0 |get word 4 582*4882a593Smuzhiyun andiw #0x000f,%d0 |clear all but last ni(y)bble 583*4882a593Smuzhiyun tstw %d0 |check for zero. 584*4882a593Smuzhiyun bnes mnot_spec 585*4882a593Smuzhiyun tstl ETEMP_HI(%a6) |check words 3 and 2 586*4882a593Smuzhiyun bnes mnot_spec 587*4882a593Smuzhiyun tstl ETEMP_LO(%a6) |check words 1 and 0 588*4882a593Smuzhiyun bnes mnot_spec 589*4882a593Smuzhiyun tstl ETEMP(%a6) |test sign of the zero 590*4882a593Smuzhiyun bges mpos_zero 591*4882a593Smuzhiyun orl #neg_mask+z_mask,USER_FPSR(%a6) |set N and Z 592*4882a593Smuzhiyun movel #0x80000000,ETEMP(%a6) |write neg zero to etemp 593*4882a593Smuzhiyun clrl ETEMP_HI(%a6) 594*4882a593Smuzhiyun clrl ETEMP_LO(%a6) 595*4882a593Smuzhiyun bras finish 596*4882a593Smuzhiyunmpos_zero: 597*4882a593Smuzhiyun orl #z_mask,USER_FPSR(%a6) |set Z 598*4882a593Smuzhiyun clrl ETEMP(%a6) 599*4882a593Smuzhiyun clrl ETEMP_HI(%a6) 600*4882a593Smuzhiyun clrl ETEMP_LO(%a6) 601*4882a593Smuzhiyun bras finish 602*4882a593Smuzhiyun 603*4882a593Smuzhiyunmnot_spec: 604*4882a593Smuzhiyun fmovemx %fp0-%fp1,-(%a7) |save fp0 ,fp1 - decbin returns in fp0 605*4882a593Smuzhiyun bsr decbin 606*4882a593Smuzhiyun fmovex %fp0,ETEMP(%a6) 607*4882a593Smuzhiyun| ;put the unpacked sop in the fsave stack 608*4882a593Smuzhiyun fmovemx (%a7)+,%fp0-%fp1 609*4882a593Smuzhiyun 610*4882a593Smuzhiyunfinish: 611*4882a593Smuzhiyun movew CMDREG1B(%a6),%d0 |get the command word 612*4882a593Smuzhiyun andw #0xfbff,%d0 |change the source specifier field to 613*4882a593Smuzhiyun| ;extended (was packed). 614*4882a593Smuzhiyun movew %d0,CMDREG1B(%a6) |write command word back to fsave stack 615*4882a593Smuzhiyun| ;we need to do this so the 040 will 616*4882a593Smuzhiyun| ;re-execute the inst. without taking 617*4882a593Smuzhiyun| ;another packed trap. 618*4882a593Smuzhiyun 619*4882a593Smuzhiyunfix_stag: 620*4882a593Smuzhiyun|Converted result is now in etemp on fsave stack, now set the source 621*4882a593Smuzhiyun|tag (stag) 622*4882a593Smuzhiyun| if (ete =$7fff) then INF or NAN 623*4882a593Smuzhiyun| if (etemp = $x.0----0) then 624*4882a593Smuzhiyun| stag = INF 625*4882a593Smuzhiyun| else 626*4882a593Smuzhiyun| stag = NAN 627*4882a593Smuzhiyun| else 628*4882a593Smuzhiyun| if (ete = $0000) then 629*4882a593Smuzhiyun| stag = ZERO 630*4882a593Smuzhiyun| else 631*4882a593Smuzhiyun| stag = NORM 632*4882a593Smuzhiyun| 633*4882a593Smuzhiyun| Note also that the etemp_15 bit (just right of the stag) must 634*4882a593Smuzhiyun| be set accordingly. 635*4882a593Smuzhiyun| 636*4882a593Smuzhiyun movew ETEMP_EX(%a6),%d1 637*4882a593Smuzhiyun andiw #0x7fff,%d1 |strip sign 638*4882a593Smuzhiyun cmpw #0x7fff,%d1 639*4882a593Smuzhiyun bnes z_or_nrm 640*4882a593Smuzhiyun movel ETEMP_HI(%a6),%d1 641*4882a593Smuzhiyun bnes is_nan 642*4882a593Smuzhiyun movel ETEMP_LO(%a6),%d1 643*4882a593Smuzhiyun bnes is_nan 644*4882a593Smuzhiyunis_inf: 645*4882a593Smuzhiyun moveb #0x40,STAG(%a6) 646*4882a593Smuzhiyun movel #0x40,%d0 647*4882a593Smuzhiyun rts 648*4882a593Smuzhiyunis_nan: 649*4882a593Smuzhiyun moveb #0x60,STAG(%a6) 650*4882a593Smuzhiyun movel #0x60,%d0 651*4882a593Smuzhiyun rts 652*4882a593Smuzhiyunz_or_nrm: 653*4882a593Smuzhiyun tstw %d1 654*4882a593Smuzhiyun bnes is_nrm 655*4882a593Smuzhiyunis_zro: 656*4882a593Smuzhiyun| For a zero, set etemp_15 657*4882a593Smuzhiyun moveb #0x30,STAG(%a6) 658*4882a593Smuzhiyun movel #0x20,%d0 659*4882a593Smuzhiyun rts 660*4882a593Smuzhiyunis_nrm: 661*4882a593Smuzhiyun| For a norm, check if the exp <= $3fff; if so, set etemp_15 662*4882a593Smuzhiyun cmpiw #0x3fff,%d1 663*4882a593Smuzhiyun bles set_bit15 664*4882a593Smuzhiyun moveb #0,STAG(%a6) 665*4882a593Smuzhiyun bras end_is_nrm 666*4882a593Smuzhiyunset_bit15: 667*4882a593Smuzhiyun moveb #0x10,STAG(%a6) 668*4882a593Smuzhiyunend_is_nrm: 669*4882a593Smuzhiyun movel #0,%d0 670*4882a593Smuzhiyunend_fix: 671*4882a593Smuzhiyun rts 672*4882a593Smuzhiyun 673*4882a593Smuzhiyunend_get: 674*4882a593Smuzhiyun rts 675*4882a593Smuzhiyun |end 676