MIPS: Major fixes and clean-up in asm. for instruction encoding.
authordusan.milosavljevic <dusan.milosavljevic@imgtec.com>
Mon, 6 Apr 2015 11:54:38 +0000 (04:54 -0700)
committerCommit bot <commit-bot@chromium.org>
Mon, 6 Apr 2015 11:54:38 +0000 (11:54 +0000)
- Fixed single float register type instruction en[de]coding in assembler and disassembler.
- Added max and min instructions for r6 and corresponding tests.
- Fixed selection instruction for boundary cases in simulator.
- Update assembler tests to be more thorough wrt boundary cases.

TEST=cctest/test-assembler-mips64/MIPS17, MIPS18
     cctest/test-disasm-mips64/Type1
     cctest/test-assembler-mips/MIPS16, MIPS17
     cctest/test-disasm-mips/Type1
BUG=

Review URL: https://codereview.chromium.org/1057323002

Cr-Commit-Position: refs/heads/master@{#27601}

14 files changed:
src/mips/assembler-mips.cc
src/mips/assembler-mips.h
src/mips/constants-mips.cc
src/mips/disasm-mips.cc
src/mips/simulator-mips.cc
src/mips64/assembler-mips64.cc
src/mips64/assembler-mips64.h
src/mips64/disasm-mips64.cc
src/mips64/simulator-mips64.cc
src/mips64/simulator-mips64.h
test/cctest/test-assembler-mips.cc
test/cctest/test-assembler-mips64.cc
test/cctest/test-disasm-mips.cc
test/cctest/test-disasm-mips64.cc

index 1955d5349a89589d9e84850380aedfc7211159a9..769abdb9465e10b6753531381d91b8d6e9eeb22b 100644 (file)
@@ -1903,28 +1903,39 @@ void Assembler::movf(Register rd, Register rs, uint16_t cc) {
 }
 
 
-void Assembler::seleqz(Register rs, Register rt, Register rd) {
+void Assembler::sel(SecondaryField fmt, FPURegister fd, FPURegister fs,
+                    FPURegister ft) {
+  DCHECK(IsMipsArchVariant(kMips32r6));
+  DCHECK((fmt == D) || (fmt == S));
+
+  Instr instr = COP1 | fmt << kRsShift | ft.code() << kFtShift |
+                fs.code() << kFsShift | fd.code() << kFdShift | SEL;
+  emit(instr);
+}
+
+
+void Assembler::seleqz(Register rd, Register rs, Register rt) {
   DCHECK(IsMipsArchVariant(kMips32r6));
   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SELEQZ_S);
 }
 
 
-void Assembler::seleqz(SecondaryField fmt, FPURegister fd, FPURegister ft,
-                       FPURegister fs) {
+void Assembler::seleqz(SecondaryField fmt, FPURegister fd, FPURegister fs,
+                       FPURegister ft) {
   DCHECK(IsMipsArchVariant(kMips32r6));
   DCHECK((fmt == D) || (fmt == S));
   GenInstrRegister(COP1, fmt, ft, fs, fd, SELEQZ_C);
 }
 
 
-void Assembler::selnez(Register rs, Register rt, Register rd) {
+void Assembler::selnez(Register rd, Register rs, Register rt) {
   DCHECK(IsMipsArchVariant(kMips32r6));
   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SELNEZ_S);
 }
 
 
-void Assembler::selnez(SecondaryField fmt, FPURegister fd, FPURegister ft,
-                       FPURegister fs) {
+void Assembler::selnez(SecondaryField fmt, FPURegister fd, FPURegister fs,
+                       FPURegister ft) {
   DCHECK(IsMipsArchVariant(kMips32r6));
   DCHECK((fmt == D) || (fmt == S));
   GenInstrRegister(COP1, fmt, ft, fs, fd, SELNEZ_C);
@@ -2244,32 +2255,32 @@ void Assembler::ceil_l_d(FPURegister fd, FPURegister fs) {
 }
 
 
-void Assembler::min(SecondaryField fmt, FPURegister fd, FPURegister ft,
-    FPURegister fs) {
+void Assembler::min(SecondaryField fmt, FPURegister fd, FPURegister fs,
+                    FPURegister ft) {
   DCHECK(IsMipsArchVariant(kMips32r6));
   DCHECK((fmt == D) || (fmt == S));
   GenInstrRegister(COP1, fmt, ft, fs, fd, MIN);
 }
 
 
-void Assembler::mina(SecondaryField fmt, FPURegister fd, FPURegister ft,
-    FPURegister fs) {
+void Assembler::mina(SecondaryField fmt, FPURegister fd, FPURegister fs,
+                     FPURegister ft) {
   DCHECK(IsMipsArchVariant(kMips32r6));
   DCHECK((fmt == D) || (fmt == S));
   GenInstrRegister(COP1, fmt, ft, fs, fd, MINA);
 }
 
 
-void Assembler::max(SecondaryField fmt, FPURegister fd, FPURegister ft,
-    FPURegister fs) {
+void Assembler::max(SecondaryField fmt, FPURegister fd, FPURegister fs,
+                    FPURegister ft) {
   DCHECK(IsMipsArchVariant(kMips32r6));
   DCHECK((fmt == D) || (fmt == S));
   GenInstrRegister(COP1, fmt, ft, fs, fd, MAX);
 }
 
 
-void Assembler::maxa(SecondaryField fmt, FPURegister fd, FPURegister ft,
-    FPURegister fs) {
+void Assembler::maxa(SecondaryField fmt, FPURegister fd, FPURegister fs,
+                     FPURegister ft) {
   DCHECK(IsMipsArchVariant(kMips32r6));
   DCHECK((fmt == D) || (fmt == S));
   GenInstrRegister(COP1, fmt, ft, fs, fd, MAXA);
index 5d9cebacb330e8bbc4e1c7d47113609e38266785..73511ac5333aca3cddd3f353fee70ad16a8043cc 100644 (file)
@@ -852,14 +852,13 @@ class Assembler : public AssemblerBase {
   void movt(Register rd, Register rs, uint16_t cc = 0);
   void movf(Register rd, Register rs, uint16_t cc = 0);
 
-  void sel(SecondaryField fmt, FPURegister fd, FPURegister ft,
-      FPURegister fs, uint8_t sel);
-  void seleqz(Register rs, Register rt, Register rd);
-  void seleqz(SecondaryField fmt, FPURegister fd, FPURegister ft,
-      FPURegister fs);
-  void selnez(Register rs, Register rt, Register rd);
-  void selnez(SecondaryField fmt, FPURegister fd, FPURegister ft,
-      FPURegister fs);
+  void sel(SecondaryField fmt, FPURegister fd, FPURegister fs, FPURegister ft);
+  void seleqz(Register rd, Register rs, Register rt);
+  void seleqz(SecondaryField fmt, FPURegister fd, FPURegister fs,
+              FPURegister ft);
+  void selnez(Register rd, Register rs, Register rt);
+  void selnez(SecondaryField fmt, FPURegister fd, FPURegister fs,
+              FPURegister ft);
 
   // Bit twiddling.
   void clz(Register rd, Register rs);
@@ -924,10 +923,10 @@ class Assembler : public AssemblerBase {
   void ceil_l_s(FPURegister fd, FPURegister fs);
   void ceil_l_d(FPURegister fd, FPURegister fs);
 
-  void min(SecondaryField fmt, FPURegister fd, FPURegister ft, FPURegister fs);
-  void mina(SecondaryField fmt, FPURegister fd, FPURegister ft, FPURegister fs);
-  void max(SecondaryField fmt, FPURegister fd, FPURegister ft, FPURegister fs);
-  void maxa(SecondaryField fmt, FPURegister fd, FPURegister ft, FPURegister fs);
+  void min(SecondaryField fmt, FPURegister fd, FPURegister fs, FPURegister ft);
+  void mina(SecondaryField fmt, FPURegister fd, FPURegister fs, FPURegister ft);
+  void max(SecondaryField fmt, FPURegister fd, FPURegister fs, FPURegister ft);
+  void maxa(SecondaryField fmt, FPURegister fd, FPURegister fs, FPURegister ft);
 
   void cvt_s_w(FPURegister fd, FPURegister fs);
   void cvt_s_l(FPURegister fd, FPURegister fs);
index 419462311a4a0063e80f2922e92478fae70de539..7ecfe742955950e4d008480a5652b45d149d7fce 100644 (file)
@@ -282,8 +282,6 @@ Instruction::Type Instruction::InstructionType() const {
         case BC1:   // Branch on coprocessor condition.
         case BC1EQZ:
         case BC1NEZ:
-        case SELEQZ_C:
-        case SELNEZ_C:
           return kImmediateType;
         default:
           return kRegisterType;
index 822aab415806de88fafe3e045b36059022ee1da2..0f7abab5a2c9b422e232874425522faebe629fe0 100644 (file)
@@ -106,6 +106,7 @@ class Decoder {
   void DecodeTypeRegisterSRsType(Instruction* instr);
   void DecodeTypeRegisterDRsType(Instruction* instr);
   void DecodeTypeRegisterLRsType(Instruction* instr);
+  void DecodeTypeRegisterWRsType(Instruction* instr);
   void DecodeTypeRegisterSPECIAL(Instruction* instr);
   void DecodeTypeRegisterSPECIAL2(Instruction* instr);
   void DecodeTypeRegisterSPECIAL3(Instruction* instr);
@@ -486,6 +487,27 @@ void Decoder::Unknown(Instruction* instr) {
 
 bool Decoder::DecodeTypeRegisterRsType(Instruction* instr) {
   switch (instr->FunctionFieldRaw()) {
+    case MIN:
+      Format(instr, "min.'t    'fd, 'fs, 'ft");
+      break;
+    case MAX:
+      Format(instr, "max.'t    'fd, 'fs, 'ft");
+      break;
+    case MINA:
+      Format(instr, "mina.'t   'fd, 'fs, 'ft");
+      break;
+    case MAXA:
+      Format(instr, "maxa.'t   'fd, 'fs, 'ft");
+      break;
+    case SEL:
+      Format(instr, "sel.'t      'fd, 'fs, 'ft");
+      break;
+    case SELEQZ_C:
+      Format(instr, "seleqz.'t    'fd, 'fs, 'ft");
+      break;
+    case SELNEZ_C:
+      Format(instr, "selnez.'t    'fd, 'fs, 'ft");
+      break;
     case ADD_D:
       Format(instr, "add.'t   'fd, 'fs, 'ft");
       break;
@@ -630,6 +652,53 @@ void Decoder::DecodeTypeRegisterLRsType(Instruction* instr) {
 }
 
 
+void Decoder::DecodeTypeRegisterWRsType(Instruction* instr) {
+  switch (instr->FunctionValue()) {
+    case CVT_S_W:  // Convert word to float (single).
+      Format(instr, "cvt.s.w 'fd, 'fs");
+      break;
+    case CVT_D_W:  // Convert word to double.
+      Format(instr, "cvt.d.w 'fd, 'fs");
+      break;
+    case CMP_AF:
+      Format(instr, "cmp.af.s    'fd, 'fs, 'ft");
+      break;
+    case CMP_UN:
+      Format(instr, "cmp.un.s    'fd, 'fs, 'ft");
+      break;
+    case CMP_EQ:
+      Format(instr, "cmp.eq.s    'fd, 'fs, 'ft");
+      break;
+    case CMP_UEQ:
+      Format(instr, "cmp.ueq.s   'fd, 'fs, 'ft");
+      break;
+    case CMP_LT:
+      Format(instr, "cmp.lt.s    'fd, 'fs, 'ft");
+      break;
+    case CMP_ULT:
+      Format(instr, "cmp.ult.s   'fd, 'fs, 'ft");
+      break;
+    case CMP_LE:
+      Format(instr, "cmp.le.s    'fd, 'fs, 'ft");
+      break;
+    case CMP_ULE:
+      Format(instr, "cmp.ule.s   'fd, 'fs, 'ft");
+      break;
+    case CMP_OR:
+      Format(instr, "cmp.or.s    'fd, 'fs, 'ft");
+      break;
+    case CMP_UNE:
+      Format(instr, "cmp.une.s   'fd, 'fs, 'ft");
+      break;
+    case CMP_NE:
+      Format(instr, "cmp.ne.s    'fd, 'fs, 'ft");
+      break;
+    default:
+      UNREACHABLE();
+  }
+}
+
+
 void Decoder::DecodeTypeRegisterSPECIAL(Instruction* instr) {
   switch (instr->FunctionFieldRaw()) {
     case JR:
@@ -805,10 +874,10 @@ void Decoder::DecodeTypeRegisterSPECIAL(Instruction* instr) {
       }
       break;
     case SELEQZ_S:
-      Format(instr, "seleqz    'rs, 'rt, 'rd");
+      Format(instr, "seleqz    'rd, 'rs, 'rt");
       break;
     case SELNEZ_S:
-      Format(instr, "selnez    'rs, 'rt, 'rd");
+      Format(instr, "selnez    'rd, 'rs, 'rt");
       break;
     default:
       UNREACHABLE();
@@ -888,21 +957,12 @@ void Decoder::DecodeTypeRegister(Instruction* instr) {
         case D:
           DecodeTypeRegisterDRsType(instr);
           break;
-        case W:
-          switch (instr->FunctionFieldRaw()) {
-            case CVT_S_W:   // Convert word to float (single).
-              Format(instr, "cvt.s.w 'fd, 'fs");
-              break;
-            case CVT_D_W:   // Convert word to double.
-              Format(instr, "cvt.d.w 'fd, 'fs");
-              break;
-            default:
-              UNREACHABLE();
-          }
-          break;
         case L:
           DecodeTypeRegisterLRsType(instr);
           break;
+        case W:
+          DecodeTypeRegisterWRsType(instr);
+          break;
         case PS:
           UNIMPLEMENTED_MIPS();
           break;
@@ -951,138 +1011,6 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) {
         case BC1NEZ:
           Format(instr, "bc1nez    'ft, 'imm16u");
           break;
-        case W:  // CMP.S instruction.
-          switch (instr->FunctionValue()) {
-            case CMP_AF:
-              Format(instr, "cmp.af.S    'ft, 'fs, 'fd");
-              break;
-            case CMP_UN:
-              Format(instr, "cmp.un.S    'ft, 'fs, 'fd");
-              break;
-            case CMP_EQ:
-              Format(instr, "cmp.eq.S    'ft, 'fs, 'fd");
-              break;
-            case CMP_UEQ:
-              Format(instr, "cmp.ueq.S   'ft, 'fs, 'fd");
-              break;
-            case CMP_LT:
-              Format(instr, "cmp.lt.S    'ft, 'fs, 'fd");
-              break;
-            case CMP_ULT:
-              Format(instr, "cmp.ult.S   'ft, 'fs, 'fd");
-              break;
-            case CMP_LE:
-              Format(instr, "cmp.le.S    'ft, 'fs, 'fd");
-              break;
-            case CMP_ULE:
-              Format(instr, "cmp.ule.S   'ft, 'fs, 'fd");
-              break;
-            case CMP_OR:
-              Format(instr, "cmp.or.S    'ft, 'fs, 'fd");
-              break;
-            case CMP_UNE:
-              Format(instr, "cmp.une.S   'ft, 'fs, 'fd");
-              break;
-            case CMP_NE:
-              Format(instr, "cmp.ne.S    'ft, 'fs, 'fd");
-              break;
-            default:
-              UNREACHABLE();
-          }
-          break;
-        case L:  // CMP.D instruction.
-          switch (instr->FunctionValue()) {
-            case CMP_AF:
-              Format(instr, "cmp.af.D    'ft, 'fs, 'fd");
-              break;
-            case CMP_UN:
-              Format(instr, "cmp.un.D    'ft, 'fs, 'fd");
-              break;
-            case CMP_EQ:
-              Format(instr, "cmp.eq.D    'ft, 'fs, 'fd");
-              break;
-            case CMP_UEQ:
-              Format(instr, "cmp.ueq.D   'ft, 'fs, 'fd");
-              break;
-            case CMP_LT:
-              Format(instr, "cmp.lt.D    'ft, 'fs, 'fd");
-              break;
-            case CMP_ULT:
-              Format(instr, "cmp.ult.D   'ft, 'fs, 'fd");
-              break;
-            case CMP_LE:
-              Format(instr, "cmp.le.D    'ft, 'fs, 'fd");
-              break;
-            case CMP_ULE:
-              Format(instr, "cmp.ule.D   'ft, 'fs, 'fd");
-              break;
-            case CMP_OR:
-              Format(instr, "cmp.or.D    'ft, 'fs, 'fd");
-              break;
-            case CMP_UNE:
-              Format(instr, "cmp.une.D   'ft, 'fs, 'fd");
-              break;
-            case CMP_NE:
-              Format(instr, "cmp.ne.D    'ft, 'fs, 'fd");
-              break;
-            default:
-              UNREACHABLE();
-          }
-          break;
-        case S:
-          switch (instr->FunctionValue()) {
-            case SEL:
-              Format(instr, "sel.S    'ft, 'fs, 'fd");
-              break;
-            case SELEQZ_C:
-              Format(instr, "seleqz.S 'ft, 'fs, 'fd");
-              break;
-            case SELNEZ_C:
-              Format(instr, "selnez.S 'ft, 'fs, 'fd");
-              break;
-            case MIN:
-              Format(instr, "min.S    'ft, 'fs, 'fd");
-              break;
-            case MINA:
-              Format(instr, "mina.S   'ft, 'fs, 'fd");
-              break;
-            case MAX:
-              Format(instr, "max.S    'ft, 'fs, 'fd");
-              break;
-            case MAXA:
-              Format(instr, "maxa.S   'ft, 'fs, 'fd");
-              break;
-            default:
-              UNREACHABLE();
-          }
-          break;
-        case D:
-          switch (instr->FunctionValue()) {
-            case SEL:
-              Format(instr, "sel.D    'ft, 'fs, 'fd");
-              break;
-            case SELEQZ_C:
-              Format(instr, "seleqz.D 'ft, 'fs, 'fd");
-              break;
-            case SELNEZ_C:
-              Format(instr, "selnez.D 'ft, 'fs, 'fd");
-              break;
-            case MIN:
-              Format(instr, "min.D    'ft, 'fs, 'fd");
-              break;
-            case MINA:
-              Format(instr, "mina.D   'ft, 'fs, 'fd");
-              break;
-            case MAX:
-              Format(instr, "max.D    'ft, 'fs, 'fd");
-              break;
-            case MAXA:
-              Format(instr, "maxa.D   'ft, 'fs, 'fd");
-              break;
-            default:
-              UNREACHABLE();
-          }
-          break;
         default:
           UNREACHABLE();
       }
index c2ac415d5723921ee7bfcc1e2e04d24394cb8e9c..6a34cb365106a5ac618b3dfa5e8196ec136c2381 100644 (file)
@@ -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;
index 51e85c9bfe6c09a283f11765193b1cd2427af061..3b418514577aa7623e83a908226286c3493de383 100644 (file)
@@ -2100,11 +2100,10 @@ void Assembler::movf(Register rd, Register rs, uint16_t cc) {
 }
 
 
-void Assembler::sel(SecondaryField fmt, FPURegister fd,
-    FPURegister ft, FPURegister fs, uint8_t sel) {
+void Assembler::sel(SecondaryField fmt, FPURegister fd, FPURegister fs,
+                    FPURegister ft) {
   DCHECK(kArchVariant == kMips64r6);
-  DCHECK(fmt == D);
-  DCHECK(fmt == S);
+  DCHECK((fmt == D) || (fmt == S));
 
   Instr instr = COP1 | fmt << kRsShift | ft.code() << kFtShift |
       fs.code() << kFsShift | fd.code() << kFdShift | SEL;
@@ -2112,31 +2111,47 @@ void Assembler::sel(SecondaryField fmt, FPURegister fd,
 }
 
 
+void Assembler::max(SecondaryField fmt, FPURegister fd, FPURegister fs,
+                    FPURegister ft) {
+  DCHECK(kArchVariant == kMips64r6);
+  DCHECK((fmt == D) || (fmt == S));
+  GenInstrRegister(COP1, fmt, ft, fs, fd, MAX);
+}
+
+
+void Assembler::min(SecondaryField fmt, FPURegister fd, FPURegister fs,
+                    FPURegister ft) {
+  DCHECK(kArchVariant == kMips64r6);
+  DCHECK((fmt == D) || (fmt == S));
+  GenInstrRegister(COP1, fmt, ft, fs, fd, MIN);
+}
+
+
 // GPR.
-void Assembler::seleqz(Register rs, Register rt, Register rd) {
+void Assembler::seleqz(Register rd, Register rs, Register rt) {
   DCHECK(kArchVariant == kMips64r6);
   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SELEQZ_S);
 }
 
 
 // FPR.
-void Assembler::seleqz(SecondaryField fmt, FPURegister fd,
-    FPURegister ft, FPURegister fs) {
+void Assembler::seleqz(SecondaryField fmt, FPURegister fd, FPURegister fs,
+                       FPURegister ft) {
   DCHECK((fmt == D) || (fmt == S));
   GenInstrRegister(COP1, fmt, ft, fs, fd, SELEQZ_C);
 }
 
 
 // GPR.
-void Assembler::selnez(Register rs, Register rt, Register rd) {
+void Assembler::selnez(Register rd, Register rs, Register rt) {
   DCHECK(kArchVariant == kMips64r6);
   GenInstrRegister(SPECIAL, rs, rt, rd, 0, SELNEZ_S);
 }
 
 
 // FPR.
-void Assembler::selnez(SecondaryField fmt, FPURegister fd,
-    FPURegister ft, FPURegister fs) {
+void Assembler::selnez(SecondaryField fmt, FPURegister fd, FPURegister fs,
+                       FPURegister ft) {
   DCHECK(kArchVariant == kMips64r6);
   DCHECK((fmt == D) || (fmt == S));
   GenInstrRegister(COP1, fmt, ft, fs, fd, SELNEZ_C);
@@ -2442,14 +2457,6 @@ void Assembler::ceil_l_d(FPURegister fd, FPURegister fs) {
 }
 
 
-void Assembler::min(SecondaryField fmt, FPURegister fd, FPURegister ft,
-    FPURegister fs) {
-  DCHECK(kArchVariant == kMips64r6);
-  DCHECK((fmt == D) || (fmt == S));
-  GenInstrRegister(COP1, fmt, ft, fs, fd, MIN);
-}
-
-
 void Assembler::mina(SecondaryField fmt, FPURegister fd, FPURegister ft,
     FPURegister fs) {
   DCHECK(kArchVariant == kMips64r6);
@@ -2458,14 +2465,6 @@ void Assembler::mina(SecondaryField fmt, FPURegister fd, FPURegister ft,
 }
 
 
-void Assembler::max(SecondaryField fmt, FPURegister fd, FPURegister ft,
-    FPURegister fs) {
-  DCHECK(kArchVariant == kMips64r6);
-  DCHECK((fmt == D) || (fmt == S));
-  GenInstrRegister(COP1, fmt, ft, fs, fd, MAX);
-}
-
-
 void Assembler::maxa(SecondaryField fmt, FPURegister fd, FPURegister ft,
     FPURegister fs) {
   DCHECK(kArchVariant == kMips64r6);
index 9c659ab0f42282d30d7ac930be46dfe601f253f8..8bc8c836da2fcaf246849cc7ff75e4b09d4a0714 100644 (file)
@@ -880,15 +880,13 @@ class Assembler : public AssemblerBase {
   void movt(Register rd, Register rs, uint16_t cc = 0);
   void movf(Register rd, Register rs, uint16_t cc = 0);
 
-  void sel(SecondaryField fmt, FPURegister fd, FPURegister ft,
-      FPURegister fs, uint8_t sel);
-  void seleqz(Register rs, Register rt, Register rd);
-  void seleqz(SecondaryField fmt, FPURegister fd, FPURegister ft,
-      FPURegister fs);
+  void sel(SecondaryField fmt, FPURegister fd, FPURegister fs, FPURegister ft);
+  void seleqz(Register rd, Register rs, Register rt);
+  void seleqz(SecondaryField fmt, FPURegister fd, FPURegister fs,
+              FPURegister ft);
   void selnez(Register rs, Register rt, Register rd);
-  void selnez(SecondaryField fmt, FPURegister fd, FPURegister ft,
-      FPURegister fs);
-
+  void selnez(SecondaryField fmt, FPURegister fd, FPURegister fs,
+              FPURegister ft);
   // Bit twiddling.
   void clz(Register rd, Register rs);
   void ins_(Register rt, Register rs, uint16_t pos, uint16_t size);
@@ -955,10 +953,10 @@ class Assembler : public AssemblerBase {
   void ceil_l_s(FPURegister fd, FPURegister fs);
   void ceil_l_d(FPURegister fd, FPURegister fs);
 
-  void min(SecondaryField fmt, FPURegister fd, FPURegister ft, FPURegister fs);
-  void mina(SecondaryField fmt, FPURegister fd, FPURegister ft, FPURegister fs);
-  void max(SecondaryField fmt, FPURegister fd, FPURegister ft, FPURegister fs);
-  void maxa(SecondaryField fmt, FPURegister fd, FPURegister ft, FPURegister fs);
+  void min(SecondaryField fmt, FPURegister fd, FPURegister fs, FPURegister ft);
+  void mina(SecondaryField fmt, FPURegister fd, FPURegister fs, FPURegister ft);
+  void max(SecondaryField fmt, FPURegister fd, FPURegister fs, FPURegister ft);
+  void maxa(SecondaryField fmt, FPURegister fd, FPURegister fs, FPURegister ft);
 
   void cvt_s_w(FPURegister fd, FPURegister fs);
   void cvt_s_l(FPURegister fd, FPURegister fs);
index 449d143686de32031f2825b5d5d194500e24f247..29b069580de67447a9e29c93eda2b7c9fefdeb46 100644 (file)
@@ -106,6 +106,7 @@ class Decoder {
   void DecodeTypeRegisterSRsType(Instruction* instr);
   void DecodeTypeRegisterDRsType(Instruction* instr);
   void DecodeTypeRegisterLRsType(Instruction* instr);
+  void DecodeTypeRegisterWRsType(Instruction* instr);
   void DecodeTypeRegisterSPECIAL(Instruction* instr);
   void DecodeTypeRegisterSPECIAL2(Instruction* instr);
   void DecodeTypeRegisterSPECIAL3(Instruction* instr);
@@ -113,10 +114,6 @@ class Decoder {
   void DecodeTypeRegisterCOP1X(Instruction* instr);
   int DecodeTypeRegister(Instruction* instr);
 
-  void DecodeTypeImmediateCOP1W(Instruction* instr);
-  void DecodeTypeImmediateCOP1L(Instruction* instr);
-  void DecodeTypeImmediateCOP1S(Instruction* instr);
-  void DecodeTypeImmediateCOP1D(Instruction* instr);
   void DecodeTypeImmediateCOP1(Instruction* instr);
   void DecodeTypeImmediateREGIMM(Instruction* instr);
   void DecodeTypeImmediate(Instruction* instr);
@@ -521,10 +518,22 @@ int Decoder::DecodeBreakInstr(Instruction* instr) {
 bool Decoder::DecodeTypeRegisterRsType(Instruction* instr) {
   switch (instr->FunctionFieldRaw()) {
     case SELEQZ_C:
-      Format(instr, "seleqz.'t    'ft, 'fs, 'fd");
+      Format(instr, "seleqz.'t    'fd, 'fs, 'ft");
       break;
     case SELNEZ_C:
-      Format(instr, "selnez.'t    'ft, 'fs, 'fd");
+      Format(instr, "selnez.'t    'fd, 'fs, 'ft");
+      break;
+    case MIN:
+      Format(instr, "min.'t    'fd, 'fs, 'ft");
+      break;
+    case MAX:
+      Format(instr, "max.'t    'fd, 'fs, 'ft");
+      break;
+    case MINA:
+      Format(instr, "mina.'t   'fd, 'fs, 'ft");
+      break;
+    case MAXA:
+      Format(instr, "maxa.'t   'fd, 'fs, 'ft");
       break;
     case ADD_D:
       Format(instr, "add.'t   'fd, 'fs, 'ft");
@@ -679,6 +688,53 @@ void Decoder::DecodeTypeRegisterLRsType(Instruction* instr) {
 }
 
 
+void Decoder::DecodeTypeRegisterWRsType(Instruction* instr) {
+  switch (instr->FunctionValue()) {
+    case CVT_S_W:  // Convert word to float (single).
+      Format(instr, "cvt.s.w 'fd, 'fs");
+      break;
+    case CVT_D_W:  // Convert word to double.
+      Format(instr, "cvt.d.w 'fd, 'fs");
+      break;
+    case CMP_AF:
+      Format(instr, "cmp.af.s    'fd, 'fs, 'ft");
+      break;
+    case CMP_UN:
+      Format(instr, "cmp.un.s    'fd, 'fs, 'ft");
+      break;
+    case CMP_EQ:
+      Format(instr, "cmp.eq.s    'fd, 'fs, 'ft");
+      break;
+    case CMP_UEQ:
+      Format(instr, "cmp.ueq.s   'fd, 'fs, 'ft");
+      break;
+    case CMP_LT:
+      Format(instr, "cmp.lt.s    'fd, 'fs, 'ft");
+      break;
+    case CMP_ULT:
+      Format(instr, "cmp.ult.s   'fd, 'fs, 'ft");
+      break;
+    case CMP_LE:
+      Format(instr, "cmp.le.s    'fd, 'fs, 'ft");
+      break;
+    case CMP_ULE:
+      Format(instr, "cmp.ule.s   'fd, 'fs, 'ft");
+      break;
+    case CMP_OR:
+      Format(instr, "cmp.or.s    'fd, 'fs, 'ft");
+      break;
+    case CMP_UNE:
+      Format(instr, "cmp.une.s   'fd, 'fs, 'ft");
+      break;
+    case CMP_NE:
+      Format(instr, "cmp.ne.s    'fd, 'fs, 'ft");
+      break;
+    default:
+      UNREACHABLE();
+  }
+}
+
+
 void Decoder::DecodeTypeRegisterCOP1(Instruction* instr) {
   switch (instr->RsFieldRaw()) {
     case MFC1:
@@ -713,13 +769,7 @@ void Decoder::DecodeTypeRegisterCOP1(Instruction* instr) {
       DecodeTypeRegisterDRsType(instr);
       break;
     case W:
-      switch (instr->FunctionFieldRaw()) {
-        case CVT_D_W:  // Convert word to double.
-          Format(instr, "cvt.d.w 'fd, 'fs");
-          break;
-        default:
-          UNREACHABLE();
-      }
+      DecodeTypeRegisterWRsType(instr);
       break;
     case L:
       DecodeTypeRegisterLRsType(instr);
@@ -1013,10 +1063,10 @@ void Decoder::DecodeTypeRegisterSPECIAL(Instruction* instr) {
       }
       break;
     case SELEQZ_S:
-      Format(instr, "seleqz    'rs, 'rt, 'rd");
+      Format(instr, "seleqz    'rd, 'rs, 'rt");
       break;
     case SELNEZ_S:
-      Format(instr, "selnez    'rs, 'rt, 'rd");
+      Format(instr, "selnez    'rd, 'rs, 'rt");
       break;
     default:
       UNREACHABLE();
@@ -1090,146 +1140,6 @@ int Decoder::DecodeTypeRegister(Instruction* instr) {
 }
 
 
-void Decoder::DecodeTypeImmediateCOP1D(Instruction* instr) {
-  switch (instr->FunctionValue()) {
-    case SEL:
-      Format(instr, "sel.D    'ft, 'fs, 'fd");
-      break;
-    case SELEQZ_C:
-      Format(instr, "seleqz.D 'ft, 'fs, 'fd");
-      break;
-    case SELNEZ_C:
-      Format(instr, "selnez.D 'ft, 'fs, 'fd");
-      break;
-    case MIN:
-      Format(instr, "min.D    'ft, 'fs, 'fd");
-      break;
-    case MINA:
-      Format(instr, "mina.D   'ft, 'fs, 'fd");
-      break;
-    case MAX:
-      Format(instr, "max.D    'ft, 'fs, 'fd");
-      break;
-    case MAXA:
-      Format(instr, "maxa.D   'ft, 'fs, 'fd");
-      break;
-    default:
-      UNREACHABLE();
-  }
-}
-
-
-void Decoder::DecodeTypeImmediateCOP1L(Instruction* instr) {
-  switch (instr->FunctionValue()) {
-    case CMP_AF:
-      Format(instr, "cmp.af.D    'ft, 'fs, 'fd");
-      break;
-    case CMP_UN:
-      Format(instr, "cmp.un.D    'ft, 'fs, 'fd");
-      break;
-    case CMP_EQ:
-      Format(instr, "cmp.eq.D    'ft, 'fs, 'fd");
-      break;
-    case CMP_UEQ:
-      Format(instr, "cmp.ueq.D   'ft, 'fs, 'fd");
-      break;
-    case CMP_LT:
-      Format(instr, "cmp.lt.D    'ft, 'fs, 'fd");
-      break;
-    case CMP_ULT:
-      Format(instr, "cmp.ult.D   'ft, 'fs, 'fd");
-      break;
-    case CMP_LE:
-      Format(instr, "cmp.le.D    'ft, 'fs, 'fd");
-      break;
-    case CMP_ULE:
-      Format(instr, "cmp.ule.D   'ft, 'fs, 'fd");
-      break;
-    case CMP_OR:
-      Format(instr, "cmp.or.D    'ft, 'fs, 'fd");
-      break;
-    case CMP_UNE:
-      Format(instr, "cmp.une.D   'ft, 'fs, 'fd");
-      break;
-    case CMP_NE:
-      Format(instr, "cmp.ne.D    'ft, 'fs, 'fd");
-      break;
-    default:
-      UNREACHABLE();
-  }
-}
-
-
-void Decoder::DecodeTypeImmediateCOP1S(Instruction* instr) {
-  switch (instr->FunctionValue()) {
-    case SEL:
-      Format(instr, "sel.S    'ft, 'fs, 'fd");
-      break;
-    case SELEQZ_C:
-      Format(instr, "seleqz.S 'ft, 'fs, 'fd");
-      break;
-    case SELNEZ_C:
-      Format(instr, "selnez.S 'ft, 'fs, 'fd");
-      break;
-    case MIN:
-      Format(instr, "min.S    'ft, 'fs, 'fd");
-      break;
-    case MINA:
-      Format(instr, "mina.S   'ft, 'fs, 'fd");
-      break;
-    case MAX:
-      Format(instr, "max.S    'ft, 'fs, 'fd");
-      break;
-    case MAXA:
-      Format(instr, "maxa.S   'ft, 'fs, 'fd");
-      break;
-    default:
-      UNREACHABLE();
-  }
-}
-
-
-void Decoder::DecodeTypeImmediateCOP1W(Instruction* instr) {
-  switch (instr->FunctionValue()) {
-    case CMP_AF:
-      Format(instr, "cmp.af.S    'ft, 'fs, 'fd");
-      break;
-    case CMP_UN:
-      Format(instr, "cmp.un.S    'ft, 'fs, 'fd");
-      break;
-    case CMP_EQ:
-      Format(instr, "cmp.eq.S    'ft, 'fs, 'fd");
-      break;
-    case CMP_UEQ:
-      Format(instr, "cmp.ueq.S   'ft, 'fs, 'fd");
-      break;
-    case CMP_LT:
-      Format(instr, "cmp.lt.S    'ft, 'fs, 'fd");
-      break;
-    case CMP_ULT:
-      Format(instr, "cmp.ult.S   'ft, 'fs, 'fd");
-      break;
-    case CMP_LE:
-      Format(instr, "cmp.le.S    'ft, 'fs, 'fd");
-      break;
-    case CMP_ULE:
-      Format(instr, "cmp.ule.S   'ft, 'fs, 'fd");
-      break;
-    case CMP_OR:
-      Format(instr, "cmp.or.S    'ft, 'fs, 'fd");
-      break;
-    case CMP_UNE:
-      Format(instr, "cmp.une.S   'ft, 'fs, 'fd");
-      break;
-    case CMP_NE:
-      Format(instr, "cmp.ne.S    'ft, 'fs, 'fd");
-      break;
-    default:
-      UNREACHABLE();
-  }
-}
-
-
 void Decoder::DecodeTypeImmediateCOP1(Instruction* instr) {
   switch (instr->RsFieldRaw()) {
     case BC1:
@@ -1245,18 +1155,6 @@ void Decoder::DecodeTypeImmediateCOP1(Instruction* instr) {
     case BC1NEZ:
       Format(instr, "bc1nez    'ft, 'imm16u");
       break;
-    case W:  // CMP.S instruction.
-      DecodeTypeImmediateCOP1W(instr);
-      break;
-    case L:  // CMP.D instruction.
-      DecodeTypeImmediateCOP1L(instr);
-      break;
-    case S:
-      DecodeTypeImmediateCOP1S(instr);
-      break;
-    case D:
-      DecodeTypeImmediateCOP1D(instr);
-      break;
     default:
       UNREACHABLE();
   }
index d5d8ed0a24a76bf36d87111ecfcd579766c7ae2b..8d1df3d38c58d413d5da43f58101bff5a16f0f54 100644 (file)
@@ -2273,7 +2273,7 @@ void Simulator::ConfigureTypeRegister(Instruction* instr,
 void Simulator::DecodeTypeRegisterSRsType(Instruction* instr,
                                           const int32_t& fs_reg,
                                           const int32_t& ft_reg,
-                                          const int64_t& fd_reg) {
+                                          const int32_t& fd_reg) {
   float fs, ft;
   fs = get_fpu_register_float(fs_reg);
   ft = get_fpu_register_float(ft_reg);
@@ -2339,16 +2339,22 @@ void Simulator::DecodeTypeRegisterSRsType(Instruction* instr,
 
 void Simulator::DecodeTypeRegisterDRsType(Instruction* instr,
                                           const int32_t& fs_reg,
-                                          const int64_t& ft_reg,
+                                          const int32_t& ft_reg,
                                           const int32_t& fd_reg) {
-  double ft, fs;
+  double ft, fs, fd;
   uint32_t cc, fcsr_cc;
   fs = get_fpu_register_double(fs_reg);
   ft = get_fpu_register_double(ft_reg);
+  fd = get_fpu_register_double(fd_reg);
   cc = instr->FCccValue();
   fcsr_cc = get_fcsr_condition_bit(cc);
-  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);
   switch (instr->FunctionFieldRaw()) {
+    case SEL:
+      DCHECK(kArchVariant == kMips64r6);
+      set_fpu_register_double(fd_reg, (fd_int & 0x1) == 0 ? fs : ft);
+      break;
     case SELEQZ_C:
       DCHECK(kArchVariant == kMips64r6);
       set_fpu_register_double(fd_reg, (ft_int & 0x1) == 0 ? fs : 0.0);
@@ -2357,6 +2363,32 @@ void Simulator::DecodeTypeRegisterDRsType(Instruction* instr,
       DCHECK(kArchVariant == kMips64r6);
       set_fpu_register_double(fd_reg, (ft_int & 0x1) != 0 ? fs : 0.0);
       break;
+    case MIN:
+      DCHECK(kArchVariant == kMips64r6);
+      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(kArchVariant == kMips64r6);
+      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 ADD_D:
       set_fpu_register_double(fd_reg, fs + ft);
       break;
@@ -2595,10 +2627,10 @@ void Simulator::DecodeTypeRegisterLRsType(Instruction* instr,
 
 
 void Simulator::DecodeTypeRegisterCOP1(
-    Instruction* instr, const int64_t& rs_reg, const int64_t& rs,
-    const uint64_t& rs_u, const int64_t& rt_reg, const int64_t& rt,
-    const uint64_t& rt_u, const int64_t& rd_reg, const int32_t& fr_reg,
-    const int32_t& fs_reg, const int32_t& ft_reg, const int64_t& fd_reg,
+    Instruction* instr, const int32_t& rs_reg, const int64_t& rs,
+    const uint64_t& rs_u, const int32_t& rt_reg, const int64_t& rt,
+    const uint64_t& rt_u, const int32_t& rd_reg, const int32_t& fr_reg,
+    const int32_t& fs_reg, const int32_t& ft_reg, const int32_t& fd_reg,
     int64_t& alu_out) {
   switch (instr->RsFieldRaw()) {
     case BC1:  // Branch on coprocessor condition.
@@ -2652,7 +2684,7 @@ void Simulator::DecodeTypeRegisterCOP1X(Instruction* instr,
                                         const int32_t& fr_reg,
                                         const int32_t& fs_reg,
                                         const int32_t& ft_reg,
-                                        const int64_t& fd_reg) {
+                                        const int32_t& fd_reg) {
   switch (instr->FunctionFieldRaw()) {
     case MADD_D:
       double fr, ft, fs;
@@ -2886,10 +2918,10 @@ void Simulator::DecodeTypeRegister(Instruction* instr) {
   const uint64_t rt_u   = static_cast<uint32_t>(rt);
   const int64_t  rd_reg = instr->RdValue();
 
-  const int32_t  fr_reg = instr->FrValue();
-  const int32_t  fs_reg = instr->FsValue();
-  const int32_t  ft_reg = instr->FtValue();
-  const int64_t  fd_reg = instr->FdValue();
+  const int32_t fr_reg = instr->FrValue();
+  const int32_t fs_reg = instr->FsValue();
+  const int32_t ft_reg = instr->FtValue();
+  const int32_t fd_reg = instr->FdValue();
   int64_t  i64hilo = 0;
   uint64_t u64hilo = 0;
 
index a4271ce3105fb222ee33f7091e19a379f4f8b75a..63172389a35a1aaaa3dafd3d5356480df1a95795 100644 (file)
@@ -313,17 +313,17 @@ class Simulator {
   inline int32_t SetDoubleLOW(double* addr);
 
   // functions called from DecodeTypeRegister
-  void DecodeTypeRegisterCOP1(Instruction* instr, const int64_t& rs_reg,
+  void DecodeTypeRegisterCOP1(Instruction* instr, const int32_t& rs_reg,
                               const int64_t& rs, const uint64_t& rs_u,
-                              const int64_t& rt_reg, const int64_t& rt,
-                              const uint64_t& rt_u, const int64_t& rd_reg,
+                              const int32_t& rt_reg, const int64_t& rt,
+                              const uint64_t& rt_u, const int32_t& rd_reg,
                               const int32_t& fr_reg, const int32_t& fs_reg,
-                              const int32_t& ft_reg, const int64_t& fd_reg,
+                              const int32_t& ft_reg, const int32_t& fd_reg,
                               int64_t& alu_out);
 
   void DecodeTypeRegisterCOP1X(Instruction* instr, const int32_t& fr_reg,
                                const int32_t& fs_reg, const int32_t& ft_reg,
-                               const int64_t& fd_reg);
+                               const int32_t& fd_reg);
 
   void DecodeTypeRegisterSPECIAL(
       Instruction* instr, const int64_t& rs_reg, const int64_t& rs,
@@ -341,10 +341,10 @@ class Simulator {
                                   int64_t& alu_out);
 
   void DecodeTypeRegisterSRsType(Instruction* instr, const int32_t& fs_reg,
-                                 const int32_t& ft_reg, const int64_t& fd_reg);
+                                 const int32_t& ft_reg, const int32_t& fd_reg);
 
   void DecodeTypeRegisterDRsType(Instruction* instr, const int32_t& fs_reg,
-                                 const int64_t& ft_reg, const int32_t& fd_reg);
+                                 const int32_t& ft_reg, const int32_t& fd_reg);
 
   void DecodeTypeRegisterWRsType(Instruction* instr, const int32_t& fs_reg,
                                  const int32_t& fd_reg, int64_t& alu_out);
index 1358c02fd1250c192a5c2609191492dae549cde7..5ad9706e33ef73df4cf682528f1b343dd4374b87 100644 (file)
@@ -1342,53 +1342,26 @@ TEST(MIPS16) {
       double f;
       double g;
       double h;
-      double i;
-      double j;
-      double k;
-      double l;
     } Test;
 
     Test test;
     // Integer part of test.
     __ addiu(t1, zero_reg, 1);                      // t1 = 1
-    __ seleqz(t1, zero_reg, t3);                    // t3 = 1
+    __ seleqz(t3, t1, zero_reg);                    // t3 = 1
     __ sw(t3, MemOperand(a0, OFFSET_OF(Test, a)));  // a = 1
-    __ seleqz(t1, t1, t2);                          // t2 = 0
+    __ seleqz(t2, t1, t1);                          // t2 = 0
     __ sw(t2, MemOperand(a0, OFFSET_OF(Test, b)));  // b = 0
-    __ selnez(t1, zero_reg, t3);                    // t3 = 1;
+    __ selnez(t3, t1, zero_reg);                    // t3 = 1;
     __ sw(t3, MemOperand(a0, OFFSET_OF(Test, c)));  // c = 0
-    __ selnez(t1, t1, t3);                          // t3 = 1
+    __ selnez(t3, t1, t1);                          // t3 = 1
     __ sw(t3, MemOperand(a0, OFFSET_OF(Test, d)));  // d = 1
-    // Floating point part of test S format.
-    __ li(t0, 0x80);
-    __ mtc1(t0, f4);
-    __ cvt_d_w(f4, f4);  // f4 = 0x80
-    __ li(t0, 0xf3);
-    __ mtc1(t0, f6);
-    __ cvt_d_w(f6, f6);                                // f6 = 0xf3
-    __ seleqz(S, f8, f4, f6);                          // f8 = 0xf3
-    __ seleqz(S, f10, f6, f6);                         // f10 = 0
-    __ sdc1(f8, MemOperand(a0, OFFSET_OF(Test, e)));   // e = 0xf3
-    __ sdc1(f10, MemOperand(a0, OFFSET_OF(Test, f)));  // f = 0
-    __ selnez(S, f8, f4, f6);                          // f8 = 0
-    __ selnez(S, f10, f6, f6);                         // f10 = 0xf3
-    __ sdc1(f8, MemOperand(a0, OFFSET_OF(Test, g)));   // g = 0
-    __ sdc1(f10, MemOperand(a0, OFFSET_OF(Test, h)));  // h = 0xf3
-
-    __ li(t0, 0x80);
-    __ mtc1(t0, f4);
-    __ cvt_d_w(f4, f4);  // f4 = 0x80
-    __ li(t0, 0xf3);
-    __ mtc1(t0, f6);
-    __ cvt_d_w(f6, f6);                                // f6 = 0xf3
-    __ seleqz(D, f8, f4, f6);                          // f8 = 0xf3
-    __ seleqz(D, f10, f6, f6);                         // f10 = 0
-    __ sdc1(f8, MemOperand(a0, OFFSET_OF(Test, i)));   // i = 0xf3
-    __ sdc1(f10, MemOperand(a0, OFFSET_OF(Test, j)));  // j = 0
-    __ selnez(S, f8, f4, f6);                          // f8 = 0
-    __ selnez(S, f10, f6, f6);                         // f10 = 0xf3
-    __ sdc1(f8, MemOperand(a0, OFFSET_OF(Test, k)));   // k = 0
-    __ sdc1(f10, MemOperand(a0, OFFSET_OF(Test, l)));  // l = 0xf3
+    // Floating point part of test.
+    __ ldc1(f0, MemOperand(a0, OFFSET_OF(Test, e)) );  // src
+    __ ldc1(f2, MemOperand(a0, OFFSET_OF(Test, f)) );  // test
+    __ seleqz(D, f4, f0, f2);
+    __ selnez(D, f6, f0, f2);
+    __ sdc1(f4, MemOperand(a0, OFFSET_OF(Test, g)) );  // src
+    __ sdc1(f6, MemOperand(a0, OFFSET_OF(Test, h)) );  // src
     __ jr(ra);
     __ nop();
     CodeDesc desc;
@@ -1404,15 +1377,92 @@ TEST(MIPS16) {
     CHECK_EQ(test.c, 0);
     CHECK_EQ(test.d, 1);
 
-    CHECK_EQ(test.e, 0xf3);
-    CHECK_EQ(test.f, 0x0);
-    CHECK_EQ(test.g, 0);
-    CHECK_EQ(test.h, 0xf3);
+    const int test_size = 3;
+    const int input_size = 5;
+
+    double inputs[input_size] = {0.0, 65.2, -70.32,
+      18446744073709551621.0, -18446744073709551621.0};
+    double outputs[input_size] = {0.0, 65.2, -70.32,
+      18446744073709551621.0, -18446744073709551621.0};
+    double tests[test_size*2] = {2.8, 2.9, -2.8, -2.9,
+      18446744073709551616.0, 18446744073709555712.0};
+    for (int j=0;j < test_size;j+=2) {
+      for (int i=0;i < input_size;i++) {
+        test.e = inputs[i];
+        test.f = tests[j];
+        (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
+        CHECK_EQ(test.g, outputs[i]);
+        CHECK_EQ(test.h, 0);
+
+        test.f = tests[j+1];
+        (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
+        CHECK_EQ(test.g, 0);
+        CHECK_EQ(test.h, outputs[i]);
+      }
+    }
+  }
+}
+
+
+TEST(MIPS17) {
+  if (IsMipsArchVariant(kMips32r6)) {
+    CcTest::InitializeVM();
+    Isolate* isolate = CcTest::i_isolate();
+    HandleScope scope(isolate);
+    MacroAssembler assm(isolate, NULL, 0);
+
+    typedef struct test_float {
+      double a;
+      double b;
+      double c;
+      double d;
+    } TestFloat;
+
+    TestFloat test;
+
+    __ ldc1(f4, MemOperand(a0, OFFSET_OF(TestFloat, a)));
+    __ ldc1(f8, MemOperand(a0, OFFSET_OF(TestFloat, b)));
+    __ min(D, f10, f8, f4);
+    __ max(D, f12, f8, f4);
+    __ sdc1(f10, MemOperand(a0, OFFSET_OF(TestFloat, c)));
+    __ sdc1(f12, MemOperand(a0, OFFSET_OF(TestFloat, d)));
+    __ jr(ra);
+    __ nop();
 
-    CHECK_EQ(test.i, 0xf3);
-    CHECK_EQ(test.j, 0x0);
-    CHECK_EQ(test.k, 0);
-    CHECK_EQ(test.l, 0xf3);
+    CodeDesc desc;
+    assm.GetCode(&desc);
+    Handle<Code> code = isolate->factory()->NewCode(
+        desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+    F3 f = FUNCTION_CAST<F3>(code->entry());
+    test.a = 2.0;  // a goes to fs
+    test.b = 3.0;  // b goes to ft
+    (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
+    CHECK_EQ(test.c, 2.0);
+    CHECK_EQ(test.d, 3.0);
+
+    test.a = 3.0;  // a goes to fs
+    test.b = 2.0;  // b goes to ft
+    (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
+    CHECK_EQ(test.c, 2.0);
+    CHECK_EQ(test.d, 3.0);
+
+    test.a = std::numeric_limits<double>::quiet_NaN();
+    test.b = 3.0;  // b goes to ft
+    (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
+    CHECK_EQ(test.c, 3.0);
+    CHECK_EQ(test.d, 3.0);
+
+    test.b = std::numeric_limits<double>::quiet_NaN();
+    test.a = 3.0;  // b goes to ft
+    (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
+    CHECK_EQ(test.c, 3.0);
+    CHECK_EQ(test.d, 3.0);
+
+    test.a = std::numeric_limits<double>::quiet_NaN();
+    test.b = std::numeric_limits<double>::quiet_NaN();
+    (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
+    DCHECK(std::isnan(test.c));
+    DCHECK(std::isnan(test.d));
   }
 }
 
index 2e87e811d4433183691de537cca5a3b5696de3f1..308cd4d5151be6964e26c8fc54cbb5a6ddf998ee 100644 (file)
@@ -1448,38 +1448,30 @@ TEST(MIPS17) {
       int b;
       int c;
       int d;
-      double i;
-      double j;
-      double k;
-      double l;
+      double e;
+      double f;
+      double g;
+      double h;
     } Test;
 
     Test test;
     // Integer part of test.
     __ addiu(t1, zero_reg, 1);                      // t1 = 1
-    __ seleqz(t1, zero_reg, t3);                    // t3 = 1
+    __ seleqz(t3, t1, zero_reg);                    // t3 = 1
     __ sw(t3, MemOperand(a0, OFFSET_OF(Test, a)));  // a = 1
-    __ seleqz(t1, t1, t2);                          // t2 = 0
+    __ seleqz(t2, t1, t1);                          // t2 = 0
     __ sw(t2, MemOperand(a0, OFFSET_OF(Test, b)));  // b = 0
-    __ selnez(t1, zero_reg, t3);                    // t3 = 1;
+    __ selnez(t3, t1, zero_reg);                    // t3 = 1;
     __ sw(t3, MemOperand(a0, OFFSET_OF(Test, c)));  // c = 0
-    __ selnez(t1, t1, t3);                          // t3 = 1
+    __ selnez(t3, t1, t1);                          // t3 = 1
     __ sw(t3, MemOperand(a0, OFFSET_OF(Test, d)));  // d = 1
     // Floating point part of test.
-    __ li(t0, 0x80);
-    __ mtc1(t0, f4);
-    __ cvt_d_w(f4, f4);  // f4=0x80
-    __ li(t0, 0xf3);
-    __ mtc1(t0, f6);
-    __ cvt_d_w(f6, f6);                                // f6 = 0xf3
-    __ seleqz(D, f8, f4, f6);                          // f8 = 0xf3
-    __ seleqz(D, f10, f6, f6);                         // f10 = 0
-    __ sdc1(f8, MemOperand(a0, OFFSET_OF(Test, i)));   // i = 0xf3
-    __ sdc1(f10, MemOperand(a0, OFFSET_OF(Test, j)));  // j = 0
-    __ selnez(D, f8, f4, f6);                          // f8 = 0
-    __ selnez(D, f10, f6, f6);                         // f10 = 0xf3
-    __ sdc1(f8, MemOperand(a0, OFFSET_OF(Test, k)));   // k = 0
-    __ sdc1(f10, MemOperand(a0, OFFSET_OF(Test, l)));  // l = 0xf3
+    __ ldc1(f0, MemOperand(a0, OFFSET_OF(Test, e)) );  // src
+    __ ldc1(f2, MemOperand(a0, OFFSET_OF(Test, f)) );  // test
+    __ seleqz(D, f4, f0, f2);
+    __ selnez(D, f6, f0, f2);
+    __ sdc1(f4, MemOperand(a0, OFFSET_OF(Test, g)) );  // src
+    __ sdc1(f6, MemOperand(a0, OFFSET_OF(Test, h)) );  // src
     __ jr(ra);
     __ nop();
     CodeDesc desc;
@@ -1495,10 +1487,92 @@ TEST(MIPS17) {
     CHECK_EQ(test.c, 0);
     CHECK_EQ(test.d, 1);
 
-    CHECK_EQ(test.i, 0xf3);
-    CHECK_EQ(test.j, 0x0);
-    CHECK_EQ(test.k, 0);
-    CHECK_EQ(test.l, 0xf3);
+    const int test_size = 3;
+    const int input_size = 5;
+
+    double inputs[input_size] = {0.0, 65.2, -70.32,
+      18446744073709551621.0, -18446744073709551621.0};
+    double outputs[input_size] = {0.0, 65.2, -70.32,
+      18446744073709551621.0, -18446744073709551621.0};
+    double tests[test_size*2] = {2.8, 2.9, -2.8, -2.9,
+      18446744073709551616.0, 18446744073709555712.0};
+    for (int j=0;j < test_size;j+=2) {
+      for (int i=0;i < input_size;i++) {
+        test.e = inputs[i];
+        test.f = tests[j];
+        (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
+        CHECK_EQ(test.g, outputs[i]);
+        CHECK_EQ(test.h, 0);
+
+        test.f = tests[j+1];
+        (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
+        CHECK_EQ(test.g, 0);
+        CHECK_EQ(test.h, outputs[i]);
+      }
+    }
+  }
+}
+
+
+TEST(MIPS18) {
+  if (kArchVariant == kMips64r6) {
+    CcTest::InitializeVM();
+    Isolate* isolate = CcTest::i_isolate();
+    HandleScope scope(isolate);
+    MacroAssembler assm(isolate, NULL, 0);
+
+    typedef struct test_float {
+      double a;
+      double b;
+      double c;
+      double d;
+    } TestFloat;
+
+    TestFloat test;
+
+    __ ldc1(f4, MemOperand(a0, OFFSET_OF(TestFloat, a)));
+    __ ldc1(f8, MemOperand(a0, OFFSET_OF(TestFloat, b)));
+    __ min(D, f10, f8, f4);
+    __ max(D, f12, f8, f4);
+    __ sdc1(f10, MemOperand(a0, OFFSET_OF(TestFloat, c)));
+    __ sdc1(f12, MemOperand(a0, OFFSET_OF(TestFloat, d)));
+    __ jr(ra);
+    __ nop();
+
+    CodeDesc desc;
+    assm.GetCode(&desc);
+    Handle<Code> code = isolate->factory()->NewCode(
+        desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+    F3 f = FUNCTION_CAST<F3>(code->entry());
+    test.a = 2.0;  // a goes to fs
+    test.b = 3.0;  // b goes to ft
+    (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
+    CHECK_EQ(test.c, 2.0);
+    CHECK_EQ(test.d, 3.0);
+
+    test.a = 3.0;  // a goes to fs
+    test.b = 2.0;  // b goes to ft
+    (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
+    CHECK_EQ(test.c, 2.0);
+    CHECK_EQ(test.d, 3.0);
+
+    test.a = std::numeric_limits<double>::quiet_NaN();
+    test.b = 3.0;  // b goes to ft
+    (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
+    CHECK_EQ(test.c, 3.0);
+    CHECK_EQ(test.d, 3.0);
+
+    test.b = std::numeric_limits<double>::quiet_NaN();
+    test.a = 3.0;  // b goes to ft
+    (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
+    CHECK_EQ(test.c, 3.0);
+    CHECK_EQ(test.d, 3.0);
+
+    test.a = std::numeric_limits<double>::quiet_NaN();
+    test.b = std::numeric_limits<double>::quiet_NaN();
+    (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0));
+    DCHECK(std::isnan(test.c));
+    DCHECK(std::isnan(test.d));
   }
 }
 
index 1023ca445cc85a64c5422548e9b7276fea29f5ad..5789a23390f392edb6db3a0173ebc75698aff1b4 100644 (file)
@@ -90,20 +90,6 @@ bool DisassembleAndCompare(byte* pc, const char* compare_string) {
 if (failure) { \
     V8_Fatal(__FILE__, __LINE__, "MIPS Disassembler tests failed.\n"); \
   }
-//  tests only seleqz, selnez, seleqz.fmt and selnez.fmt
-TEST(Type1) {
-  SET_UP();
-  if (IsMipsArchVariant(kMips32r6)) {
-    COMPARE(seleqz(a0, a1, a2), "00853035       seleqz    a0, a1, a2");
-    COMPARE(selnez(a0, a1, a2), "00853037       selnez    a0, a1, a2");
-
-    COMPARE(seleqz(S, f0, f1, f2), "45000894       seleqz.S    f0, f1, f2");
-    COMPARE(selnez(S, f0, f1, f2), "45000897       selnez.S    f0, f1, f2");
-    COMPARE(seleqz(D, f3, f4, f5), "00853035       seleqz.D    f3, f4, f5");
-    COMPARE(selnez(D, f3, f4, f5), "00853037       selnez.D    f3, f4, f5");
-  }
-  VERIFY_RUN();
-}
 
 
 TEST(Type0) {
@@ -537,3 +523,21 @@ TEST(Type0) {
 
   VERIFY_RUN();
 }
+
+
+//  Tests only seleqz, selnez, seleqz.fmt and selnez.fmt
+TEST(Type1) {
+  if (IsMipsArchVariant(kMips32r6)) {
+    SET_UP();
+    COMPARE(seleqz(a0, a1, a2), "00a62035       seleqz    a0, a1, a2");
+    COMPARE(selnez(a0, a1, a2), "00a62037       selnez    a0, a1, a2");
+
+
+    COMPARE(seleqz(D, f3, f4, f5), "462520d4       seleqz.d    f3, f4, f5");
+    COMPARE(selnez(D, f3, f4, f5), "462520d7       selnez.d    f3, f4, f5");
+
+    COMPARE(min(D, f3, f4, f5), "462520dc       min.d    f3, f4, f5");
+    COMPARE(max(D, f3, f4, f5), "462520de       max.d    f3, f4, f5");
+    VERIFY_RUN();
+  }
+}
index 638cfee3b82a9998caf1efc680a60f6ba02f9f15..2914cb66dda2fc3f57816639f9112df9d863cbb6 100644 (file)
@@ -92,25 +92,6 @@ if (failure) { \
   }
 
 
-TEST(Type1) {
-  if (kArchVariant == kMips64r6) {
-    SET_UP();
-    COMPARE(seleqz(a0, a1, a2), "00853035       seleqz    a0, a1, a2");
-    COMPARE(selnez(a0, a1, a2), "00853037       selnez    a0, a1, a2");
-
-
-    COMPARE(seleqz(D, f3, f4, f5), "462428d4       seleqz.D    f4, f5, f3");
-    COMPARE(selnez(D, f3, f4, f5), "462428d7       selnez.D    f4, f5, f3");
-
-    /*COMPARE(min(D, f3, f4, f5),
-          "462428dc       min.D    f4, f5, f3");
-    COMPARE(max(D, f3, f4, f5),
-          "462428de       max.D    f4, f5, f3");*/
-    VERIFY_RUN();
-  }
-}
-
-
 TEST(Type0) {
   SET_UP();
 
@@ -690,3 +671,20 @@ TEST(Type0) {
 
   VERIFY_RUN();
 }
+
+
+TEST(Type1) {
+  if (kArchVariant == kMips64r6) {
+    SET_UP();
+    COMPARE(seleqz(a0, a1, a2), "00a62035       seleqz    a0, a1, a2");
+    COMPARE(selnez(a0, a1, a2), "00a62037       selnez    a0, a1, a2");
+
+
+    COMPARE(seleqz(D, f3, f4, f5), "462520d4       seleqz.d    f3, f4, f5");
+    COMPARE(selnez(D, f3, f4, f5), "462520d7       selnez.d    f3, f4, f5");
+
+    COMPARE(min(D, f3, f4, f5), "462520dc       min.d    f3, f4, f5");
+    COMPARE(max(D, f3, f4, f5), "462520de       max.d    f3, f4, f5");
+    VERIFY_RUN();
+  }
+}