11da177e4SLinus Torvalds| 21da177e4SLinus Torvalds| x_store.sa 3.2 1/24/91 31da177e4SLinus Torvalds| 41da177e4SLinus Torvalds| store --- store operand to memory or register 51da177e4SLinus Torvalds| 61da177e4SLinus Torvalds| Used by underflow and overflow handlers. 71da177e4SLinus Torvalds| 81da177e4SLinus Torvalds| a6 = points to fp value to be stored. 91da177e4SLinus Torvalds| 101da177e4SLinus Torvalds 111da177e4SLinus Torvalds| Copyright (C) Motorola, Inc. 1990 121da177e4SLinus Torvalds| All Rights Reserved 131da177e4SLinus Torvalds| 14*e00d82d0SMatt Waddel| For details on the license for this file, please see the 15*e00d82d0SMatt Waddel| file, README, in this same directory. 161da177e4SLinus Torvalds 171da177e4SLinus TorvaldsX_STORE: |idnt 2,1 | Motorola 040 Floating Point Software Package 181da177e4SLinus Torvalds 191da177e4SLinus Torvalds |section 8 201da177e4SLinus Torvalds 211da177e4SLinus Torvaldsfpreg_mask: 221da177e4SLinus Torvalds .byte 0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01 231da177e4SLinus Torvalds 241da177e4SLinus Torvalds#include "fpsp.h" 251da177e4SLinus Torvalds 261da177e4SLinus Torvalds |xref mem_write 271da177e4SLinus Torvalds |xref get_fline 281da177e4SLinus Torvalds |xref g_opcls 291da177e4SLinus Torvalds |xref g_dfmtou 301da177e4SLinus Torvalds |xref reg_dest 311da177e4SLinus Torvalds 321da177e4SLinus Torvalds .global dest_ext 331da177e4SLinus Torvalds .global dest_dbl 341da177e4SLinus Torvalds .global dest_sgl 351da177e4SLinus Torvalds 361da177e4SLinus Torvalds .global store 371da177e4SLinus Torvaldsstore: 381da177e4SLinus Torvalds btstb #E3,E_BYTE(%a6) 391da177e4SLinus Torvalds beqs E1_sto 401da177e4SLinus TorvaldsE3_sto: 411da177e4SLinus Torvalds movel CMDREG3B(%a6),%d0 421da177e4SLinus Torvalds bfextu %d0{#6:#3},%d0 |isolate dest. reg from cmdreg3b 431da177e4SLinus Torvaldssto_fp: 441da177e4SLinus Torvalds lea fpreg_mask,%a1 451da177e4SLinus Torvalds moveb (%a1,%d0.w),%d0 |convert reg# to dynamic register mask 461da177e4SLinus Torvalds tstb LOCAL_SGN(%a0) 471da177e4SLinus Torvalds beqs is_pos 481da177e4SLinus Torvalds bsetb #sign_bit,LOCAL_EX(%a0) 491da177e4SLinus Torvaldsis_pos: 501da177e4SLinus Torvalds fmovemx (%a0),%d0 |move to correct register 511da177e4SLinus Torvalds| 521da177e4SLinus Torvalds| if fp0-fp3 is being modified, we must put a copy 531da177e4SLinus Torvalds| in the USER_FPn variable on the stack because all exception 541da177e4SLinus Torvalds| handlers restore fp0-fp3 from there. 551da177e4SLinus Torvalds| 561da177e4SLinus Torvalds cmpb #0x80,%d0 571da177e4SLinus Torvalds bnes not_fp0 581da177e4SLinus Torvalds fmovemx %fp0-%fp0,USER_FP0(%a6) 591da177e4SLinus Torvalds rts 601da177e4SLinus Torvaldsnot_fp0: 611da177e4SLinus Torvalds cmpb #0x40,%d0 621da177e4SLinus Torvalds bnes not_fp1 631da177e4SLinus Torvalds fmovemx %fp1-%fp1,USER_FP1(%a6) 641da177e4SLinus Torvalds rts 651da177e4SLinus Torvaldsnot_fp1: 661da177e4SLinus Torvalds cmpb #0x20,%d0 671da177e4SLinus Torvalds bnes not_fp2 681da177e4SLinus Torvalds fmovemx %fp2-%fp2,USER_FP2(%a6) 691da177e4SLinus Torvalds rts 701da177e4SLinus Torvaldsnot_fp2: 711da177e4SLinus Torvalds cmpb #0x10,%d0 721da177e4SLinus Torvalds bnes not_fp3 731da177e4SLinus Torvalds fmovemx %fp3-%fp3,USER_FP3(%a6) 741da177e4SLinus Torvalds rts 751da177e4SLinus Torvaldsnot_fp3: 761da177e4SLinus Torvalds rts 771da177e4SLinus Torvalds 781da177e4SLinus TorvaldsE1_sto: 791da177e4SLinus Torvalds bsrl g_opcls |returns opclass in d0 801da177e4SLinus Torvalds cmpib #3,%d0 811da177e4SLinus Torvalds beq opc011 |branch if opclass 3 821da177e4SLinus Torvalds movel CMDREG1B(%a6),%d0 831da177e4SLinus Torvalds bfextu %d0{#6:#3},%d0 |extract destination register 841da177e4SLinus Torvalds bras sto_fp 851da177e4SLinus Torvalds 861da177e4SLinus Torvaldsopc011: 871da177e4SLinus Torvalds bsrl g_dfmtou |returns dest format in d0 881da177e4SLinus Torvalds| ;ext=00, sgl=01, dbl=10 891da177e4SLinus Torvalds movel %a0,%a1 |save source addr in a1 901da177e4SLinus Torvalds movel EXC_EA(%a6),%a0 |get the address 911da177e4SLinus Torvalds cmpil #0,%d0 |if dest format is extended 921da177e4SLinus Torvalds beq dest_ext |then branch 931da177e4SLinus Torvalds cmpil #1,%d0 |if dest format is single 941da177e4SLinus Torvalds beq dest_sgl |then branch 951da177e4SLinus Torvalds| 961da177e4SLinus Torvalds| fall through to dest_dbl 971da177e4SLinus Torvalds| 981da177e4SLinus Torvalds 991da177e4SLinus Torvalds| 1001da177e4SLinus Torvalds| dest_dbl --- write double precision value to user space 1011da177e4SLinus Torvalds| 1021da177e4SLinus Torvalds|Input 1031da177e4SLinus Torvalds| a0 -> destination address 1041da177e4SLinus Torvalds| a1 -> source in extended precision 1051da177e4SLinus Torvalds|Output 1061da177e4SLinus Torvalds| a0 -> destroyed 1071da177e4SLinus Torvalds| a1 -> destroyed 1081da177e4SLinus Torvalds| d0 -> 0 1091da177e4SLinus Torvalds| 1101da177e4SLinus Torvalds|Changes extended precision to double precision. 1111da177e4SLinus Torvalds| Note: no attempt is made to round the extended value to double. 1121da177e4SLinus Torvalds| dbl_sign = ext_sign 1131da177e4SLinus Torvalds| dbl_exp = ext_exp - $3fff(ext bias) + $7ff(dbl bias) 1141da177e4SLinus Torvalds| get rid of ext integer bit 1151da177e4SLinus Torvalds| dbl_mant = ext_mant{62:12} 1161da177e4SLinus Torvalds| 1171da177e4SLinus Torvalds| --------------- --------------- --------------- 1181da177e4SLinus Torvalds| extended -> |s| exp | |1| ms mant | | ls mant | 1191da177e4SLinus Torvalds| --------------- --------------- --------------- 1201da177e4SLinus Torvalds| 95 64 63 62 32 31 11 0 1211da177e4SLinus Torvalds| | | 1221da177e4SLinus Torvalds| | | 1231da177e4SLinus Torvalds| | | 1241da177e4SLinus Torvalds| v v 1251da177e4SLinus Torvalds| --------------- --------------- 1261da177e4SLinus Torvalds| double -> |s|exp| mant | | mant | 1271da177e4SLinus Torvalds| --------------- --------------- 1281da177e4SLinus Torvalds| 63 51 32 31 0 1291da177e4SLinus Torvalds| 1301da177e4SLinus Torvaldsdest_dbl: 1311da177e4SLinus Torvalds clrl %d0 |clear d0 1321da177e4SLinus Torvalds movew LOCAL_EX(%a1),%d0 |get exponent 1331da177e4SLinus Torvalds subw #0x3fff,%d0 |subtract extended precision bias 1341da177e4SLinus Torvalds cmpw #0x4000,%d0 |check if inf 1351da177e4SLinus Torvalds beqs inf |if so, special case 1361da177e4SLinus Torvalds addw #0x3ff,%d0 |add double precision bias 1371da177e4SLinus Torvalds swap %d0 |d0 now in upper word 1381da177e4SLinus Torvalds lsll #4,%d0 |d0 now in proper place for dbl prec exp 1391da177e4SLinus Torvalds tstb LOCAL_SGN(%a1) 1401da177e4SLinus Torvalds beqs get_mant |if positive, go process mantissa 1411da177e4SLinus Torvalds bsetl #31,%d0 |if negative, put in sign information 1421da177e4SLinus Torvalds| ; before continuing 1431da177e4SLinus Torvalds bras get_mant |go process mantissa 1441da177e4SLinus Torvaldsinf: 1451da177e4SLinus Torvalds movel #0x7ff00000,%d0 |load dbl inf exponent 1461da177e4SLinus Torvalds clrl LOCAL_HI(%a1) |clear msb 1471da177e4SLinus Torvalds tstb LOCAL_SGN(%a1) 1481da177e4SLinus Torvalds beqs dbl_inf |if positive, go ahead and write it 1491da177e4SLinus Torvalds bsetl #31,%d0 |if negative put in sign information 1501da177e4SLinus Torvaldsdbl_inf: 1511da177e4SLinus Torvalds movel %d0,LOCAL_EX(%a1) |put the new exp back on the stack 1521da177e4SLinus Torvalds bras dbl_wrt 1531da177e4SLinus Torvaldsget_mant: 1541da177e4SLinus Torvalds movel LOCAL_HI(%a1),%d1 |get ms mantissa 1551da177e4SLinus Torvalds bfextu %d1{#1:#20},%d1 |get upper 20 bits of ms 1561da177e4SLinus Torvalds orl %d1,%d0 |put these bits in ms word of double 1571da177e4SLinus Torvalds movel %d0,LOCAL_EX(%a1) |put the new exp back on the stack 1581da177e4SLinus Torvalds movel LOCAL_HI(%a1),%d1 |get ms mantissa 1591da177e4SLinus Torvalds movel #21,%d0 |load shift count 1601da177e4SLinus Torvalds lsll %d0,%d1 |put lower 11 bits in upper bits 1611da177e4SLinus Torvalds movel %d1,LOCAL_HI(%a1) |build lower lword in memory 1621da177e4SLinus Torvalds movel LOCAL_LO(%a1),%d1 |get ls mantissa 1631da177e4SLinus Torvalds bfextu %d1{#0:#21},%d0 |get ls 21 bits of double 1641da177e4SLinus Torvalds orl %d0,LOCAL_HI(%a1) |put them in double result 1651da177e4SLinus Torvaldsdbl_wrt: 1661da177e4SLinus Torvalds movel #0x8,%d0 |byte count for double precision number 1671da177e4SLinus Torvalds exg %a0,%a1 |a0=supervisor source, a1=user dest 1681da177e4SLinus Torvalds bsrl mem_write |move the number to the user's memory 1691da177e4SLinus Torvalds rts 1701da177e4SLinus Torvalds| 1711da177e4SLinus Torvalds| dest_sgl --- write single precision value to user space 1721da177e4SLinus Torvalds| 1731da177e4SLinus Torvalds|Input 1741da177e4SLinus Torvalds| a0 -> destination address 1751da177e4SLinus Torvalds| a1 -> source in extended precision 1761da177e4SLinus Torvalds| 1771da177e4SLinus Torvalds|Output 1781da177e4SLinus Torvalds| a0 -> destroyed 1791da177e4SLinus Torvalds| a1 -> destroyed 1801da177e4SLinus Torvalds| d0 -> 0 1811da177e4SLinus Torvalds| 1821da177e4SLinus Torvalds|Changes extended precision to single precision. 1831da177e4SLinus Torvalds| sgl_sign = ext_sign 1841da177e4SLinus Torvalds| sgl_exp = ext_exp - $3fff(ext bias) + $7f(sgl bias) 1851da177e4SLinus Torvalds| get rid of ext integer bit 1861da177e4SLinus Torvalds| sgl_mant = ext_mant{62:12} 1871da177e4SLinus Torvalds| 1881da177e4SLinus Torvalds| --------------- --------------- --------------- 1891da177e4SLinus Torvalds| extended -> |s| exp | |1| ms mant | | ls mant | 1901da177e4SLinus Torvalds| --------------- --------------- --------------- 1911da177e4SLinus Torvalds| 95 64 63 62 40 32 31 12 0 1921da177e4SLinus Torvalds| | | 1931da177e4SLinus Torvalds| | | 1941da177e4SLinus Torvalds| | | 1951da177e4SLinus Torvalds| v v 1961da177e4SLinus Torvalds| --------------- 1971da177e4SLinus Torvalds| single -> |s|exp| mant | 1981da177e4SLinus Torvalds| --------------- 1991da177e4SLinus Torvalds| 31 22 0 2001da177e4SLinus Torvalds| 2011da177e4SLinus Torvaldsdest_sgl: 2021da177e4SLinus Torvalds clrl %d0 2031da177e4SLinus Torvalds movew LOCAL_EX(%a1),%d0 |get exponent 2041da177e4SLinus Torvalds subw #0x3fff,%d0 |subtract extended precision bias 2051da177e4SLinus Torvalds cmpw #0x4000,%d0 |check if inf 2061da177e4SLinus Torvalds beqs sinf |if so, special case 2071da177e4SLinus Torvalds addw #0x7f,%d0 |add single precision bias 2081da177e4SLinus Torvalds swap %d0 |put exp in upper word of d0 2091da177e4SLinus Torvalds lsll #7,%d0 |shift it into single exp bits 2101da177e4SLinus Torvalds tstb LOCAL_SGN(%a1) 2111da177e4SLinus Torvalds beqs get_sman |if positive, continue 2121da177e4SLinus Torvalds bsetl #31,%d0 |if negative, put in sign first 2131da177e4SLinus Torvalds bras get_sman |get mantissa 2141da177e4SLinus Torvaldssinf: 2151da177e4SLinus Torvalds movel #0x7f800000,%d0 |load single inf exp to d0 2161da177e4SLinus Torvalds tstb LOCAL_SGN(%a1) 2171da177e4SLinus Torvalds beqs sgl_wrt |if positive, continue 2181da177e4SLinus Torvalds bsetl #31,%d0 |if negative, put in sign info 2191da177e4SLinus Torvalds bras sgl_wrt 2201da177e4SLinus Torvalds 2211da177e4SLinus Torvaldsget_sman: 2221da177e4SLinus Torvalds movel LOCAL_HI(%a1),%d1 |get ms mantissa 2231da177e4SLinus Torvalds bfextu %d1{#1:#23},%d1 |get upper 23 bits of ms 2241da177e4SLinus Torvalds orl %d1,%d0 |put these bits in ms word of single 2251da177e4SLinus Torvalds 2261da177e4SLinus Torvaldssgl_wrt: 2271da177e4SLinus Torvalds movel %d0,L_SCR1(%a6) |put the new exp back on the stack 2281da177e4SLinus Torvalds movel #0x4,%d0 |byte count for single precision number 2291da177e4SLinus Torvalds tstl %a0 |users destination address 2301da177e4SLinus Torvalds beqs sgl_Dn |destination is a data register 2311da177e4SLinus Torvalds exg %a0,%a1 |a0=supervisor source, a1=user dest 2321da177e4SLinus Torvalds leal L_SCR1(%a6),%a0 |point a0 to data 2331da177e4SLinus Torvalds bsrl mem_write |move the number to the user's memory 2341da177e4SLinus Torvalds rts 2351da177e4SLinus Torvaldssgl_Dn: 2361da177e4SLinus Torvalds bsrl get_fline |returns fline word in d0 2371da177e4SLinus Torvalds andw #0x7,%d0 |isolate register number 2381da177e4SLinus Torvalds movel %d0,%d1 |d1 has size:reg formatted for reg_dest 2391da177e4SLinus Torvalds orl #0x10,%d1 |reg_dest wants size added to reg# 2401da177e4SLinus Torvalds bral reg_dest |size is X, rts in reg_dest will 2411da177e4SLinus Torvalds| ;return to caller of dest_sgl 2421da177e4SLinus Torvalds 2431da177e4SLinus Torvaldsdest_ext: 2441da177e4SLinus Torvalds tstb LOCAL_SGN(%a1) |put back sign into exponent word 2451da177e4SLinus Torvalds beqs dstx_cont 2461da177e4SLinus Torvalds bsetb #sign_bit,LOCAL_EX(%a1) 2471da177e4SLinus Torvaldsdstx_cont: 2481da177e4SLinus Torvalds clrb LOCAL_SGN(%a1) |clear out the sign byte 2491da177e4SLinus Torvalds 2501da177e4SLinus Torvalds movel #0x0c,%d0 |byte count for extended number 2511da177e4SLinus Torvalds exg %a0,%a1 |a0=supervisor source, a1=user dest 2521da177e4SLinus Torvalds bsrl mem_write |move the number to the user's memory 2531da177e4SLinus Torvalds rts 2541da177e4SLinus Torvalds 2551da177e4SLinus Torvalds |end 256