c869df6afb
symbols--even when the branches are local and would otherwise work with bxx.b. Compensate for this by shadowing the relevant labels with local labels.
775 lines
18 KiB
Plaintext
775 lines
18 KiB
Plaintext
* $NetBSD: util.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.
|
|
|
|
*
|
|
* 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 short_ovf_res
|
|
|
|
ovff_sgl:
|
|
move.l #$00000001,d0 ;set single
|
|
bra.b short_ovf_res
|
|
ovff_dbl:
|
|
move.l #$00000002,d0 ;set double
|
|
bra.b short_ovf_res
|
|
*
|
|
* The precision is in the fpcr.
|
|
*
|
|
ovf_fpcr:
|
|
bfextu FPCR_MODE(a6){0:2},d0 ;set round precision
|
|
bra.b short_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:
|
|
short_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
|