sys7.1-doc-wip/OS/FPUEmulation/XStore.a
2019-07-27 22:37:48 +08:00

328 lines
10 KiB
Plaintext

;
; File: XStore.a
;
; Contains: Routines to store operands to memory or registers
;
; Originally Written by: Motorola Inc.
; Adapted to Apple/MPW: Jon Okada
;
; Copyright: © 1990, 1991 by Apple Computer, Inc., all rights reserved.
;
; This file is used in these builds: Mac32
;
; Change History (most recent first):
;
; <2> 3/30/91 BG Rolling in Jon Okada's latest changes.
; <1> 12/14/90 BG First checked into TERROR/BBS.
; xstore.a
; Based upon Motorola file 'x_store.sa'.
; CHANGE LOG:
; 09 Jan 91 JPO Deleted unreferenced label "E3_sto". Renamed labels
; "opc011" and "sinf" to "stopc011" and "stsinf",
; respectively. Replaced "bsr mem_write" with in-line
; code in subroutines 'dest_dbl', 'dest_sgl', and
; 'dest_ext'. Replaced "bsr get_fline" with in_line
; code in subroutine 'dest_sgl'.
; 24 Jan 91 JPO Corrected code to store result if destination is FP2
; or FP3 (see routine 'sto_fp' below).
; 18 Feb 91 JPO Modified routine 'sto_fp' to normalize unnormalized
; results prior to storing in dst FP register.
;
*
* x_store.sa 3.1 12/10/90
*
* store --- store operand to memory or register
*
* Used by underflow and overflow handlers.
*
* a0 = points to fp value to be stored.
*
* Copyright (C) Motorola, Inc. 1990
* All Rights Reserved
*
* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
* The copyright notice above does not evidence any
* actual or intended publication of such source code.
* X_STORE IDNT 2,1 Motorola 040 Floating Point Software Package
fpreg_mask:
dc.b $80,$40,$20,$10,$08,$04,$02,$01
store:
btst.b #E3,E_BYTE(a6)
beq E1_sto
;E3_sto: ; label DELETED <1/9/91, JPO>
move.l CMDREG3B(a6),d0
bfextu d0{6:3},d0 ;isolate dest. reg from cmdreg3b
;
; First normalize any unnormalized result; lack of normalization is due
; to underflow for single- or double-precision rounding, so result is
; guaranteed to be zero or normal to extended precision.
;
sto_fp:
move.w LOCAL_EX(a0),d1 ; isolate exponent <2/18/91, JPO>
andi.w #$7fff,d1 ; <2/18/91, JPO>
beq.b @2 ; zero exponent <2/18/91, JPO>
cmpi.w #$7fff,d1 ; <2/18/91, JPO>
beq.b @2 ; infinity <2/18/91, JPO>
tst.l LOCAL_HI(a0) ; test high mantissa <2/18/91, JPO>
bmi.b @2 ; normal <2/18/91, JPO>
bne.b @1 ; unnormalized <2/18/91, JPO>
tst.l LOCAL_LO(a0) ; test low mantissa <2/18/91, JPO>
bne.b @1 ; unnormalized <2/18/91, JPO>
clr.w LOCAL_EX(a0) ; zero result. zero exponent <2/18/91, JPO>
bra.b @2 ; <2/18/91, JPO>
@1: ; label ADDED <2/18/91, JPO>
move.l d0,-(sp) ; save d0 <2/18/91, JPO>
bsr.w nrm_set ; normalize <2/18/91, JPO>
move.l (sp)+,d0 ; restore d0 <2/18/91, JPO>
@2: ; label ADDED <2/18/91, JPO>
lea fpreg_mask,a1
move.b (a1,d0.w),d0 ;convert reg# to dynamic register mask
tst.b LOCAL_SGN(a0)
beq.b is_pos
bset.b #sign_bit,LOCAL_EX(a0)
is_pos:
fmovem.x (a0),d0 ;move to correct register
*
* if fp0-fp3 is being modified, we must put a copy
* in the USER_FPn variable on the stack because all exception
* handlers restore fp0-fp3 from there.
*
cmp.b #$80,d0
bne.b not_fp0
fmovem.x fp0,USER_FP0(a6)
rts
not_fp0:
cmp.b #$40,d0
bne.b not_fp1
fmovem.x fp1,USER_FP1(a6)
rts
not_fp1:
cmp.b #$20,d0
bne.b not_fp2
; fmovem.x fp1,USER_FP2(a6) ; DELETED <1/24/91, JPO>
fmovem.x fp2,USER_FP2(a6) ; copy fp2 to stack storage <1/24/91, JPO>
rts
not_fp2:
cmp.b #$10,d0
bne.b not_fp3
; fmovem.x fp1,USER_FP3(a6) ; DELETED <1/24/91, JPO>
fmovem.x fp3,USER_FP3(a6) ; copy fp3 to stack storage <1/24/91, JPO>
rts
not_fp3:
rts
E1_sto:
bsr g_opcls ;returns opclass in d0
cmpi.b #3,d0
beq.b stopc011 ;branch if opclass 3 - label renamed <1/9/91, JPO>
move.l CMDREG1B(a6),d0
bfextu d0{6:3},d0 ;extract destination register
bra sto_fp
stopc011: ; label renamed <1/9/91, JPO>
bsr g_dfmtou ;returns dest format in d0
* ;ext=00, sgl=01, dbl=10
move.l a0,a1 ;save source addr in a1
move.l EXC_EA(a6),a0 ;get the address
; cmpi.l #0,d0 ;if dest format is extended - DELETED <1/9/91, JPO>
tst.l d0 ; replaces "cmpi.l #0,d0" <1/9/91, JPO>
beq.w dest_ext ;then branch
cmpi.l #1,d0 ;if dest format is single
beq.b dest_sgl ;then branch
*
* fall through to dest_dbl
*
*
* dest_dbl --- write double precision value to user space
*
*Input
* a0 -> destination address
* a1 -> source in extended precision
*Output
* a0 -> destroyed
* a1 -> destroyed
* d0 -> 0
*
*Changes extended precision to double precision.
* Note: no attempt is made to round the extended value to double.
* dbl_sign = ext_sign
* dbl_exp = ext_exp - $3fff(ext bias) + $7ff(dbl bias)
* get rid of ext integer bit
* dbl_mant = ext_mant{62:12}
*
* --------------- --------------- ---------------
* extended -> |s| exp | |1| ms mant | | ls mant |
* --------------- --------------- ---------------
* 95 64 63 62 32 31 11 0
* | |
* | |
* | |
* v v
* --------------- ---------------
* double -> |s|exp| mant | | mant |
* --------------- ---------------
* 63 51 32 31 0
*
dest_dbl:
clr.l d0 ;clear d0
move.w LOCAL_EX(a1),d0 ;get exponent
sub.w #$3fff,d0 ;subtract extended precision bias
cmp.w #$4000,d0 ;check if inf
beq.b inf ;if so, special case
add.w #$3ff,d0 ;add double precision bias
swap d0 ;d0 now in upper word
lsl.l #4,d0 ;d0 now in proper place for dbl prec exp
tst.b LOCAL_SGN(a1)
beq.b get_mant ;if postive, go process mantissa
bset.l #31,d0 ;if negative, put in sign information
* ; before continuing
bra.b get_mant ;go process mantissa
inf:
move.l #$7ff00000,d0 ;load dbl inf exponent
clr.l LOCAL_HI(a1) ;clear msb
tst.b LOCAL_SGN(a1)
beq.b dbl_inf ;if positive, go ahead and write it
bset.l #31,d0 ;if negative put in sign information
dbl_inf:
move.l d0,LOCAL_EX(a1) ;put the new exp back on the stack
bra.b dbl_wrt
get_mant:
move.l LOCAL_HI(a1),d1 ;get ms mantissa
bfextu d1{1:20},d1 ;get upper 20 bits of ms
or.l d1,d0 ;put these bits in ms word of double
move.l d0,LOCAL_EX(a1) ;put the new exp back on the stack
move.l LOCAL_HI(a1),d1 ;get ms mantissa
move.l #21,d0 ;load shift count
lsl.l d0,d1 ;put lower 11 bits in upper bits
move.l d1,LOCAL_HI(a1) ;build lower lword in memory
move.l LOCAL_LO(a1),d1 ;get ls mantissa
bfextu d1{0:21},d0 ;get ls 21 bits of double
or.l d0,LOCAL_HI(a1) ;put them in double result
dbl_wrt:
; move.l #$8,d0 ;byte count for double precision number - DELETED <1/9/91, JPO>
; exg a0,a1 ;a0=supervisor source, a1=user dest - DELETED <1/9/91, JPO>
; bsr.l mem_write ;move the number to the user's memory - DELETED <1/9/91, JPO>
move.l (a1)+,(a0)+ ; move d.p. number to user memory <1/9/91, JPO>
move.l (a1),(a0) ; <1/9/91, JPO>
rts
*
* dest_sgl --- write single precision value to user space
*
*Input
* a0 -> destination address
* a1 -> source in extended precision
*
*Output
* a0 -> destroyed
* a1 -> destroyed
* d0 -> 0
*
*Changes extended precision to single precision.
* sgl_sign = ext_sign
* sgl_exp = ext_exp - $3fff(ext bias) + $7f(sgl bias)
* get rid of ext integer bit
* sgl_mant = ext_mant{62:12}
*
* --------------- --------------- ---------------
* extended -> |s| exp | |1| ms mant | | ls mant |
* --------------- --------------- ---------------
* 95 64 63 62 40 32 31 12 0
* | |
* | |
* | |
* v v
* ---------------
* single -> |s|exp| mant |
* ---------------
* 31 22 0
*
dest_sgl:
clr.l d0
move.w LOCAL_EX(a1),d0 ;get exponent
sub.w #$3fff,d0 ;subtract extended precision bias
cmp.w #$4000,d0 ;check if inf
beq.b stsinf ;if so, special case - label renamed <1/9/91, JPO>
add.w #$7f,d0 ;add single precision bias
swap d0 ;put exp in upper word of d0
lsl.l #7,d0 ;shift it into single exp bits
tst.b LOCAL_SGN(a1)
beq.b get_sman ;if positive, continue
bset.l #31,d0 ;if negative, put in sign first
bra.b get_sman ;get mantissa
stsinf: ; label renamed <1/9/91, JPO>
move.l #$7f800000,d0 ;load single inf exp to d0
tst.b LOCAL_SGN(a1)
beq.b sgl_wrt ;if positive, continue
bset.l #31,d0 ;if negative, put in sign info
bra.b sgl_wrt
get_sman:
move.l LOCAL_HI(a1),d1 ;get ms mantissa
bfextu d1{1:23},d1 ;get upper 23 bits of ms
or.l d1,d0 ;put these bits in ms word of single
sgl_wrt:
move.l d0,L_SCR1(a6) ;put the new exp back on the stack
move.l #$4,d0 ;byte count for single precision number
tst.l a0 ;users destination address
beq.b sgl_Dn ;destination is a data register
; exg a0,a1 ;a0=supervisor source, a1=user dest - DELETED <1/9/91, JPO>
; lea.l L_SCR1(a6),a0 ;point a0 to data - DELETED <1/9/91, JPO>
; bsr.l mem_write ;move the number to the user's memory - DELETED <1/9/91, JPO>
lea.l L_SCR1(a6),a1 ; point a1 to data <1/9/91, JPO>
move.l (a1),(a0) ; move the number to user memory <1/9/91, JPO>
rts
sgl_Dn:
; bsr.l get_fline ;returns fline word in d0 - DELETED <1/9/91, JPO>
; and.w #$7,d0 ;isolate register number - DELETED <1/9/91, JPO>
; move.l d0,d1 ;d1 has size:reg formatted for reg_dest - DELETED <1/9/91, JPO>
; or.l #$10,d1 ;reg_dest wants size added to reg# - DELETED <1/9/91, JPO>
move.l USER_FPIAR(a6),a0 ; read opcode into d1.w <1/9/91, JPO>
sub.l d1,d1 ; with d1 high word cleared <1/9/91, JPO>
move.w (a0),d1 ; <1/9/91, JPO>
and.w #7,d1 ; isolate register number <1/9/91, JPO>
or.b #$10,d1 ; set size to 32 bits <1/9/91, JPO>
bra reg_dest ;size is X, rts in reg_dest will
* ;return to caller of dest_sgl
dest_ext:
tst.b LOCAL_SGN(a1) ;put back sign into exponent word
beq.b dstx_cont
bset.b #sign_bit,LOCAL_EX(a1)
dstx_cont:
clr.b LOCAL_SGN(a1) ;clear out the sign byte
; move.l #$0c,d0 ;byte count for extended number - DELETED <1/9/91, JPO>
; exg a0,a1 ;a0=supervisor source, a1=user dest - DELETED <1/9/91, JPO>
; bsr.l mem_write ;move the number to the user's memory - DELETED <1/9/91, JPO>
move.l (a1)+,(a0)+ ; move the number to user's memory <1/9/91, JPO>
move.l (a1)+,(a0)+
move.l (a1),(a0)
rts