774 lines
18 KiB
Plaintext
774 lines
18 KiB
Plaintext
* $NetBSD: util.sa,v 1.3 1994/10/26 07:50:20 cgd 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.
|
|
|
|
*
|
|
* util.sa 3.7 7/29/91
|
|
*
|
|
* This file contains routines used by other programs.
|
|
*
|
|
* ovf_res: used by overflow to force the correct
|
|
* result. ovf_r_k, ovf_r_x2, ovf_r_x3 are
|
|
* derivatives of this routine.
|
|
* get_fline: get user's opcode word
|
|
* g_dfmtou: returns the destination format.
|
|
* g_opcls: returns the opclass of the float instruction.
|
|
* g_rndpr: returns the rounding precision.
|
|
* reg_dest: write byte, word, or long data to Dn
|
|
*
|
|
|
|
UTIL IDNT 2,1 Motorola 040 Floating Point Software Package
|
|
|
|
section 8
|
|
|
|
include fpsp.h
|
|
|
|
xref mem_read
|
|
|
|
xdef g_dfmtou
|
|
xdef g_opcls
|
|
xdef g_rndpr
|
|
xdef get_fline
|
|
xdef reg_dest
|
|
|
|
*
|
|
* Final result table for ovf_res. Note that the negative counterparts
|
|
* are unnecessary as ovf_res always returns the sign separately from
|
|
* the exponent.
|
|
* ;+inf
|
|
EXT_PINF dc.l $7fff0000,$00000000,$00000000,$00000000
|
|
* ;largest +ext
|
|
EXT_PLRG dc.l $7ffe0000,$ffffffff,$ffffffff,$00000000
|
|
* ;largest magnitude +sgl in ext
|
|
SGL_PLRG dc.l $407e0000,$ffffff00,$00000000,$00000000
|
|
* ;largest magnitude +dbl in ext
|
|
DBL_PLRG dc.l $43fe0000,$ffffffff,$fffff800,$00000000
|
|
* ;largest -ext
|
|
|
|
tblovfl:
|
|
dc.l EXT_RN
|
|
dc.l EXT_RZ
|
|
dc.l EXT_RM
|
|
dc.l EXT_RP
|
|
dc.l SGL_RN
|
|
dc.l SGL_RZ
|
|
dc.l SGL_RM
|
|
dc.l SGL_RP
|
|
dc.l DBL_RN
|
|
dc.l DBL_RZ
|
|
dc.l DBL_RM
|
|
dc.l DBL_RP
|
|
dc.l error
|
|
dc.l error
|
|
dc.l error
|
|
dc.l error
|
|
|
|
|
|
*
|
|
* ovf_r_k --- overflow result calculation
|
|
*
|
|
* This entry point is used by kernel_ex.
|
|
*
|
|
* This forces the destination precision to be extended
|
|
*
|
|
* Input: operand in ETEMP
|
|
* Output: a result is in ETEMP (internal extended format)
|
|
*
|
|
xdef ovf_r_k
|
|
ovf_r_k:
|
|
lea ETEMP(a6),a0 ;a0 points to source operand
|
|
bclr.b #sign_bit,ETEMP_EX(a6)
|
|
sne ETEMP_SGN(a6) ;convert to internal IEEE format
|
|
|
|
*
|
|
* ovf_r_x2 --- overflow result calculation
|
|
*
|
|
* This entry point used by x_ovfl. (opclass 0 and 2)
|
|
*
|
|
* Input a0 points to an operand in the internal extended format
|
|
* Output a0 points to the result in the internal extended format
|
|
*
|
|
* This sets the round precision according to the user's FPCR unless the
|
|
* instruction is fsgldiv or fsglmul or fsadd, fdadd, fsub, fdsub, fsmul,
|
|
* fdmul, fsdiv, fddiv, fssqrt, fsmove, fdmove, fsabs, fdabs, fsneg, fdneg.
|
|
* If the instruction is fsgldiv of fsglmul, the rounding precision must be
|
|
* extended. If the instruction is not fsgldiv or fsglmul but a force-
|
|
* precision instruction, the rounding precision is then set to the force
|
|
* precision.
|
|
|
|
xdef ovf_r_x2
|
|
ovf_r_x2:
|
|
btst.b #E3,E_BYTE(a6) ;check for nu exception
|
|
beq.l ovf_e1_exc ;it is cu exception
|
|
ovf_e3_exc:
|
|
move.w CMDREG3B(a6),d0 ;get the command word
|
|
andi.w #$00000060,d0 ;clear all bits except 6 and 5
|
|
cmpi.l #$00000040,d0
|
|
beq.l ovff_sgl ;force precision is single
|
|
cmpi.l #$00000060,d0
|
|
beq.l ovff_dbl ;force precision is double
|
|
move.w CMDREG3B(a6),d0 ;get the command word again
|
|
andi.l #$7f,d0 ;clear all except operation
|
|
cmpi.l #$33,d0
|
|
beq.l ovf_fsgl ;fsglmul or fsgldiv
|
|
cmpi.l #$30,d0
|
|
beq.l ovf_fsgl
|
|
bra ovf_fpcr ;instruction is none of the above
|
|
* ;use FPCR
|
|
ovf_e1_exc:
|
|
move.w CMDREG1B(a6),d0 ;get command word
|
|
andi.l #$00000044,d0 ;clear all bits except 6 and 2
|
|
cmpi.l #$00000040,d0
|
|
beq.l ovff_sgl ;the instruction is force single
|
|
cmpi.l #$00000044,d0
|
|
beq.l ovff_dbl ;the instruction is force double
|
|
move.w CMDREG1B(a6),d0 ;again get the command word
|
|
andi.l #$0000007f,d0 ;clear all except the op code
|
|
cmpi.l #$00000027,d0
|
|
beq.l ovf_fsgl ;fsglmul
|
|
cmpi.l #$00000024,d0
|
|
beq.l ovf_fsgl ;fsgldiv
|
|
bra ovf_fpcr ;none of the above, use FPCR
|
|
*
|
|
*
|
|
* Inst is either fsgldiv or fsglmul. Force extended precision.
|
|
*
|
|
ovf_fsgl:
|
|
clr.l d0
|
|
bra.b ovf_res
|
|
|
|
ovff_sgl:
|
|
move.l #$00000001,d0 ;set single
|
|
bra.b ovf_res
|
|
ovff_dbl:
|
|
move.l #$00000002,d0 ;set double
|
|
bra.b ovf_res
|
|
*
|
|
* The precision is in the fpcr.
|
|
*
|
|
ovf_fpcr:
|
|
bfextu FPCR_MODE(a6){0:2},d0 ;set round precision
|
|
bra.b ovf_res
|
|
|
|
*
|
|
*
|
|
* ovf_r_x3 --- overflow result calculation
|
|
*
|
|
* This entry point used by x_ovfl. (opclass 3 only)
|
|
*
|
|
* Input a0 points to an operand in the internal extended format
|
|
* Output a0 points to the result in the internal extended format
|
|
*
|
|
* This sets the round precision according to the destination size.
|
|
*
|
|
xdef ovf_r_x3
|
|
ovf_r_x3:
|
|
bsr g_dfmtou ;get dest fmt in d0{1:0}
|
|
* ;for fmovout, the destination format
|
|
* ;is the rounding precision
|
|
|
|
*
|
|
* ovf_res --- overflow result calculation
|
|
*
|
|
* Input:
|
|
* a0 points to operand in internal extended format
|
|
* Output:
|
|
* a0 points to result in internal extended format
|
|
*
|
|
xdef ovf_res
|
|
ovf_res:
|
|
lsl.l #2,d0 ;move round precision to d0{3:2}
|
|
bfextu FPCR_MODE(a6){2:2},d1 ;set round mode
|
|
or.l d1,d0 ;index is fmt:mode in d0{3:0}
|
|
lea.l tblovfl,a1 ;load a1 with table address
|
|
move.l (a1,d0*4),a1 ;use d0 as index to the table
|
|
jmp (a1) ;go to the correct routine
|
|
*
|
|
*case DEST_FMT = EXT
|
|
*
|
|
EXT_RN:
|
|
lea.l EXT_PINF,a1 ;answer is +/- infinity
|
|
bset.b #inf_bit,FPSR_CC(a6)
|
|
bra set_sign ;now go set the sign
|
|
EXT_RZ:
|
|
lea.l EXT_PLRG,a1 ;answer is +/- large number
|
|
bra set_sign ;now go set the sign
|
|
EXT_RM:
|
|
tst.b LOCAL_SGN(a0) ;if negative overflow
|
|
beq.b e_rm_pos
|
|
e_rm_neg:
|
|
lea.l EXT_PINF,a1 ;answer is negative infinity
|
|
or.l #neginf_mask,USER_FPSR(a6)
|
|
bra end_ovfr
|
|
e_rm_pos:
|
|
lea.l EXT_PLRG,a1 ;answer is large positive number
|
|
bra end_ovfr
|
|
EXT_RP:
|
|
tst.b LOCAL_SGN(a0) ;if negative overflow
|
|
beq.b e_rp_pos
|
|
e_rp_neg:
|
|
lea.l EXT_PLRG,a1 ;answer is large negative number
|
|
bset.b #neg_bit,FPSR_CC(a6)
|
|
bra end_ovfr
|
|
e_rp_pos:
|
|
lea.l EXT_PINF,a1 ;answer is positive infinity
|
|
bset.b #inf_bit,FPSR_CC(a6)
|
|
bra end_ovfr
|
|
*
|
|
*case DEST_FMT = DBL
|
|
*
|
|
DBL_RN:
|
|
lea.l EXT_PINF,a1 ;answer is +/- infinity
|
|
bset.b #inf_bit,FPSR_CC(a6)
|
|
bra set_sign
|
|
DBL_RZ:
|
|
lea.l DBL_PLRG,a1 ;answer is +/- large number
|
|
bra set_sign ;now go set the sign
|
|
DBL_RM:
|
|
tst.b LOCAL_SGN(a0) ;if negative overflow
|
|
beq.b d_rm_pos
|
|
d_rm_neg:
|
|
lea.l EXT_PINF,a1 ;answer is negative infinity
|
|
or.l #neginf_mask,USER_FPSR(a6)
|
|
bra end_ovfr ;inf is same for all precisions (ext,dbl,sgl)
|
|
d_rm_pos:
|
|
lea.l DBL_PLRG,a1 ;answer is large positive number
|
|
bra end_ovfr
|
|
DBL_RP:
|
|
tst.b LOCAL_SGN(a0) ;if negative overflow
|
|
beq.b d_rp_pos
|
|
d_rp_neg:
|
|
lea.l DBL_PLRG,a1 ;answer is large negative number
|
|
bset.b #neg_bit,FPSR_CC(a6)
|
|
bra end_ovfr
|
|
d_rp_pos:
|
|
lea.l EXT_PINF,a1 ;answer is positive infinity
|
|
bset.b #inf_bit,FPSR_CC(a6)
|
|
bra end_ovfr
|
|
*
|
|
*case DEST_FMT = SGL
|
|
*
|
|
SGL_RN:
|
|
lea.l EXT_PINF,a1 ;answer is +/- infinity
|
|
bset.b #inf_bit,FPSR_CC(a6)
|
|
bra.b set_sign
|
|
SGL_RZ:
|
|
lea.l SGL_PLRG,a1 ;anwer is +/- large number
|
|
bra.b set_sign
|
|
SGL_RM:
|
|
tst.b LOCAL_SGN(a0) ;if negative overflow
|
|
beq.b s_rm_pos
|
|
s_rm_neg:
|
|
lea.l EXT_PINF,a1 ;answer is negative infinity
|
|
or.l #neginf_mask,USER_FPSR(a6)
|
|
bra.b end_ovfr
|
|
s_rm_pos:
|
|
lea.l SGL_PLRG,a1 ;answer is large positive number
|
|
bra.b end_ovfr
|
|
SGL_RP:
|
|
tst.b LOCAL_SGN(a0) ;if negative overflow
|
|
beq.b s_rp_pos
|
|
s_rp_neg:
|
|
lea.l SGL_PLRG,a1 ;answer is large negative number
|
|
bset.b #neg_bit,FPSR_CC(a6)
|
|
bra.b end_ovfr
|
|
s_rp_pos:
|
|
lea.l EXT_PINF,a1 ;answer is postive infinity
|
|
bset.b #inf_bit,FPSR_CC(a6)
|
|
bra.b end_ovfr
|
|
|
|
set_sign:
|
|
tst.b LOCAL_SGN(a0) ;if negative overflow
|
|
beq.b end_ovfr
|
|
neg_sign:
|
|
bset.b #neg_bit,FPSR_CC(a6)
|
|
|
|
end_ovfr:
|
|
move.w LOCAL_EX(a1),LOCAL_EX(a0) ;do not overwrite sign
|
|
move.l LOCAL_HI(a1),LOCAL_HI(a0)
|
|
move.l LOCAL_LO(a1),LOCAL_LO(a0)
|
|
rts
|
|
|
|
|
|
*
|
|
* ERROR
|
|
*
|
|
error:
|
|
rts
|
|
*
|
|
* get_fline --- get f-line opcode of interrupted instruction
|
|
*
|
|
* Returns opcode in the low word of d0.
|
|
*
|
|
get_fline:
|
|
move.l USER_FPIAR(a6),a0 ;opcode address
|
|
clr.l -(a7) ;reserve a word on the stack
|
|
lea.l 2(a7),a1 ;point to low word of temporary
|
|
move.l #2,d0 ;count
|
|
bsr.l mem_read
|
|
move.l (a7)+,d0
|
|
rts
|
|
*
|
|
* g_rndpr --- put rounding precision in d0{1:0}
|
|
*
|
|
* valid return codes are:
|
|
* 00 - extended
|
|
* 01 - single
|
|
* 10 - double
|
|
*
|
|
* begin
|
|
* get rounding precision (cmdreg3b{6:5})
|
|
* begin
|
|
* case opclass = 011 (move out)
|
|
* get destination format - this is the also the rounding precision
|
|
*
|
|
* case opclass = 0x0
|
|
* if E3
|
|
* *case RndPr(from cmdreg3b{6:5} = 11 then RND_PREC = DBL
|
|
* *case RndPr(from cmdreg3b{6:5} = 10 then RND_PREC = SGL
|
|
* case RndPr(from cmdreg3b{6:5} = 00 | 01
|
|
* use precision from FPCR{7:6}
|
|
* case 00 then RND_PREC = EXT
|
|
* case 01 then RND_PREC = SGL
|
|
* case 10 then RND_PREC = DBL
|
|
* else E1
|
|
* use precision in FPCR{7:6}
|
|
* case 00 then RND_PREC = EXT
|
|
* case 01 then RND_PREC = SGL
|
|
* case 10 then RND_PREC = DBL
|
|
* end
|
|
*
|
|
g_rndpr:
|
|
bsr.w g_opcls ;get opclass in d0{2:0}
|
|
cmp.w #$0003,d0 ;check for opclass 011
|
|
bne.b op_0x0
|
|
|
|
*
|
|
* For move out instructions (opclass 011) the destination format
|
|
* is the same as the rounding precision. Pass results from g_dfmtou.
|
|
*
|
|
bsr.w g_dfmtou
|
|
rts
|
|
op_0x0:
|
|
btst.b #E3,E_BYTE(a6)
|
|
beq.l unf_e1_exc ;branch to e1 underflow
|
|
unf_e3_exc:
|
|
move.l CMDREG3B(a6),d0 ;rounding precision in d0{10:9}
|
|
bfextu d0{9:2},d0 ;move the rounding prec bits to d0{1:0}
|
|
cmpi.l #$2,d0
|
|
beq.l unff_sgl ;force precision is single
|
|
cmpi.l #$3,d0 ;force precision is double
|
|
beq.l unff_dbl
|
|
move.w CMDREG3B(a6),d0 ;get the command word again
|
|
andi.l #$7f,d0 ;clear all except operation
|
|
cmpi.l #$33,d0
|
|
beq.l unf_fsgl ;fsglmul or fsgldiv
|
|
cmpi.l #$30,d0
|
|
beq.l unf_fsgl ;fsgldiv or fsglmul
|
|
bra unf_fpcr
|
|
unf_e1_exc:
|
|
move.l CMDREG1B(a6),d0 ;get 32 bits off the stack, 1st 16 bits
|
|
* ;are the command word
|
|
andi.l #$00440000,d0 ;clear all bits except bits 6 and 2
|
|
cmpi.l #$00400000,d0
|
|
beq.l unff_sgl ;force single
|
|
cmpi.l #$00440000,d0 ;force double
|
|
beq.l unff_dbl
|
|
move.l CMDREG1B(a6),d0 ;get the command word again
|
|
andi.l #$007f0000,d0 ;clear all bits except the operation
|
|
cmpi.l #$00270000,d0
|
|
beq.l unf_fsgl ;fsglmul
|
|
cmpi.l #$00240000,d0
|
|
beq.l unf_fsgl ;fsgldiv
|
|
bra unf_fpcr
|
|
|
|
*
|
|
* Convert to return format. The values from cmdreg3b and the return
|
|
* values are:
|
|
* cmdreg3b return precision
|
|
* -------- ------ ---------
|
|
* 00,01 0 ext
|
|
* 10 1 sgl
|
|
* 11 2 dbl
|
|
* Force single
|
|
*
|
|
unff_sgl:
|
|
move.l #1,d0 ;return 1
|
|
rts
|
|
*
|
|
* Force double
|
|
*
|
|
unff_dbl:
|
|
move.l #2,d0 ;return 2
|
|
rts
|
|
*
|
|
* Force extended
|
|
*
|
|
unf_fsgl:
|
|
clr.l d0
|
|
rts
|
|
*
|
|
* Get rounding precision set in FPCR{7:6}.
|
|
*
|
|
unf_fpcr:
|
|
move.l USER_FPCR(a6),d0 ;rounding precision bits in d0{7:6}
|
|
bfextu d0{24:2},d0 ;move the rounding prec bits to d0{1:0}
|
|
rts
|
|
*
|
|
* g_opcls --- put opclass in d0{2:0}
|
|
*
|
|
g_opcls:
|
|
btst.b #E3,E_BYTE(a6)
|
|
beq.b opc_1b ;if set, go to cmdreg1b
|
|
opc_3b:
|
|
clr.l d0 ;if E3, only opclass 0x0 is possible
|
|
rts
|
|
opc_1b:
|
|
move.l CMDREG1B(a6),d0
|
|
bfextu d0{0:3},d0 ;shift opclass bits d0{31:29} to d0{2:0}
|
|
rts
|
|
*
|
|
* g_dfmtou --- put destination format in d0{1:0}
|
|
*
|
|
* If E1, the format is from cmdreg1b{12:10}
|
|
* If E3, the format is extended.
|
|
*
|
|
* Dest. Fmt.
|
|
* extended 010 -> 00
|
|
* single 001 -> 01
|
|
* double 101 -> 10
|
|
*
|
|
g_dfmtou:
|
|
btst.b #E3,E_BYTE(a6)
|
|
beq.b op011
|
|
clr.l d0 ;if E1, size is always ext
|
|
rts
|
|
op011:
|
|
move.l CMDREG1B(a6),d0
|
|
bfextu d0{3:3},d0 ;dest fmt from cmdreg1b{12:10}
|
|
cmp.b #1,d0 ;check for single
|
|
bne.b not_sgl
|
|
move.l #1,d0
|
|
rts
|
|
not_sgl:
|
|
cmp.b #5,d0 ;check for double
|
|
bne.b not_dbl
|
|
move.l #2,d0
|
|
rts
|
|
not_dbl:
|
|
clr.l d0 ;must be extended
|
|
rts
|
|
|
|
*
|
|
*
|
|
* Final result table for unf_sub. Note that the negative counterparts
|
|
* are unnecessary as unf_sub always returns the sign separately from
|
|
* the exponent.
|
|
* ;+zero
|
|
EXT_PZRO dc.l $00000000,$00000000,$00000000,$00000000
|
|
* ;+zero
|
|
SGL_PZRO dc.l $3f810000,$00000000,$00000000,$00000000
|
|
* ;+zero
|
|
DBL_PZRO dc.l $3c010000,$00000000,$00000000,$00000000
|
|
* ;smallest +ext denorm
|
|
EXT_PSML dc.l $00000000,$00000000,$00000001,$00000000
|
|
* ;smallest +sgl denorm
|
|
SGL_PSML dc.l $3f810000,$00000100,$00000000,$00000000
|
|
* ;smallest +dbl denorm
|
|
DBL_PSML dc.l $3c010000,$00000000,$00000800,$00000000
|
|
*
|
|
* UNF_SUB --- underflow result calculation
|
|
*
|
|
* Input:
|
|
* d0 contains round precision
|
|
* a0 points to input operand in the internal extended format
|
|
*
|
|
* Output:
|
|
* a0 points to correct internal extended precision result.
|
|
*
|
|
|
|
tblunf:
|
|
dc.l uEXT_RN
|
|
dc.l uEXT_RZ
|
|
dc.l uEXT_RM
|
|
dc.l uEXT_RP
|
|
dc.l uSGL_RN
|
|
dc.l uSGL_RZ
|
|
dc.l uSGL_RM
|
|
dc.l uSGL_RP
|
|
dc.l uDBL_RN
|
|
dc.l uDBL_RZ
|
|
dc.l uDBL_RM
|
|
dc.l uDBL_RP
|
|
dc.l uDBL_RN
|
|
dc.l uDBL_RZ
|
|
dc.l uDBL_RM
|
|
dc.l uDBL_RP
|
|
|
|
xdef unf_sub
|
|
unf_sub:
|
|
lsl.l #2,d0 ;move round precision to d0{3:2}
|
|
bfextu FPCR_MODE(a6){2:2},d1 ;set round mode
|
|
or.l d1,d0 ;index is fmt:mode in d0{3:0}
|
|
lea.l tblunf,a1 ;load a1 with table address
|
|
move.l (a1,d0*4),a1 ;use d0 as index to the table
|
|
jmp (a1) ;go to the correct routine
|
|
*
|
|
*case DEST_FMT = EXT
|
|
*
|
|
uEXT_RN:
|
|
lea.l EXT_PZRO,a1 ;answer is +/- zero
|
|
bset.b #z_bit,FPSR_CC(a6)
|
|
bra uset_sign ;now go set the sign
|
|
uEXT_RZ:
|
|
lea.l EXT_PZRO,a1 ;answer is +/- zero
|
|
bset.b #z_bit,FPSR_CC(a6)
|
|
bra uset_sign ;now go set the sign
|
|
uEXT_RM:
|
|
tst.b LOCAL_SGN(a0) ;if negative underflow
|
|
beq.b ue_rm_pos
|
|
ue_rm_neg:
|
|
lea.l EXT_PSML,a1 ;answer is negative smallest denorm
|
|
bset.b #neg_bit,FPSR_CC(a6)
|
|
bra end_unfr
|
|
ue_rm_pos:
|
|
lea.l EXT_PZRO,a1 ;answer is positive zero
|
|
bset.b #z_bit,FPSR_CC(a6)
|
|
bra end_unfr
|
|
uEXT_RP:
|
|
tst.b LOCAL_SGN(a0) ;if negative underflow
|
|
beq.b ue_rp_pos
|
|
ue_rp_neg:
|
|
lea.l EXT_PZRO,a1 ;answer is negative zero
|
|
ori.l #negz_mask,USER_FPSR(a6)
|
|
bra end_unfr
|
|
ue_rp_pos:
|
|
lea.l EXT_PSML,a1 ;answer is positive smallest denorm
|
|
bra end_unfr
|
|
*
|
|
*case DEST_FMT = DBL
|
|
*
|
|
uDBL_RN:
|
|
lea.l DBL_PZRO,a1 ;answer is +/- zero
|
|
bset.b #z_bit,FPSR_CC(a6)
|
|
bra uset_sign
|
|
uDBL_RZ:
|
|
lea.l DBL_PZRO,a1 ;answer is +/- zero
|
|
bset.b #z_bit,FPSR_CC(a6)
|
|
bra uset_sign ;now go set the sign
|
|
uDBL_RM:
|
|
tst.b LOCAL_SGN(a0) ;if negative overflow
|
|
beq.b ud_rm_pos
|
|
ud_rm_neg:
|
|
lea.l DBL_PSML,a1 ;answer is smallest denormalized negative
|
|
bset.b #neg_bit,FPSR_CC(a6)
|
|
bra end_unfr
|
|
ud_rm_pos:
|
|
lea.l DBL_PZRO,a1 ;answer is positive zero
|
|
bset.b #z_bit,FPSR_CC(a6)
|
|
bra end_unfr
|
|
uDBL_RP:
|
|
tst.b LOCAL_SGN(a0) ;if negative overflow
|
|
beq.b ud_rp_pos
|
|
ud_rp_neg:
|
|
lea.l DBL_PZRO,a1 ;answer is negative zero
|
|
ori.l #negz_mask,USER_FPSR(a6)
|
|
bra end_unfr
|
|
ud_rp_pos:
|
|
lea.l DBL_PSML,a1 ;answer is smallest denormalized negative
|
|
bra end_unfr
|
|
*
|
|
*case DEST_FMT = SGL
|
|
*
|
|
uSGL_RN:
|
|
lea.l SGL_PZRO,a1 ;answer is +/- zero
|
|
bset.b #z_bit,FPSR_CC(a6)
|
|
bra.b uset_sign
|
|
uSGL_RZ:
|
|
lea.l SGL_PZRO,a1 ;answer is +/- zero
|
|
bset.b #z_bit,FPSR_CC(a6)
|
|
bra.b uset_sign
|
|
uSGL_RM:
|
|
tst.b LOCAL_SGN(a0) ;if negative overflow
|
|
beq.b us_rm_pos
|
|
us_rm_neg:
|
|
lea.l SGL_PSML,a1 ;answer is smallest denormalized negative
|
|
bset.b #neg_bit,FPSR_CC(a6)
|
|
bra.b end_unfr
|
|
us_rm_pos:
|
|
lea.l SGL_PZRO,a1 ;answer is positive zero
|
|
bset.b #z_bit,FPSR_CC(a6)
|
|
bra.b end_unfr
|
|
uSGL_RP:
|
|
tst.b LOCAL_SGN(a0) ;if negative overflow
|
|
beq.b us_rp_pos
|
|
us_rp_neg:
|
|
lea.l SGL_PZRO,a1 ;answer is negative zero
|
|
ori.l #negz_mask,USER_FPSR(a6)
|
|
bra.b end_unfr
|
|
us_rp_pos:
|
|
lea.l SGL_PSML,a1 ;answer is smallest denormalized positive
|
|
bra.b end_unfr
|
|
|
|
uset_sign:
|
|
tst.b LOCAL_SGN(a0) ;if negative overflow
|
|
beq.b end_unfr
|
|
uneg_sign:
|
|
bset.b #neg_bit,FPSR_CC(a6)
|
|
|
|
end_unfr:
|
|
move.w LOCAL_EX(a1),LOCAL_EX(a0) ;be careful not to overwrite sign
|
|
move.l LOCAL_HI(a1),LOCAL_HI(a0)
|
|
move.l LOCAL_LO(a1),LOCAL_LO(a0)
|
|
rts
|
|
*
|
|
* reg_dest --- write byte, word, or long data to Dn
|
|
*
|
|
*
|
|
* Input:
|
|
* L_SCR1: Data
|
|
* d1: data size and dest register number formatted as:
|
|
*
|
|
* 32 5 4 3 2 1 0
|
|
* -----------------------------------------------
|
|
* | 0 | Size | Dest Reg # |
|
|
* -----------------------------------------------
|
|
*
|
|
* Size is:
|
|
* 0 - Byte
|
|
* 1 - Word
|
|
* 2 - Long/Single
|
|
*
|
|
pregdst:
|
|
dc.l byte_d0
|
|
dc.l byte_d1
|
|
dc.l byte_d2
|
|
dc.l byte_d3
|
|
dc.l byte_d4
|
|
dc.l byte_d5
|
|
dc.l byte_d6
|
|
dc.l byte_d7
|
|
dc.l word_d0
|
|
dc.l word_d1
|
|
dc.l word_d2
|
|
dc.l word_d3
|
|
dc.l word_d4
|
|
dc.l word_d5
|
|
dc.l word_d6
|
|
dc.l word_d7
|
|
dc.l long_d0
|
|
dc.l long_d1
|
|
dc.l long_d2
|
|
dc.l long_d3
|
|
dc.l long_d4
|
|
dc.l long_d5
|
|
dc.l long_d6
|
|
dc.l long_d7
|
|
|
|
reg_dest:
|
|
lea.l pregdst,a0
|
|
move.l (a0,d1*4),a0
|
|
jmp (a0)
|
|
|
|
byte_d0:
|
|
move.b L_SCR1(a6),USER_D0+3(a6)
|
|
rts
|
|
byte_d1:
|
|
move.b L_SCR1(a6),USER_D1+3(a6)
|
|
rts
|
|
byte_d2:
|
|
move.b L_SCR1(a6),d2
|
|
rts
|
|
byte_d3:
|
|
move.b L_SCR1(a6),d3
|
|
rts
|
|
byte_d4:
|
|
move.b L_SCR1(a6),d4
|
|
rts
|
|
byte_d5:
|
|
move.b L_SCR1(a6),d5
|
|
rts
|
|
byte_d6:
|
|
move.b L_SCR1(a6),d6
|
|
rts
|
|
byte_d7:
|
|
move.b L_SCR1(a6),d7
|
|
rts
|
|
word_d0:
|
|
move.w L_SCR1(a6),USER_D0+2(a6)
|
|
rts
|
|
word_d1:
|
|
move.w L_SCR1(a6),USER_D1+2(a6)
|
|
rts
|
|
word_d2:
|
|
move.w L_SCR1(a6),d2
|
|
rts
|
|
word_d3:
|
|
move.w L_SCR1(a6),d3
|
|
rts
|
|
word_d4:
|
|
move.w L_SCR1(a6),d4
|
|
rts
|
|
word_d5:
|
|
move.w L_SCR1(a6),d5
|
|
rts
|
|
word_d6:
|
|
move.w L_SCR1(a6),d6
|
|
rts
|
|
word_d7:
|
|
move.w L_SCR1(a6),d7
|
|
rts
|
|
long_d0:
|
|
move.l L_SCR1(a6),USER_D0(a6)
|
|
rts
|
|
long_d1:
|
|
move.l L_SCR1(a6),USER_D1(a6)
|
|
rts
|
|
long_d2:
|
|
move.l L_SCR1(a6),d2
|
|
rts
|
|
long_d3:
|
|
move.l L_SCR1(a6),d3
|
|
rts
|
|
long_d4:
|
|
move.l L_SCR1(a6),d4
|
|
rts
|
|
long_d5:
|
|
move.l L_SCR1(a6),d5
|
|
rts
|
|
long_d6:
|
|
move.l L_SCR1(a6),d6
|
|
rts
|
|
long_d7:
|
|
move.l L_SCR1(a6),d7
|
|
rts
|
|
end
|