Index: src/mips/simulator-mips.cc |
diff --git a/src/mips/simulator-mips.cc b/src/mips/simulator-mips.cc |
index c2ac415d5723921ee7bfcc1e2e04d24394cb8e9c..6a34cb365106a5ac618b3dfa5e8196ec136c2381 100644 |
--- a/src/mips/simulator-mips.cc |
+++ b/src/mips/simulator-mips.cc |
@@ -2137,15 +2137,20 @@ void Simulator::DecodeTypeRegisterDRsType(Instruction* instr, |
const int32_t& fs_reg, |
const int32_t& ft_reg, |
const int32_t& fd_reg) { |
- double ft, fs; |
+ double ft, fs, fd; |
uint32_t cc, fcsr_cc; |
int64_t i64; |
fs = get_fpu_register_double(fs_reg); |
ft = get_fpu_register_double(ft_reg); |
- int64_t ft_int = static_cast<int64_t>(ft); |
+ int64_t ft_int = bit_cast<int64_t>(ft); |
+ int64_t fd_int = bit_cast<int64_t>(fd); |
cc = instr->FCccValue(); |
fcsr_cc = get_fcsr_condition_bit(cc); |
switch (instr->FunctionFieldRaw()) { |
+ case SEL: |
+ DCHECK(IsMipsArchVariant(kMips32r6)); |
+ set_fpu_register_double(fd_reg, (fd_int & 0x1) == 0 ? fs : ft); |
+ break; |
case SELEQZ_C: |
DCHECK(IsMipsArchVariant(kMips32r6)); |
set_fpu_register_double(fd_reg, (ft_int & 0x1) == 0 ? fs : 0.0); |
@@ -2154,6 +2159,33 @@ void Simulator::DecodeTypeRegisterDRsType(Instruction* instr, |
DCHECK(IsMipsArchVariant(kMips32r6)); |
set_fpu_register_double(fd_reg, (ft_int & 0x1) != 0 ? fs : 0.0); |
break; |
+ case MIN: |
+ DCHECK(IsMipsArchVariant(kMips32r6)); |
+ fs = get_fpu_register_double(fs_reg); |
+ if (std::isnan(fs) && std::isnan(ft)) { |
+ set_fpu_register_double(fd_reg, fs); |
+ } else if (std::isnan(fs) && !std::isnan(ft)) { |
+ set_fpu_register_double(fd_reg, ft); |
+ } else if (!std::isnan(fs) && std::isnan(ft)) { |
+ set_fpu_register_double(fd_reg, fs); |
+ } else { |
+ set_fpu_register_double(fd_reg, (fs >= ft) ? ft : fs); |
+ } |
+ break; |
+ case MAX: |
+ DCHECK(IsMipsArchVariant(kMips32r6)); |
+ fs = get_fpu_register_double(fs_reg); |
+ if (std::isnan(fs) && std::isnan(ft)) { |
+ set_fpu_register_double(fd_reg, fs); |
+ } else if (std::isnan(fs) && !std::isnan(ft)) { |
+ set_fpu_register_double(fd_reg, ft); |
+ } else if (!std::isnan(fs) && std::isnan(ft)) { |
+ set_fpu_register_double(fd_reg, fs); |
+ } else { |
+ set_fpu_register_double(fd_reg, (fs <= ft) ? ft : fs); |
+ } |
+ break; |
+ break; |
case ADD_D: |
set_fpu_register_double(fd_reg, fs + ft); |
break; |