1244 lines
53 KiB
Plaintext
1244 lines
53 KiB
Plaintext
|
|
############################
|
|
#
|
|
# MIPS Floating Point (COP1 - coprocessor 1) instructions
|
|
# includes arithmetic, compares, branch on FP condition flag, conversions
|
|
# Also Coprocessor 0 instructions
|
|
#
|
|
# Note a MIPS word is 32-bits, and a long is a 64-bit integer
|
|
#
|
|
# mipsP6float.sinc contains floating point instructions that are in pre-Release 6 but not in Release 6
|
|
#
|
|
# mipsR6float.sinc contains floating point instructions that are in Release 6 and later
|
|
#
|
|
############################
|
|
|
|
define pcodeop mipsFloatPS;
|
|
|
|
# 0100 01ff fff0 0000 ssss sddd dd00 0101
|
|
:abs.S fd, fs is $(AMODE) & prime=17 & fct=5 & fmt1 & format=0x10 & fs & fd {
|
|
fd[0,32] = abs( fs:4 );
|
|
}
|
|
:abs.D fd, fs is $(AMODE) & prime=17 & fct=5 & fmt1 & format=0x11 & fs & fd & fsD & fdD {
|
|
fdD = abs(fsD);
|
|
}
|
|
:abs.PS fd, fs is $(AMODE) & REL6=0 & prime=17 & fct=5 & fmt1 & fs & fd & format=0x16 & fdD & fsD {
|
|
fdD = mipsFloatPS(fsD);
|
|
}
|
|
|
|
# 0100 01ff ffft tttt ssss sddd dd00 0000
|
|
:add.S fd, fs, ft is $(AMODE) & prime=17 & fct=0 & fmt1 & format=0x10 & ft & fs & fd {
|
|
fd[0,32] = fs:4 f+ ft:4;
|
|
}
|
|
:add.D fd, fs, ft is $(AMODE) & prime=17 & fct=0 & fmt1 & format=0x11 & ft & fs & fd & ftD & fsD & fdD {
|
|
fdD = fsD f+ ftD;
|
|
}
|
|
:add.PS fd, fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=0 & fmt1 & ft & fs & fd & format=0x16 & ftD & fsD & fdD {
|
|
fdD = mipsFloatPS(fsD, ftD);
|
|
}
|
|
|
|
# 0100 01ff fff0 0000 ssss sddd dd00 1010
|
|
:ceil.l.S fd, fs is $(AMODE) & prime=0x11 & ft=0x0 & fct=0x0A & fmt2 & fd & fs & format=0x10 & fdD {
|
|
# Note this instruction is in release 2 and later
|
|
fd_tmp:4 = ceil(fs:4); # Note that ceil returns a float the same size as its argument
|
|
fdD = trunc(fd_tmp); # Note that trunc converts a float to an integer
|
|
}
|
|
|
|
:ceil.l.D fd, fs is $(AMODE) & prime=0x11 & ft=0x0 & fct=0x0A & fmt2 & fd & fs & format=0x11 & fsD & fdD {
|
|
# Note this instruction is in release 2 and later
|
|
fsD_tmp:8 = ceil(fsD); # Note that ceil returns a float the same size as its argument
|
|
fdD = trunc(fsD_tmp); # Convert to 64-bit integer
|
|
}
|
|
# 0100 01ff fff0 0000 ssss sddd dd00 1110
|
|
:ceil.w.S fd, fs is $(AMODE) & prime=0x11 & ft=0x0 & fct=0x0E & fmt2 & fd & fs & format=0x10 {
|
|
fs_ceil_tmp:4 = ceil(fs:4); # Note that ceil returns a float the same size as its argument
|
|
fd[0,32] = trunc(fs_ceil_tmp);
|
|
}
|
|
:ceil.w.D fd, fs is $(AMODE) & prime=0x11 & ft=0x0 & fct=0x0E & fmt2 & fd & fs & format=0x11 & fsD {
|
|
fs_tmp:8 = ceil(fsD); # Note that ceil returns a float the same size as its argument
|
|
fd[0,32] = trunc( fs_tmp ); # Need to set only 32 bits of fd
|
|
}
|
|
|
|
# 0100 0100 010t tttt ssss s000 0000 0000
|
|
:cfc1 RT, fs_unk is $(AMODE) & prime=17 & copop=2 & RT & fs_unk & bigfunct=0 {
|
|
tmp:4 = getCopControlWord( 1:1, fs_unk:4 );
|
|
RT = sext(tmp);
|
|
}
|
|
:cfc1 RT, fs_fcr is $(AMODE) & prime=17 & copop=2 & RT & fs_fcr & (fs=0 | fs=25 | fs=26 | fs=28 | fs=31) & bigfunct=0 {
|
|
RT = sext(fs_fcr);
|
|
}
|
|
# Since we don't track the state of the FCSR bits, no sense in introducing complex code
|
|
#:cfc1 RT, fs_fcr is $(AMODE) & prime=17 & copop=2 & RT & fs_fcr & fs=25 & bigfunct=0 {
|
|
# tmp1:4 = (fcsr & 0x00800000) >> 23;
|
|
# tmp2:4 = (fcsr & 0xfe000000) >> 24;
|
|
# RT = sext(tmp2 + tmp1);
|
|
#}
|
|
#:cfc1 RT, fs_fcr is $(AMODE) & prime=17 & copop=2 & RT & fs_fcr & fs=26 & bigfunct=0 {
|
|
# tmp1:4 = fcsr & 0x0003f07c;
|
|
# RT = sext(tmp1);
|
|
#}
|
|
#:cfc1 RT, fs_fcr is $(AMODE) & prime=17 & copop=2 & RT & fs_fcr & fs=28 & bigfunct=0 {
|
|
# tmp1:4 = fcsr & 0x00000f83;
|
|
# tmp2:4 = (fcsr & 0x01000000) >> 24;
|
|
# RT = sext(tmp1 + tmp2);
|
|
#}
|
|
#:cfc1 RT, fs_fcr is $(AMODE) & prime=17 & copop=2 & RT & fs_fcr & fs=31 & bigfunct=0 {
|
|
# RT = sext(fcsr);
|
|
#}
|
|
|
|
# 0100 0100 110t tttt ssss s000 0000 0000
|
|
:ctc1 RTsrc, fs_unk is $(AMODE) & prime=17 & copop=6 & RTsrc & fs_unk & bigfunct=0 {
|
|
setCopControlWord( 1:1, fs_unk:4, RTsrc );
|
|
}
|
|
:ctc1 RTsrc, fs_fcr is $(AMODE) & prime=17 & copop=6 & RTsrc & fs_fcr & (fs=0 | fs=25 | fs=26 | fs=28 | fs=31) & bigfunct=0 {
|
|
fs_fcr = RTsrc:$(SIZETO4);
|
|
}
|
|
|
|
# 0100 01ff fff0 0000 ssss sddd dd10 0001
|
|
:cvt.d.S fd, fs is $(AMODE) & prime=0x11 & ft=0x0 & fct=0x21 & fmt3 & fd & fs & format=0x10 & fdD {
|
|
# Convert from single float to double float
|
|
fdD = float2float(fs:4);
|
|
}
|
|
:cvt.d.W fd, fs is $(AMODE) & prime=0x11 & ft=0x0 & fct=0x21 & fmt3 & fd & fs & format=0x14 & fdD {
|
|
# Convert from 32-bit int word source to double float
|
|
fs_tmp:4 = fs:4;
|
|
fdD = int2float(fs_tmp);
|
|
}
|
|
:cvt.d.L fd, fs is $(AMODE) & prime=0x11 & ft=0x0 & fct=0x21 & fmt3 & fd & fs & format=0x15 & fdD & fsD {
|
|
# Note this instruction is in release 2 and later
|
|
# Convert from 64-bit long source to double float
|
|
fdD = int2float(fsD);
|
|
}
|
|
# 0100 01ff fff0 0000 ssss sddd dd10 0101
|
|
:cvt.l.S fd, fs is $(AMODE) & prime=0x11 & ft=0x0 & fct=0x25 & fmt2 & fd & fs & format=0x10 & fdD {
|
|
# Note this instruction is in release 2 and later
|
|
# Convert from single float source to 64-bit long integer, using the fcsr RM rounding mode bits
|
|
rm_tmp:1 = fcsr[0,2]; # Get RM rounding mode bits
|
|
fs_tmp:4 = fs:4; # Get the lower 32-bits as a floating point single
|
|
fs_cvt_tmp:4 = 0;
|
|
if (rm_tmp == 0) goto <do_round>;
|
|
fs_cvt_tmp = floor(fs_tmp); # RM is 1, no rounding, and floor returns a float
|
|
goto <done>;
|
|
<do_round>
|
|
fs_cvt_tmp = round(fs_tmp); # round returns a float
|
|
<done>
|
|
fdD = trunc(fs_cvt_tmp); # trunc returns an integer
|
|
}
|
|
:cvt.l.D fd, fs is $(AMODE) & prime=0x11 & ft=0x0 & fct=0x25 & fmt2 & fd & fs & format=0x11 & fsD & fdD {
|
|
# Note this instruction is in release 2 and later
|
|
# Convert from double float to 64-bit long integer, using fcsr RM rounding mode bits
|
|
rm_tmp:1 = fcsr[0,2]; # Get RM rounding mode bits
|
|
if (rm_tmp == 0) goto <do_round>;
|
|
fd_tmp:8 = floor(fsD); # RM is 1, no rounding
|
|
goto <done>;
|
|
<do_round>
|
|
fd_tmp = round(fsD);
|
|
<done>
|
|
fdD = trunc(fd_tmp);
|
|
}
|
|
# 0100 0110 000t tttt ssss sddd dd10 0110
|
|
:cvt.PS.S fd, fs, ft is $(AMODE) & REL6=0 & prime=0x11 & format=0x10 & fct=0x26 & fd & fs & ft & ftD & fsD & fdD {
|
|
fdD = mipsFloatPS(fsD, ftD);
|
|
}
|
|
|
|
# 0100 01ff fff0 0000 ssss sddd dd10 0000
|
|
:cvt.s.D fd, fs is $(AMODE) & prime=0x11 & ft=0x0 & fct=0x20 & fmt4 & fd & fs & format=0x11 & fsD {
|
|
fd[0,32] = float2float(fsD);
|
|
}
|
|
:cvt.s.W fd, fs is $(AMODE) & prime=0x11 & ft=0x0 & fct=0x20 & fmt4 & fd & fs & format=0x14 {
|
|
fd[0,32] = int2float(fs:4);
|
|
}
|
|
:cvt.s.L fd, fs is $(AMODE) & prime=0x11 & ft=0x0 & fct=0x20 & fmt4 & fd & fs & format=0x15 & fsD {
|
|
# Note this instruction is in release 2 and later
|
|
fd[0,32] = int2float(fsD);
|
|
}
|
|
# 0100 0110 1100 0000 ssss sddd dd10 1000
|
|
:cvt.s.pl fd, fs is $(AMODE) & REL6=0 & prime=0x11 & format=0x16 & ft=0x0 & fct=0x28 & fd & fs & fdD & fsD {
|
|
fdD = mipsFloatPS(fsD);
|
|
}
|
|
# 0100 0110 1100 0000 ssss sddd dd10 0000
|
|
:cvt.s.pu fd, fs is $(AMODE) & REL6=0 & prime=0x11 & format=0x16 & ft=0x0 & fct=0x20 & fd & fs & fdD & fsD {
|
|
fdD = mipsFloatPS(fsD);
|
|
}
|
|
|
|
# 0100 01ff fff0 0000 ssss sddd dd10 0100
|
|
:cvt.w.S fd, fs is $(AMODE) & prime=0x11 & ft=0x0 & fct=0x24 & fmt2 & fd & fs & format=0x10 {
|
|
# Convert from single float source to 32-bit integer word, using the fcsr RM rounding mode bits
|
|
rm_tmp:1 = fcsr[0,2]; # Get RM rounding mode bits
|
|
fs_tmp:4 = fs:4;
|
|
fs_cvt_tmp:4 = 0;
|
|
if (rm_tmp == 0) goto <do_round>;
|
|
fs_cvt_tmp = floor(fs_tmp); # RM is 1, no rounding, and floor returns a float
|
|
goto <done>;
|
|
<do_round>
|
|
fs_cvt_tmp = round(fs_tmp); # round returns a float
|
|
<done>
|
|
fd[0,32] = trunc(fs_cvt_tmp); # trunc returns an integer
|
|
}
|
|
:cvt.w.D fd, fs is $(AMODE) & prime=0x11 & ft=0x0 & fct=0x24 & fmt2 & fd & fs & format=0x11 & fsD {
|
|
# Convert from double float source to 32-bit integer word, using the fcsr RM rounding mode bits
|
|
rm_tmp:1 = fcsr[0,2]; # Get RM rounding mode bits
|
|
if (rm_tmp == 0) goto <do_round>;
|
|
fs_tmp:8 = floor(fsD); # RM is 1, no rounding
|
|
goto <done>;
|
|
<do_round>
|
|
fs_tmp = round(fsD);
|
|
<done>
|
|
fd[0,32] = trunc(fs_tmp);
|
|
}
|
|
|
|
# 0100 01ff ffft tttt ssss sddd dd00 0011
|
|
:div.S fd, fs, ft is $(AMODE) & prime=17 & fct=3 & fmt2 & ft & fs & fd & format=0x10 {
|
|
fd[0,32] = fs:4 f/ ft:4;
|
|
}
|
|
:div.D fd, fs, ft is $(AMODE) & prime=17 & fct=3 & fmt2 & ft & fs & fd & format=0x11 & fdD & fsD & ftD {
|
|
fdD = fsD f/ ftD;
|
|
}
|
|
|
|
# 0100 01ff fff0 0000 ssss sddd dd00 1011
|
|
:floor.l.S fd, fs is $(AMODE) & prime=0x11 & ft=0x0 & fct=0x0B & fmt2 & fd & fs & format=0x10 & fdD {
|
|
# Note this instruction is in release 2 and later
|
|
# Convert floor of single float to a 64-bit long integer
|
|
fd_tmp:4 = floor(fs:4); # returns a float
|
|
fdD = trunc(fd_tmp); # converts float to int
|
|
}
|
|
:floor.l.D fd, fs is $(AMODE) & prime=0x11 & ft=0x0 & fct=0x0B & fmt2 & fd & fs & format=0x11 & fdD & fsD {
|
|
# Note this instruction is in release 2 and later
|
|
fsD_tmp:8 = floor(fsD);
|
|
fdD = trunc(fsD_tmp);
|
|
}
|
|
# 0100 01ff fff0 0000 ssss sddd dd00 1111
|
|
:floor.w.S fd, fs is $(AMODE) & prime=0x11 & ft=0x0 & fct=0x0F & fmt2 & fd & fs & format=0x10 {
|
|
# Floor of single float copied to a 32-bit integer word
|
|
fd_tmp:4 = floor(fs:4); # returns a float
|
|
fd = trunc(fd_tmp); # converts float to int
|
|
}
|
|
:floor.w.D fd, fs is $(AMODE) & prime=0x11 & ft=0x0 & fct=0x0F & fmt2 & fd & fs & format=0x11 & fsD {
|
|
# Floor of double float to a 32-bit integer word
|
|
fd[0,32] = trunc(floor(fsD));
|
|
}
|
|
|
|
# 1101 01bb bbbt tttt iiii iiii iiii iiii
|
|
:ldc1 ft, OFF_BASE is $(AMODE) & prime=53 & OFF_BASE & ft & ftD {
|
|
ftD = *[ram]:8 OFF_BASE;
|
|
}
|
|
|
|
# 1111 01bb bbbt tttt iiii iiii iiii iiii
|
|
:sdc1 ft, OFF_BASE is $(AMODE) & prime=61 & OFF_BASE & ft & ftD {
|
|
*[ram]:8 OFF_BASE = ftD;
|
|
}
|
|
|
|
# 1100 01bb bbbt tttt iiii iiii iiii iiii
|
|
:lwc1 ft, OFF_BASE is $(AMODE) & prime=49 & OFF_BASE & ft {
|
|
ft[0,32] = *[ram]:4 OFF_BASE;
|
|
}
|
|
|
|
# 0100 0100 000t tttt ssss s000 0000 0000
|
|
:mfc1 RT, fs is $(AMODE) & prime=17 & copop=0 & RT & fs & bigfunct=0 {
|
|
# Move just a word, 32-bits
|
|
RT = sext( fs:$(SIZETO4) );
|
|
}
|
|
|
|
# 0100 0100 011t tttt ssss s000 0000 0000
|
|
:mfhc1 RT, fs is $(AMODE) & prime=17 & copop=3 & bigfunct=0 & RT & fs & fsD {
|
|
RT = sext(fsD[32,32]);
|
|
}
|
|
|
|
# 0100 01ff fff0 0000 ssss sddd dd00 0110
|
|
:mov.S fd, fs is $(AMODE) & prime=17 & fct=6 & fmt1 & fs & fd & format=0x10 {
|
|
fd[0,32] = fs:4;
|
|
}
|
|
:mov.D fd, fs is $(AMODE) & prime=17 & fct=6 & fmt1 & fs & fd & format=0x11 & fdD & fsD {
|
|
fdD = fsD;
|
|
}
|
|
:mov.PS fd, fs is $(AMODE) & REL6=0 & prime=17 & fct=6 & fmt1 & fs & fd & format=0x16 & fsD & fdD {
|
|
fdD = mipsFloatPS(fsD);
|
|
}
|
|
|
|
# 0100 0100 100t tttt dddd d000 0000 0000
|
|
:mtc1 RTsrc, fs is $(AMODE) & prime=17 & copop=4 & RTsrc & fs & bigfunct=0 {
|
|
# Move 32-bits of RTsrc to Low Half of FPR fs
|
|
fs[0,32] = RTsrc:$(SIZETO4);
|
|
}
|
|
|
|
# 0100 0100 111t tttt ssss s000 0000 0000
|
|
:mthc1 RTsrc, fs is $(AMODE) & prime=17 & copop=0x07 & bigfunct=0x0 & RTsrc & fs & fsD {
|
|
# Move 32-bits of RTsrc to High Half of FPR
|
|
fsD[32,32] = RTsrc:4;
|
|
}
|
|
|
|
# 0100 01ff ffft tttt ssss sddd dd00 0010
|
|
:mul.S fd, fs, ft is $(AMODE) & prime=17 & fct=2 & fmt1 & ft & fs & fd & format=0x10 {
|
|
fd[0,32] = fs:4 f* ft:4; # need to only get the single float 32-bit (fs might be 64-bits)
|
|
}
|
|
:mul.D fd, fs, ft is $(AMODE) & prime=17 & fct=2 & fmt1 & ft & fs & fd & format=0x11 & fdD & fsD & ftD {
|
|
fdD = fsD f* ftD;
|
|
}
|
|
:mul.PS fd, fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=2 & fmt1 & ft & fs & fd & format=0x16 & ftD & fsD & fdD {
|
|
fdD = mipsFloatPS(fsD, ftD);
|
|
}
|
|
|
|
# 0100 01ff fff0 0000 ssss sddd dd00 0111
|
|
:neg.S fd, fs is $(AMODE) & prime=17 & fct=7 & fmt1 & fs & fd & format=0x10 {
|
|
fd[0,32] = f- fs:4;
|
|
}
|
|
:neg.D fd, fs is $(AMODE) & prime=17 & fct=7 & fmt1 & fs & fd & format=0x11 & fdD & fsD {
|
|
fdD = f- fsD;
|
|
}
|
|
:neg.PS fd, fs is $(AMODE) & REL6=0 & prime=17 & fct=7 & fmt1 & fs & fd & format=0x16 & fsD & fdD {
|
|
fdD = mipsFloatPS(fsD);
|
|
}
|
|
|
|
# 0100 01ff fff0 0000 ssss sddd dd01 0101
|
|
:recip.S fd, fs is $(AMODE) & prime=17 & ft=0 & fct=21 & fmt2 & fd & fs & format=0x10 {
|
|
fd[0,32] = 1:4 f/ fs:4;
|
|
}
|
|
:recip.D fd, fs is $(AMODE) & prime=17 & ft=0 & fct=21 & fmt2 & fd & fs & format=0x11 & fdD & fsD {
|
|
fdD = 1:8 f/ fsD;
|
|
}
|
|
|
|
# 0100 01ff fff0 0000 ssss sddd dd00 1000
|
|
:round.l.S fd, fs is $(AMODE) & prime=17 & ft=0 & fct=8 & fmt2 & fd & fs & format=0x10 & fdD {
|
|
# Note this instruction is in release 2 and later
|
|
fd_tmp:4 = round(fs:4); # round returns a float of the same size are the arg
|
|
fdD = trunc(fd_tmp); # trunc converts to any size integer
|
|
}
|
|
:round.l.D fd, fs is $(AMODE) & prime=17 & ft=0 & fct=8 & fmt2 & fd & fs &format=0x11 & fsD & fdD {
|
|
# Note this instruction is in release 2 and later
|
|
fsD_tmp:8 = round(fsD);
|
|
fdD = trunc(fsD_tmp);
|
|
}
|
|
# 0100 01ff fff0 0000 ssss sddd dd00 1100
|
|
:round.w.S fd, fs is $(AMODE) & prime=17 & ft=0 & fct=12 & fmt2 & fd & fs & format=0x10 {
|
|
fd_tmp:4 = round(fs:4);
|
|
fd = trunc(fd_tmp);
|
|
}
|
|
:round.w.D fd, fs is $(AMODE) & prime=17 & ft=0 & fct=12 & fmt2 & fd & fs & format=0x11 & fsD {
|
|
fdD_tmp:8 = round(fsD); # round returns a float, not an int
|
|
fd[0,32] = trunc(fdD_tmp); # We need only a 32-bit integer
|
|
}
|
|
|
|
# 0100 01ff fff0 0000 ssss sddd dd01 0110
|
|
:rsqrt.S fd, fs is $(AMODE) & prime=17 & ft=0 & fct=22 & fmt2 & fd & fs & format=0x10 {
|
|
fd[0,32] = 1:4 f/ sqrt(fs:4);
|
|
}
|
|
:rsqrt.D fd, fs is $(AMODE) & prime=17 & ft=0 & fct=22 & fmt2 & fd & fs & format=0x11 & fdD & fsD {
|
|
fdD = 1:8 f/ sqrt(fsD);
|
|
}
|
|
|
|
# 0100 01ff fff0 0000 ssss sddd dd00 0100
|
|
:sqrt.S fd, fs is $(AMODE) & prime=17 & ft=0 & fct=4 & fmt2 & fd & fs & format=0x10 {
|
|
fd[0,32] = sqrt(fs:4);
|
|
}
|
|
:sqrt.D fd, fs is $(AMODE) & prime=17 & ft=0 & fct=4 & fmt2 & fd & fs & format=0x11 & fsD & fdD {
|
|
fdD = sqrt(fsD);
|
|
}
|
|
|
|
# 0100 01ff ffft tttt ssss sddd dd00 0001
|
|
:sub.S fmt1 fd, fs, ft is $(AMODE) & prime=17 & fct=1 & fmt1 & ft & fs & fd & format=0x10 {
|
|
fd[0,32] = fs:4 f- ft:4;
|
|
}
|
|
:sub.D fmt1 fd, fs, ft is $(AMODE) & prime=17 & fct=1 & fmt1 & ft & fs & fd & format=0x11 & fdD & fsD & ftD {
|
|
fdD = fsD f- ftD;
|
|
}
|
|
:sub.PS fmt1 fd, fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=1 & fmt1 & ft & fs & fd & format=0x16 & ftD & fsD & fdD {
|
|
fdD = mipsFloatPS(fsD, ftD);
|
|
}
|
|
|
|
# 1110 01bb bbbt tttt iiii iiii iiii iiii
|
|
:swc1 ft, OFF_BASE is $(AMODE) & prime=57 & OFF_BASE & ft {
|
|
*[ram]:4 OFF_BASE = ft:$(SIZETO4);
|
|
}
|
|
|
|
# 0100 01ff fff0 0000 ssss sddd dd00 1001
|
|
:trunc.l.S fd, fs is $(AMODE) & prime=17 & cop1code=0 & fmt2 & fs & fd & fct=9 & format=0x10 & fdD {
|
|
# Note this instruction is in release 2 and later
|
|
fd = trunc(fs:4);
|
|
}
|
|
:trunc.l.D fd, fs is $(AMODE) & prime=17 & cop1code=0 & fmt2 & fs & fd & fct=9 & format=0x11 & fdD & fsD {
|
|
# Note this instruction is in release 2 and later
|
|
fdD = trunc(fsD);
|
|
}
|
|
# 0100 01ff fff0 0000 ssss sddd dd00 1101
|
|
:trunc.w.S fd, fs is $(AMODE) & prime=17 & cop1code=0 & fmt2 & fs & fd & fct=13 & format=0x10 {
|
|
fd[0,32] = trunc(fs:4);
|
|
}
|
|
:trunc.w.D fd, fs is $(AMODE) & prime=17 & cop1code=0 & fmt2 & fs & fd & fct=13 & format=0x11 & fsD {
|
|
fd[0,32] = trunc(fsD);
|
|
}
|
|
|
|
############################
|
|
#
|
|
# COP1X (Extended FP)
|
|
#
|
|
############################
|
|
|
|
# 0100 11ss ssst tttt ssss sddd dd01 1110
|
|
:alnv.PS fd, fs, ft, rs is $(AMODE) & REL6=0 & prime=0x13 & fct=0x1E & rs & ft & fs & fd & ftD & fsD & fdD {
|
|
fdD = mipsFloatPS(fsD, ftD);
|
|
}
|
|
|
|
# 0100 11bb bbbi iiii 0000 0ddd dd00 0001
|
|
:ldxc1 fd, INDEX_BASE is $(AMODE) & REL6=0 & prime=0x13 & zero4=0 & fct=0x01 & INDEX_BASE & fd & fdD {
|
|
fdD = *[ram]:8 INDEX_BASE;
|
|
}
|
|
|
|
# 0100 11bb bbbi iiii 0000 0ddd dd00 0101
|
|
:luxc1 fd, INDEX_BASE is $(AMODE) & REL6=0 & prime=0x13 & zero4=0 & fct=0x05 & INDEX_BASE & fd & fdD {
|
|
ptr:$(ADDRSIZE) = INDEX_BASE & -16:$(ADDRSIZE);
|
|
fdD = *[ram]:8 ptr;
|
|
}
|
|
|
|
# 0100 11bb bbbi iiii 0000 0ddd dd00 0000
|
|
:lwxc1 fd, INDEX_BASE is $(AMODE) & REL6=0 & prime=0x13 & zero4=0 & fct=0x0 & INDEX_BASE & fd {
|
|
fd[0,32] = *[ram]:4 INDEX_BASE;
|
|
}
|
|
|
|
# 0100 11rr rrrt tttt ssss sddd dd10 0fff
|
|
:madd.S fd, fr, fs, ft is $(AMODE) & REL6=0 & prime=0x13 & op4=0x04 & fmt5 & fd & fr & fs & ft & format1X=0x0 {
|
|
fd[0,32] = (fs:4 f* ft:4) f+ fr:4; # must do floating arithmetic in 32 bit
|
|
}
|
|
:madd.D fd, fr, fs, ft is $(AMODE) & REL6=0 & prime=0x13 & op4=0x04 & fmt5 & fd & fr & fs & ft &
|
|
format1X=0x1 & fdD & fsD & frD & ftD {
|
|
fdD = (fsD f* ftD) f+ frD;
|
|
}
|
|
:madd.PS fd, fr, fs, ft is $(AMODE) & REL6=0 & prime=0x13 & op4=0x04 & fmt5 & fd & fr & fs & ft & format1X=0x6 & ftD & fsD & fdD {
|
|
fdD = mipsFloatPS(fsD, ftD);
|
|
}
|
|
|
|
# 0100 11rr rrrt tttt ssss sddd dd10 1fff
|
|
:msub.S fd, fr, fs, ft is $(AMODE) & REL6=0 & prime=0x13 & op4=0x05 & fmt5 & fd & fr & fs & ft & format1X=0x0 {
|
|
fd[0,32] = (fs:4 f* ft:4) f- fr:4; # must do floating arithmetic in 32 bit
|
|
}
|
|
:msub.D fd, fr, fs, ft is $(AMODE) & REL6=0 & prime=0x13 & op4=0x05 & fmt5 & fd & fr & fs & ft &
|
|
format1X=0x1 & fdD & fsD & ftD & frD {
|
|
fdD = (fsD f* ftD) f- frD;
|
|
}
|
|
:msub.PS fd, fr, fs, ft is $(AMODE) & REL6=0 & prime=0x13 & op4=0x05 & fmt5 & fd & fr & fs & ft & format1X=0x6 & ftD & fsD & fdD {
|
|
fdD = mipsFloatPS(fsD, ftD);
|
|
}
|
|
|
|
# 0100 11rr rrrt tttt ssss sddd dd11 0fff
|
|
:nmadd.S fd, fr, fs, ft is $(AMODE) & REL6=0 & prime=0x13 & op4=0x06 & fmt5 & fd & fr & fs & ft & format1X=0x0 {
|
|
fd[0,32] = f- (fs:4 f* ft:4) f+ fr:4; # must do floating arithmetic in 32 bit
|
|
}
|
|
:nmadd.D fd, fr, fs, ft is $(AMODE) & REL6=0 & prime=0x13 & op4=0x06 & fmt5 & fd & fr & fs & ft &
|
|
format1X=0x1 & fdD & fsD & ftD & frD {
|
|
fdD = f- ((fsD f* ftD) f+ frD);
|
|
}
|
|
:nmadd.PS fd, fr, fs, ft is $(AMODE) & REL6=0 & prime=0x13 & op4=0x06 & fmt5 & fd & fr & fs & ft & format1X=0x6 & ftD & fsD & fdD {
|
|
fdD = mipsFloatPS(fsD, ftD);
|
|
}
|
|
|
|
# 0100 11rr rrrt tttt ssss sddd dd11 1fff
|
|
:nmsub.S fd, fr, fs, ft is $(AMODE) & REL6=0 & prime=0x13 & op4=0x07 & fmt5 & fd & fr & fs & ft & format1X=0x0 {
|
|
fd[0,32] = f- (fs:4 f* ft:4) f- fr:4; # must do floating arithmetic in 32 bit
|
|
}
|
|
:nmsub.D fd, fr, fs, ft is $(AMODE) & REL6=0 & prime=0x13 & op4=0x07 & fmt5 & fd & fr & fs & ft &
|
|
format1X=0x1 & fdD & fsD & ftD & frD {
|
|
fdD = f- ((fsD f* ftD) f- frD);
|
|
}
|
|
:nmsub.PS fd, fr, fs, ft is $(AMODE) & REL6=0 & prime=0x13 & op4=0x07 & fmt5 & fd & fr & fs & ft & format1X=0x6 & ftD & fsD & fdD {
|
|
fdD = mipsFloatPS(fsD, ftD);
|
|
}
|
|
|
|
# 0100 11bb bbbi iiii hhhh h000 0000 1111
|
|
:prefx hint, INDEX_BASE is $(AMODE) & REL6=0 & prime=0x13 & zero5=0x0 & fct=0x0F & hint & INDEX_BASE {
|
|
prefetch(INDEX_BASE, hint:1);
|
|
}
|
|
# 0100 11bb bbbi iiii ssss s000 0000 1001
|
|
:sdxc1 fs, INDEX_BASE is $(AMODE) & REL6=0 & prime=0x13 & zero5=0x0 & fct=0x09 & fs & fsD & INDEX_BASE {
|
|
*[ram]:8 INDEX_BASE = fsD;
|
|
}
|
|
# 0100 11bb bbbi iiii ssss s000 0000 1101
|
|
:suxc1 fs, INDEX_BASE is $(AMODE) & REL6=0 & prime=19 & fct=13 & INDEX_BASE & fs & fsD {
|
|
INDEX_BASE = INDEX_BASE & 0xfffffffffffffff0;
|
|
*[ram]:8 INDEX_BASE = fsD;
|
|
}
|
|
# 0100 11bb bbbi iiii ssss s000 0000 1000
|
|
:swxc1 fs, INDEX_BASE is $(AMODE) & REL6=0 & prime=19 & INDEX_BASE & fs & fd=0 & fct=8 {
|
|
*[ram]:4 INDEX_BASE = fs:$(SIZETO4);
|
|
}
|
|
####
|
|
#
|
|
# Pre-6 semantics
|
|
#
|
|
####
|
|
# 0100 0101 000c cc00 iiii iiii iiii iiii
|
|
:bc1f Rel16 is $(AMODE) & REL6=0 & prime=17 & copop=8 & cc=0 & nd=0 & tf=0 & Rel16 {
|
|
tmp:1 = fcsr[23,1]; # The floating point condition bit
|
|
delayslot(1);
|
|
if (tmp != 0) goto inst_next;
|
|
goto Rel16;
|
|
}
|
|
:bc1f cc,Rel16 is $(AMODE) & REL6=0 & prime=17 & copop=8 & cc & nd=0 & tf=0 & Rel16 {
|
|
# tmp:1 = getFpCondition(cc:1); # Note that other cc conditions are not implemented
|
|
tmp:1 = fcsr[23,1]; # The floating point condition bit
|
|
delayslot(1);
|
|
if (tmp != 0) goto inst_next;
|
|
goto Rel16;
|
|
}
|
|
# 0100 0101 000c cc10 iiii iiii iiii iiii
|
|
:bc1fl Rel16 is $(AMODE) & REL6=0 & prime=17 & copop=8 & cc=0 & nd=1 & tf=0 & Rel16 {
|
|
tmp:1 = fcsr[23,1];
|
|
if (tmp != 0) goto inst_next;
|
|
delayslot(1);
|
|
goto Rel16;
|
|
}
|
|
:bc1fl cc,Rel16 is $(AMODE) & REL6=0 & prime=17 & copop=8 & cc & nd=1 & tf=0 & Rel16 {
|
|
# tmp:1 = getFpCondition(cc:1);
|
|
tmp:1 = fcsr[23,1]; # The floating point condition bit
|
|
if (tmp != 0) goto inst_next;
|
|
delayslot(1);
|
|
goto Rel16;
|
|
}
|
|
|
|
# 0100 0101 000c cc01 iiii iiii iiii iiii
|
|
:bc1t Rel16 is $(AMODE) & REL6=0 & prime=17 & copop=8 & cc=0 & nd=0 & tf=1 & Rel16 {
|
|
tmp:1 = fcsr[23,1];
|
|
delayslot(1);
|
|
if (tmp == 0) goto inst_next;
|
|
goto Rel16;
|
|
}
|
|
:bc1t cc,Rel16 is $(AMODE) & REL6=0 & prime=17 & copop=8 & cc & nd=0 & tf=1 & Rel16 {
|
|
# tmp:1 = getFpCondition(cc:1);
|
|
tmp:1 = fcsr[23,1]; # The floating point condition bit
|
|
delayslot(1);
|
|
if (tmp == 0) goto inst_next;
|
|
goto Rel16;
|
|
}
|
|
# 0100 0101 000c cc11 iiii iiii iiii iiii
|
|
:bc1tl Rel16 is $(AMODE) & REL6=0 & prime=17 & copop=8 & cc=0 & nd=1 & tf=1 & Rel16 {
|
|
tmp:1 = fcsr[23,1];
|
|
if (tmp == 0) goto inst_next;
|
|
delayslot(1);
|
|
goto Rel16;
|
|
}
|
|
:bc1tl cc,Rel16 is $(AMODE) & REL6=0 & prime=17 & copop=8 & cc & nd=1 & tf=1 & Rel16 {
|
|
# tmp:1 = getFpCondition(cc:1);
|
|
tmp:1 = fcsr[23,1]; # The floating point condition bit
|
|
if (tmp == 0) goto inst_next;
|
|
delayslot(1);
|
|
goto Rel16;
|
|
}
|
|
|
|
# The pre-release 6 floating point compare instructions, c.condn.S or .D, set the fcsr bit 23
|
|
|
|
macro trapIfNaN(x1, x2) { }
|
|
macro trapIfSNaN(x1, x2) { }
|
|
|
|
:c.f.S fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=48 & fmt1 & format=0x10 & fs & ft {
|
|
trapIfSNaN(fs:4, ft:4); # Trap if either operand is a Signaling NaN
|
|
fcsr[23,1] = 0; # Always false
|
|
}
|
|
:c.f.D fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=48 & fmt1 & format=0x11 & fs & ft & fsD & ftD {
|
|
trapIfSNaN(fsD, ftD);
|
|
fcsr[23,1] = 0;
|
|
}
|
|
:c.f.PS fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=48 & fmt1 & fs & ft & format=0x16 & ftD & fsD & fdD {
|
|
fcsr[23,1] = mipsFloatPS(fsD, ftD);
|
|
}
|
|
|
|
:c.un.S fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=49 & fmt1 & format=0x10 & fs & ft {
|
|
trapIfSNaN(fs:4, ft:4);
|
|
fcsr[23,1] = nan(fs:4) || nan(ft:4); # True if operands are NaN
|
|
}
|
|
:c.un.D fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=49 & fmt1 & fs & ft & format=0x11 & fsD & ftD {
|
|
trapIfSNaN(fsD, ftD);
|
|
fcsr[23,1] = nan(fsD) || nan(ftD);
|
|
}
|
|
:c.un.PS fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=49 & fmt1 & fs & ft & format=0x16 & ftD & fsD {
|
|
fcsr[23,1] = mipsFloatPS(fsD, ftD);
|
|
}
|
|
|
|
:c.eq.S fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=50 & fmt1 & format=0x10 & fs & ft {
|
|
trapIfSNaN(fs:4, ft:4);
|
|
fcsr[23,1] = (fs:4 f== ft:4);
|
|
}
|
|
:c.eq.D fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=50 & fmt1 & fs & ft & format=0x11 & fsD & ftD {
|
|
trapIfSNaN(fsD, ftD);
|
|
fcsr[23,1] = (fsD f== ftD);
|
|
}
|
|
:c.eq.PS fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=50 & fmt1 & fs & ft & format=0x16 & ftD & fsD {
|
|
fcsr[23,1] = mipsFloatPS(fsD, ftD);
|
|
}
|
|
|
|
:c.ueq.S fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=51 & fmt1 & format=0x10 & fs & ft {
|
|
trapIfSNaN(fs:4, ft:4);
|
|
fcsr[23,1] = (fs:4 f== ft:4);
|
|
}
|
|
:c.ueq.D fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=51 & fmt1 & fs & ft & format=0x11 & fsD & ftD {
|
|
trapIfSNaN(fsD, ftD);
|
|
fcsr[23,1] = (fsD f== ftD);
|
|
}
|
|
:c.ueq.PS fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=51 & fmt1 & fs & ft & format=0x16 & ftD & fsD {
|
|
fcsr[23,1] = mipsFloatPS(fsD, ftD);
|
|
}
|
|
|
|
:c.olt.S fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=52 & fmt1 & format=0x10 & fs & ft {
|
|
trapIfSNaN(fs:4, ft:4);
|
|
fcsr[23,1] = (fs:4 f< ft:4);
|
|
}
|
|
:c.olt.D fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=52 & fmt1 & fs & ft & format=0x11 & fsD & ftD {
|
|
trapIfSNaN(fsD, ftD);
|
|
fcsr[23,1] = (fsD f< ftD);
|
|
}
|
|
:c.olt.PS fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=52 & fmt1 & fs & ft & format=0x16 & ftD & fsD {
|
|
fcsr[23,1] = mipsFloatPS(fsD, ftD);
|
|
}
|
|
|
|
:c.ult.S fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=53 & fmt1 & format=0x10 & fs & ft {
|
|
trapIfSNaN(fs:4, ft:4);
|
|
fcsr[23,1] = (fs:4 f< ft:4) || nan(fs:4) || nan(ft:4); # Less than or NaN
|
|
}
|
|
:c.ult.D fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=53 & fmt1 & fs & ft & format=0x11 & fsD & ftD {
|
|
trapIfSNaN(fsD, ftD);
|
|
fcsr[23,1] = (fsD f< ftD) || nan(fsD) || nan(ftD);
|
|
}
|
|
:c.ult.PS fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=53 & fmt1 & fs & ft & format=0x16 & ftD & fsD {
|
|
fcsr[23,1] = mipsFloatPS(fsD, ftD);
|
|
}
|
|
|
|
:c.ole.S fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=54 & fmt1 & format=0x10 & fs & ft {
|
|
trapIfSNaN(fs:4, ft:4);
|
|
fcsr[23,1] = (fs:4 f<= ft:4);
|
|
}
|
|
:c.ole.D fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=54 & fmt1 & fs & ft & format=0x11 & fsD & ftD {
|
|
trapIfSNaN(fsD, ftD);
|
|
fcsr[23,1] = (fsD f<= ftD);
|
|
}
|
|
:c.ole.PS fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=54 & fmt1 & fs & ft & format=0x16 & ftD & fsD {
|
|
fcsr[23,1] = mipsFloatPS(fsD, ftD);
|
|
}
|
|
|
|
:c.ule.S fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=55 & fmt1 & format=0x10 & fs & ft {
|
|
trapIfSNaN(fs:4, ft:4);
|
|
fcsr[23,1] = (fs:4 f<= ft:4) || nan(fs:4) || nan(ft:4); # Less than or equal or NaN
|
|
}
|
|
:c.ule.D fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=55 & fmt1 & fs & ft & format=0x11 & fsD & ftD {
|
|
trapIfSNaN(fsD, ftD);
|
|
fcsr[23,1] = (fsD f<= ftD) || nan(fsD) || nan(ftD);
|
|
}
|
|
:c.ule.PS fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=55 & fmt1 & fs & ft & format=0x16 & ftD & fsD {
|
|
fcsr[23,1] = mipsFloatPS(fsD, ftD);
|
|
}
|
|
|
|
# The pre-release 6 floating point compare instructions that trap if either operand is NaN (either QNaN or SNaN)
|
|
|
|
:c.sf.S fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=56 & fmt1 & fs & ft & format=0x10 {
|
|
trapIfNaN(fs:4, ft:4);
|
|
fcsr[23,1] = 0; # Always false
|
|
}
|
|
:c.sf.D fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=56 & fmt1 & fs & ft & format=0x11 & fsD & ftD {
|
|
trapIfNaN(fsD, ftD);
|
|
fcsr[23,1] = 0;
|
|
}
|
|
:c.sf.PS fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=56 & fmt1 & fs & ft & format=0x16 & ftD & fsD {
|
|
fcsr[23,1] = mipsFloatPS(fsD, ftD);
|
|
}
|
|
|
|
:c.ngle.S fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=57 & fmt1 & format=0x10 & fs & ft {
|
|
trapIfNaN(fs:4, ft:4);
|
|
fcsr[23,1] = nan(fs:4) || nan(ft:4);
|
|
}
|
|
:c.ngle.D fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=57 & fmt1 & fs & ft & format=0x11 & fsD & ftD {
|
|
trapIfNaN(fsD, ftD);
|
|
fcsr[23,1] = nan(fsD) || nan(ftD);
|
|
}
|
|
:c.ngle.PS fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=57 & fmt1 & fs & ft & format=0x16 & ftD & fsD {
|
|
fcsr[23,1] = mipsFloatPS(fsD, ftD);
|
|
}
|
|
|
|
:c.seq.S fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=58 & fmt1 & format=0x10 & fs & ft {
|
|
trapIfNaN(fs:4, ft:4);
|
|
fcsr[23,1] = (fs:4 f== ft:4);
|
|
}
|
|
:c.seq.D fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=58 & fmt1 & fs & ft & format=0x11 & fsD & ftD {
|
|
trapIfNaN(fsD, ftD);
|
|
fcsr[23,1] = (fsD f== ftD);
|
|
}
|
|
:c.seq.PS fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=58 & fmt1 & fs & ft & format=0x16 & ftD & fsD {
|
|
fcsr[23,1] = mipsFloatPS(fsD, ftD);
|
|
}
|
|
|
|
:c.ngl.S fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=59 & fmt1 & format=0x10 & fs & ft {
|
|
trapIfNaN(fs:4, ft:4);
|
|
fcsr[23,1] = (fs:4 f== ft:4) || nan(fs:4) || nan(ft:4);
|
|
}
|
|
:c.ngl.D fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=59 & fmt1 & fs & ft & format=0x11 & fsD & ftD {
|
|
trapIfNaN(fsD, ftD);
|
|
fcsr[23,1] = (fsD f== ftD) || nan(fsD) || nan(ftD);
|
|
}
|
|
:c.ngl.PS fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=59 & fmt1 & fs & ft & format=0x16 & ftD & fsD {
|
|
fcsr[23,1] = mipsFloatPS(fsD, ftD);
|
|
}
|
|
|
|
:c.lt.S fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=60 & fmt1 & format=0x10 & fs & ft {
|
|
trapIfNaN(fs:4, ft:4);
|
|
fcsr[23,1] = (fs:4 f< ft:4);
|
|
}
|
|
:c.lt.D fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=60 & fmt1 & fs & ft & format=0x11 & fsD & ftD {
|
|
trapIfNaN(fsD, ftD);
|
|
fcsr[23,1] = (fsD f< ftD);
|
|
}
|
|
:c.lt.PS fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=60 & fmt1 & fs & ft & format=0x16 & ftD & fsD {
|
|
fcsr[23,1] = mipsFloatPS(fsD, ftD);
|
|
}
|
|
|
|
:c.nge.S fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=61 & fmt1 & format=0x10 & fs & ft {
|
|
trapIfNaN(fs:4, ft:4);
|
|
fcsr[23,1] = (fs:4 f< ft:4) || nan(fs:4) || nan(ft:4);
|
|
}
|
|
:c.nge.D fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=61 & fmt1 & fs & ft & format=0x11 & fsD & ftD {
|
|
trapIfNaN(fsD, ftD);
|
|
fcsr[23,1] = (fsD f< ftD) || nan(fsD) || nan(ftD);
|
|
}
|
|
:c.nge.PS fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=61 & fmt1 & fs & ft & format=0x16 & ftD & fsD {
|
|
fcsr[23,1] = mipsFloatPS(fsD, ftD);
|
|
}
|
|
|
|
:c.le.S fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=62 & fmt1 & format=0x10 & fs & ft {
|
|
trapIfNaN(fs:4, ft:4);
|
|
fcsr[23,1] = (fs:4 f<= ft:4);
|
|
}
|
|
:c.le.D fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=62 & fmt1 & fs & ft & format=0x11 & fsD & ftD {
|
|
trapIfNaN(fsD, ftD);
|
|
fcsr[23,1] = (fsD f<= ftD);
|
|
}
|
|
:c.le.PS fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=62 & fmt1 & fs & ft & format=0x16 & ftD & fsD {
|
|
fcsr[23,1] = mipsFloatPS(fsD, ftD);
|
|
}
|
|
|
|
:c.ngt.S fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=63 & fmt1 & format=0x10 & fs & ft {
|
|
trapIfNaN(fs:4, ft:4);
|
|
fcsr[23,1] = (fs:4 f<= ft:4) || nan(fs:4) || nan(ft:4); # Less than or equal or NaN
|
|
}
|
|
:c.ngt.D fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=63 & fmt1 & fs & ft & format=0x11 & fsD & ftD {
|
|
trapIfNaN(fsD, ftD);
|
|
fcsr[23,1] = (fsD f<= ftD) || nan(fsD) || nan(ftD);
|
|
}
|
|
:c.ngt.PS fs, ft is $(AMODE) & REL6=0 & prime=17 & fct=63 & fmt1 & fs & ft & format=0x16 & ftD & fsD {
|
|
fcsr[23,1] = mipsFloatPS(fsD, ftD);
|
|
}
|
|
|
|
# 0000 00ss sssc cc00 dddd d000 0000 0001
|
|
:movf RD, RSsrc, cc is $(AMODE) & REL6=0 & prime=0 & nd=0 & tf=0 & zero5=0 & fct=1 & RD & RSsrc & cc {
|
|
# Move if FP condition flag is false
|
|
tmp:1 = fcsr[23,1];
|
|
if (tmp != 0) goto <done>;
|
|
RD = RSsrc;
|
|
<done>
|
|
}
|
|
|
|
# 0100 01ff fffc cc00 ssss sddd dd01 0001
|
|
:movf.S fd, fs, cc is $(AMODE) & REL6=0 & prime=17 & nd=0 & tf=0 & fct=17 & fmt1 & fd & fs & cc & format=0x10 {
|
|
# Move if FP condition flag is false
|
|
tmp:1 = fcsr[23,1];
|
|
if (tmp != 0) goto <done>;
|
|
fd[0,32] = fs:4;
|
|
<done>
|
|
}
|
|
:movf.D fd, fs, cc is $(AMODE) & REL6=0 & prime=17 & nd=0 & tf=0 & fct=17 & fmt1 & fd & fs & cc & format=0x11 & fdD & fsD {
|
|
# Move if FP condition flag is false
|
|
tmp:1 = fcsr[23,1];
|
|
if (tmp != 0) goto <done>;
|
|
fdD = fsD;
|
|
<done>
|
|
}
|
|
:movf.PS fd, fs, cc is $(AMODE) & REL6=0 & prime=17 & nd=0 & tf=0 & fct=17 & fmt1 & fd & fs & cc & format=0x16 & fsD & fdD {
|
|
fdD = mipsFloatPS(fcsr[23,1], fsD);
|
|
}
|
|
|
|
# 0100 01ff ffft tttt ssss sddd dd01 0011
|
|
:movn.S fd, fs, RTsrc is $(AMODE) & REL6=0 & prime=17 & fct=19 & fmt1 & fd & fs & RTsrc & format=0x10 {
|
|
if (RTsrc == 0) goto <done>;
|
|
fd[0,32] = fs:4;
|
|
<done>
|
|
}
|
|
:movn.D fd, fs, RTsrc is $(AMODE) & REL6=0 & prime=17 & fct=19 & fmt1 & fd & fs & RTsrc & format=0x11 & fdD & fsD {
|
|
if (RTsrc == 0) goto <done>;
|
|
fdD = fsD;
|
|
<done>
|
|
}
|
|
:movn.PS fd, fs, RTsrc is $(AMODE) & REL6=0 & prime=17 & fct=19 & fmt1 & fd & fs & RTsrc & format=0x16 & fsD & fdD {
|
|
fdD = mipsFloatPS(fcsr[23,1], fsD);
|
|
}
|
|
|
|
# 0000 00ss sssc cc01 dddd d000 0000 0001
|
|
:movt RD, RSsrc, cc is $(AMODE) & REL6=0 & prime=0 & nd=0 & tf=1 & zero5=0 & fct=1 & RD & RSsrc & cc {
|
|
# Move if FP condition flag is true
|
|
tmp:1 = fcsr[23,1];
|
|
if (tmp != 1) goto <done>;
|
|
RD = RSsrc;
|
|
<done>
|
|
}
|
|
|
|
# 0100 01ff fffc cc01 ssss sddd dd01 0001
|
|
:movt.S fd, fs, cc is $(AMODE) & REL6=0 & prime=17 & nd=0 & tf=1 & fct=17 & fmt1 & fd & fs & cc & format=0x10 {
|
|
# Move if FP condition flag is true
|
|
tmp:1 = fcsr[23,1];
|
|
if (tmp != 1) goto <done>;
|
|
fd[0,32] = fs:4;
|
|
<done>
|
|
}
|
|
:movt.D fd, fs, cc is $(AMODE) & REL6=0 & prime=17 & nd=0 & tf=1 & fct=17 & fmt1 & fd & fs & cc & format=0x11 & fdD & fsD {
|
|
# Move if FP condition flag is true
|
|
tmp:1 = fcsr[23,1];
|
|
if (tmp != 1) goto <done>;
|
|
fdD = fsD;
|
|
<done>
|
|
}
|
|
:movt.PS fd, fs, cc is $(AMODE) & REL6=0 & prime=17 & nd=0 & tf=1 & fct=17 & fmt1 & fd & fs & cc & format=0x16 & fsD & ftD & fdD {
|
|
fdD = mipsFloatPS(fsD, ftD);
|
|
}
|
|
|
|
# 0100 01ff ffft tttt ssss sddd dd01 0010
|
|
:movz.S fd, fs, RTsrc is $(AMODE) & REL6=0 & prime=17 & fct=18 & fmt1 & fd & fs & RTsrc & format=0x10 {
|
|
if (RTsrc != 0) goto <done>;
|
|
fd[0,32] = fs:4;
|
|
<done>
|
|
}
|
|
:movz.D fd, fs, RTsrc is $(AMODE) & REL6=0 & prime=17 & fct=18 & fmt1 & fd & fs & RTsrc & format=0x11 & fdD & fsD {
|
|
if (RTsrc != 0) goto <done>;
|
|
fdD = fsD;
|
|
<done>
|
|
}
|
|
:movz.PS fd, fs, RTsrc is $(AMODE) & REL6=0 & prime=17 & fct=18 & fmt1 & fd & fs & RTsrc & format=0x16 & fsD & fdD {
|
|
fdD = mipsFloatPS(RTsrc, fsD);
|
|
}
|
|
|
|
####
|
|
#
|
|
# Release 6 semantics
|
|
#
|
|
####
|
|
:bc1eqz ft,Rel16 is $(AMODE) & REL6=1 & prime=0x11 & format=0x09 & Rel16 & ft {
|
|
# Branch if FPR ft LSB equals 0 (false) (This insn replaces bc1f)
|
|
tmp:1 = ft[0,8] & 0x01; # Only need to check the LSB
|
|
delayslot(1);
|
|
if (tmp == 0x00) goto Rel16;
|
|
}
|
|
|
|
:bc1nez ft,Rel16 is $(AMODE) & REL6=1 & prime=0x11 & format=0x0d & Rel16 & ft & ftD {
|
|
# Branch if FPR ft LSB equals 1 (true) (This insn replaces bc1t)
|
|
tmp:1 = ft[0,8] & 0x01; # Only need to check the LSB
|
|
delayslot(1);
|
|
if (tmp == 0x01) goto Rel16;
|
|
}
|
|
|
|
:class.S fd,fs is $(AMODE) & REL6=1 & prime=0x11 & format=0x10 & op=0x00 & fct=0x1b & fd & fs {
|
|
# Set fd to the 10-bit mask that is the IEEE floating point class of the value in fs
|
|
# Bit 0: signaling SNaN
|
|
# Bit 1: quiet QNaN
|
|
# Bit 2: negative infinity
|
|
|
|
# Bit 3: negative normalized number
|
|
# Bit 4: negative subnormal, ie denormalized
|
|
# Bit 5: negative zero
|
|
# Bit 6: positive infinity
|
|
# Bit 7: positive normal
|
|
# Bit 8: positive subnormal
|
|
# Bit 9: positive zero
|
|
# Bits 31-10 are set to 0
|
|
|
|
tmp_fs:4 = fs:4; # Get just the 4 byte single floating point value
|
|
tmp_exponent:4 = zext(tmp_fs[23,8]);
|
|
tmp_fraction:4 = zext(tmp_fs[0,23]);
|
|
tmp_sign:4 = zext(tmp_fs[31,1]);
|
|
tmp_b1:4 = zext(tmp_fs[22,1]); # High order bit of fraction, used for NaN
|
|
|
|
tmp_SNaN:4 = zext((tmp_exponent == 0x0ff) && (tmp_fraction != 0x0) && (tmp_b1 == 0x0));
|
|
tmp_QNaN:4 = zext((tmp_exponent == 0x0ff) && (tmp_fraction != 0x0) && (tmp_b1 == 0x01));
|
|
tmp_Neg_Infinity:4 = zext((tmp_sign == 0x01) && (tmp_exponent == 0x0ff) && (tmp_fraction == 0x0));
|
|
tmp_Neg_Normal:4 = zext((tmp_sign == 0x01) && (tmp_exponent != 0x0) && (tmp_exponent != 0x0ff));
|
|
tmp_Neg_Subnormal:4 = zext((tmp_sign == 0x01) && (tmp_exponent == 0x0) && (tmp_fraction != 0x0));
|
|
tmp_Neg_Zero:4 = zext((tmp_sign == 0x01) && (tmp_exponent == 0x0) && (tmp_fraction == 0x0));
|
|
tmp_Pos_Infinity:4 = zext((tmp_sign == 0x0) && (tmp_exponent == 0x0ff) && (tmp_fraction == 0x0));
|
|
tmp_Pos_Normal:4 = zext((tmp_sign == 0x0) && (tmp_exponent != 0x0) && (tmp_exponent != 0x0ff));
|
|
tmp_Pos_Subnormal:4 = zext((tmp_sign == 0x0) && (tmp_exponent == 0x0) && (tmp_fraction != 0x0));
|
|
tmp_Pos_Zero:4 = zext((tmp_sign == 0x0) && (tmp_exponent == 0x0) && (tmp_fraction == 0x0));
|
|
|
|
tmp_fd:4 = 0;
|
|
tmp_fd = tmp_SNaN | (tmp_QNaN << 1) | (tmp_Neg_Infinity << 2) | (tmp_Neg_Normal << 3) |
|
|
(tmp_Neg_Subnormal << 4) | (tmp_Neg_Zero << 5) | (tmp_Pos_Infinity << 6) |
|
|
(tmp_Pos_Normal << 7) | (tmp_Pos_Subnormal << 8) | (tmp_Pos_Zero << 9);
|
|
|
|
fd = zext(tmp_fd);
|
|
}
|
|
|
|
:class.D fd,fs is $(AMODE) & REL6=1 & prime=0x11 & format=0x11 & op=0x00 & fct=0x1b & fd & fs & fdD & fsD {
|
|
# Set fd to the 10-bit mask that is the IEEE floating point class of the value in fs
|
|
# Bit 0: signaling SNaN
|
|
# Bit 1: quiet QNaN
|
|
# Bit 2: negative infinity
|
|
# Bit 3: negative normalized number
|
|
# Bit 4: negative subnormal, ie denormalized
|
|
# Bit 5: negative zero
|
|
# Bit 6: positive infinity
|
|
# Bit 7: positive normal
|
|
# Bit 8: positive subnormal
|
|
# Bit 9: positive zero
|
|
# Bits 31-10 are set to 0
|
|
|
|
tmp_fs:8 = fsD;
|
|
tmp_sign:4 = zext(tmp_fs[63,1]);
|
|
tmp_exponent:4 = zext(tmp_fs[52,11]);
|
|
tmp_fraction:8 = zext(tmp_fs[0,51]);
|
|
tmp_b1:4 = zext(tmp_fs[51,1]); # High order bit of fraction, used for NaN
|
|
|
|
tmp_SNaN:4 = zext((tmp_exponent == 0x07ff) && (tmp_fraction != 0x0) && (tmp_b1 == 0x0));
|
|
tmp_QNaN:4 = zext((tmp_exponent == 0x07ff) && (tmp_fraction != 0x0) && (tmp_b1 == 0x01));
|
|
tmp_Neg_Infinity:4 = zext((tmp_sign == 0x01) && (tmp_exponent == 0x07ff) && (tmp_fraction == 0x0));
|
|
tmp_Neg_Normal:4 = zext((tmp_sign == 0x01) && (tmp_exponent != 0x0) && (tmp_exponent != 0x07ff));
|
|
tmp_Neg_Subnormal:4 = zext((tmp_sign == 0x01) && (tmp_exponent == 0x0) && (tmp_fraction != 0x0));
|
|
tmp_Neg_Zero:4 = zext((tmp_sign == 0x01) && (tmp_exponent == 0x0) && (tmp_fraction == 0x0));
|
|
tmp_Pos_Infinity:4 = zext((tmp_sign == 0x0) && (tmp_exponent == 0x07ff) && (tmp_fraction == 0x0));
|
|
tmp_Pos_Normal:4 = zext((tmp_sign == 0x0) && (tmp_exponent != 0x0) && (tmp_exponent != 0x07ff));
|
|
tmp_Pos_Subnormal:4 = zext((tmp_sign == 0x0) && (tmp_exponent == 0x0) && (tmp_fraction != 0x0));
|
|
tmp_Pos_Zero:4 = zext((tmp_sign == 0x0) && (tmp_exponent == 0x0) && (tmp_fraction == 0x0));
|
|
|
|
tmp_fd:4 = 0;
|
|
tmp_fd = tmp_SNaN | (tmp_QNaN << 1) | (tmp_Neg_Infinity << 2) | (tmp_Neg_Normal << 3) |
|
|
(tmp_Neg_Subnormal << 4) | (tmp_Neg_Zero << 5) | (tmp_Pos_Infinity << 6) |
|
|
(tmp_Pos_Normal << 7) | (tmp_Pos_Subnormal << 8) | (tmp_Pos_Zero << 9);
|
|
|
|
fdD = zext(tmp_fd);
|
|
}
|
|
|
|
:sel.S fd,fs,ft is $(AMODE) & REL6=1 & prime=0x11 & format=0x10 & fct=0x10 & fd & fs & ft {
|
|
# Floating point select, if LSB of fd == 1 then fd = ft, else fd = fs
|
|
# Note that the data in the FPRs might be 32-bit ints, ie there's no interpretation of the values
|
|
tmp:1 = (fd[0,1] == 0x01);
|
|
fd = (zext(tmp) * ft) | (zext(tmp == 0x0) * fs);
|
|
}
|
|
:sel.D fd,fs,ft is $(AMODE) & REL6=1 & prime=0x11 & format=0x11 & fct=0x10 & fd & fs & ft & fdD & fsD & ftD {
|
|
# Floating point select, if LSB of fd == 1 then fd = ft, else fd = fs
|
|
# Note that the data in the FPRs might be 64-bit ints, ie there's no interpretation of the values
|
|
tmp:1 = (fdD[0,1] == 0x01);
|
|
fdD = (zext(tmp) * ftD) | (zext(tmp == 0x0) * fsD);
|
|
}
|
|
|
|
#
|
|
# The R6 floating point compare cmp instruction is described on page 146 of the
|
|
# MIPS64 Architecture Volume II ISA manual
|
|
#
|
|
# Note that when the condition is true the target FPR is set to all ones, and to 0 if false.
|
|
# If the target is 32-bit and you have 64-bit FPRs, then setting the top word is optional
|
|
#
|
|
# Note that when the format is Single and you have 64-bit FPRS,
|
|
# then you need to first pull out the 32-bit float word and then pass that to the correct p-code
|
|
#
|
|
# TBD: Note that when fct bits 5 and 4 (left most 2 bits) are 01 then the condition is negated
|
|
#
|
|
|
|
:cmp.af.S fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x00 & bit5=0 & fmt6 & format=0x14 & fd & fs & ft {
|
|
trapIfSNaN(fs:4, ft:4); # Trap if either operand is a Signaling NaN
|
|
fd = 0x0; # Always false
|
|
}
|
|
:cmp.af.D fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x00 & bit5=0 & fmt6 & format=0x15 & fd & fdD & fs & ft & fsD & ftD {
|
|
trapIfSNaN(fsD, ftD);
|
|
fdD = 0x0;
|
|
}
|
|
|
|
:cmp.un.S fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x01 & bit5=0 & fmt6 & format=0x14 & fd & fs & ft {
|
|
trapIfSNaN(fs:4, ft:4);
|
|
fd[0,32] = sext((nan(fs:4) || nan(ft:4)) * 0xff); # True if operands are NaN
|
|
}
|
|
:cmp.un.D fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x01 & bit5=0 & fmt6 & format=0x15 & fd & fdD & fs & fsD & ft & ftD {
|
|
trapIfSNaN(fsD, ftD);
|
|
fdD = sext((nan(fsD) || nan(ftD)) * 0xff);
|
|
}
|
|
|
|
:cmp.or.S fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x11 & bit5=0 & fmt6 & format=0x14 & fd & fs & ft {
|
|
trapIfSNaN(fs:4, ft:4);
|
|
fd[0,32] = sext( (!(nan(fs:4) || nan(ft:4))) * 0xff); # The negated predicate of "c.un"
|
|
}
|
|
:cmp.or.D fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x11 & bit5=0 & fmt6 & format=0x15 & fd & fdD & fs & fsD & ft & ftD {
|
|
trapIfSNaN(fsD, ftD);
|
|
fdD = sext( (!(nan(fsD) || nan(ftD))) * 0xff);
|
|
}
|
|
|
|
:cmp.eq.S fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x02 & bit5=0 & fmt6 & format=0x14 & fd & fs & ft {
|
|
trapIfSNaN(fs:4, ft:4);
|
|
fd[0,32] = sext((fs:4 f== ft:4) * 0xff);
|
|
}
|
|
:cmp.eq.D fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x02 & bit5=0 & fmt6 & format=0x15 & fd & fdD & fs & fsD & ft & ftD {
|
|
trapIfSNaN(fsD, ftD);
|
|
fdD = sext((fsD f== ftD) * 0xff);
|
|
}
|
|
|
|
:cmp.une.S fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x12 & bit5=0 & fmt6 & format=0x14 & fd & fs & ft {
|
|
# The negated predicate of cmp.eq
|
|
trapIfSNaN(fs:4, ft:4);
|
|
fd[0,32] = sext((fs:4 f!= ft:4) * 0xff);
|
|
}
|
|
:cmp.une.D fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x12 & bit5=0 & fmt6 & format=0x15 & fd & fdD & fs & fsD & ft & ftD {
|
|
trapIfSNaN(fsD, ftD);
|
|
fdD = sext((fsD f!= ftD) * 0xff);
|
|
}
|
|
|
|
:cmp.ueq.S fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x03 & bit5=0 & fmt6 & format=0x14 & fd & fs & ft {
|
|
# NaN or equal
|
|
trapIfSNaN(fs:4, ft:4);
|
|
fd[0,32] = sext( ( nan(fs:4) || nan(ft:4) || (fs:4 f== ft:4) ) * 0xff);
|
|
}
|
|
:cmp.ueq.D fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x03 & bit5=0 & fmt6 & format=0x15 & fd & fdD & fs & fsD & ft & ftD {
|
|
trapIfSNaN(fsD, ftD);
|
|
fdD = sext( ( nan(fsD) || nan(ftD) || (fsD f== ftD) ) * 0xff);
|
|
}
|
|
|
|
:cmp.ne.S fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x13 & bit5=0 & fmt6 & format=0x14 & fd & fs & ft {
|
|
# The negated predicate of cmp.ueq
|
|
trapIfSNaN(fs:4, ft:4);
|
|
fd[0,32] = sext( (!( ( nan(fs:4) || nan(ft:4) || (fs:4 f== ft:4) ))) * 0xff);
|
|
}
|
|
:cmp.ne.D fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x13 & bit5=0 & fmt6 & format=0x15 & fd & fdD & fs & fsD & ft & ftD {
|
|
trapIfSNaN(fsD, ftD);
|
|
fdD = sext( (!( ( nan(fsD) || nan(ftD) || (fsD f== ftD) ))) * 0xff);
|
|
}
|
|
|
|
:cmp.lt.S fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x04 & bit5=0 & fmt6 & format=0x14 & fd & fs & ft {
|
|
trapIfSNaN(fs:4, ft:4);
|
|
fd[0,32] = sext((fs:4 f< ft:4) * 0xff);
|
|
}
|
|
:cmp.lt.D fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x04 & bit5=0 & fmt6 & format=0x15 & fd & fdD & fs & fsD & ft & ftD {
|
|
trapIfSNaN(fsD, ftD);
|
|
fdD = sext((fsD f< ftD) * 0xff);
|
|
}
|
|
|
|
:cmp.ult.S fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x05 & bit5=0 & fmt6 & format=0x14 & fd & fs & ft {
|
|
# NaN or less than
|
|
trapIfSNaN(fs:4, ft:4);
|
|
fd[0,32] = sext( ( nan(fs:4) || nan(ft:4) || (fs:4 f< ft:4) ) * 0xff);
|
|
}
|
|
:cmp.ult.D fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x05 & bit5=0 & fmt6 & format=0x15 & fd & fdD & fs & fsD & ft & ftD {
|
|
trapIfSNaN(fsD, ftD);
|
|
fdD = sext( ( nan(fsD) || nan(ftD) || (fsD f< ftD) ) * 0xff);
|
|
}
|
|
|
|
:cmp.le.S fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x06 & bit5=0 & fmt6 & format=0x14 & fd & fs & ft {
|
|
# Less than or equal
|
|
trapIfSNaN(fs:4, ft:4);
|
|
fd[0,32] = sext((fs:4 f<= ft:4) * 0xff);
|
|
}
|
|
:cmp.le.D fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x06 & bit5=0 & fmt6 & format=0x15 & fd & fdD & fs & fsD & ft & ftD {
|
|
trapIfSNaN(fsD, ftD);
|
|
fdD = sext((fsD f<= ftD) * 0xff);
|
|
}
|
|
|
|
:cmp.ule.S fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x07 & bit5=0 & fmt6 & format=0x14 & fd & fs & ft {
|
|
# NaN or less than or equal
|
|
trapIfSNaN(fs:4, ft:4);
|
|
fd[0,32] = sext( ( nan(fs:4) || nan(ft:4) || (fs:4 f<= ft:4) ) * 0xff);
|
|
}
|
|
:cmp.ule.D fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x07 & bit5=0 & fmt6 & format=0x15 & fd & fdD & fs & fsD & ft & ftD {
|
|
trapIfSNaN(fsD, ftD);
|
|
fdD = sext( ( nan(fsD) || nan(ftD) || (fsD f<= ftD) ) * 0xff);
|
|
}
|
|
|
|
# The cmp instructions that signal (ie trap) if either of the operands are NaN
|
|
|
|
:cmp.saf.S fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x08 & bit5=0 & fmt6 & format=0x14 & fd & fs & ft {
|
|
trapIfNaN(fs:4, ft:4);
|
|
fd = 0x0; # Always false
|
|
}
|
|
:cmp.saf.D fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x08 & bit5=0 & fmt6 & format=0x15 & fd & fdD & fs & fsD & ft & ftD {
|
|
trapIfNaN(fsD, ftD);
|
|
fdD = 0x0;
|
|
}
|
|
|
|
:cmp.sun.S fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x09 & bit5=0 & fmt6 & format=0x14 & fd & fdD & fs & fsD & ft & ftD {
|
|
trapIfNaN(fs:4, ft:4);
|
|
fd[0,32] = sext((nan(fs:4) || nan(ft:4)) * 0xff);
|
|
}
|
|
:cmp.sun.D fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x09 & bit5=0 & fmt6 & format=0x15 & fd & fdD & fs & fsD & ft & ftD {
|
|
trapIfNaN(fsD, ftD);
|
|
fdD = sext((nan(fsD) || nan(ftD)) * 0xff);
|
|
}
|
|
|
|
:cmp.sor.S fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x19 & bit5=0 & fmt6 & format=0x14 & fd & fdD & fs & fsD & ft & ftD {
|
|
trapIfNaN(fs:4, ft:4);
|
|
fd[0,32] = sext( (!(nan(fs:4) || nan(ft:4))) * 0xff); # negate of cmp.sun
|
|
}
|
|
:cmp.sor.D fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x19 & bit5=0 & fmt6 & format=0x15 & fd & fdD & fs & fsD & ft & ftD {
|
|
trapIfNaN(fsD, ftD);
|
|
fdD = sext( (!(nan(fsD) || nan(ftD))) * 0xff);
|
|
}
|
|
|
|
:cmp.seq.S fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x0a & bit5=0 & fmt6 & format=0x14 & fd & fs & ft {
|
|
trapIfNaN(fs:4, ft:4);
|
|
fd[0,32] = sext((fs:4 f== ft:4) * 0xff);
|
|
}
|
|
:cmp.seq.D fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x0a & bit5=0 & fmt6 & format=0x15 & fd & fdD & fs & fsD & ft & ftD {
|
|
trapIfNaN(fsD, ftD);
|
|
fdD = sext((fsD f== ftD) * 0xff);
|
|
}
|
|
|
|
:cmp.sune.S fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x1a & bit5=0 & fmt6 & format=0x14 & fd & fs & ft {
|
|
trapIfNaN(fs:4, ft:4);
|
|
fd[0,32] = sext((fs:4 f!= ft:4) * 0xff);
|
|
}
|
|
:cmp.sune.D fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x1a & bit5=0 & fmt6 & format=0x15 & fd & fdD & fs & fsD & ft & ftD {
|
|
trapIfNaN(fsD, ftD);
|
|
fdD = sext((fsD f!= ftD) * 0xff);
|
|
}
|
|
|
|
:cmp.sueq.S fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x0b & bit5=0 & fmt6 & format=0x14 & fd & fs & ft {
|
|
# NaN or equal
|
|
trapIfNaN(fs:4, ft:4);
|
|
fd[0,32] = sext( ( nan(fs:4) || nan(ft:4) || (fs:4 f== ft:4) ) * 0xff);
|
|
}
|
|
:cmp.sueq.D fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x0b & bit5=0 & fmt6 & format=0x15 & fd & fdD & fs & fsD & ft & ftD {
|
|
trapIfNaN(fsD, ftD);
|
|
fdD = sext( ( nan(fsD) || nan(ftD) || (fsD f== ftD) ) * 0xff);
|
|
}
|
|
|
|
:cmp.sne.S fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x1b & bit5=0 & fmt6 & format=0x14 & fd & fs & ft {
|
|
trapIfNaN(fs:4, ft:4); # negate of cmp.sueq
|
|
fd[0,32] = sext( (! ( nan(fs:4) || nan(ft:4) || (fs:4 f== ft:4) )) * 0xff);
|
|
}
|
|
:cmp.sne.D fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x1b & bit5=0 & fmt6 & format=0x15 & fd & fdD & fs & fsD & ft & ftD {
|
|
trapIfNaN(fsD, ftD);
|
|
fdD = sext( (! ( nan(fsD) || nan(ftD) || (fsD f== ftD) )) * 0xff);
|
|
}
|
|
|
|
:cmp.slt.S fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x0c & bit5=0 & fmt6 & format=0x14 & fd & fs & ft {
|
|
trapIfNaN(fs:4, ft:4);
|
|
fd[0,32] = sext( (fs:4 f< ft:4) * 0xff);
|
|
}
|
|
:cmp.slt.D fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x0c & bit5=0 & fmt6 & format=0x15 & fd & fdD & fs & fsD & ft & ftD {
|
|
trapIfNaN(fsD, ftD);
|
|
fdD = sext( (fsD f< ftD) * 0xff);
|
|
}
|
|
|
|
:cmp.sult.S fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x0d & bit5=0 & fmt6 & format=0x14 & fd & fs & ft {
|
|
trapIfNaN(fs:4, ft:4);
|
|
fd[0,32] = sext( ( nan(fs:4) || nan(ft:4) || (fs:4 f< ft:4) ) * 0xff);
|
|
}
|
|
:cmp.sult.D fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x0d & bit5=0 & fmt6 & format=0x15 & fd & fdD & fs & fsD & ft & ftD {
|
|
trapIfNaN(fsD, ftD);
|
|
fdD = sext( ( nan(fsD) || nan(ftD) || (fsD f< ftD) ) * 0xff);
|
|
}
|
|
|
|
:cmp.sle.S fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x0e & bit5=0 & fmt6 & format=0x14 & fd & fs & ft {
|
|
trapIfNaN(fs:4, ft:4);
|
|
fd[0,32] = sext( (fs:4 f<= ft:4) * 0xff);
|
|
}
|
|
:cmp.sle.D fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x0e & bit5=0 & fmt6 & format=0x15 & fd & fdD & fs & fsD & ft & ftD {
|
|
trapIfNaN(fsD, ftD);
|
|
fdD = sext( (fsD f<= ftD) * 0xff);
|
|
}
|
|
|
|
:cmp.sule.S fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x0f & bit5=0 & fmt6 & format=0x14 & fd & fs & ft {
|
|
trapIfNaN(fs:4, ft:4);
|
|
fd[0,32] = sext( ( nan(fs:4) || nan(ft:4) || (fs:4 f<= ft:4) ) * 0xff);
|
|
}
|
|
:cmp.sule.D fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & fct=0x0f & bit5=0 & fmt6 & format=0x15 & fd & fdD & fs & fsD & ft & ftD {
|
|
trapIfNaN(fsD, ftD);
|
|
fdD = sext( ( nan(fsD) || nan(ftD) || (fsD f<= ftD) ) * 0xff);
|
|
}
|
|
|
|
:rint.S fd, fs is $(AMODE) & REL6=1 & prime=0x11 & format=0x10 & cop1code=0x0 & fs & fd & fct=0x1a {
|
|
# floating point round to integral floating point
|
|
rm_tmp:1 = fcsr[0,2]; # Get RM rounding mode bits
|
|
fs_tmp:4 = fs:4;
|
|
if (rm_tmp == 0) goto <do_round>;
|
|
fd[0,32] = floor(fs_tmp); # RM is 1, no rounding, and floor returns a float
|
|
goto <done>;
|
|
<do_round>
|
|
fd[0,32] = round(fs_tmp); # round returns a float
|
|
<done>
|
|
}
|
|
|
|
:rint.D fd, fs is $(AMODE) & REL6=1 & prime=0x11 & format=0x11 & cop1code=0x0 & fs & fd & fsD & fdD & fct=0x1a {
|
|
# floating point round to integral floating point
|
|
rm_tmp:1 = fcsr[0,2]; # Get RM rounding mode bits
|
|
if (rm_tmp == 0) goto <do_round>;
|
|
fdD = floor(fsD); # RM is 1, no rounding, and floor returns a float
|
|
goto <done>;
|
|
<do_round>
|
|
fdD = round(fsD); # round returns a float
|
|
<done>
|
|
}
|
|
|
|
:min.S fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & format=0x10 & cop1code=0x0 & fs & fd & ft & fct=0x1c {
|
|
# set floating point fd to the min of fs and ft, TBD special case for NaN
|
|
tmp_cond:1 = fs:4 f< ft:4;
|
|
fd[0,32] = (fs:4 * zext(tmp_cond == 1)) | (ft:4 * zext(tmp_cond == 0) );
|
|
}
|
|
:min.D fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & format=0x11 & cop1code=0x0 & fs & fd & ft & fct=0x1c
|
|
& fsD & fdD & ftD {
|
|
tmp_cond:1 = fsD f< ftD;
|
|
fdD = zext( (fsD * zext(tmp_cond == 1)) | (ftD * zext(tmp_cond == 0) ) );
|
|
}
|
|
|
|
:max.S fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & format=0x10 & cop1code=0x0 & fs & fd & ft & fct=0x1d {
|
|
# set floating point fd to the max of fs and ft, TBD special case for NaN
|
|
tmp_cond:1 = fs:4 f> ft:4;
|
|
fd[0,32] = (fs:4 * zext(tmp_cond == 1)) | (ft:4 * zext(tmp_cond == 0) );
|
|
}
|
|
:max.D fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & format=0x11 & cop1code=0x0 & fs & fd & ft & fct=0x1d
|
|
& fsD & fdD & ftD {
|
|
tmp_cond:1 = fsD f> ftD;
|
|
fdD = zext( (fsD * zext(tmp_cond == 1)) | (ftD * zext(tmp_cond == 0) ) );
|
|
}
|
|
|
|
:mina.S fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & format=0x10 & cop1code=0x0 & fs & fd & ft & fct=0x1e {
|
|
# set floating point fd to the min of absolute values of fs and ft, TBD special case for NaN
|
|
tmp_cond:1 = abs(fs:4) f< abs(ft:4);
|
|
fd[0,32] = (fs:4 * zext(tmp_cond == 1)) | (ft:4 * zext(tmp_cond == 0) );
|
|
}
|
|
:mina.D fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & format=0x11 & cop1code=0x0 & fs & fd & ft & fct=0x1e
|
|
& fsD & fdD & ftD {
|
|
tmp_cond:1 = abs(fsD) f< abs(ftD);
|
|
fdD = zext( (fsD * zext(tmp_cond == 1)) | (ftD * zext(tmp_cond == 0) ) );
|
|
}
|
|
|
|
:maxa.S fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & format=0x10 & cop1code=0x0 & fs & fd & ft & fct=0x1f {
|
|
# set floating point fd to the max of absolute values of fs and ft, TBD special case for NaN
|
|
tmp_cond:1 = abs(fs:4) f> abs(ft:4);
|
|
fd[0,32] = (fs:4 * zext(tmp_cond == 1)) | (ft:4 * zext(tmp_cond == 0) );
|
|
}
|
|
:maxa.D fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & format=0x11 & cop1code=0x0 & fs & fd & ft & fct=0x1f
|
|
& fsD & fdD & ftD {
|
|
tmp_cond:1 = abs(fsD) f> abs(ftD);
|
|
fdD = zext( (fsD * zext(tmp_cond == 1)) | (ftD * zext(tmp_cond == 0) ) );
|
|
}
|
|
|
|
:maddf.S fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & format=0x10 & cop1code=0x0 & fs & fd & ft & fct=0x18 {
|
|
# set floating point fd = fd + fs * ft, using 32-bit floating values
|
|
fd[0,32] = fd:4 f+ (fs:4 f* ft:4);
|
|
}
|
|
:maddf.D fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & format=0x11 & cop1code=0x0 & fs & fd & ft & fct=0x18
|
|
& fsD & fdD & ftD {
|
|
fdD = fdD f+ (fsD f* ftD);
|
|
}
|
|
|
|
:msubf.S fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & format=0x10 & cop1code=0x0 & fs & fd & ft & fct=0x19 {
|
|
# set floating point fd = fd - fs * ft, using 32-bit floating values
|
|
fd[0,32] = fd:4 f- (fs:4 f* ft:4);
|
|
}
|
|
:msubf.D fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & format=0x11 & cop1code=0x0 & fs & fd & ft & fct=0x19
|
|
& fsD & fdD & ftD {
|
|
fdD = fdD f- (fsD f* ftD);
|
|
}
|
|
|
|
:seleqz.S fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & format=0x10 & cop1code=0x0 & fs & fd & ft & fct=0x14 {
|
|
# Set floating point register fd to fs if ft[0] == 0, else if == 1 then set fd to 0, TBD special case for NaN
|
|
# Note that the description of these select instructions in the MIPS manual does not properly use the C conditional operator
|
|
fd = zext(fs * zext(ft[0,1] == 0));
|
|
}
|
|
:seleqz.D fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & format=0x11 & cop1code=0x0 & fs & fd & ft & fct=0x14
|
|
& fsD & fdD & ftD {
|
|
fdD = zext(fsD * zext(ftD[0,1] == 0));
|
|
}
|
|
|
|
:selnez.S fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & format=0x10 & cop1code=0x0 & fs & fd & ft & fct=0x17 {
|
|
# set floating point register fd to fs if ft[0] == 1, else if == 0 then set fd to 0, TBD special case for NaN
|
|
fd = zext(fs * zext(ft[0,1] == 1));
|
|
}
|
|
:selnez.D fd, fs, ft is $(AMODE) & REL6=1 & prime=0x11 & format=0x11 & cop1code=0x0 & fs & fd & ft & fct=0x17
|
|
& fsD & fdD & ftD {
|
|
fdD = zext(fsD * zext(ftD[0,1] == 1));
|
|
}
|