freebsd-skq/sys/mips/mips/fp.S

3609 lines
78 KiB
ArmAsm

/* $OpenBSD: fp.S,v 1.2 1998/03/16 09:03:31 pefo Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Ralph Campbell.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: @(#)fp.s 8.1 (Berkeley) 6/10/93
* JNPR: fp.S,v 1.1 2006/08/07 05:38:57 katta
* $FreeBSD$
*/
/*
* Standard header stuff.
*/
#include <machine/asm.h>
#include <machine/regnum.h>
#include <machine/cpuregs.h>
#include "assym.s"
#define SEXP_INF 0xff
#define DEXP_INF 0x7ff
#define SEXP_BIAS 127
#define DEXP_BIAS 1023
#define SEXP_MIN -126
#define DEXP_MIN -1022
#define SEXP_MAX 127
#define DEXP_MAX 1023
#define WEXP_MAX 30 /* maximum unbiased exponent for int */
#define WEXP_MIN -1 /* minimum unbiased exponent for int */
#define SFRAC_BITS 23
#define DFRAC_BITS 52
#define SIMPL_ONE 0x00800000
#define DIMPL_ONE 0x00100000
#define SLEAD_ZEROS 31 - 23
#define DLEAD_ZEROS 31 - 20
#define STICKYBIT 1
#define GUARDBIT 0x80000000
#define SSIGNAL_NAN 0x00400000
#define DSIGNAL_NAN 0x00080000
#define SQUIET_NAN 0x003fffff
#define DQUIET_NAN0 0x0007ffff
#define DQUIET_NAN1 0xffffffff
#define INT_MIN 0x80000000
#define INT_MAX 0x7fffffff
#define COND_UNORDERED 0x1
#define COND_EQUAL 0x2
#define COND_LESS 0x4
#define COND_SIGNAL 0x8
/*----------------------------------------------------------------------------
*
* MipsEmulateFP --
*
* Emulate unimplemented floating point operations.
* This routine should only be called by MipsFPInterrupt().
*
* MipsEmulateFP(instr)
* unsigned instr;
*
* Results:
* None.
*
* Side effects:
* Floating point registers are modified according to instruction.
*
*----------------------------------------------------------------------------
*/
NON_LEAF(MipsEmulateFP, CALLFRAME_SIZ, ra)
subu sp, sp, CALLFRAME_SIZ
sw ra, CALLFRAME_RA(sp)
/*
* Decode the FMT field (bits 24-21) and FUNCTION field (bits 5-0).
*/
srl v0, a0, 21 - 2 # get FMT field
and v0, v0, 0xF << 2 # mask FMT field
and v1, a0, 0x3F # mask FUNC field
sll v1, v1, 5 # align for table lookup
bgt v0, 4 << 2, ill # illegal format
or v1, v1, v0
cfc1 a1, MIPS_FPU_CSR # get exception register
lw a3, func_fmt_tbl(v1) # switch on FUNC & FMT
and a1, a1, ~MIPS_FPU_EXCEPTION_UNIMPL # clear exception
ctc1 a1, MIPS_FPU_CSR
j a3
.rdata
func_fmt_tbl:
.word add_s # 0
.word add_d # 0
.word ill # 0
.word ill # 0
.word ill # 0
.word ill # 0
.word ill # 0
.word ill # 0
.word sub_s # 1
.word sub_d # 1
.word ill # 1
.word ill # 1
.word ill # 1
.word ill # 1
.word ill # 1
.word ill # 1
.word mul_s # 2
.word mul_d # 2
.word ill # 2
.word ill # 2
.word ill # 2
.word ill # 2
.word ill # 2
.word ill # 2
.word div_s # 3
.word div_d # 3
.word ill # 3
.word ill # 3
.word ill # 3
.word ill # 3
.word ill # 3
.word ill # 3
.word ill # 4
.word ill # 4
.word ill # 4
.word ill # 4
.word ill # 4
.word ill # 4
.word ill # 4
.word ill # 4
.word abs_s # 5
.word abs_d # 5
.word ill # 5
.word ill # 5
.word ill # 5
.word ill # 5
.word ill # 5
.word ill # 5
.word mov_s # 6
.word mov_d # 6
.word ill # 6
.word ill # 6
.word ill # 6
.word ill # 6
.word ill # 6
.word ill # 6
.word neg_s # 7
.word neg_d # 7
.word ill # 7
.word ill # 7
.word ill # 7
.word ill # 7
.word ill # 7
.word ill # 7
.word ill # 8
.word ill # 8
.word ill # 8
.word ill # 8
.word ill # 8
.word ill # 8
.word ill # 8
.word ill # 8
.word ill # 9
.word ill # 9
.word ill # 9
.word ill # 9
.word ill # 9
.word ill # 9
.word ill # 9
.word ill # 9
.word ill # 10
.word ill # 10
.word ill # 10
.word ill # 10
.word ill # 10
.word ill # 10
.word ill # 10
.word ill # 10
.word ill # 11
.word ill # 11
.word ill # 11
.word ill # 11
.word ill # 11
.word ill # 11
.word ill # 11
.word ill # 11
.word ill # 12
.word ill # 12
.word ill # 12
.word ill # 12
.word ill # 12
.word ill # 12
.word ill # 12
.word ill # 12
.word ill # 13
.word ill # 13
.word ill # 13
.word ill # 13
.word ill # 13
.word ill # 13
.word ill # 13
.word ill # 13
.word ill # 14
.word ill # 14
.word ill # 14
.word ill # 14
.word ill # 14
.word ill # 14
.word ill # 14
.word ill # 14
.word ill # 15
.word ill # 15
.word ill # 15
.word ill # 15
.word ill # 15
.word ill # 15
.word ill # 15
.word ill # 15
.word ill # 16
.word ill # 16
.word ill # 16
.word ill # 16
.word ill # 16
.word ill # 16
.word ill # 16
.word ill # 16
.word ill # 17
.word ill # 17
.word ill # 17
.word ill # 17
.word ill # 17
.word ill # 17
.word ill # 17
.word ill # 17
.word ill # 18
.word ill # 18
.word ill # 18
.word ill # 18
.word ill # 18
.word ill # 18
.word ill # 18
.word ill # 18
.word ill # 19
.word ill # 19
.word ill # 19
.word ill # 19
.word ill # 19
.word ill # 19
.word ill # 19
.word ill # 19
.word ill # 20
.word ill # 20
.word ill # 20
.word ill # 20
.word ill # 20
.word ill # 20
.word ill # 20
.word ill # 20
.word ill # 21
.word ill # 21
.word ill # 21
.word ill # 21
.word ill # 21
.word ill # 21
.word ill # 21
.word ill # 21
.word ill # 22
.word ill # 22
.word ill # 22
.word ill # 22
.word ill # 22
.word ill # 22
.word ill # 22
.word ill # 22
.word ill # 23
.word ill # 23
.word ill # 23
.word ill # 23
.word ill # 23
.word ill # 23
.word ill # 23
.word ill # 23
.word ill # 24
.word ill # 24
.word ill # 24
.word ill # 24
.word ill # 24
.word ill # 24
.word ill # 24
.word ill # 24
.word ill # 25
.word ill # 25
.word ill # 25
.word ill # 25
.word ill # 25
.word ill # 25
.word ill # 25
.word ill # 25
.word ill # 26
.word ill # 26
.word ill # 26
.word ill # 26
.word ill # 26
.word ill # 26
.word ill # 26
.word ill # 26
.word ill # 27
.word ill # 27
.word ill # 27
.word ill # 27
.word ill # 27
.word ill # 27
.word ill # 27
.word ill # 27
.word ill # 28
.word ill # 28
.word ill # 28
.word ill # 28
.word ill # 28
.word ill # 28
.word ill # 28
.word ill # 28
.word ill # 29
.word ill # 29
.word ill # 29
.word ill # 29
.word ill # 29
.word ill # 29
.word ill # 29
.word ill # 29
.word ill # 30
.word ill # 30
.word ill # 30
.word ill # 30
.word ill # 30
.word ill # 30
.word ill # 30
.word ill # 30
.word ill # 31
.word ill # 31
.word ill # 31
.word ill # 31
.word ill # 31
.word ill # 31
.word ill # 31
.word ill # 31
.word ill # 32
.word cvt_s_d # 32
.word ill # 32
.word ill # 32
.word cvt_s_w # 32
.word ill # 32
.word ill # 32
.word ill # 32
.word cvt_d_s # 33
.word ill # 33
.word ill # 33
.word ill # 33
.word cvt_d_w # 33
.word ill # 33
.word ill # 33
.word ill # 33
.word ill # 34
.word ill # 34
.word ill # 34
.word ill # 34
.word ill # 34
.word ill # 34
.word ill # 34
.word ill # 34
.word ill # 35
.word ill # 35
.word ill # 35
.word ill # 35
.word ill # 35
.word ill # 35
.word ill # 35
.word ill # 35
.word cvt_w_s # 36
.word cvt_w_d # 36
.word ill # 36
.word ill # 36
.word ill # 36
.word ill # 36
.word ill # 36
.word ill # 36
.word ill # 37
.word ill # 37
.word ill # 37
.word ill # 37
.word ill # 37
.word ill # 37
.word ill # 37
.word ill # 37
.word ill # 38
.word ill # 38
.word ill # 38
.word ill # 38
.word ill # 38
.word ill # 38
.word ill # 38
.word ill # 38
.word ill # 39
.word ill # 39
.word ill # 39
.word ill # 39
.word ill # 39
.word ill # 39
.word ill # 39
.word ill # 39
.word ill # 40
.word ill # 40
.word ill # 40
.word ill # 40
.word ill # 40
.word ill # 40
.word ill # 40
.word ill # 40
.word ill # 41
.word ill # 41
.word ill # 41
.word ill # 41
.word ill # 41
.word ill # 41
.word ill # 41
.word ill # 41
.word ill # 42
.word ill # 42
.word ill # 42
.word ill # 42
.word ill # 42
.word ill # 42
.word ill # 42
.word ill # 42
.word ill # 43
.word ill # 43
.word ill # 43
.word ill # 43
.word ill # 43
.word ill # 43
.word ill # 43
.word ill # 43
.word ill # 44
.word ill # 44
.word ill # 44
.word ill # 44
.word ill # 44
.word ill # 44
.word ill # 44
.word ill # 44
.word ill # 45
.word ill # 45
.word ill # 45
.word ill # 45
.word ill # 45
.word ill # 45
.word ill # 45
.word ill # 45
.word ill # 46
.word ill # 46
.word ill # 46
.word ill # 46
.word ill # 46
.word ill # 46
.word ill # 46
.word ill # 46
.word ill # 47
.word ill # 47
.word ill # 47
.word ill # 47
.word ill # 47
.word ill # 47
.word ill # 47
.word ill # 47
.word cmp_s # 48
.word cmp_d # 48
.word ill # 48
.word ill # 48
.word ill # 48
.word ill # 48
.word ill # 48
.word ill # 48
.word cmp_s # 49
.word cmp_d # 49
.word ill # 49
.word ill # 49
.word ill # 49
.word ill # 49
.word ill # 49
.word ill # 49
.word cmp_s # 50
.word cmp_d # 50
.word ill # 50
.word ill # 50
.word ill # 50
.word ill # 50
.word ill # 50
.word ill # 50
.word cmp_s # 51
.word cmp_d # 51
.word ill # 51
.word ill # 51
.word ill # 51
.word ill # 51
.word ill # 51
.word ill # 51
.word cmp_s # 52
.word cmp_d # 52
.word ill # 52
.word ill # 52
.word ill # 52
.word ill # 52
.word ill # 52
.word ill # 52
.word cmp_s # 53
.word cmp_d # 53
.word ill # 53
.word ill # 53
.word ill # 53
.word ill # 53
.word ill # 53
.word ill # 53
.word cmp_s # 54
.word cmp_d # 54
.word ill # 54
.word ill # 54
.word ill # 54
.word ill # 54
.word ill # 54
.word ill # 54
.word cmp_s # 55
.word cmp_d # 55
.word ill # 55
.word ill # 55
.word ill # 55
.word ill # 55
.word ill # 55
.word ill # 55
.word cmp_s # 56
.word cmp_d # 56
.word ill # 56
.word ill # 56
.word ill # 56
.word ill # 56
.word ill # 56
.word ill # 56
.word cmp_s # 57
.word cmp_d # 57
.word ill # 57
.word ill # 57
.word ill # 57
.word ill # 57
.word ill # 57
.word ill # 57
.word cmp_s # 58
.word cmp_d # 58
.word ill # 58
.word ill # 58
.word ill # 58
.word ill # 58
.word ill # 58
.word ill # 58
.word cmp_s # 59
.word cmp_d # 59
.word ill # 59
.word ill # 59
.word ill # 59
.word ill # 59
.word ill # 59
.word ill # 59
.word cmp_s # 60
.word cmp_d # 60
.word ill # 60
.word ill # 60
.word ill # 60
.word ill # 60
.word ill # 60
.word ill # 60
.word cmp_s # 61
.word cmp_d # 61
.word ill # 61
.word ill # 61
.word ill # 61
.word ill # 61
.word ill # 61
.word ill # 61
.word cmp_s # 62
.word cmp_d # 62
.word ill # 62
.word ill # 62
.word ill # 62
.word ill # 62
.word ill # 62
.word ill # 62
.word cmp_s # 63
.word cmp_d # 63
.word ill # 63
.word ill # 63
.word ill # 63
.word ill # 63
.word ill # 63
.word ill # 63
.text
/*
* Single precision subtract.
*/
sub_s:
jal get_ft_fs_s
xor ta0, ta0, 1 # negate FT sign bit
b add_sub_s
/*
* Single precision add.
*/
add_s:
jal get_ft_fs_s
add_sub_s:
bne t1, SEXP_INF, 1f # is FS an infinity?
bne ta1, SEXP_INF, result_fs_s # if FT is not inf, result=FS
bne t2, zero, result_fs_s # if FS is NAN, result is FS
bne ta2, zero, result_ft_s # if FT is NAN, result is FT
bne t0, ta0, invalid_s # both infinities same sign?
b result_fs_s # result is in FS
1:
beq ta1, SEXP_INF, result_ft_s # if FT is inf, result=FT
bne t1, zero, 4f # is FS a denormalized num?
beq t2, zero, 3f # is FS zero?
bne ta1, zero, 2f # is FT a denormalized num?
beq ta2, zero, result_fs_s # FT is zero, result=FS
jal renorm_fs_s
jal renorm_ft_s
b 5f
2:
jal renorm_fs_s
subu ta1, ta1, SEXP_BIAS # unbias FT exponent
or ta2, ta2, SIMPL_ONE # set implied one bit
b 5f
3:
bne ta1, zero, result_ft_s # if FT != 0, result=FT
bne ta2, zero, result_ft_s
and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
bne v0, MIPS_FPU_ROUND_RM, 1f # round to -infinity?
or t0, t0, ta0 # compute result sign
b result_fs_s
1:
and t0, t0, ta0 # compute result sign
b result_fs_s
4:
bne ta1, zero, 2f # is FT a denormalized num?
beq ta2, zero, result_fs_s # FT is zero, result=FS
subu t1, t1, SEXP_BIAS # unbias FS exponent
or t2, t2, SIMPL_ONE # set implied one bit
jal renorm_ft_s
b 5f
2:
subu t1, t1, SEXP_BIAS # unbias FS exponent
or t2, t2, SIMPL_ONE # set implied one bit
subu ta1, ta1, SEXP_BIAS # unbias FT exponent
or ta2, ta2, SIMPL_ONE # set implied one bit
/*
* Perform the addition.
*/
5:
move t8, zero # no shifted bits (sticky reg)
beq t1, ta1, 4f # no shift needed
subu v0, t1, ta1 # v0 = difference of exponents
move v1, v0 # v1 = abs(difference)
bge v0, zero, 1f
negu v1
1:
ble v1, SFRAC_BITS+2, 2f # is difference too great?
li t8, STICKYBIT # set the sticky bit
bge v0, zero, 1f # check which exp is larger
move t1, ta1 # result exp is FTs
move t2, zero # FSs fraction shifted is zero
b 4f
1:
move ta2, zero # FTs fraction shifted is zero
b 4f
2:
li t9, 32 # compute 32 - abs(exp diff)
subu t9, t9, v1
bgt v0, zero, 3f # if FS > FT, shift FTs frac
move t1, ta1 # FT > FS, result exp is FTs
sll t8, t2, t9 # save bits shifted out
srl t2, t2, v1 # shift FSs fraction
b 4f
3:
sll t8, ta2, t9 # save bits shifted out
srl ta2, ta2, v1 # shift FTs fraction
4:
bne t0, ta0, 1f # if signs differ, subtract
addu t2, t2, ta2 # add fractions
b norm_s
1:
blt t2, ta2, 3f # subtract larger from smaller
bne t2, ta2, 2f # if same, result=0
move t1, zero # result=0
move t2, zero
and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
bne v0, MIPS_FPU_ROUND_RM, 1f # round to -infinity?
or t0, t0, ta0 # compute result sign
b result_fs_s
1:
and t0, t0, ta0 # compute result sign
b result_fs_s
2:
sltu t9, zero, t8 # compute t2:zero - ta2:t8
subu t8, zero, t8
subu t2, t2, ta2 # subtract fractions
subu t2, t2, t9 # subtract barrow
b norm_s
3:
move t0, ta0 # sign of result = FTs
sltu t9, zero, t8 # compute ta2:zero - t2:t8
subu t8, zero, t8
subu t2, ta2, t2 # subtract fractions
subu t2, t2, t9 # subtract barrow
b norm_s
/*
* Double precision subtract.
*/
sub_d:
jal get_ft_fs_d
xor ta0, ta0, 1 # negate sign bit
b add_sub_d
/*
* Double precision add.
*/
add_d:
jal get_ft_fs_d
add_sub_d:
bne t1, DEXP_INF, 1f # is FS an infinity?
bne ta1, DEXP_INF, result_fs_d # if FT is not inf, result=FS
bne t2, zero, result_fs_d # if FS is NAN, result is FS
bne t3, zero, result_fs_d
bne ta2, zero, result_ft_d # if FT is NAN, result is FT
bne ta3, zero, result_ft_d
bne t0, ta0, invalid_d # both infinities same sign?
b result_fs_d # result is in FS
1:
beq ta1, DEXP_INF, result_ft_d # if FT is inf, result=FT
bne t1, zero, 4f # is FS a denormalized num?
bne t2, zero, 1f # is FS zero?
beq t3, zero, 3f
1:
bne ta1, zero, 2f # is FT a denormalized num?
bne ta2, zero, 1f
beq ta3, zero, result_fs_d # FT is zero, result=FS
1:
jal renorm_fs_d
jal renorm_ft_d
b 5f
2:
jal renorm_fs_d
subu ta1, ta1, DEXP_BIAS # unbias FT exponent
or ta2, ta2, DIMPL_ONE # set implied one bit
b 5f
3:
bne ta1, zero, result_ft_d # if FT != 0, result=FT
bne ta2, zero, result_ft_d
bne ta3, zero, result_ft_d
and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
bne v0, MIPS_FPU_ROUND_RM, 1f # round to -infinity?
or t0, t0, ta0 # compute result sign
b result_fs_d
1:
and t0, t0, ta0 # compute result sign
b result_fs_d
4:
bne ta1, zero, 2f # is FT a denormalized num?
bne ta2, zero, 1f
beq ta3, zero, result_fs_d # FT is zero, result=FS
1:
subu t1, t1, DEXP_BIAS # unbias FS exponent
or t2, t2, DIMPL_ONE # set implied one bit
jal renorm_ft_d
b 5f
2:
subu t1, t1, DEXP_BIAS # unbias FS exponent
or t2, t2, DIMPL_ONE # set implied one bit
subu ta1, ta1, DEXP_BIAS # unbias FT exponent
or ta2, ta2, DIMPL_ONE # set implied one bit
/*
* Perform the addition.
*/
5:
move t8, zero # no shifted bits (sticky reg)
beq t1, ta1, 4f # no shift needed
subu v0, t1, ta1 # v0 = difference of exponents
move v1, v0 # v1 = abs(difference)
bge v0, zero, 1f
negu v1
1:
ble v1, DFRAC_BITS+2, 2f # is difference too great?
li t8, STICKYBIT # set the sticky bit
bge v0, zero, 1f # check which exp is larger
move t1, ta1 # result exp is FTs
move t2, zero # FSs fraction shifted is zero
move t3, zero
b 4f
1:
move ta2, zero # FTs fraction shifted is zero
move ta3, zero
b 4f
2:
li t9, 32
bge v0, zero, 3f # if FS > FT, shift FTs frac
move t1, ta1 # FT > FS, result exp is FTs
blt v1, t9, 1f # shift right by < 32?
subu v1, v1, t9
subu t9, t9, v1
sll t8, t2, t9 # save bits shifted out
sltu t9, zero, t3 # dont lose any one bits
or t8, t8, t9 # save sticky bit
srl t3, t2, v1 # shift FSs fraction
move t2, zero
b 4f
1:
subu t9, t9, v1
sll t8, t3, t9 # save bits shifted out
srl t3, t3, v1 # shift FSs fraction
sll t9, t2, t9 # save bits shifted out of t2
or t3, t3, t9 # and put into t3
srl t2, t2, v1
b 4f
3:
blt v1, t9, 1f # shift right by < 32?
subu v1, v1, t9
subu t9, t9, v1
sll t8, ta2, t9 # save bits shifted out
srl ta3, ta2, v1 # shift FTs fraction
move ta2, zero
b 4f
1:
subu t9, t9, v1
sll t8, ta3, t9 # save bits shifted out
srl ta3, ta3, v1 # shift FTs fraction
sll t9, ta2, t9 # save bits shifted out of t2
or ta3, ta3, t9 # and put into t3
srl ta2, ta2, v1
4:
bne t0, ta0, 1f # if signs differ, subtract
addu t3, t3, ta3 # add fractions
sltu t9, t3, ta3 # compute carry
addu t2, t2, ta2 # add fractions
addu t2, t2, t9 # add carry
b norm_d
1:
blt t2, ta2, 3f # subtract larger from smaller
bne t2, ta2, 2f
bltu t3, ta3, 3f
bne t3, ta3, 2f # if same, result=0
move t1, zero # result=0
move t2, zero
move t3, zero
and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
bne v0, MIPS_FPU_ROUND_RM, 1f # round to -infinity?
or t0, t0, ta0 # compute result sign
b result_fs_d
1:
and t0, t0, ta0 # compute result sign
b result_fs_d
2:
beq t8, zero, 1f # compute t2:t3:zero - ta2:ta3:t8
subu t8, zero, t8
sltu v0, t3, 1 # compute barrow out
subu t3, t3, 1 # subtract barrow
subu t2, t2, v0
1:
sltu v0, t3, ta3
subu t3, t3, ta3 # subtract fractions
subu t2, t2, ta2 # subtract fractions
subu t2, t2, v0 # subtract barrow
b norm_d
3:
move t0, ta0 # sign of result = FTs
beq t8, zero, 1f # compute ta2:ta3:zero - t2:t3:t8
subu t8, zero, t8
sltu v0, ta3, 1 # compute barrow out
subu ta3, ta3, 1 # subtract barrow
subu ta2, ta2, v0
1:
sltu v0, ta3, t3
subu t3, ta3, t3 # subtract fractions
subu t2, ta2, t2 # subtract fractions
subu t2, t2, v0 # subtract barrow
b norm_d
/*
* Single precision multiply.
*/
mul_s:
jal get_ft_fs_s
xor t0, t0, ta0 # compute sign of result
move ta0, t0
bne t1, SEXP_INF, 2f # is FS an infinity?
bne t2, zero, result_fs_s # if FS is a NAN, result=FS
bne ta1, SEXP_INF, 1f # FS is inf, is FT an infinity?
bne ta2, zero, result_ft_s # if FT is a NAN, result=FT
b result_fs_s # result is infinity
1:
bne ta1, zero, result_fs_s # inf * zero? if no, result=FS
bne ta2, zero, result_fs_s
b invalid_s # infinity * zero is invalid
2:
bne ta1, SEXP_INF, 1f # FS != inf, is FT an infinity?
bne t1, zero, result_ft_s # zero * inf? if no, result=FT
bne t2, zero, result_ft_s
bne ta2, zero, result_ft_s # if FT is a NAN, result=FT
b invalid_s # zero * infinity is invalid
1:
bne t1, zero, 1f # is FS zero?
beq t2, zero, result_fs_s # result is zero
jal renorm_fs_s
b 2f
1:
subu t1, t1, SEXP_BIAS # unbias FS exponent
or t2, t2, SIMPL_ONE # set implied one bit
2:
bne ta1, zero, 1f # is FT zero?
beq ta2, zero, result_ft_s # result is zero
jal renorm_ft_s
b 2f
1:
subu ta1, ta1, SEXP_BIAS # unbias FT exponent
or ta2, ta2, SIMPL_ONE # set implied one bit
2:
addu t1, t1, ta1 # compute result exponent
addu t1, t1, 9 # account for binary point
multu t2, ta2 # multiply fractions
mflo t8
mfhi t2
b norm_s
/*
* Double precision multiply.
*/
mul_d:
jal get_ft_fs_d
xor t0, t0, ta0 # compute sign of result
move ta0, t0
bne t1, DEXP_INF, 2f # is FS an infinity?
bne t2, zero, result_fs_d # if FS is a NAN, result=FS
bne t3, zero, result_fs_d
bne ta1, DEXP_INF, 1f # FS is inf, is FT an infinity?
bne ta2, zero, result_ft_d # if FT is a NAN, result=FT
bne ta3, zero, result_ft_d
b result_fs_d # result is infinity
1:
bne ta1, zero, result_fs_d # inf * zero? if no, result=FS
bne ta2, zero, result_fs_d
bne ta3, zero, result_fs_d
b invalid_d # infinity * zero is invalid
2:
bne ta1, DEXP_INF, 1f # FS != inf, is FT an infinity?
bne t1, zero, result_ft_d # zero * inf? if no, result=FT
bne t2, zero, result_ft_d # if FS is a NAN, result=FS
bne t3, zero, result_ft_d
bne ta2, zero, result_ft_d # if FT is a NAN, result=FT
bne ta3, zero, result_ft_d
b invalid_d # zero * infinity is invalid
1:
bne t1, zero, 2f # is FS zero?
bne t2, zero, 1f
beq t3, zero, result_fs_d # result is zero
1:
jal renorm_fs_d
b 3f
2:
subu t1, t1, DEXP_BIAS # unbias FS exponent
or t2, t2, DIMPL_ONE # set implied one bit
3:
bne ta1, zero, 2f # is FT zero?
bne ta2, zero, 1f
beq ta3, zero, result_ft_d # result is zero
1:
jal renorm_ft_d
b 3f
2:
subu ta1, ta1, DEXP_BIAS # unbias FT exponent
or ta2, ta2, DIMPL_ONE # set implied one bit
3:
addu t1, t1, ta1 # compute result exponent
addu t1, t1, 12 # ???
multu t3, ta3 # multiply fractions (low * low)
move ta0, t2 # free up t2,t3 for result
move ta1, t3
mflo a3 # save low order bits
mfhi t8
not v0, t8
multu ta0, ta3 # multiply FS(high) * FT(low)
mflo v1
mfhi t3 # init low result
sltu v0, v0, v1 # compute carry
addu t8, v1
multu ta1, ta2 # multiply FS(low) * FT(high)
addu t3, t3, v0 # add carry
not v0, t8
mflo v1
mfhi t2
sltu v0, v0, v1
addu t8, v1
multu ta0, ta2 # multiply FS(high) * FT(high)
addu t3, v0
not v1, t3
sltu v1, v1, t2
addu t3, t2
not v0, t3
mfhi t2
addu t2, v1
mflo v1
sltu v0, v0, v1
addu t2, v0
addu t3, v1
sltu a3, zero, a3 # reduce t8,a3 to just t8
or t8, a3
b norm_d
/*
* Single precision divide.
*/
div_s:
jal get_ft_fs_s
xor t0, t0, ta0 # compute sign of result
move ta0, t0
bne t1, SEXP_INF, 1f # is FS an infinity?
bne t2, zero, result_fs_s # if FS is NAN, result is FS
bne ta1, SEXP_INF, result_fs_s # is FT an infinity?
bne ta2, zero, result_ft_s # if FT is NAN, result is FT
b invalid_s # infinity/infinity is invalid
1:
bne ta1, SEXP_INF, 1f # is FT an infinity?
bne ta2, zero, result_ft_s # if FT is NAN, result is FT
move t1, zero # x / infinity is zero
move t2, zero
b result_fs_s
1:
bne t1, zero, 2f # is FS zero?
bne t2, zero, 1f
bne ta1, zero, result_fs_s # FS=zero, is FT zero?
beq ta2, zero, invalid_s # 0 / 0
b result_fs_s # result = zero
1:
jal renorm_fs_s
b 3f
2:
subu t1, t1, SEXP_BIAS # unbias FS exponent
or t2, t2, SIMPL_ONE # set implied one bit
3:
bne ta1, zero, 2f # is FT zero?
bne ta2, zero, 1f
or a1, a1, MIPS_FPU_EXCEPTION_DIV0 | MIPS_FPU_STICKY_DIV0
and v0, a1, MIPS_FPU_ENABLE_DIV0 # trap enabled?
bne v0, zero, fpe_trap
ctc1 a1, MIPS_FPU_CSR # save exceptions
li t1, SEXP_INF # result is infinity
move t2, zero
b result_fs_s
1:
jal renorm_ft_s
b 3f
2:
subu ta1, ta1, SEXP_BIAS # unbias FT exponent
or ta2, ta2, SIMPL_ONE # set implied one bit
3:
subu t1, t1, ta1 # compute exponent
subu t1, t1, 3 # compensate for result position
li v0, SFRAC_BITS+3 # number of bits to divide
move t8, t2 # init dividend
move t2, zero # init result
1:
bltu t8, ta2, 3f # is dividend >= divisor?
2:
subu t8, t8, ta2 # subtract divisor from dividend
or t2, t2, 1 # remember that we did
bne t8, zero, 3f # if not done, continue
sll t2, t2, v0 # shift result to final position
b norm_s
3:
sll t8, t8, 1 # shift dividend
sll t2, t2, 1 # shift result
subu v0, v0, 1 # are we done?
bne v0, zero, 1b # no, continue
b norm_s
/*
* Double precision divide.
*/
div_d:
jal get_ft_fs_d
xor t0, t0, ta0 # compute sign of result
move ta0, t0
bne t1, DEXP_INF, 1f # is FS an infinity?
bne t2, zero, result_fs_d # if FS is NAN, result is FS
bne t3, zero, result_fs_d
bne ta1, DEXP_INF, result_fs_d # is FT an infinity?
bne ta2, zero, result_ft_d # if FT is NAN, result is FT
bne ta3, zero, result_ft_d
b invalid_d # infinity/infinity is invalid
1:
bne ta1, DEXP_INF, 1f # is FT an infinity?
bne ta2, zero, result_ft_d # if FT is NAN, result is FT
bne ta3, zero, result_ft_d
move t1, zero # x / infinity is zero
move t2, zero
move t3, zero
b result_fs_d
1:
bne t1, zero, 2f # is FS zero?
bne t2, zero, 1f
bne t3, zero, 1f
bne ta1, zero, result_fs_d # FS=zero, is FT zero?
bne ta2, zero, result_fs_d
beq ta3, zero, invalid_d # 0 / 0
b result_fs_d # result = zero
1:
jal renorm_fs_d
b 3f
2:
subu t1, t1, DEXP_BIAS # unbias FS exponent
or t2, t2, DIMPL_ONE # set implied one bit
3:
bne ta1, zero, 2f # is FT zero?
bne ta2, zero, 1f
bne ta3, zero, 1f
or a1, a1, MIPS_FPU_EXCEPTION_DIV0 | MIPS_FPU_STICKY_DIV0
and v0, a1, MIPS_FPU_ENABLE_DIV0 # trap enabled?
bne v0, zero, fpe_trap
ctc1 a1, MIPS_FPU_CSR # Save exceptions
li t1, DEXP_INF # result is infinity
move t2, zero
move t3, zero
b result_fs_d
1:
jal renorm_ft_d
b 3f
2:
subu ta1, ta1, DEXP_BIAS # unbias FT exponent
or ta2, ta2, DIMPL_ONE # set implied one bit
3:
subu t1, t1, ta1 # compute exponent
subu t1, t1, 3 # compensate for result position
li v0, DFRAC_BITS+3 # number of bits to divide
move t8, t2 # init dividend
move t9, t3
move t2, zero # init result
move t3, zero
1:
bltu t8, ta2, 3f # is dividend >= divisor?
bne t8, ta2, 2f
bltu t9, ta3, 3f
2:
sltu v1, t9, ta3 # subtract divisor from dividend
subu t9, t9, ta3
subu t8, t8, ta2
subu t8, t8, v1
or t3, t3, 1 # remember that we did
bne t8, zero, 3f # if not done, continue
bne t9, zero, 3f
li v1, 32 # shift result to final position
blt v0, v1, 2f # shift < 32 bits?
subu v0, v0, v1 # shift by > 32 bits
sll t2, t3, v0 # shift upper part
move t3, zero
b norm_d
2:
subu v1, v1, v0 # shift by < 32 bits
sll t2, t2, v0 # shift upper part
srl t9, t3, v1 # save bits shifted out
or t2, t2, t9 # and put into upper part
sll t3, t3, v0
b norm_d
3:
sll t8, t8, 1 # shift dividend
srl v1, t9, 31 # save bit shifted out
or t8, t8, v1 # and put into upper part
sll t9, t9, 1
sll t2, t2, 1 # shift result
srl v1, t3, 31 # save bit shifted out
or t2, t2, v1 # and put into upper part
sll t3, t3, 1
subu v0, v0, 1 # are we done?
bne v0, zero, 1b # no, continue
sltu v0, zero, t9 # be sure to save any one bits
or t8, t8, v0 # from the lower remainder
b norm_d
/*
* Single precision absolute value.
*/
abs_s:
jal get_fs_s
move t0, zero # set sign positive
b result_fs_s
/*
* Double precision absolute value.
*/
abs_d:
jal get_fs_d
move t0, zero # set sign positive
b result_fs_d
/*
* Single precision move.
*/
mov_s:
jal get_fs_s
b result_fs_s
/*
* Double precision move.
*/
mov_d:
jal get_fs_d
b result_fs_d
/*
* Single precision negate.
*/
neg_s:
jal get_fs_s
xor t0, t0, 1 # reverse sign
b result_fs_s
/*
* Double precision negate.
*/
neg_d:
jal get_fs_d
xor t0, t0, 1 # reverse sign
b result_fs_d
/*
* Convert double to single.
*/
cvt_s_d:
jal get_fs_d
bne t1, DEXP_INF, 1f # is FS an infinity?
li t1, SEXP_INF # convert to single
sll t2, t2, 3 # convert D fraction to S
srl t8, t3, 32 - 3
or t2, t2, t8
b result_fs_s
1:
bne t1, zero, 2f # is FS zero?
bne t2, zero, 1f
beq t3, zero, result_fs_s # result=0
1:
jal renorm_fs_d
subu t1, t1, 3 # correct exp for shift below
b 3f
2:
subu t1, t1, DEXP_BIAS # unbias exponent
or t2, t2, DIMPL_ONE # add implied one bit
3:
sll t2, t2, 3 # convert D fraction to S
srl t8, t3, 32 - 3
or t2, t2, t8
sll t8, t3, 3
b norm_noshift_s
/*
* Convert integer to single.
*/
cvt_s_w:
jal get_fs_int
bne t2, zero, 1f # check for zero
move t1, zero
b result_fs_s
/*
* Find out how many leading zero bits are in t2 and put in t9.
*/
1:
move v0, t2
move t9, zero
srl v1, v0, 16
bne v1, zero, 1f
addu t9, 16
sll v0, 16
1:
srl v1, v0, 24
bne v1, zero, 1f
addu t9, 8
sll v0, 8
1:
srl v1, v0, 28
bne v1, zero, 1f
addu t9, 4
sll v0, 4
1:
srl v1, v0, 30
bne v1, zero, 1f
addu t9, 2
sll v0, 2
1:
srl v1, v0, 31
bne v1, zero, 1f
addu t9, 1
/*
* Now shift t2 the correct number of bits.
*/
1:
subu t9, t9, SLEAD_ZEROS # dont count leading zeros
li t1, 23 # init exponent
subu t1, t1, t9 # compute exponent
beq t9, zero, 1f
li v0, 32
blt t9, zero, 2f # if shift < 0, shift right
subu v0, v0, t9
sll t2, t2, t9 # shift left
1:
add t1, t1, SEXP_BIAS # bias exponent
and t2, t2, ~SIMPL_ONE # clear implied one bit
b result_fs_s
2:
negu t9 # shift right by t9
subu v0, v0, t9
sll t8, t2, v0 # save bits shifted out
srl t2, t2, t9
b norm_noshift_s
/*
* Convert single to double.
*/
cvt_d_s:
jal get_fs_s
move t3, zero
bne t1, SEXP_INF, 1f # is FS an infinity?
li t1, DEXP_INF # convert to double
b result_fs_d
1:
bne t1, zero, 2f # is FS denormalized or zero?
beq t2, zero, result_fs_d # is FS zero?
jal renorm_fs_s
move t8, zero
b norm_d
2:
addu t1, t1, DEXP_BIAS - SEXP_BIAS # bias exponent correctly
sll t3, t2, 32 - 3 # convert S fraction to D
srl t2, t2, 3
b result_fs_d
/*
* Convert integer to double.
*/
cvt_d_w:
jal get_fs_int
bne t2, zero, 1f # check for zero
move t1, zero # result=0
move t3, zero
b result_fs_d
/*
* Find out how many leading zero bits are in t2 and put in t9.
*/
1:
move v0, t2
move t9, zero
srl v1, v0, 16
bne v1, zero, 1f
addu t9, 16
sll v0, 16
1:
srl v1, v0, 24
bne v1, zero, 1f
addu t9, 8
sll v0, 8
1:
srl v1, v0, 28
bne v1, zero, 1f
addu t9, 4
sll v0, 4
1:
srl v1, v0, 30
bne v1, zero, 1f
addu t9, 2
sll v0, 2
1:
srl v1, v0, 31
bne v1, zero, 1f
addu t9, 1
/*
* Now shift t2 the correct number of bits.
*/
1:
subu t9, t9, DLEAD_ZEROS # dont count leading zeros
li t1, DEXP_BIAS + 20 # init exponent
subu t1, t1, t9 # compute exponent
beq t9, zero, 1f
li v0, 32
blt t9, zero, 2f # if shift < 0, shift right
subu v0, v0, t9
sll t2, t2, t9 # shift left
1:
and t2, t2, ~DIMPL_ONE # clear implied one bit
move t3, zero
b result_fs_d
2:
negu t9 # shift right by t9
subu v0, v0, t9
sll t3, t2, v0
srl t2, t2, t9
and t2, t2, ~DIMPL_ONE # clear implied one bit
b result_fs_d
/*
* Convert single to integer.
*/
cvt_w_s:
jal get_fs_s
bne t1, SEXP_INF, 1f # is FS an infinity?
bne t2, zero, invalid_w # invalid conversion
1:
bne t1, zero, 1f # is FS zero?
beq t2, zero, result_fs_w # result is zero
move t2, zero # result is an inexact zero
b inexact_w
1:
subu t1, t1, SEXP_BIAS # unbias exponent
or t2, t2, SIMPL_ONE # add implied one bit
sll t3, t2, 32 - 3 # convert S fraction to D
srl t2, t2, 3
b cvt_w
/*
* Convert double to integer.
*/
cvt_w_d:
jal get_fs_d
bne t1, DEXP_INF, 1f # is FS an infinity?
bne t2, zero, invalid_w # invalid conversion
bne t3, zero, invalid_w # invalid conversion
1:
bne t1, zero, 2f # is FS zero?
bne t2, zero, 1f
beq t3, zero, result_fs_w # result is zero
1:
move t2, zero # result is an inexact zero
b inexact_w
2:
subu t1, t1, DEXP_BIAS # unbias exponent
or t2, t2, DIMPL_ONE # add implied one bit
cvt_w:
blt t1, WEXP_MIN, underflow_w # is exponent too small?
li v0, WEXP_MAX+1
bgt t1, v0, overflow_w # is exponent too large?
bne t1, v0, 1f # special check for INT_MIN
beq t0, zero, overflow_w # if positive, overflow
bne t2, DIMPL_ONE, overflow_w
bne t3, zero, overflow_w
li t2, INT_MIN # result is INT_MIN
b result_fs_w
1:
subu v0, t1, 20 # compute amount to shift
beq v0, zero, 2f # is shift needed?
li v1, 32
blt v0, zero, 1f # if shift < 0, shift right
subu v1, v1, v0 # shift left
sll t2, t2, v0
srl t9, t3, v1 # save bits shifted out of t3
or t2, t2, t9 # and put into t2
sll t3, t3, v0 # shift FSs fraction
b 2f
1:
negu v0 # shift right by v0
subu v1, v1, v0
sll t8, t3, v1 # save bits shifted out
sltu t8, zero, t8 # dont lose any ones
srl t3, t3, v0 # shift FSs fraction
or t3, t3, t8
sll t9, t2, v1 # save bits shifted out of t2
or t3, t3, t9 # and put into t3
srl t2, t2, v0
/*
* round result (t0 is sign, t2 is integer part, t3 is fractional part).
*/
2:
and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest
beq v0, MIPS_FPU_ROUND_RZ, 5f # round to zero (truncate)
beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity
beq t0, zero, 5f # if sign is positive, truncate
b 2f
1:
bne t0, zero, 5f # if sign is negative, truncate
2:
beq t3, zero, 5f # if no fraction bits, continue
addu t2, t2, 1 # add rounding bit
blt t2, zero, overflow_w # overflow?
b 5f
3:
li v0, GUARDBIT # load guard bit for rounding
addu v0, v0, t3 # add remainder
sltu v1, v0, t3 # compute carry out
beq v1, zero, 4f # if no carry, continue
addu t2, t2, 1 # add carry to result
blt t2, zero, overflow_w # overflow?
4:
bne v0, zero, 5f # if rounded remainder is zero
and t2, t2, ~1 # clear LSB (round to nearest)
5:
beq t0, zero, 1f # result positive?
negu t2 # convert to negative integer
1:
beq t3, zero, result_fs_w # is result exact?
/*
* Handle inexact exception.
*/
inexact_w:
or a1, a1, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT
and v0, a1, MIPS_FPU_ENABLE_INEXACT
bne v0, zero, fpe_trap
ctc1 a1, MIPS_FPU_CSR # save exceptions
b result_fs_w
/*
* Conversions to integer which overflow will trap (if enabled),
* or generate an inexact trap (if enabled),
* or generate an invalid exception.
*/
overflow_w:
or a1, a1, MIPS_FPU_EXCEPTION_OVERFLOW | MIPS_FPU_STICKY_OVERFLOW
and v0, a1, MIPS_FPU_ENABLE_OVERFLOW
bne v0, zero, fpe_trap
and v0, a1, MIPS_FPU_ENABLE_INEXACT
bne v0, zero, inexact_w # inexact traps enabled?
b invalid_w
/*
* Conversions to integer which underflow will trap (if enabled),
* or generate an inexact trap (if enabled),
* or generate an invalid exception.
*/
underflow_w:
or a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
and v0, a1, MIPS_FPU_ENABLE_UNDERFLOW
bne v0, zero, fpe_trap
and v0, a1, MIPS_FPU_ENABLE_INEXACT
bne v0, zero, inexact_w # inexact traps enabled?
b invalid_w
/*
* Compare single.
*/
cmp_s:
jal get_cmp_s
bne t1, SEXP_INF, 1f # is FS an infinity?
bne t2, zero, unordered # FS is a NAN
1:
bne ta1, SEXP_INF, 2f # is FT an infinity?
bne ta2, zero, unordered # FT is a NAN
2:
sll t1, t1, 23 # reassemble exp & frac
or t1, t1, t2
sll ta1, ta1, 23 # reassemble exp & frac
or ta1, ta1, ta2
beq t0, zero, 1f # is FS positive?
negu t1
1:
beq ta0, zero, 1f # is FT positive?
negu ta1
1:
li v0, COND_LESS
blt t1, ta1, test_cond # is FS < FT?
li v0, COND_EQUAL
beq t1, ta1, test_cond # is FS == FT?
move v0, zero # FS > FT
b test_cond
/*
* Compare double.
*/
cmp_d:
jal get_cmp_d
bne t1, DEXP_INF, 1f # is FS an infinity?
bne t2, zero, unordered
bne t3, zero, unordered # FS is a NAN
1:
bne ta1, DEXP_INF, 2f # is FT an infinity?
bne ta2, zero, unordered
bne ta3, zero, unordered # FT is a NAN
2:
sll t1, t1, 20 # reassemble exp & frac
or t1, t1, t2
sll ta1, ta1, 20 # reassemble exp & frac
or ta1, ta1, ta2
beq t0, zero, 1f # is FS positive?
not t3 # negate t1,t3
not t1
addu t3, t3, 1
seq v0, t3, zero # compute carry
addu t1, t1, v0
1:
beq ta0, zero, 1f # is FT positive?
not ta3 # negate ta1,ta3
not ta1
addu ta3, ta3, 1
seq v0, ta3, zero # compute carry
addu ta1, ta1, v0
1:
li v0, COND_LESS
blt t1, ta1, test_cond # is FS(MSW) < FT(MSW)?
move v0, zero
bne t1, ta1, test_cond # is FS(MSW) > FT(MSW)?
li v0, COND_LESS
bltu t3, ta3, test_cond # is FS(LSW) < FT(LSW)?
li v0, COND_EQUAL
beq t3, ta3, test_cond # is FS(LSW) == FT(LSW)?
move v0, zero # FS > FT
test_cond:
and v0, v0, a0 # condition match instruction?
set_cond:
bne v0, zero, 1f
and a1, a1, ~MIPS_FPU_COND_BIT # clear condition bit
b 2f
1:
or a1, a1, MIPS_FPU_COND_BIT # set condition bit
2:
ctc1 a1, MIPS_FPU_CSR # save condition bit
b done
unordered:
and v0, a0, COND_UNORDERED # this cmp match unordered?
bne v0, zero, 1f
and a1, a1, ~MIPS_FPU_COND_BIT # clear condition bit
b 2f
1:
or a1, a1, MIPS_FPU_COND_BIT # set condition bit
2:
and v0, a0, COND_SIGNAL
beq v0, zero, 1f # is this a signaling cmp?
or a1, a1, MIPS_FPU_EXCEPTION_INVALID | MIPS_FPU_STICKY_INVALID
and v0, a1, MIPS_FPU_ENABLE_INVALID
bne v0, zero, fpe_trap
1:
ctc1 a1, MIPS_FPU_CSR # save condition bit
b done
/*
* Determine the amount to shift the fraction in order to restore the
* normalized position. After that, round and handle exceptions.
*/
norm_s:
move v0, t2
move t9, zero # t9 = num of leading zeros
bne t2, zero, 1f
move v0, t8
addu t9, 32
1:
srl v1, v0, 16
bne v1, zero, 1f
addu t9, 16
sll v0, 16
1:
srl v1, v0, 24
bne v1, zero, 1f
addu t9, 8
sll v0, 8
1:
srl v1, v0, 28
bne v1, zero, 1f
addu t9, 4
sll v0, 4
1:
srl v1, v0, 30
bne v1, zero, 1f
addu t9, 2
sll v0, 2
1:
srl v1, v0, 31
bne v1, zero, 1f
addu t9, 1
/*
* Now shift t2,t8 the correct number of bits.
*/
1:
subu t9, t9, SLEAD_ZEROS # dont count leading zeros
subu t1, t1, t9 # adjust the exponent
beq t9, zero, norm_noshift_s
li v1, 32
blt t9, zero, 1f # if shift < 0, shift right
subu v1, v1, t9
sll t2, t2, t9 # shift t2,t8 left
srl v0, t8, v1 # save bits shifted out
or t2, t2, v0
sll t8, t8, t9
b norm_noshift_s
1:
negu t9 # shift t2,t8 right by t9
subu v1, v1, t9
sll v0, t8, v1 # save bits shifted out
sltu v0, zero, v0 # be sure to save any one bits
srl t8, t8, t9
or t8, t8, v0
sll v0, t2, v1 # save bits shifted out
or t8, t8, v0
srl t2, t2, t9
norm_noshift_s:
move ta1, t1 # save unrounded exponent
move ta2, t2 # save unrounded fraction
and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest
beq v0, MIPS_FPU_ROUND_RZ, 5f # round to zero (truncate)
beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity
beq t0, zero, 5f # if sign is positive, truncate
b 2f
1:
bne t0, zero, 5f # if sign is negative, truncate
2:
beq t8, zero, 5f # if exact, continue
addu t2, t2, 1 # add rounding bit
bne t2, SIMPL_ONE<<1, 5f # need to adjust exponent?
addu t1, t1, 1 # adjust exponent
srl t2, t2, 1 # renormalize fraction
b 5f
3:
li v0, GUARDBIT # load guard bit for rounding
addu v0, v0, t8 # add remainder
sltu v1, v0, t8 # compute carry out
beq v1, zero, 4f # if no carry, continue
addu t2, t2, 1 # add carry to result
bne t2, SIMPL_ONE<<1, 4f # need to adjust exponent?
addu t1, t1, 1 # adjust exponent
srl t2, t2, 1 # renormalize fraction
4:
bne v0, zero, 5f # if rounded remainder is zero
and t2, t2, ~1 # clear LSB (round to nearest)
5:
bgt t1, SEXP_MAX, overflow_s # overflow?
blt t1, SEXP_MIN, underflow_s # underflow?
bne t8, zero, inexact_s # is result inexact?
addu t1, t1, SEXP_BIAS # bias exponent
and t2, t2, ~SIMPL_ONE # clear implied one bit
b result_fs_s
/*
* Handle inexact exception.
*/
inexact_s:
addu t1, t1, SEXP_BIAS # bias exponent
and t2, t2, ~SIMPL_ONE # clear implied one bit
inexact_nobias_s:
jal set_fd_s # save result
or a1, a1, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT
and v0, a1, MIPS_FPU_ENABLE_INEXACT
bne v0, zero, fpe_trap
ctc1 a1, MIPS_FPU_CSR # save exceptions
b done
/*
* Overflow will trap (if enabled),
* or generate an inexact trap (if enabled),
* or generate an infinity.
*/
overflow_s:
or a1, a1, MIPS_FPU_EXCEPTION_OVERFLOW | MIPS_FPU_STICKY_OVERFLOW
and v0, a1, MIPS_FPU_ENABLE_OVERFLOW
beq v0, zero, 1f
subu t1, t1, 192 # bias exponent
and t2, t2, ~SIMPL_ONE # clear implied one bit
jal set_fd_s # save result
b fpe_trap
1:
and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest
beq v0, MIPS_FPU_ROUND_RZ, 1f # round to zero (truncate)
beq v0, MIPS_FPU_ROUND_RP, 2f # round to +infinity
bne t0, zero, 3f
1:
li t1, SEXP_MAX # result is max finite
li t2, 0x007fffff
b inexact_s
2:
bne t0, zero, 1b
3:
li t1, SEXP_MAX + 1 # result is infinity
move t2, zero
b inexact_s
/*
* In this implementation, "tininess" is detected "after rounding" and
* "loss of accuracy" is detected as "an inexact result".
*/
underflow_s:
and v0, a1, MIPS_FPU_ENABLE_UNDERFLOW
beq v0, zero, 1f
/*
* Underflow is enabled so compute the result and trap.
*/
addu t1, t1, 192 # bias exponent
and t2, t2, ~SIMPL_ONE # clear implied one bit
jal set_fd_s # save result
or a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
b fpe_trap
/*
* Underflow is not enabled so compute the result,
* signal inexact result (if it is) and trap (if enabled).
*/
1:
move t1, ta1 # get unrounded exponent
move t2, ta2 # get unrounded fraction
li t9, SEXP_MIN # compute shift amount
subu t9, t9, t1 # shift t2,t8 right by t9
blt t9, SFRAC_BITS+2, 3f # shift all the bits out?
move t1, zero # result is inexact zero
move t2, zero
or a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
/*
* Now round the zero result.
* Only need to worry about rounding to +- infinity when the sign matches.
*/
and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
beq v0, MIPS_FPU_ROUND_RN, inexact_nobias_s # round to nearest
beq v0, MIPS_FPU_ROUND_RZ, inexact_nobias_s # round to zero
beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity
beq t0, zero, inexact_nobias_s # if sign is positive, truncate
b 2f
1:
bne t0, zero, inexact_nobias_s # if sign is negative, truncate
2:
addu t2, t2, 1 # add rounding bit
b inexact_nobias_s
3:
li v1, 32
subu v1, v1, t9
sltu v0, zero, t8 # be sure to save any one bits
sll t8, t2, v1 # save bits shifted out
or t8, t8, v0 # include sticky bits
srl t2, t2, t9
/*
* Now round the denormalized result.
*/
and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest
beq v0, MIPS_FPU_ROUND_RZ, 5f # round to zero (truncate)
beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity
beq t0, zero, 5f # if sign is positive, truncate
b 2f
1:
bne t0, zero, 5f # if sign is negative, truncate
2:
beq t8, zero, 5f # if exact, continue
addu t2, t2, 1 # add rounding bit
b 5f
3:
li v0, GUARDBIT # load guard bit for rounding
addu v0, v0, t8 # add remainder
sltu v1, v0, t8 # compute carry out
beq v1, zero, 4f # if no carry, continue
addu t2, t2, 1 # add carry to result
4:
bne v0, zero, 5f # if rounded remainder is zero
and t2, t2, ~1 # clear LSB (round to nearest)
5:
move t1, zero # denorm or zero exponent
jal set_fd_s # save result
beq t8, zero, done # check for exact result
or a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
or a1, a1, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT
and v0, a1, MIPS_FPU_ENABLE_INEXACT
bne v0, zero, fpe_trap
ctc1 a1, MIPS_FPU_CSR # save exceptions
b done
/*
* Determine the amount to shift the fraction in order to restore the
* normalized position. After that, round and handle exceptions.
*/
norm_d:
move v0, t2
move t9, zero # t9 = num of leading zeros
bne t2, zero, 1f
move v0, t3
addu t9, 32
bne t3, zero, 1f
move v0, t8
addu t9, 32
1:
srl v1, v0, 16
bne v1, zero, 1f
addu t9, 16
sll v0, 16
1:
srl v1, v0, 24
bne v1, zero, 1f
addu t9, 8
sll v0, 8
1:
srl v1, v0, 28
bne v1, zero, 1f
addu t9, 4
sll v0, 4
1:
srl v1, v0, 30
bne v1, zero, 1f
addu t9, 2
sll v0, 2
1:
srl v1, v0, 31
bne v1, zero, 1f
addu t9, 1
/*
* Now shift t2,t3,t8 the correct number of bits.
*/
1:
subu t9, t9, DLEAD_ZEROS # dont count leading zeros
subu t1, t1, t9 # adjust the exponent
beq t9, zero, norm_noshift_d
li v1, 32
blt t9, zero, 2f # if shift < 0, shift right
blt t9, v1, 1f # shift by < 32?
subu t9, t9, v1 # shift by >= 32
subu v1, v1, t9
sll t2, t3, t9 # shift left by t9
srl v0, t8, v1 # save bits shifted out
or t2, t2, v0
sll t3, t8, t9
move t8, zero
b norm_noshift_d
1:
subu v1, v1, t9
sll t2, t2, t9 # shift left by t9
srl v0, t3, v1 # save bits shifted out
or t2, t2, v0
sll t3, t3, t9
srl v0, t8, v1 # save bits shifted out
or t3, t3, v0
sll t8, t8, t9
b norm_noshift_d
2:
negu t9 # shift right by t9
subu v1, v1, t9 # (known to be < 32 bits)
sll v0, t8, v1 # save bits shifted out
sltu v0, zero, v0 # be sure to save any one bits
srl t8, t8, t9
or t8, t8, v0
sll v0, t3, v1 # save bits shifted out
or t8, t8, v0
srl t3, t3, t9
sll v0, t2, v1 # save bits shifted out
or t3, t3, v0
srl t2, t2, t9
norm_noshift_d:
move ta1, t1 # save unrounded exponent
move ta2, t2 # save unrounded fraction (MS)
move ta3, t3 # save unrounded fraction (LS)
and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest
beq v0, MIPS_FPU_ROUND_RZ, 5f # round to zero (truncate)
beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity
beq t0, zero, 5f # if sign is positive, truncate
b 2f
1:
bne t0, zero, 5f # if sign is negative, truncate
2:
beq t8, zero, 5f # if exact, continue
addu t3, t3, 1 # add rounding bit
bne t3, zero, 5f # branch if no carry
addu t2, t2, 1 # add carry
bne t2, DIMPL_ONE<<1, 5f # need to adjust exponent?
addu t1, t1, 1 # adjust exponent
srl t2, t2, 1 # renormalize fraction
b 5f
3:
li v0, GUARDBIT # load guard bit for rounding
addu v0, v0, t8 # add remainder
sltu v1, v0, t8 # compute carry out
beq v1, zero, 4f # branch if no carry
addu t3, t3, 1 # add carry
bne t3, zero, 4f # branch if no carry
addu t2, t2, 1 # add carry to result
bne t2, DIMPL_ONE<<1, 4f # need to adjust exponent?
addu t1, t1, 1 # adjust exponent
srl t2, t2, 1 # renormalize fraction
4:
bne v0, zero, 5f # if rounded remainder is zero
and t3, t3, ~1 # clear LSB (round to nearest)
5:
bgt t1, DEXP_MAX, overflow_d # overflow?
blt t1, DEXP_MIN, underflow_d # underflow?
bne t8, zero, inexact_d # is result inexact?
addu t1, t1, DEXP_BIAS # bias exponent
and t2, t2, ~DIMPL_ONE # clear implied one bit
b result_fs_d
/*
* Handle inexact exception.
*/
inexact_d:
addu t1, t1, DEXP_BIAS # bias exponent
and t2, t2, ~DIMPL_ONE # clear implied one bit
inexact_nobias_d:
jal set_fd_d # save result
or a1, a1, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT
and v0, a1, MIPS_FPU_ENABLE_INEXACT
bne v0, zero, fpe_trap
ctc1 a1, MIPS_FPU_CSR # save exceptions
b done
/*
* Overflow will trap (if enabled),
* or generate an inexact trap (if enabled),
* or generate an infinity.
*/
overflow_d:
or a1, a1, MIPS_FPU_EXCEPTION_OVERFLOW | MIPS_FPU_STICKY_OVERFLOW
and v0, a1, MIPS_FPU_ENABLE_OVERFLOW
beq v0, zero, 1f
subu t1, t1, 1536 # bias exponent
and t2, t2, ~DIMPL_ONE # clear implied one bit
jal set_fd_d # save result
b fpe_trap
1:
and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest
beq v0, MIPS_FPU_ROUND_RZ, 1f # round to zero (truncate)
beq v0, MIPS_FPU_ROUND_RP, 2f # round to +infinity
bne t0, zero, 3f
1:
li t1, DEXP_MAX # result is max finite
li t2, 0x000fffff
li t3, 0xffffffff
b inexact_d
2:
bne t0, zero, 1b
3:
li t1, DEXP_MAX + 1 # result is infinity
move t2, zero
move t3, zero
b inexact_d
/*
* In this implementation, "tininess" is detected "after rounding" and
* "loss of accuracy" is detected as "an inexact result".
*/
underflow_d:
and v0, a1, MIPS_FPU_ENABLE_UNDERFLOW
beq v0, zero, 1f
/*
* Underflow is enabled so compute the result and trap.
*/
addu t1, t1, 1536 # bias exponent
and t2, t2, ~DIMPL_ONE # clear implied one bit
jal set_fd_d # save result
or a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
b fpe_trap
/*
* Underflow is not enabled so compute the result,
* signal inexact result (if it is) and trap (if enabled).
*/
1:
move t1, ta1 # get unrounded exponent
move t2, ta2 # get unrounded fraction (MS)
move t3, ta3 # get unrounded fraction (LS)
li t9, DEXP_MIN # compute shift amount
subu t9, t9, t1 # shift t2,t8 right by t9
blt t9, DFRAC_BITS+2, 3f # shift all the bits out?
move t1, zero # result is inexact zero
move t2, zero
move t3, zero
or a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
/*
* Now round the zero result.
* Only need to worry about rounding to +- infinity when the sign matches.
*/
and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
beq v0, MIPS_FPU_ROUND_RN, inexact_nobias_d # round to nearest
beq v0, MIPS_FPU_ROUND_RZ, inexact_nobias_d # round to zero
beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity
beq t0, zero, inexact_nobias_d # if sign is positive, truncate
b 2f
1:
bne t0, zero, inexact_nobias_d # if sign is negative, truncate
2:
addu t3, t3, 1 # add rounding bit
b inexact_nobias_d
3:
li v1, 32
blt t9, v1, 1f # shift by < 32?
subu t9, t9, v1 # shift right by >= 32
subu v1, v1, t9
sltu v0, zero, t8 # be sure to save any one bits
sll t8, t2, v1 # save bits shifted out
or t8, t8, v0 # include sticky bits
srl t3, t2, t9
move t2, zero
b 2f
1:
subu v1, v1, t9 # shift right by t9
sltu v0, zero, t8 # be sure to save any one bits
sll t8, t3, v1 # save bits shifted out
or t8, t8, v0 # include sticky bits
srl t3, t3, t9
sll v0, t2, v1 # save bits shifted out
or t3, t3, v0
srl t2, t2, t9
/*
* Now round the denormalized result.
*/
2:
and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest
beq v0, MIPS_FPU_ROUND_RZ, 5f # round to zero (truncate)
beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity
beq t0, zero, 5f # if sign is positive, truncate
b 2f
1:
bne t0, zero, 5f # if sign is negative, truncate
2:
beq t8, zero, 5f # if exact, continue
addu t3, t3, 1 # add rounding bit
bne t3, zero, 5f # if no carry, continue
addu t2, t2, 1 # add carry
b 5f
3:
li v0, GUARDBIT # load guard bit for rounding
addu v0, v0, t8 # add remainder
sltu v1, v0, t8 # compute carry out
beq v1, zero, 4f # if no carry, continue
addu t3, t3, 1 # add rounding bit
bne t3, zero, 4f # if no carry, continue
addu t2, t2, 1 # add carry
4:
bne v0, zero, 5f # if rounded remainder is zero
and t3, t3, ~1 # clear LSB (round to nearest)
5:
move t1, zero # denorm or zero exponent
jal set_fd_d # save result
beq t8, zero, done # check for exact result
or a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
or a1, a1, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT
and v0, a1, MIPS_FPU_ENABLE_INEXACT
bne v0, zero, fpe_trap
ctc1 a1, MIPS_FPU_CSR # save exceptions
b done
/*
* Signal an invalid operation if the trap is enabled; otherwise,
* the result is a quiet NAN.
*/
invalid_s: # trap invalid operation
or a1, a1, MIPS_FPU_EXCEPTION_INVALID | MIPS_FPU_STICKY_INVALID
and v0, a1, MIPS_FPU_ENABLE_INVALID
bne v0, zero, fpe_trap
ctc1 a1, MIPS_FPU_CSR # save exceptions
move t0, zero # result is a quiet NAN
li t1, SEXP_INF
li t2, SQUIET_NAN
jal set_fd_s # save result (in t0,t1,t2)
b done
/*
* Signal an invalid operation if the trap is enabled; otherwise,
* the result is a quiet NAN.
*/
invalid_d: # trap invalid operation
or a1, a1, MIPS_FPU_EXCEPTION_INVALID | MIPS_FPU_STICKY_INVALID
and v0, a1, MIPS_FPU_ENABLE_INVALID
bne v0, zero, fpe_trap
ctc1 a1, MIPS_FPU_CSR # save exceptions
move t0, zero # result is a quiet NAN
li t1, DEXP_INF
li t2, DQUIET_NAN0
li t3, DQUIET_NAN1
jal set_fd_d # save result (in t0,t1,t2,t3)
b done
/*
* Signal an invalid operation if the trap is enabled; otherwise,
* the result is INT_MAX or INT_MIN.
*/
invalid_w: # trap invalid operation
or a1, a1, MIPS_FPU_EXCEPTION_INVALID | MIPS_FPU_STICKY_INVALID
and v0, a1, MIPS_FPU_ENABLE_INVALID
bne v0, zero, fpe_trap
ctc1 a1, MIPS_FPU_CSR # save exceptions
bne t0, zero, 1f
li t2, INT_MAX # result is INT_MAX
b result_fs_w
1:
li t2, INT_MIN # result is INT_MIN
b result_fs_w
/*
* Trap if the hardware should have handled this case.
*/
fpe_trap:
move a2, a1 # code = FP CSR
ctc1 a1, MIPS_FPU_CSR # save exceptions
break 0
/*
* Send an illegal instruction signal to the current process.
*/
ill:
ctc1 a1, MIPS_FPU_CSR # save exceptions
move a2, a0 # code = FP instruction
break 0
result_ft_s:
move t0, ta0 # result is FT
move t1, ta1
move t2, ta2
result_fs_s: # result is FS
jal set_fd_s # save result (in t0,t1,t2)
b done
result_fs_w:
jal set_fd_word # save result (in t2)
b done
result_ft_d:
move t0, ta0 # result is FT
move t1, ta1
move t2, ta2
move t3, ta3
result_fs_d: # result is FS
jal set_fd_d # save result (in t0,t1,t2,t3)
done:
lw ra, CALLFRAME_RA(sp)
addu sp, sp, CALLFRAME_SIZ
j ra
END(MipsEmulateFP)
/*----------------------------------------------------------------------------
* get_fs_int --
*
* Read (integer) the FS register (bits 15-11).
* This is an internal routine used by MipsEmulateFP only.
*
* Results:
* t0 contains the sign
* t2 contains the fraction
*
*----------------------------------------------------------------------------
*/
LEAF(get_fs_int)
srl a3, a0, 12 - 2 # get FS field (even regs only)
and a3, a3, 0xF << 2 # mask FS field
lw a3, get_fs_int_tbl(a3) # switch on register number
j a3
.rdata
get_fs_int_tbl:
.word get_fs_int_f0
.word get_fs_int_f2
.word get_fs_int_f4
.word get_fs_int_f6
.word get_fs_int_f8
.word get_fs_int_f10
.word get_fs_int_f12
.word get_fs_int_f14
.word get_fs_int_f16
.word get_fs_int_f18
.word get_fs_int_f20
.word get_fs_int_f22
.word get_fs_int_f24
.word get_fs_int_f26
.word get_fs_int_f28
.word get_fs_int_f30
.text
get_fs_int_f0:
mfc1 t2, $f0
b get_fs_int_done
get_fs_int_f2:
mfc1 t2, $f2
b get_fs_int_done
get_fs_int_f4:
mfc1 t2, $f4
b get_fs_int_done
get_fs_int_f6:
mfc1 t2, $f6
b get_fs_int_done
get_fs_int_f8:
mfc1 t2, $f8
b get_fs_int_done
get_fs_int_f10:
mfc1 t2, $f10
b get_fs_int_done
get_fs_int_f12:
mfc1 t2, $f12
b get_fs_int_done
get_fs_int_f14:
mfc1 t2, $f14
b get_fs_int_done
get_fs_int_f16:
mfc1 t2, $f16
b get_fs_int_done
get_fs_int_f18:
mfc1 t2, $f18
b get_fs_int_done
get_fs_int_f20:
mfc1 t2, $f20
b get_fs_int_done
get_fs_int_f22:
mfc1 t2, $f22
b get_fs_int_done
get_fs_int_f24:
mfc1 t2, $f24
b get_fs_int_done
get_fs_int_f26:
mfc1 t2, $f26
b get_fs_int_done
get_fs_int_f28:
mfc1 t2, $f28
b get_fs_int_done
get_fs_int_f30:
mfc1 t2, $f30
get_fs_int_done:
srl t0, t2, 31 # init the sign bit
bge t2, zero, 1f
negu t2
1:
j ra
END(get_fs_int)
/*----------------------------------------------------------------------------
* get_ft_fs_s --
*
* Read (single precision) the FT register (bits 20-16) and
* the FS register (bits 15-11) and break up into fields.
* This is an internal routine used by MipsEmulateFP only.
*
* Results:
* t0 contains the FS sign
* t1 contains the FS (biased) exponent
* t2 contains the FS fraction
* ta0 contains the FT sign
* ta1 contains the FT (biased) exponent
* ta2 contains the FT fraction
*
*----------------------------------------------------------------------------
*/
LEAF(get_ft_fs_s)
srl a3, a0, 17 - 2 # get FT field (even regs only)
and a3, a3, 0xF << 2 # mask FT field
lw a3, get_ft_s_tbl(a3) # switch on register number
j a3
.rdata
get_ft_s_tbl:
.word get_ft_s_f0
.word get_ft_s_f2
.word get_ft_s_f4
.word get_ft_s_f6
.word get_ft_s_f8
.word get_ft_s_f10
.word get_ft_s_f12
.word get_ft_s_f14
.word get_ft_s_f16
.word get_ft_s_f18
.word get_ft_s_f20
.word get_ft_s_f22
.word get_ft_s_f24
.word get_ft_s_f26
.word get_ft_s_f28
.word get_ft_s_f30
.text
get_ft_s_f0:
mfc1 ta0, $f0
b get_ft_s_done
get_ft_s_f2:
mfc1 ta0, $f2
b get_ft_s_done
get_ft_s_f4:
mfc1 ta0, $f4
b get_ft_s_done
get_ft_s_f6:
mfc1 ta0, $f6
b get_ft_s_done
get_ft_s_f8:
mfc1 ta0, $f8
b get_ft_s_done
get_ft_s_f10:
mfc1 ta0, $f10
b get_ft_s_done
get_ft_s_f12:
mfc1 ta0, $f12
b get_ft_s_done
get_ft_s_f14:
mfc1 ta0, $f14
b get_ft_s_done
get_ft_s_f16:
mfc1 ta0, $f16
b get_ft_s_done
get_ft_s_f18:
mfc1 ta0, $f18
b get_ft_s_done
get_ft_s_f20:
mfc1 ta0, $f20
b get_ft_s_done
get_ft_s_f22:
mfc1 ta0, $f22
b get_ft_s_done
get_ft_s_f24:
mfc1 ta0, $f24
b get_ft_s_done
get_ft_s_f26:
mfc1 ta0, $f26
b get_ft_s_done
get_ft_s_f28:
mfc1 ta0, $f28
b get_ft_s_done
get_ft_s_f30:
mfc1 ta0, $f30
get_ft_s_done:
srl ta1, ta0, 23 # get exponent
and ta1, ta1, 0xFF
and ta2, ta0, 0x7FFFFF # get fraction
srl ta0, ta0, 31 # get sign
bne ta1, SEXP_INF, 1f # is it a signaling NAN?
and v0, ta2, SSIGNAL_NAN
bne v0, zero, invalid_s
1:
/* fall through to get FS */
/*----------------------------------------------------------------------------
* get_fs_s --
*
* Read (single precision) the FS register (bits 15-11) and
* break up into fields.
* This is an internal routine used by MipsEmulateFP only.
*
* Results:
* t0 contains the sign
* t1 contains the (biased) exponent
* t2 contains the fraction
*
*----------------------------------------------------------------------------
*/
ALEAF(get_fs_s)
srl a3, a0, 12 - 2 # get FS field (even regs only)
and a3, a3, 0xF << 2 # mask FS field
lw a3, get_fs_s_tbl(a3) # switch on register number
j a3
.rdata
get_fs_s_tbl:
.word get_fs_s_f0
.word get_fs_s_f2
.word get_fs_s_f4
.word get_fs_s_f6
.word get_fs_s_f8
.word get_fs_s_f10
.word get_fs_s_f12
.word get_fs_s_f14
.word get_fs_s_f16
.word get_fs_s_f18
.word get_fs_s_f20
.word get_fs_s_f22
.word get_fs_s_f24
.word get_fs_s_f26
.word get_fs_s_f28
.word get_fs_s_f30
.text
get_fs_s_f0:
mfc1 t0, $f0
b get_fs_s_done
get_fs_s_f2:
mfc1 t0, $f2
b get_fs_s_done
get_fs_s_f4:
mfc1 t0, $f4
b get_fs_s_done
get_fs_s_f6:
mfc1 t0, $f6
b get_fs_s_done
get_fs_s_f8:
mfc1 t0, $f8
b get_fs_s_done
get_fs_s_f10:
mfc1 t0, $f10
b get_fs_s_done
get_fs_s_f12:
mfc1 t0, $f12
b get_fs_s_done
get_fs_s_f14:
mfc1 t0, $f14
b get_fs_s_done
get_fs_s_f16:
mfc1 t0, $f16
b get_fs_s_done
get_fs_s_f18:
mfc1 t0, $f18
b get_fs_s_done
get_fs_s_f20:
mfc1 t0, $f20
b get_fs_s_done
get_fs_s_f22:
mfc1 t0, $f22
b get_fs_s_done
get_fs_s_f24:
mfc1 t0, $f24
b get_fs_s_done
get_fs_s_f26:
mfc1 t0, $f26
b get_fs_s_done
get_fs_s_f28:
mfc1 t0, $f28
b get_fs_s_done
get_fs_s_f30:
mfc1 t0, $f30
get_fs_s_done:
srl t1, t0, 23 # get exponent
and t1, t1, 0xFF
and t2, t0, 0x7FFFFF # get fraction
srl t0, t0, 31 # get sign
bne t1, SEXP_INF, 1f # is it a signaling NAN?
and v0, t2, SSIGNAL_NAN
bne v0, zero, invalid_s
1:
j ra
END(get_ft_fs_s)
/*----------------------------------------------------------------------------
* get_ft_fs_d --
*
* Read (double precision) the FT register (bits 20-16) and
* the FS register (bits 15-11) and break up into fields.
* This is an internal routine used by MipsEmulateFP only.
*
* Results:
* t0 contains the FS sign
* t1 contains the FS (biased) exponent
* t2 contains the FS fraction
* t3 contains the FS remaining fraction
* ta0 contains the FT sign
* ta1 contains the FT (biased) exponent
* ta2 contains the FT fraction
* ta3 contains the FT remaining fraction
*
*----------------------------------------------------------------------------
*/
LEAF(get_ft_fs_d)
srl a3, a0, 17 - 2 # get FT field (even regs only)
and a3, a3, 0xF << 2 # mask FT field
lw a3, get_ft_d_tbl(a3) # switch on register number
j a3
.rdata
get_ft_d_tbl:
.word get_ft_d_f0
.word get_ft_d_f2
.word get_ft_d_f4
.word get_ft_d_f6
.word get_ft_d_f8
.word get_ft_d_f10
.word get_ft_d_f12
.word get_ft_d_f14
.word get_ft_d_f16
.word get_ft_d_f18
.word get_ft_d_f20
.word get_ft_d_f22
.word get_ft_d_f24
.word get_ft_d_f26
.word get_ft_d_f28
.word get_ft_d_f30
.text
get_ft_d_f0:
mfc1 ta3, $f0
mfc1 ta0, $f1
b get_ft_d_done
get_ft_d_f2:
mfc1 ta3, $f2
mfc1 ta0, $f3
b get_ft_d_done
get_ft_d_f4:
mfc1 ta3, $f4
mfc1 ta0, $f5
b get_ft_d_done
get_ft_d_f6:
mfc1 ta3, $f6
mfc1 ta0, $f7
b get_ft_d_done
get_ft_d_f8:
mfc1 ta3, $f8
mfc1 ta0, $f9
b get_ft_d_done
get_ft_d_f10:
mfc1 ta3, $f10
mfc1 ta0, $f11
b get_ft_d_done
get_ft_d_f12:
mfc1 ta3, $f12
mfc1 ta0, $f13
b get_ft_d_done
get_ft_d_f14:
mfc1 ta3, $f14
mfc1 ta0, $f15
b get_ft_d_done
get_ft_d_f16:
mfc1 ta3, $f16
mfc1 ta0, $f17
b get_ft_d_done
get_ft_d_f18:
mfc1 ta3, $f18
mfc1 ta0, $f19
b get_ft_d_done
get_ft_d_f20:
mfc1 ta3, $f20
mfc1 ta0, $f21
b get_ft_d_done
get_ft_d_f22:
mfc1 ta3, $f22
mfc1 ta0, $f23
b get_ft_d_done
get_ft_d_f24:
mfc1 ta3, $f24
mfc1 ta0, $f25
b get_ft_d_done
get_ft_d_f26:
mfc1 ta3, $f26
mfc1 ta0, $f27
b get_ft_d_done
get_ft_d_f28:
mfc1 ta3, $f28
mfc1 ta0, $f29
b get_ft_d_done
get_ft_d_f30:
mfc1 ta3, $f30
mfc1 ta0, $f31
get_ft_d_done:
srl ta1, ta0, 20 # get exponent
and ta1, ta1, 0x7FF
and ta2, ta0, 0xFFFFF # get fraction
srl ta0, ta0, 31 # get sign
bne ta1, DEXP_INF, 1f # is it a signaling NAN?
and v0, ta2, DSIGNAL_NAN
bne v0, zero, invalid_d
1:
/* fall through to get FS */
/*----------------------------------------------------------------------------
* get_fs_d --
*
* Read (double precision) the FS register (bits 15-11) and
* break up into fields.
* This is an internal routine used by MipsEmulateFP only.
*
* Results:
* t0 contains the sign
* t1 contains the (biased) exponent
* t2 contains the fraction
* t3 contains the remaining fraction
*
*----------------------------------------------------------------------------
*/
ALEAF(get_fs_d)
srl a3, a0, 12 - 2 # get FS field (even regs only)
and a3, a3, 0xF << 2 # mask FS field
lw a3, get_fs_d_tbl(a3) # switch on register number
j a3
.rdata
get_fs_d_tbl:
.word get_fs_d_f0
.word get_fs_d_f2
.word get_fs_d_f4
.word get_fs_d_f6
.word get_fs_d_f8
.word get_fs_d_f10
.word get_fs_d_f12
.word get_fs_d_f14
.word get_fs_d_f16
.word get_fs_d_f18
.word get_fs_d_f20
.word get_fs_d_f22
.word get_fs_d_f24
.word get_fs_d_f26
.word get_fs_d_f28
.word get_fs_d_f30
.text
get_fs_d_f0:
mfc1 t3, $f0
mfc1 t0, $f1
b get_fs_d_done
get_fs_d_f2:
mfc1 t3, $f2
mfc1 t0, $f3
b get_fs_d_done
get_fs_d_f4:
mfc1 t3, $f4
mfc1 t0, $f5
b get_fs_d_done
get_fs_d_f6:
mfc1 t3, $f6
mfc1 t0, $f7
b get_fs_d_done
get_fs_d_f8:
mfc1 t3, $f8
mfc1 t0, $f9
b get_fs_d_done
get_fs_d_f10:
mfc1 t3, $f10
mfc1 t0, $f11
b get_fs_d_done
get_fs_d_f12:
mfc1 t3, $f12
mfc1 t0, $f13
b get_fs_d_done
get_fs_d_f14:
mfc1 t3, $f14
mfc1 t0, $f15
b get_fs_d_done
get_fs_d_f16:
mfc1 t3, $f16
mfc1 t0, $f17
b get_fs_d_done
get_fs_d_f18:
mfc1 t3, $f18
mfc1 t0, $f19
b get_fs_d_done
get_fs_d_f20:
mfc1 t3, $f20
mfc1 t0, $f21
b get_fs_d_done
get_fs_d_f22:
mfc1 t3, $f22
mfc1 t0, $f23
b get_fs_d_done
get_fs_d_f24:
mfc1 t3, $f24
mfc1 t0, $f25
b get_fs_d_done
get_fs_d_f26:
mfc1 t3, $f26
mfc1 t0, $f27
b get_fs_d_done
get_fs_d_f28:
mfc1 t3, $f28
mfc1 t0, $f29
b get_fs_d_done
get_fs_d_f30:
mfc1 t3, $f30
mfc1 t0, $f31
get_fs_d_done:
srl t1, t0, 20 # get exponent
and t1, t1, 0x7FF
and t2, t0, 0xFFFFF # get fraction
srl t0, t0, 31 # get sign
bne t1, DEXP_INF, 1f # is it a signaling NAN?
and v0, t2, DSIGNAL_NAN
bne v0, zero, invalid_d
1:
j ra
END(get_ft_fs_d)
/*----------------------------------------------------------------------------
* get_cmp_s --
*
* Read (single precision) the FS register (bits 15-11) and
* the FT register (bits 20-16) and break up into fields.
* This is an internal routine used by MipsEmulateFP only.
*
* Results:
* t0 contains the sign
* t1 contains the (biased) exponent
* t2 contains the fraction
* ta0 contains the sign
* ta1 contains the (biased) exponent
* ta2 contains the fraction
*
*----------------------------------------------------------------------------
*/
LEAF(get_cmp_s)
srl a3, a0, 12 - 2 # get FS field (even regs only)
and a3, a3, 0xF << 2 # mask FS field
lw a3, cmp_fs_s_tbl(a3) # switch on register number
j a3
.rdata
cmp_fs_s_tbl:
.word cmp_fs_s_f0
.word cmp_fs_s_f2
.word cmp_fs_s_f4
.word cmp_fs_s_f6
.word cmp_fs_s_f8
.word cmp_fs_s_f10
.word cmp_fs_s_f12
.word cmp_fs_s_f14
.word cmp_fs_s_f16
.word cmp_fs_s_f18
.word cmp_fs_s_f20
.word cmp_fs_s_f22
.word cmp_fs_s_f24
.word cmp_fs_s_f26
.word cmp_fs_s_f28
.word cmp_fs_s_f30
.text
cmp_fs_s_f0:
mfc1 t0, $f0
b cmp_fs_s_done
cmp_fs_s_f2:
mfc1 t0, $f2
b cmp_fs_s_done
cmp_fs_s_f4:
mfc1 t0, $f4
b cmp_fs_s_done
cmp_fs_s_f6:
mfc1 t0, $f6
b cmp_fs_s_done
cmp_fs_s_f8:
mfc1 t0, $f8
b cmp_fs_s_done
cmp_fs_s_f10:
mfc1 t0, $f10
b cmp_fs_s_done
cmp_fs_s_f12:
mfc1 t0, $f12
b cmp_fs_s_done
cmp_fs_s_f14:
mfc1 t0, $f14
b cmp_fs_s_done
cmp_fs_s_f16:
mfc1 t0, $f16
b cmp_fs_s_done
cmp_fs_s_f18:
mfc1 t0, $f18
b cmp_fs_s_done
cmp_fs_s_f20:
mfc1 t0, $f20
b cmp_fs_s_done
cmp_fs_s_f22:
mfc1 t0, $f22
b cmp_fs_s_done
cmp_fs_s_f24:
mfc1 t0, $f24
b cmp_fs_s_done
cmp_fs_s_f26:
mfc1 t0, $f26
b cmp_fs_s_done
cmp_fs_s_f28:
mfc1 t0, $f28
b cmp_fs_s_done
cmp_fs_s_f30:
mfc1 t0, $f30
cmp_fs_s_done:
srl t1, t0, 23 # get exponent
and t1, t1, 0xFF
and t2, t0, 0x7FFFFF # get fraction
srl t0, t0, 31 # get sign
srl a3, a0, 17 - 2 # get FT field (even regs only)
and a3, a3, 0xF << 2 # mask FT field
lw a3, cmp_ft_s_tbl(a3) # switch on register number
j a3
.rdata
cmp_ft_s_tbl:
.word cmp_ft_s_f0
.word cmp_ft_s_f2
.word cmp_ft_s_f4
.word cmp_ft_s_f6
.word cmp_ft_s_f8
.word cmp_ft_s_f10
.word cmp_ft_s_f12
.word cmp_ft_s_f14
.word cmp_ft_s_f16
.word cmp_ft_s_f18
.word cmp_ft_s_f20
.word cmp_ft_s_f22
.word cmp_ft_s_f24
.word cmp_ft_s_f26
.word cmp_ft_s_f28
.word cmp_ft_s_f30
.text
cmp_ft_s_f0:
mfc1 ta0, $f0
b cmp_ft_s_done
cmp_ft_s_f2:
mfc1 ta0, $f2
b cmp_ft_s_done
cmp_ft_s_f4:
mfc1 ta0, $f4
b cmp_ft_s_done
cmp_ft_s_f6:
mfc1 ta0, $f6
b cmp_ft_s_done
cmp_ft_s_f8:
mfc1 ta0, $f8
b cmp_ft_s_done
cmp_ft_s_f10:
mfc1 ta0, $f10
b cmp_ft_s_done
cmp_ft_s_f12:
mfc1 ta0, $f12
b cmp_ft_s_done
cmp_ft_s_f14:
mfc1 ta0, $f14
b cmp_ft_s_done
cmp_ft_s_f16:
mfc1 ta0, $f16
b cmp_ft_s_done
cmp_ft_s_f18:
mfc1 ta0, $f18
b cmp_ft_s_done
cmp_ft_s_f20:
mfc1 ta0, $f20
b cmp_ft_s_done
cmp_ft_s_f22:
mfc1 ta0, $f22
b cmp_ft_s_done
cmp_ft_s_f24:
mfc1 ta0, $f24
b cmp_ft_s_done
cmp_ft_s_f26:
mfc1 ta0, $f26
b cmp_ft_s_done
cmp_ft_s_f28:
mfc1 ta0, $f28
b cmp_ft_s_done
cmp_ft_s_f30:
mfc1 ta0, $f30
cmp_ft_s_done:
srl ta1, ta0, 23 # get exponent
and ta1, ta1, 0xFF
and ta2, ta0, 0x7FFFFF # get fraction
srl ta0, ta0, 31 # get sign
j ra
END(get_cmp_s)
/*----------------------------------------------------------------------------
* get_cmp_d --
*
* Read (double precision) the FS register (bits 15-11) and
* the FT register (bits 20-16) and break up into fields.
* This is an internal routine used by MipsEmulateFP only.
*
* Results:
* t0 contains the sign
* t1 contains the (biased) exponent
* t2 contains the fraction
* t3 contains the remaining fraction
* ta0 contains the sign
* ta1 contains the (biased) exponent
* ta2 contains the fraction
* ta3 contains the remaining fraction
*
*----------------------------------------------------------------------------
*/
LEAF(get_cmp_d)
srl a3, a0, 12 - 2 # get FS field (even regs only)
and a3, a3, 0xF << 2 # mask FS field
lw a3, cmp_fs_d_tbl(a3) # switch on register number
j a3
.rdata
cmp_fs_d_tbl:
.word cmp_fs_d_f0
.word cmp_fs_d_f2
.word cmp_fs_d_f4
.word cmp_fs_d_f6
.word cmp_fs_d_f8
.word cmp_fs_d_f10
.word cmp_fs_d_f12
.word cmp_fs_d_f14
.word cmp_fs_d_f16
.word cmp_fs_d_f18
.word cmp_fs_d_f20
.word cmp_fs_d_f22
.word cmp_fs_d_f24
.word cmp_fs_d_f26
.word cmp_fs_d_f28
.word cmp_fs_d_f30
.text
cmp_fs_d_f0:
mfc1 t3, $f0
mfc1 t0, $f1
b cmp_fs_d_done
cmp_fs_d_f2:
mfc1 t3, $f2
mfc1 t0, $f3
b cmp_fs_d_done
cmp_fs_d_f4:
mfc1 t3, $f4
mfc1 t0, $f5
b cmp_fs_d_done
cmp_fs_d_f6:
mfc1 t3, $f6
mfc1 t0, $f7
b cmp_fs_d_done
cmp_fs_d_f8:
mfc1 t3, $f8
mfc1 t0, $f9
b cmp_fs_d_done
cmp_fs_d_f10:
mfc1 t3, $f10
mfc1 t0, $f11
b cmp_fs_d_done
cmp_fs_d_f12:
mfc1 t3, $f12
mfc1 t0, $f13
b cmp_fs_d_done
cmp_fs_d_f14:
mfc1 t3, $f14
mfc1 t0, $f15
b cmp_fs_d_done
cmp_fs_d_f16:
mfc1 t3, $f16
mfc1 t0, $f17
b cmp_fs_d_done
cmp_fs_d_f18:
mfc1 t3, $f18
mfc1 t0, $f19
b cmp_fs_d_done
cmp_fs_d_f20:
mfc1 t3, $f20
mfc1 t0, $f21
b cmp_fs_d_done
cmp_fs_d_f22:
mfc1 t3, $f22
mfc1 t0, $f23
b cmp_fs_d_done
cmp_fs_d_f24:
mfc1 t3, $f24
mfc1 t0, $f25
b cmp_fs_d_done
cmp_fs_d_f26:
mfc1 t3, $f26
mfc1 t0, $f27
b cmp_fs_d_done
cmp_fs_d_f28:
mfc1 t3, $f28
mfc1 t0, $f29
b cmp_fs_d_done
cmp_fs_d_f30:
mfc1 t3, $f30
mfc1 t0, $f31
cmp_fs_d_done:
srl t1, t0, 20 # get exponent
and t1, t1, 0x7FF
and t2, t0, 0xFFFFF # get fraction
srl t0, t0, 31 # get sign
srl a3, a0, 17 - 2 # get FT field (even regs only)
and a3, a3, 0xF << 2 # mask FT field
lw a3, cmp_ft_d_tbl(a3) # switch on register number
j a3
.rdata
cmp_ft_d_tbl:
.word cmp_ft_d_f0
.word cmp_ft_d_f2
.word cmp_ft_d_f4
.word cmp_ft_d_f6
.word cmp_ft_d_f8
.word cmp_ft_d_f10
.word cmp_ft_d_f12
.word cmp_ft_d_f14
.word cmp_ft_d_f16
.word cmp_ft_d_f18
.word cmp_ft_d_f20
.word cmp_ft_d_f22
.word cmp_ft_d_f24
.word cmp_ft_d_f26
.word cmp_ft_d_f28
.word cmp_ft_d_f30
.text
cmp_ft_d_f0:
mfc1 ta3, $f0
mfc1 ta0, $f1
b cmp_ft_d_done
cmp_ft_d_f2:
mfc1 ta3, $f2
mfc1 ta0, $f3
b cmp_ft_d_done
cmp_ft_d_f4:
mfc1 ta3, $f4
mfc1 ta0, $f5
b cmp_ft_d_done
cmp_ft_d_f6:
mfc1 ta3, $f6
mfc1 ta0, $f7
b cmp_ft_d_done
cmp_ft_d_f8:
mfc1 ta3, $f8
mfc1 ta0, $f9
b cmp_ft_d_done
cmp_ft_d_f10:
mfc1 ta3, $f10
mfc1 ta0, $f11
b cmp_ft_d_done
cmp_ft_d_f12:
mfc1 ta3, $f12
mfc1 ta0, $f13
b cmp_ft_d_done
cmp_ft_d_f14:
mfc1 ta3, $f14
mfc1 ta0, $f15
b cmp_ft_d_done
cmp_ft_d_f16:
mfc1 ta3, $f16
mfc1 ta0, $f17
b cmp_ft_d_done
cmp_ft_d_f18:
mfc1 ta3, $f18
mfc1 ta0, $f19
b cmp_ft_d_done
cmp_ft_d_f20:
mfc1 ta3, $f20
mfc1 ta0, $f21
b cmp_ft_d_done
cmp_ft_d_f22:
mfc1 ta3, $f22
mfc1 ta0, $f23
b cmp_ft_d_done
cmp_ft_d_f24:
mfc1 ta3, $f24
mfc1 ta0, $f25
b cmp_ft_d_done
cmp_ft_d_f26:
mfc1 ta3, $f26
mfc1 ta0, $f27
b cmp_ft_d_done
cmp_ft_d_f28:
mfc1 ta3, $f28
mfc1 ta0, $f29
b cmp_ft_d_done
cmp_ft_d_f30:
mfc1 ta3, $f30
mfc1 ta0, $f31
cmp_ft_d_done:
srl ta1, ta0, 20 # get exponent
and ta1, ta1, 0x7FF
and ta2, ta0, 0xFFFFF # get fraction
srl ta0, ta0, 31 # get sign
j ra
END(get_cmp_d)
/*----------------------------------------------------------------------------
* set_fd_s --
*
* Write (single precision) the FD register (bits 10-6).
* This is an internal routine used by MipsEmulateFP only.
*
* Arguments:
* a0 contains the FP instruction
* t0 contains the sign
* t1 contains the (biased) exponent
* t2 contains the fraction
*
* set_fd_word --
*
* Write (integer) the FD register (bits 10-6).
* This is an internal routine used by MipsEmulateFP only.
*
* Arguments:
* a0 contains the FP instruction
* t2 contains the integer
*
*----------------------------------------------------------------------------
*/
LEAF(set_fd_s)
sll t0, t0, 31 # position sign
sll t1, t1, 23 # position exponent
or t2, t2, t0
or t2, t2, t1
ALEAF(set_fd_word)
srl a3, a0, 7 - 2 # get FD field (even regs only)
and a3, a3, 0xF << 2 # mask FT field
lw a3, set_fd_s_tbl(a3) # switch on register number
j a3
.rdata
set_fd_s_tbl:
.word set_fd_s_f0
.word set_fd_s_f2
.word set_fd_s_f4
.word set_fd_s_f6
.word set_fd_s_f8
.word set_fd_s_f10
.word set_fd_s_f12
.word set_fd_s_f14
.word set_fd_s_f16
.word set_fd_s_f18
.word set_fd_s_f20
.word set_fd_s_f22
.word set_fd_s_f24
.word set_fd_s_f26
.word set_fd_s_f28
.word set_fd_s_f30
.text
set_fd_s_f0:
mtc1 t2, $f0
j ra
set_fd_s_f2:
mtc1 t2, $f2
j ra
set_fd_s_f4:
mtc1 t2, $f4
j ra
set_fd_s_f6:
mtc1 t2, $f6
j ra
set_fd_s_f8:
mtc1 t2, $f8
j ra
set_fd_s_f10:
mtc1 t2, $f10
j ra
set_fd_s_f12:
mtc1 t2, $f12
j ra
set_fd_s_f14:
mtc1 t2, $f14
j ra
set_fd_s_f16:
mtc1 t2, $f16
j ra
set_fd_s_f18:
mtc1 t2, $f18
j ra
set_fd_s_f20:
mtc1 t2, $f20
j ra
set_fd_s_f22:
mtc1 t2, $f22
j ra
set_fd_s_f24:
mtc1 t2, $f24
j ra
set_fd_s_f26:
mtc1 t2, $f26
j ra
set_fd_s_f28:
mtc1 t2, $f28
j ra
set_fd_s_f30:
mtc1 t2, $f30
j ra
END(set_fd_s)
/*----------------------------------------------------------------------------
* set_fd_d --
*
* Write (double precision) the FT register (bits 10-6).
* This is an internal routine used by MipsEmulateFP only.
*
* Arguments:
* a0 contains the FP instruction
* t0 contains the sign
* t1 contains the (biased) exponent
* t2 contains the fraction
* t3 contains the remaining fraction
*
*----------------------------------------------------------------------------
*/
LEAF(set_fd_d)
sll t0, t0, 31 # set sign
sll t1, t1, 20 # set exponent
or t0, t0, t1
or t0, t0, t2 # set fraction
srl a3, a0, 7 - 2 # get FD field (even regs only)
and a3, a3, 0xF << 2 # mask FD field
lw a3, set_fd_d_tbl(a3) # switch on register number
j a3
.rdata
set_fd_d_tbl:
.word set_fd_d_f0
.word set_fd_d_f2
.word set_fd_d_f4
.word set_fd_d_f6
.word set_fd_d_f8
.word set_fd_d_f10
.word set_fd_d_f12
.word set_fd_d_f14
.word set_fd_d_f16
.word set_fd_d_f18
.word set_fd_d_f20
.word set_fd_d_f22
.word set_fd_d_f24
.word set_fd_d_f26
.word set_fd_d_f28
.word set_fd_d_f30
.text
set_fd_d_f0:
mtc1 t3, $f0
mtc1 t0, $f1
j ra
set_fd_d_f2:
mtc1 t3, $f2
mtc1 t0, $f3
j ra
set_fd_d_f4:
mtc1 t3, $f4
mtc1 t0, $f5
j ra
set_fd_d_f6:
mtc1 t3, $f6
mtc1 t0, $f7
j ra
set_fd_d_f8:
mtc1 t3, $f8
mtc1 t0, $f9
j ra
set_fd_d_f10:
mtc1 t3, $f10
mtc1 t0, $f11
j ra
set_fd_d_f12:
mtc1 t3, $f12
mtc1 t0, $f13
j ra
set_fd_d_f14:
mtc1 t3, $f14
mtc1 t0, $f15
j ra
set_fd_d_f16:
mtc1 t3, $f16
mtc1 t0, $f17
j ra
set_fd_d_f18:
mtc1 t3, $f18
mtc1 t0, $f19
j ra
set_fd_d_f20:
mtc1 t3, $f20
mtc1 t0, $f21
j ra
set_fd_d_f22:
mtc1 t3, $f22
mtc1 t0, $f23
j ra
set_fd_d_f24:
mtc1 t3, $f24
mtc1 t0, $f25
j ra
set_fd_d_f26:
mtc1 t3, $f26
mtc1 t0, $f27
j ra
set_fd_d_f28:
mtc1 t3, $f28
mtc1 t0, $f29
j ra
set_fd_d_f30:
mtc1 t3, $f30
mtc1 t0, $f31
j ra
END(set_fd_d)
/*----------------------------------------------------------------------------
* renorm_fs_s --
*
* Results:
* t1 unbiased exponent
* t2 normalized fraction
*
*----------------------------------------------------------------------------
*/
LEAF(renorm_fs_s)
/*
* Find out how many leading zero bits are in t2 and put in t9.
*/
move v0, t2
move t9, zero
srl v1, v0, 16
bne v1, zero, 1f
addu t9, 16
sll v0, 16
1:
srl v1, v0, 24
bne v1, zero, 1f
addu t9, 8
sll v0, 8
1:
srl v1, v0, 28
bne v1, zero, 1f
addu t9, 4
sll v0, 4
1:
srl v1, v0, 30
bne v1, zero, 1f
addu t9, 2
sll v0, 2
1:
srl v1, v0, 31
bne v1, zero, 1f
addu t9, 1
/*
* Now shift t2 the correct number of bits.
*/
1:
subu t9, t9, SLEAD_ZEROS # dont count normal leading zeros
li t1, SEXP_MIN
subu t1, t1, t9 # adjust exponent
sll t2, t2, t9
j ra
END(renorm_fs_s)
/*----------------------------------------------------------------------------
* renorm_fs_d --
*
* Results:
* t1 unbiased exponent
* t2,t3 normalized fraction
*
*----------------------------------------------------------------------------
*/
LEAF(renorm_fs_d)
/*
* Find out how many leading zero bits are in t2,t3 and put in t9.
*/
move v0, t2
move t9, zero
bne t2, zero, 1f
move v0, t3
addu t9, 32
1:
srl v1, v0, 16
bne v1, zero, 1f
addu t9, 16
sll v0, 16
1:
srl v1, v0, 24
bne v1, zero, 1f
addu t9, 8
sll v0, 8
1:
srl v1, v0, 28
bne v1, zero, 1f
addu t9, 4
sll v0, 4
1:
srl v1, v0, 30
bne v1, zero, 1f
addu t9, 2
sll v0, 2
1:
srl v1, v0, 31
bne v1, zero, 1f
addu t9, 1
/*
* Now shift t2,t3 the correct number of bits.
*/
1:
subu t9, t9, DLEAD_ZEROS # dont count normal leading zeros
li t1, DEXP_MIN
subu t1, t1, t9 # adjust exponent
li v0, 32
blt t9, v0, 1f
subu t9, t9, v0 # shift fraction left >= 32 bits
sll t2, t3, t9
move t3, zero
j ra
1:
subu v0, v0, t9 # shift fraction left < 32 bits
sll t2, t2, t9
srl v1, t3, v0
or t2, t2, v1
sll t3, t3, t9
j ra
END(renorm_fs_d)
/*----------------------------------------------------------------------------
* renorm_ft_s --
*
* Results:
* ta1 unbiased exponent
* ta2 normalized fraction
*
*----------------------------------------------------------------------------
*/
LEAF(renorm_ft_s)
/*
* Find out how many leading zero bits are in ta2 and put in t9.
*/
move v0, ta2
move t9, zero
srl v1, v0, 16
bne v1, zero, 1f
addu t9, 16
sll v0, 16
1:
srl v1, v0, 24
bne v1, zero, 1f
addu t9, 8
sll v0, 8
1:
srl v1, v0, 28
bne v1, zero, 1f
addu t9, 4
sll v0, 4
1:
srl v1, v0, 30
bne v1, zero, 1f
addu t9, 2
sll v0, 2
1:
srl v1, v0, 31
bne v1, zero, 1f
addu t9, 1
/*
* Now shift ta2 the correct number of bits.
*/
1:
subu t9, t9, SLEAD_ZEROS # dont count normal leading zeros
li ta1, SEXP_MIN
subu ta1, ta1, t9 # adjust exponent
sll ta2, ta2, t9
j ra
END(renorm_ft_s)
/*----------------------------------------------------------------------------
* renorm_ft_d --
*
* Results:
* ta1 unbiased exponent
* ta2,ta3 normalized fraction
*
*----------------------------------------------------------------------------
*/
LEAF(renorm_ft_d)
/*
* Find out how many leading zero bits are in ta2,ta3 and put in t9.
*/
move v0, ta2
move t9, zero
bne ta2, zero, 1f
move v0, ta3
addu t9, 32
1:
srl v1, v0, 16
bne v1, zero, 1f
addu t9, 16
sll v0, 16
1:
srl v1, v0, 24
bne v1, zero, 1f
addu t9, 8
sll v0, 8
1:
srl v1, v0, 28
bne v1, zero, 1f
addu t9, 4
sll v0, 4
1:
srl v1, v0, 30
bne v1, zero, 1f
addu t9, 2
sll v0, 2
1:
srl v1, v0, 31
bne v1, zero, 1f
addu t9, 1
/*
* Now shift ta2,ta3 the correct number of bits.
*/
1:
subu t9, t9, DLEAD_ZEROS # dont count normal leading zeros
li ta1, DEXP_MIN
subu ta1, ta1, t9 # adjust exponent
li v0, 32
blt t9, v0, 1f
subu t9, t9, v0 # shift fraction left >= 32 bits
sll ta2, ta3, t9
move ta3, zero
j ra
1:
subu v0, v0, t9 # shift fraction left < 32 bits
sll ta2, ta2, t9
srl v1, ta3, v0
or ta2, ta2, v1
sll ta3, ta3, t9
j ra
END(renorm_ft_d)