283 lines
8.1 KiB
Plaintext
283 lines
8.1 KiB
Plaintext
* $NetBSD: x_store.sa,v 1.4 2001/12/09 01:43:13 briggs Exp $
|
|
|
|
* MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
|
|
* M68000 Hi-Performance Microprocessor Division
|
|
* M68040 Software Package
|
|
*
|
|
* M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc.
|
|
* All rights reserved.
|
|
*
|
|
* THE SOFTWARE is provided on an "AS IS" basis and without warranty.
|
|
* To the maximum extent permitted by applicable law,
|
|
* MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
|
|
* INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
|
|
* PARTICULAR PURPOSE and any warranty against infringement with
|
|
* regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
|
|
* and any accompanying written materials.
|
|
*
|
|
* To the maximum extent permitted by applicable law,
|
|
* IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
|
|
* (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS
|
|
* PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR
|
|
* OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE
|
|
* SOFTWARE. Motorola assumes no responsibility for the maintenance
|
|
* and support of the SOFTWARE.
|
|
*
|
|
* You are hereby granted a copyright license to use, modify, and
|
|
* distribute the SOFTWARE so long as this entire notice is retained
|
|
* without alteration in any modified and/or redistributed versions,
|
|
* and that such modified versions are clearly identified as such.
|
|
* No licenses are granted by implication, estoppel or otherwise
|
|
* under any patents or trademarks of Motorola, Inc.
|
|
|
|
*
|
|
* x_store.sa 3.2 1/24/91
|
|
*
|
|
* store --- store operand to memory or register
|
|
*
|
|
* Used by underflow and overflow handlers.
|
|
*
|
|
* a6 = points to fp value to be stored.
|
|
*
|
|
|
|
X_STORE IDNT 2,1 Motorola 040 Floating Point Software Package
|
|
|
|
section 8
|
|
|
|
fpreg_mask:
|
|
dc.b $80,$40,$20,$10,$08,$04,$02,$01
|
|
|
|
include fpsp.h
|
|
|
|
xref mem_write
|
|
xref get_fline
|
|
xref g_opcls
|
|
xref g_dfmtou
|
|
xref reg_dest
|
|
|
|
xdef dest_ext
|
|
xdef dest_dbl
|
|
xdef dest_sgl
|
|
|
|
xdef store
|
|
store:
|
|
btst.b #E3,E_BYTE(a6)
|
|
beq.b E1_sto
|
|
E3_sto:
|
|
move.l CMDREG3B(a6),d0
|
|
bfextu d0{6:3},d0 ;isolate dest. reg from cmdreg3b
|
|
sto_fp:
|
|
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 fp2,USER_FP2(a6)
|
|
rts
|
|
not_fp2:
|
|
cmp.b #$10,d0
|
|
bne.b not_fp3
|
|
fmovem.x fp3,USER_FP3(a6)
|
|
rts
|
|
not_fp3:
|
|
rts
|
|
|
|
E1_sto:
|
|
bsr.l g_opcls ;returns opclass in d0
|
|
cmpi.b #3,d0
|
|
beq opc011 ;branch if opclass 3
|
|
move.l CMDREG1B(a6),d0
|
|
bfextu d0{6:3},d0 ;extract destination register
|
|
bra.b sto_fp
|
|
|
|
opc011:
|
|
bsr.l 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
|
|
tst.l d0 ;if dest format is extended
|
|
beq.w dest_ext ;then branch
|
|
cmpi.l #1,d0 ;if dest format is single
|
|
beq.b short_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
|
|
exg a0,a1 ;a0=supervisor source, a1=user dest
|
|
bsr.l mem_write ;move the number to the user's memory
|
|
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:
|
|
short_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 sinf ;if so, special case
|
|
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
|
|
sinf:
|
|
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
|
|
lea.l L_SCR1(a6),a0 ;point a0 to data
|
|
bsr.l mem_write ;move the number to the user's memory
|
|
rts
|
|
sgl_Dn:
|
|
bsr.l get_fline ;returns fline word in d0
|
|
and.w #$7,d0 ;isolate register number
|
|
move.l d0,d1 ;d1 has size:reg formatted for reg_dest
|
|
or.l #$10,d1 ;reg_dest wants size added to reg#
|
|
bra.l 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
|
|
exg a0,a1 ;a0=supervisor source, a1=user dest
|
|
bsr.l mem_write ;move the number to the user's memory
|
|
rts
|
|
|
|
end
|