mac-rom/OS/FPUEmulation/XStore.a
Elliot Nunn 4325cdcc78 Bring in CubeE sources
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included.

The Tools directory, containing mostly junk, is also excluded.
2017-12-26 09:52:23 +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