util.sa revision 1.5
11.5Sandvar* $NetBSD: util.sa,v 1.5 2022/04/08 10:17:53 andvar Exp $ 21.3Scgd 31.1Smycroft* MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP 41.1Smycroft* M68000 Hi-Performance Microprocessor Division 51.1Smycroft* M68040 Software Package 61.1Smycroft* 71.1Smycroft* M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc. 81.1Smycroft* All rights reserved. 91.1Smycroft* 101.1Smycroft* THE SOFTWARE is provided on an "AS IS" basis and without warranty. 111.1Smycroft* To the maximum extent permitted by applicable law, 121.1Smycroft* MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, 131.1Smycroft* INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A 141.1Smycroft* PARTICULAR PURPOSE and any warranty against infringement with 151.1Smycroft* regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF) 161.1Smycroft* and any accompanying written materials. 171.1Smycroft* 181.1Smycroft* To the maximum extent permitted by applicable law, 191.1Smycroft* IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER 201.1Smycroft* (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS 211.1Smycroft* PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR 221.1Smycroft* OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE 231.1Smycroft* SOFTWARE. Motorola assumes no responsibility for the maintenance 241.1Smycroft* and support of the SOFTWARE. 251.1Smycroft* 261.1Smycroft* You are hereby granted a copyright license to use, modify, and 271.1Smycroft* distribute the SOFTWARE so long as this entire notice is retained 281.1Smycroft* without alteration in any modified and/or redistributed versions, 291.1Smycroft* and that such modified versions are clearly identified as such. 301.1Smycroft* No licenses are granted by implication, estoppel or otherwise 311.1Smycroft* under any patents or trademarks of Motorola, Inc. 321.1Smycroft 331.1Smycroft* 341.1Smycroft* util.sa 3.7 7/29/91 351.1Smycroft* 361.1Smycroft* This file contains routines used by other programs. 371.1Smycroft* 381.1Smycroft* ovf_res: used by overflow to force the correct 391.1Smycroft* result. ovf_r_k, ovf_r_x2, ovf_r_x3 are 401.1Smycroft* derivatives of this routine. 411.1Smycroft* get_fline: get user's opcode word 421.1Smycroft* g_dfmtou: returns the destination format. 431.1Smycroft* g_opcls: returns the opclass of the float instruction. 441.1Smycroft* g_rndpr: returns the rounding precision. 451.1Smycroft* reg_dest: write byte, word, or long data to Dn 461.1Smycroft* 471.1Smycroft 481.1SmycroftUTIL IDNT 2,1 Motorola 040 Floating Point Software Package 491.1Smycroft 501.1Smycroft section 8 511.1Smycroft 521.1Smycroft include fpsp.h 531.1Smycroft 541.1Smycroft xref mem_read 551.1Smycroft 561.1Smycroft xdef g_dfmtou 571.1Smycroft xdef g_opcls 581.1Smycroft xdef g_rndpr 591.1Smycroft xdef get_fline 601.1Smycroft xdef reg_dest 611.1Smycroft 621.1Smycroft* 631.1Smycroft* Final result table for ovf_res. Note that the negative counterparts 641.1Smycroft* are unnecessary as ovf_res always returns the sign separately from 651.1Smycroft* the exponent. 661.1Smycroft* ;+inf 671.1SmycroftEXT_PINF dc.l $7fff0000,$00000000,$00000000,$00000000 681.1Smycroft* ;largest +ext 691.1SmycroftEXT_PLRG dc.l $7ffe0000,$ffffffff,$ffffffff,$00000000 701.1Smycroft* ;largest magnitude +sgl in ext 711.1SmycroftSGL_PLRG dc.l $407e0000,$ffffff00,$00000000,$00000000 721.1Smycroft* ;largest magnitude +dbl in ext 731.1SmycroftDBL_PLRG dc.l $43fe0000,$ffffffff,$fffff800,$00000000 741.1Smycroft* ;largest -ext 751.1Smycroft 761.1Smycrofttblovfl: 771.1Smycroft dc.l EXT_RN 781.1Smycroft dc.l EXT_RZ 791.1Smycroft dc.l EXT_RM 801.1Smycroft dc.l EXT_RP 811.1Smycroft dc.l SGL_RN 821.1Smycroft dc.l SGL_RZ 831.1Smycroft dc.l SGL_RM 841.1Smycroft dc.l SGL_RP 851.1Smycroft dc.l DBL_RN 861.1Smycroft dc.l DBL_RZ 871.1Smycroft dc.l DBL_RM 881.1Smycroft dc.l DBL_RP 891.1Smycroft dc.l error 901.1Smycroft dc.l error 911.1Smycroft dc.l error 921.1Smycroft dc.l error 931.1Smycroft 941.1Smycroft 951.1Smycroft* 961.1Smycroft* ovf_r_k --- overflow result calculation 971.1Smycroft* 981.1Smycroft* This entry point is used by kernel_ex. 991.1Smycroft* 1001.1Smycroft* This forces the destination precision to be extended 1011.1Smycroft* 1021.1Smycroft* Input: operand in ETEMP 1031.1Smycroft* Output: a result is in ETEMP (internal extended format) 1041.1Smycroft* 1051.1Smycroft xdef ovf_r_k 1061.1Smycroftovf_r_k: 1071.1Smycroft lea ETEMP(a6),a0 ;a0 points to source operand 1081.1Smycroft bclr.b #sign_bit,ETEMP_EX(a6) 1091.1Smycroft sne ETEMP_SGN(a6) ;convert to internal IEEE format 1101.1Smycroft 1111.1Smycroft* 1121.1Smycroft* ovf_r_x2 --- overflow result calculation 1131.1Smycroft* 1141.1Smycroft* This entry point used by x_ovfl. (opclass 0 and 2) 1151.1Smycroft* 1161.1Smycroft* Input a0 points to an operand in the internal extended format 1171.1Smycroft* Output a0 points to the result in the internal extended format 1181.1Smycroft* 1191.1Smycroft* This sets the round precision according to the user's FPCR unless the 1201.1Smycroft* instruction is fsgldiv or fsglmul or fsadd, fdadd, fsub, fdsub, fsmul, 1211.1Smycroft* fdmul, fsdiv, fddiv, fssqrt, fsmove, fdmove, fsabs, fdabs, fsneg, fdneg. 1221.1Smycroft* If the instruction is fsgldiv of fsglmul, the rounding precision must be 1231.1Smycroft* extended. If the instruction is not fsgldiv or fsglmul but a force- 1241.1Smycroft* precision instruction, the rounding precision is then set to the force 1251.1Smycroft* precision. 1261.1Smycroft 1271.1Smycroft xdef ovf_r_x2 1281.1Smycroftovf_r_x2: 1291.1Smycroft btst.b #E3,E_BYTE(a6) ;check for nu exception 1301.1Smycroft beq.l ovf_e1_exc ;it is cu exception 1311.1Smycroftovf_e3_exc: 1321.1Smycroft move.w CMDREG3B(a6),d0 ;get the command word 1331.1Smycroft andi.w #$00000060,d0 ;clear all bits except 6 and 5 1341.1Smycroft cmpi.l #$00000040,d0 1351.1Smycroft beq.l ovff_sgl ;force precision is single 1361.1Smycroft cmpi.l #$00000060,d0 1371.1Smycroft beq.l ovff_dbl ;force precision is double 1381.1Smycroft move.w CMDREG3B(a6),d0 ;get the command word again 1391.1Smycroft andi.l #$7f,d0 ;clear all except operation 1401.1Smycroft cmpi.l #$33,d0 1411.1Smycroft beq.l ovf_fsgl ;fsglmul or fsgldiv 1421.1Smycroft cmpi.l #$30,d0 1431.1Smycroft beq.l ovf_fsgl 1441.1Smycroft bra ovf_fpcr ;instruction is none of the above 1451.1Smycroft* ;use FPCR 1461.1Smycroftovf_e1_exc: 1471.1Smycroft move.w CMDREG1B(a6),d0 ;get command word 1481.1Smycroft andi.l #$00000044,d0 ;clear all bits except 6 and 2 1491.1Smycroft cmpi.l #$00000040,d0 1501.1Smycroft beq.l ovff_sgl ;the instruction is force single 1511.1Smycroft cmpi.l #$00000044,d0 1521.1Smycroft beq.l ovff_dbl ;the instruction is force double 1531.1Smycroft move.w CMDREG1B(a6),d0 ;again get the command word 1541.1Smycroft andi.l #$0000007f,d0 ;clear all except the op code 1551.1Smycroft cmpi.l #$00000027,d0 1561.1Smycroft beq.l ovf_fsgl ;fsglmul 1571.1Smycroft cmpi.l #$00000024,d0 1581.1Smycroft beq.l ovf_fsgl ;fsgldiv 1591.1Smycroft bra ovf_fpcr ;none of the above, use FPCR 1601.1Smycroft* 1611.1Smycroft* 1621.1Smycroft* Inst is either fsgldiv or fsglmul. Force extended precision. 1631.1Smycroft* 1641.1Smycroftovf_fsgl: 1651.1Smycroft clr.l d0 1661.4Sbriggs bra.b short_ovf_res 1671.1Smycroft 1681.1Smycroftovff_sgl: 1691.1Smycroft move.l #$00000001,d0 ;set single 1701.4Sbriggs bra.b short_ovf_res 1711.1Smycroftovff_dbl: 1721.1Smycroft move.l #$00000002,d0 ;set double 1731.4Sbriggs bra.b short_ovf_res 1741.1Smycroft* 1751.1Smycroft* The precision is in the fpcr. 1761.1Smycroft* 1771.1Smycroftovf_fpcr: 1781.1Smycroft bfextu FPCR_MODE(a6){0:2},d0 ;set round precision 1791.4Sbriggs bra.b short_ovf_res 1801.1Smycroft 1811.1Smycroft* 1821.1Smycroft* 1831.1Smycroft* ovf_r_x3 --- overflow result calculation 1841.1Smycroft* 1851.1Smycroft* This entry point used by x_ovfl. (opclass 3 only) 1861.1Smycroft* 1871.1Smycroft* Input a0 points to an operand in the internal extended format 1881.1Smycroft* Output a0 points to the result in the internal extended format 1891.1Smycroft* 1901.1Smycroft* This sets the round precision according to the destination size. 1911.1Smycroft* 1921.1Smycroft xdef ovf_r_x3 1931.1Smycroftovf_r_x3: 1941.1Smycroft bsr g_dfmtou ;get dest fmt in d0{1:0} 1951.1Smycroft* ;for fmovout, the destination format 1961.1Smycroft* ;is the rounding precision 1971.1Smycroft 1981.1Smycroft* 1991.1Smycroft* ovf_res --- overflow result calculation 2001.1Smycroft* 2011.1Smycroft* Input: 2021.1Smycroft* a0 points to operand in internal extended format 2031.1Smycroft* Output: 2041.1Smycroft* a0 points to result in internal extended format 2051.1Smycroft* 2061.1Smycroft xdef ovf_res 2071.1Smycroftovf_res: 2081.4Sbriggsshort_ovf_res: 2091.1Smycroft lsl.l #2,d0 ;move round precision to d0{3:2} 2101.1Smycroft bfextu FPCR_MODE(a6){2:2},d1 ;set round mode 2111.1Smycroft or.l d1,d0 ;index is fmt:mode in d0{3:0} 2121.1Smycroft lea.l tblovfl,a1 ;load a1 with table address 2131.1Smycroft move.l (a1,d0*4),a1 ;use d0 as index to the table 2141.1Smycroft jmp (a1) ;go to the correct routine 2151.1Smycroft* 2161.1Smycroft*case DEST_FMT = EXT 2171.1Smycroft* 2181.1SmycroftEXT_RN: 2191.1Smycroft lea.l EXT_PINF,a1 ;answer is +/- infinity 2201.1Smycroft bset.b #inf_bit,FPSR_CC(a6) 2211.1Smycroft bra set_sign ;now go set the sign 2221.1SmycroftEXT_RZ: 2231.1Smycroft lea.l EXT_PLRG,a1 ;answer is +/- large number 2241.1Smycroft bra set_sign ;now go set the sign 2251.1SmycroftEXT_RM: 2261.1Smycroft tst.b LOCAL_SGN(a0) ;if negative overflow 2271.1Smycroft beq.b e_rm_pos 2281.1Smycrofte_rm_neg: 2291.1Smycroft lea.l EXT_PINF,a1 ;answer is negative infinity 2301.1Smycroft or.l #neginf_mask,USER_FPSR(a6) 2311.1Smycroft bra end_ovfr 2321.1Smycrofte_rm_pos: 2331.1Smycroft lea.l EXT_PLRG,a1 ;answer is large positive number 2341.1Smycroft bra end_ovfr 2351.1SmycroftEXT_RP: 2361.1Smycroft tst.b LOCAL_SGN(a0) ;if negative overflow 2371.1Smycroft beq.b e_rp_pos 2381.1Smycrofte_rp_neg: 2391.1Smycroft lea.l EXT_PLRG,a1 ;answer is large negative number 2401.1Smycroft bset.b #neg_bit,FPSR_CC(a6) 2411.1Smycroft bra end_ovfr 2421.1Smycrofte_rp_pos: 2431.1Smycroft lea.l EXT_PINF,a1 ;answer is positive infinity 2441.1Smycroft bset.b #inf_bit,FPSR_CC(a6) 2451.1Smycroft bra end_ovfr 2461.1Smycroft* 2471.1Smycroft*case DEST_FMT = DBL 2481.1Smycroft* 2491.1SmycroftDBL_RN: 2501.1Smycroft lea.l EXT_PINF,a1 ;answer is +/- infinity 2511.1Smycroft bset.b #inf_bit,FPSR_CC(a6) 2521.1Smycroft bra set_sign 2531.1SmycroftDBL_RZ: 2541.1Smycroft lea.l DBL_PLRG,a1 ;answer is +/- large number 2551.1Smycroft bra set_sign ;now go set the sign 2561.1SmycroftDBL_RM: 2571.1Smycroft tst.b LOCAL_SGN(a0) ;if negative overflow 2581.1Smycroft beq.b d_rm_pos 2591.1Smycroftd_rm_neg: 2601.1Smycroft lea.l EXT_PINF,a1 ;answer is negative infinity 2611.1Smycroft or.l #neginf_mask,USER_FPSR(a6) 2621.1Smycroft bra end_ovfr ;inf is same for all precisions (ext,dbl,sgl) 2631.1Smycroftd_rm_pos: 2641.1Smycroft lea.l DBL_PLRG,a1 ;answer is large positive number 2651.1Smycroft bra end_ovfr 2661.1SmycroftDBL_RP: 2671.1Smycroft tst.b LOCAL_SGN(a0) ;if negative overflow 2681.1Smycroft beq.b d_rp_pos 2691.1Smycroftd_rp_neg: 2701.1Smycroft lea.l DBL_PLRG,a1 ;answer is large negative number 2711.1Smycroft bset.b #neg_bit,FPSR_CC(a6) 2721.1Smycroft bra end_ovfr 2731.1Smycroftd_rp_pos: 2741.1Smycroft lea.l EXT_PINF,a1 ;answer is positive infinity 2751.1Smycroft bset.b #inf_bit,FPSR_CC(a6) 2761.1Smycroft bra end_ovfr 2771.1Smycroft* 2781.1Smycroft*case DEST_FMT = SGL 2791.1Smycroft* 2801.1SmycroftSGL_RN: 2811.1Smycroft lea.l EXT_PINF,a1 ;answer is +/- infinity 2821.1Smycroft bset.b #inf_bit,FPSR_CC(a6) 2831.1Smycroft bra.b set_sign 2841.1SmycroftSGL_RZ: 2851.1Smycroft lea.l SGL_PLRG,a1 ;anwer is +/- large number 2861.1Smycroft bra.b set_sign 2871.1SmycroftSGL_RM: 2881.1Smycroft tst.b LOCAL_SGN(a0) ;if negative overflow 2891.1Smycroft beq.b s_rm_pos 2901.1Smycrofts_rm_neg: 2911.1Smycroft lea.l EXT_PINF,a1 ;answer is negative infinity 2921.1Smycroft or.l #neginf_mask,USER_FPSR(a6) 2931.1Smycroft bra.b end_ovfr 2941.1Smycrofts_rm_pos: 2951.1Smycroft lea.l SGL_PLRG,a1 ;answer is large positive number 2961.1Smycroft bra.b end_ovfr 2971.1SmycroftSGL_RP: 2981.1Smycroft tst.b LOCAL_SGN(a0) ;if negative overflow 2991.1Smycroft beq.b s_rp_pos 3001.1Smycrofts_rp_neg: 3011.1Smycroft lea.l SGL_PLRG,a1 ;answer is large negative number 3021.1Smycroft bset.b #neg_bit,FPSR_CC(a6) 3031.1Smycroft bra.b end_ovfr 3041.1Smycrofts_rp_pos: 3051.5Sandvar lea.l EXT_PINF,a1 ;answer is positive infinity 3061.1Smycroft bset.b #inf_bit,FPSR_CC(a6) 3071.1Smycroft bra.b end_ovfr 3081.1Smycroft 3091.1Smycroftset_sign: 3101.1Smycroft tst.b LOCAL_SGN(a0) ;if negative overflow 3111.1Smycroft beq.b end_ovfr 3121.1Smycroftneg_sign: 3131.1Smycroft bset.b #neg_bit,FPSR_CC(a6) 3141.1Smycroft 3151.1Smycroftend_ovfr: 3161.1Smycroft move.w LOCAL_EX(a1),LOCAL_EX(a0) ;do not overwrite sign 3171.1Smycroft move.l LOCAL_HI(a1),LOCAL_HI(a0) 3181.1Smycroft move.l LOCAL_LO(a1),LOCAL_LO(a0) 3191.1Smycroft rts 3201.1Smycroft 3211.1Smycroft 3221.1Smycroft* 3231.1Smycroft* ERROR 3241.1Smycroft* 3251.1Smycrofterror: 3261.1Smycroft rts 3271.1Smycroft* 3281.1Smycroft* get_fline --- get f-line opcode of interrupted instruction 3291.1Smycroft* 3301.1Smycroft* Returns opcode in the low word of d0. 3311.1Smycroft* 3321.1Smycroftget_fline: 3331.1Smycroft move.l USER_FPIAR(a6),a0 ;opcode address 3341.2Smycroft clr.l -(a7) ;reserve a word on the stack 3351.1Smycroft lea.l 2(a7),a1 ;point to low word of temporary 3361.1Smycroft move.l #2,d0 ;count 3371.1Smycroft bsr.l mem_read 3381.1Smycroft move.l (a7)+,d0 3391.1Smycroft rts 3401.1Smycroft* 3411.1Smycroft* g_rndpr --- put rounding precision in d0{1:0} 3421.1Smycroft* 3431.1Smycroft* valid return codes are: 3441.1Smycroft* 00 - extended 3451.1Smycroft* 01 - single 3461.1Smycroft* 10 - double 3471.1Smycroft* 3481.1Smycroft* begin 3491.1Smycroft* get rounding precision (cmdreg3b{6:5}) 3501.1Smycroft* begin 3511.1Smycroft* case opclass = 011 (move out) 3521.1Smycroft* get destination format - this is the also the rounding precision 3531.1Smycroft* 3541.1Smycroft* case opclass = 0x0 3551.1Smycroft* if E3 3561.1Smycroft* *case RndPr(from cmdreg3b{6:5} = 11 then RND_PREC = DBL 3571.1Smycroft* *case RndPr(from cmdreg3b{6:5} = 10 then RND_PREC = SGL 3581.1Smycroft* case RndPr(from cmdreg3b{6:5} = 00 | 01 3591.1Smycroft* use precision from FPCR{7:6} 3601.1Smycroft* case 00 then RND_PREC = EXT 3611.1Smycroft* case 01 then RND_PREC = SGL 3621.1Smycroft* case 10 then RND_PREC = DBL 3631.1Smycroft* else E1 3641.1Smycroft* use precision in FPCR{7:6} 3651.1Smycroft* case 00 then RND_PREC = EXT 3661.1Smycroft* case 01 then RND_PREC = SGL 3671.1Smycroft* case 10 then RND_PREC = DBL 3681.1Smycroft* end 3691.1Smycroft* 3701.1Smycroftg_rndpr: 3711.1Smycroft bsr.w g_opcls ;get opclass in d0{2:0} 3721.1Smycroft cmp.w #$0003,d0 ;check for opclass 011 3731.1Smycroft bne.b op_0x0 3741.1Smycroft 3751.1Smycroft* 3761.1Smycroft* For move out instructions (opclass 011) the destination format 3771.1Smycroft* is the same as the rounding precision. Pass results from g_dfmtou. 3781.1Smycroft* 3791.1Smycroft bsr.w g_dfmtou 3801.1Smycroft rts 3811.1Smycroftop_0x0: 3821.1Smycroft btst.b #E3,E_BYTE(a6) 3831.1Smycroft beq.l unf_e1_exc ;branch to e1 underflow 3841.1Smycroftunf_e3_exc: 3851.1Smycroft move.l CMDREG3B(a6),d0 ;rounding precision in d0{10:9} 3861.1Smycroft bfextu d0{9:2},d0 ;move the rounding prec bits to d0{1:0} 3871.1Smycroft cmpi.l #$2,d0 3881.1Smycroft beq.l unff_sgl ;force precision is single 3891.1Smycroft cmpi.l #$3,d0 ;force precision is double 3901.1Smycroft beq.l unff_dbl 3911.1Smycroft move.w CMDREG3B(a6),d0 ;get the command word again 3921.1Smycroft andi.l #$7f,d0 ;clear all except operation 3931.1Smycroft cmpi.l #$33,d0 3941.1Smycroft beq.l unf_fsgl ;fsglmul or fsgldiv 3951.1Smycroft cmpi.l #$30,d0 3961.1Smycroft beq.l unf_fsgl ;fsgldiv or fsglmul 3971.1Smycroft bra unf_fpcr 3981.1Smycroftunf_e1_exc: 3991.1Smycroft move.l CMDREG1B(a6),d0 ;get 32 bits off the stack, 1st 16 bits 4001.1Smycroft* ;are the command word 4011.1Smycroft andi.l #$00440000,d0 ;clear all bits except bits 6 and 2 4021.1Smycroft cmpi.l #$00400000,d0 4031.1Smycroft beq.l unff_sgl ;force single 4041.1Smycroft cmpi.l #$00440000,d0 ;force double 4051.1Smycroft beq.l unff_dbl 4061.1Smycroft move.l CMDREG1B(a6),d0 ;get the command word again 4071.1Smycroft andi.l #$007f0000,d0 ;clear all bits except the operation 4081.1Smycroft cmpi.l #$00270000,d0 4091.1Smycroft beq.l unf_fsgl ;fsglmul 4101.1Smycroft cmpi.l #$00240000,d0 4111.1Smycroft beq.l unf_fsgl ;fsgldiv 4121.1Smycroft bra unf_fpcr 4131.1Smycroft 4141.1Smycroft* 4151.1Smycroft* Convert to return format. The values from cmdreg3b and the return 4161.1Smycroft* values are: 4171.1Smycroft* cmdreg3b return precision 4181.1Smycroft* -------- ------ --------- 4191.1Smycroft* 00,01 0 ext 4201.1Smycroft* 10 1 sgl 4211.1Smycroft* 11 2 dbl 4221.1Smycroft* Force single 4231.1Smycroft* 4241.1Smycroftunff_sgl: 4251.1Smycroft move.l #1,d0 ;return 1 4261.1Smycroft rts 4271.1Smycroft* 4281.1Smycroft* Force double 4291.1Smycroft* 4301.1Smycroftunff_dbl: 4311.1Smycroft move.l #2,d0 ;return 2 4321.1Smycroft rts 4331.1Smycroft* 4341.1Smycroft* Force extended 4351.1Smycroft* 4361.1Smycroftunf_fsgl: 4371.2Smycroft clr.l d0 4381.1Smycroft rts 4391.1Smycroft* 4401.1Smycroft* Get rounding precision set in FPCR{7:6}. 4411.1Smycroft* 4421.1Smycroftunf_fpcr: 4431.1Smycroft move.l USER_FPCR(a6),d0 ;rounding precision bits in d0{7:6} 4441.1Smycroft bfextu d0{24:2},d0 ;move the rounding prec bits to d0{1:0} 4451.1Smycroft rts 4461.1Smycroft* 4471.1Smycroft* g_opcls --- put opclass in d0{2:0} 4481.1Smycroft* 4491.1Smycroftg_opcls: 4501.1Smycroft btst.b #E3,E_BYTE(a6) 4511.1Smycroft beq.b opc_1b ;if set, go to cmdreg1b 4521.1Smycroftopc_3b: 4531.1Smycroft clr.l d0 ;if E3, only opclass 0x0 is possible 4541.1Smycroft rts 4551.1Smycroftopc_1b: 4561.1Smycroft move.l CMDREG1B(a6),d0 4571.1Smycroft bfextu d0{0:3},d0 ;shift opclass bits d0{31:29} to d0{2:0} 4581.1Smycroft rts 4591.1Smycroft* 4601.1Smycroft* g_dfmtou --- put destination format in d0{1:0} 4611.1Smycroft* 4621.1Smycroft* If E1, the format is from cmdreg1b{12:10} 4631.1Smycroft* If E3, the format is extended. 4641.1Smycroft* 4651.1Smycroft* Dest. Fmt. 4661.1Smycroft* extended 010 -> 00 4671.1Smycroft* single 001 -> 01 4681.1Smycroft* double 101 -> 10 4691.1Smycroft* 4701.1Smycroftg_dfmtou: 4711.1Smycroft btst.b #E3,E_BYTE(a6) 4721.1Smycroft beq.b op011 4731.1Smycroft clr.l d0 ;if E1, size is always ext 4741.1Smycroft rts 4751.1Smycroftop011: 4761.1Smycroft move.l CMDREG1B(a6),d0 4771.1Smycroft bfextu d0{3:3},d0 ;dest fmt from cmdreg1b{12:10} 4781.1Smycroft cmp.b #1,d0 ;check for single 4791.1Smycroft bne.b not_sgl 4801.1Smycroft move.l #1,d0 4811.1Smycroft rts 4821.1Smycroftnot_sgl: 4831.1Smycroft cmp.b #5,d0 ;check for double 4841.1Smycroft bne.b not_dbl 4851.1Smycroft move.l #2,d0 4861.1Smycroft rts 4871.1Smycroftnot_dbl: 4881.1Smycroft clr.l d0 ;must be extended 4891.1Smycroft rts 4901.1Smycroft 4911.1Smycroft* 4921.1Smycroft* 4931.1Smycroft* Final result table for unf_sub. Note that the negative counterparts 4941.1Smycroft* are unnecessary as unf_sub always returns the sign separately from 4951.1Smycroft* the exponent. 4961.1Smycroft* ;+zero 4971.1SmycroftEXT_PZRO dc.l $00000000,$00000000,$00000000,$00000000 4981.1Smycroft* ;+zero 4991.1SmycroftSGL_PZRO dc.l $3f810000,$00000000,$00000000,$00000000 5001.1Smycroft* ;+zero 5011.1SmycroftDBL_PZRO dc.l $3c010000,$00000000,$00000000,$00000000 5021.1Smycroft* ;smallest +ext denorm 5031.1SmycroftEXT_PSML dc.l $00000000,$00000000,$00000001,$00000000 5041.1Smycroft* ;smallest +sgl denorm 5051.1SmycroftSGL_PSML dc.l $3f810000,$00000100,$00000000,$00000000 5061.1Smycroft* ;smallest +dbl denorm 5071.1SmycroftDBL_PSML dc.l $3c010000,$00000000,$00000800,$00000000 5081.1Smycroft* 5091.1Smycroft* UNF_SUB --- underflow result calculation 5101.1Smycroft* 5111.1Smycroft* Input: 5121.1Smycroft* d0 contains round precision 5131.1Smycroft* a0 points to input operand in the internal extended format 5141.1Smycroft* 5151.1Smycroft* Output: 5161.1Smycroft* a0 points to correct internal extended precision result. 5171.1Smycroft* 5181.1Smycroft 5191.1Smycrofttblunf: 5201.1Smycroft dc.l uEXT_RN 5211.1Smycroft dc.l uEXT_RZ 5221.1Smycroft dc.l uEXT_RM 5231.1Smycroft dc.l uEXT_RP 5241.1Smycroft dc.l uSGL_RN 5251.1Smycroft dc.l uSGL_RZ 5261.1Smycroft dc.l uSGL_RM 5271.1Smycroft dc.l uSGL_RP 5281.1Smycroft dc.l uDBL_RN 5291.1Smycroft dc.l uDBL_RZ 5301.1Smycroft dc.l uDBL_RM 5311.1Smycroft dc.l uDBL_RP 5321.1Smycroft dc.l uDBL_RN 5331.1Smycroft dc.l uDBL_RZ 5341.1Smycroft dc.l uDBL_RM 5351.1Smycroft dc.l uDBL_RP 5361.1Smycroft 5371.1Smycroft xdef unf_sub 5381.1Smycroftunf_sub: 5391.1Smycroft lsl.l #2,d0 ;move round precision to d0{3:2} 5401.1Smycroft bfextu FPCR_MODE(a6){2:2},d1 ;set round mode 5411.1Smycroft or.l d1,d0 ;index is fmt:mode in d0{3:0} 5421.1Smycroft lea.l tblunf,a1 ;load a1 with table address 5431.1Smycroft move.l (a1,d0*4),a1 ;use d0 as index to the table 5441.1Smycroft jmp (a1) ;go to the correct routine 5451.1Smycroft* 5461.1Smycroft*case DEST_FMT = EXT 5471.1Smycroft* 5481.1SmycroftuEXT_RN: 5491.1Smycroft lea.l EXT_PZRO,a1 ;answer is +/- zero 5501.1Smycroft bset.b #z_bit,FPSR_CC(a6) 5511.1Smycroft bra uset_sign ;now go set the sign 5521.1SmycroftuEXT_RZ: 5531.1Smycroft lea.l EXT_PZRO,a1 ;answer is +/- zero 5541.1Smycroft bset.b #z_bit,FPSR_CC(a6) 5551.1Smycroft bra uset_sign ;now go set the sign 5561.1SmycroftuEXT_RM: 5571.1Smycroft tst.b LOCAL_SGN(a0) ;if negative underflow 5581.1Smycroft beq.b ue_rm_pos 5591.1Smycroftue_rm_neg: 5601.1Smycroft lea.l EXT_PSML,a1 ;answer is negative smallest denorm 5611.1Smycroft bset.b #neg_bit,FPSR_CC(a6) 5621.1Smycroft bra end_unfr 5631.1Smycroftue_rm_pos: 5641.1Smycroft lea.l EXT_PZRO,a1 ;answer is positive zero 5651.1Smycroft bset.b #z_bit,FPSR_CC(a6) 5661.1Smycroft bra end_unfr 5671.1SmycroftuEXT_RP: 5681.1Smycroft tst.b LOCAL_SGN(a0) ;if negative underflow 5691.1Smycroft beq.b ue_rp_pos 5701.1Smycroftue_rp_neg: 5711.1Smycroft lea.l EXT_PZRO,a1 ;answer is negative zero 5721.1Smycroft ori.l #negz_mask,USER_FPSR(a6) 5731.1Smycroft bra end_unfr 5741.1Smycroftue_rp_pos: 5751.1Smycroft lea.l EXT_PSML,a1 ;answer is positive smallest denorm 5761.1Smycroft bra end_unfr 5771.1Smycroft* 5781.1Smycroft*case DEST_FMT = DBL 5791.1Smycroft* 5801.1SmycroftuDBL_RN: 5811.1Smycroft lea.l DBL_PZRO,a1 ;answer is +/- zero 5821.1Smycroft bset.b #z_bit,FPSR_CC(a6) 5831.1Smycroft bra uset_sign 5841.1SmycroftuDBL_RZ: 5851.1Smycroft lea.l DBL_PZRO,a1 ;answer is +/- zero 5861.1Smycroft bset.b #z_bit,FPSR_CC(a6) 5871.1Smycroft bra uset_sign ;now go set the sign 5881.1SmycroftuDBL_RM: 5891.1Smycroft tst.b LOCAL_SGN(a0) ;if negative overflow 5901.1Smycroft beq.b ud_rm_pos 5911.1Smycroftud_rm_neg: 5921.1Smycroft lea.l DBL_PSML,a1 ;answer is smallest denormalized negative 5931.1Smycroft bset.b #neg_bit,FPSR_CC(a6) 5941.1Smycroft bra end_unfr 5951.1Smycroftud_rm_pos: 5961.1Smycroft lea.l DBL_PZRO,a1 ;answer is positive zero 5971.1Smycroft bset.b #z_bit,FPSR_CC(a6) 5981.1Smycroft bra end_unfr 5991.1SmycroftuDBL_RP: 6001.1Smycroft tst.b LOCAL_SGN(a0) ;if negative overflow 6011.1Smycroft beq.b ud_rp_pos 6021.1Smycroftud_rp_neg: 6031.1Smycroft lea.l DBL_PZRO,a1 ;answer is negative zero 6041.1Smycroft ori.l #negz_mask,USER_FPSR(a6) 6051.1Smycroft bra end_unfr 6061.1Smycroftud_rp_pos: 6071.1Smycroft lea.l DBL_PSML,a1 ;answer is smallest denormalized negative 6081.1Smycroft bra end_unfr 6091.1Smycroft* 6101.1Smycroft*case DEST_FMT = SGL 6111.1Smycroft* 6121.1SmycroftuSGL_RN: 6131.1Smycroft lea.l SGL_PZRO,a1 ;answer is +/- zero 6141.1Smycroft bset.b #z_bit,FPSR_CC(a6) 6151.1Smycroft bra.b uset_sign 6161.1SmycroftuSGL_RZ: 6171.1Smycroft lea.l SGL_PZRO,a1 ;answer is +/- zero 6181.1Smycroft bset.b #z_bit,FPSR_CC(a6) 6191.1Smycroft bra.b uset_sign 6201.1SmycroftuSGL_RM: 6211.1Smycroft tst.b LOCAL_SGN(a0) ;if negative overflow 6221.1Smycroft beq.b us_rm_pos 6231.1Smycroftus_rm_neg: 6241.1Smycroft lea.l SGL_PSML,a1 ;answer is smallest denormalized negative 6251.1Smycroft bset.b #neg_bit,FPSR_CC(a6) 6261.1Smycroft bra.b end_unfr 6271.1Smycroftus_rm_pos: 6281.1Smycroft lea.l SGL_PZRO,a1 ;answer is positive zero 6291.1Smycroft bset.b #z_bit,FPSR_CC(a6) 6301.1Smycroft bra.b end_unfr 6311.1SmycroftuSGL_RP: 6321.1Smycroft tst.b LOCAL_SGN(a0) ;if negative overflow 6331.1Smycroft beq.b us_rp_pos 6341.1Smycroftus_rp_neg: 6351.1Smycroft lea.l SGL_PZRO,a1 ;answer is negative zero 6361.1Smycroft ori.l #negz_mask,USER_FPSR(a6) 6371.1Smycroft bra.b end_unfr 6381.1Smycroftus_rp_pos: 6391.1Smycroft lea.l SGL_PSML,a1 ;answer is smallest denormalized positive 6401.1Smycroft bra.b end_unfr 6411.1Smycroft 6421.1Smycroftuset_sign: 6431.1Smycroft tst.b LOCAL_SGN(a0) ;if negative overflow 6441.1Smycroft beq.b end_unfr 6451.1Smycroftuneg_sign: 6461.1Smycroft bset.b #neg_bit,FPSR_CC(a6) 6471.1Smycroft 6481.1Smycroftend_unfr: 6491.1Smycroft move.w LOCAL_EX(a1),LOCAL_EX(a0) ;be careful not to overwrite sign 6501.1Smycroft move.l LOCAL_HI(a1),LOCAL_HI(a0) 6511.1Smycroft move.l LOCAL_LO(a1),LOCAL_LO(a0) 6521.1Smycroft rts 6531.1Smycroft* 6541.1Smycroft* reg_dest --- write byte, word, or long data to Dn 6551.1Smycroft* 6561.1Smycroft* 6571.1Smycroft* Input: 6581.1Smycroft* L_SCR1: Data 6591.1Smycroft* d1: data size and dest register number formatted as: 6601.1Smycroft* 6611.1Smycroft* 32 5 4 3 2 1 0 6621.1Smycroft* ----------------------------------------------- 6631.1Smycroft* | 0 | Size | Dest Reg # | 6641.1Smycroft* ----------------------------------------------- 6651.1Smycroft* 6661.1Smycroft* Size is: 6671.1Smycroft* 0 - Byte 6681.1Smycroft* 1 - Word 6691.1Smycroft* 2 - Long/Single 6701.1Smycroft* 6711.1Smycroftpregdst: 6721.1Smycroft dc.l byte_d0 6731.1Smycroft dc.l byte_d1 6741.1Smycroft dc.l byte_d2 6751.1Smycroft dc.l byte_d3 6761.1Smycroft dc.l byte_d4 6771.1Smycroft dc.l byte_d5 6781.1Smycroft dc.l byte_d6 6791.1Smycroft dc.l byte_d7 6801.1Smycroft dc.l word_d0 6811.1Smycroft dc.l word_d1 6821.1Smycroft dc.l word_d2 6831.1Smycroft dc.l word_d3 6841.1Smycroft dc.l word_d4 6851.1Smycroft dc.l word_d5 6861.1Smycroft dc.l word_d6 6871.1Smycroft dc.l word_d7 6881.1Smycroft dc.l long_d0 6891.1Smycroft dc.l long_d1 6901.1Smycroft dc.l long_d2 6911.1Smycroft dc.l long_d3 6921.1Smycroft dc.l long_d4 6931.1Smycroft dc.l long_d5 6941.1Smycroft dc.l long_d6 6951.1Smycroft dc.l long_d7 6961.1Smycroft 6971.1Smycroftreg_dest: 6981.1Smycroft lea.l pregdst,a0 6991.1Smycroft move.l (a0,d1*4),a0 7001.1Smycroft jmp (a0) 7011.1Smycroft 7021.1Smycroftbyte_d0: 7031.1Smycroft move.b L_SCR1(a6),USER_D0+3(a6) 7041.1Smycroft rts 7051.1Smycroftbyte_d1: 7061.1Smycroft move.b L_SCR1(a6),USER_D1+3(a6) 7071.1Smycroft rts 7081.1Smycroftbyte_d2: 7091.1Smycroft move.b L_SCR1(a6),d2 7101.1Smycroft rts 7111.1Smycroftbyte_d3: 7121.1Smycroft move.b L_SCR1(a6),d3 7131.1Smycroft rts 7141.1Smycroftbyte_d4: 7151.1Smycroft move.b L_SCR1(a6),d4 7161.1Smycroft rts 7171.1Smycroftbyte_d5: 7181.1Smycroft move.b L_SCR1(a6),d5 7191.1Smycroft rts 7201.1Smycroftbyte_d6: 7211.1Smycroft move.b L_SCR1(a6),d6 7221.1Smycroft rts 7231.1Smycroftbyte_d7: 7241.1Smycroft move.b L_SCR1(a6),d7 7251.1Smycroft rts 7261.1Smycroftword_d0: 7271.1Smycroft move.w L_SCR1(a6),USER_D0+2(a6) 7281.1Smycroft rts 7291.1Smycroftword_d1: 7301.1Smycroft move.w L_SCR1(a6),USER_D1+2(a6) 7311.1Smycroft rts 7321.1Smycroftword_d2: 7331.1Smycroft move.w L_SCR1(a6),d2 7341.1Smycroft rts 7351.1Smycroftword_d3: 7361.1Smycroft move.w L_SCR1(a6),d3 7371.1Smycroft rts 7381.1Smycroftword_d4: 7391.1Smycroft move.w L_SCR1(a6),d4 7401.1Smycroft rts 7411.1Smycroftword_d5: 7421.1Smycroft move.w L_SCR1(a6),d5 7431.1Smycroft rts 7441.1Smycroftword_d6: 7451.1Smycroft move.w L_SCR1(a6),d6 7461.1Smycroft rts 7471.1Smycroftword_d7: 7481.1Smycroft move.w L_SCR1(a6),d7 7491.1Smycroft rts 7501.1Smycroftlong_d0: 7511.1Smycroft move.l L_SCR1(a6),USER_D0(a6) 7521.1Smycroft rts 7531.1Smycroftlong_d1: 7541.1Smycroft move.l L_SCR1(a6),USER_D1(a6) 7551.1Smycroft rts 7561.1Smycroftlong_d2: 7571.1Smycroft move.l L_SCR1(a6),d2 7581.1Smycroft rts 7591.1Smycroftlong_d3: 7601.1Smycroft move.l L_SCR1(a6),d3 7611.1Smycroft rts 7621.1Smycroftlong_d4: 7631.1Smycroft move.l L_SCR1(a6),d4 7641.1Smycroft rts 7651.1Smycroftlong_d5: 7661.1Smycroft move.l L_SCR1(a6),d5 7671.1Smycroft rts 7681.1Smycroftlong_d6: 7691.1Smycroft move.l L_SCR1(a6),d6 7701.1Smycroft rts 7711.1Smycroftlong_d7: 7721.1Smycroft move.l L_SCR1(a6),d7 7731.1Smycroft rts 7741.1Smycroft end 775