MIPS32: Fix and refactor in/out reg mask code

This is mostly for clarity and future work.

This fixes the following:
- aui has an out reg, not an in/out reg
- maddv.df, msubv.df, fmadd.df, fmsub.df have an
  in/out reg, not a simply out reg

This also ensures consistent marking of even-numbered 32-bit
FPRs used by FPR load and store instructions (odd-numbered
32-bit FPRs remain unmarked as if there are no paired FPRs;
we don't use odd-numbered 32-bit FPRs to hold single-precision
values).

Test: test-art-host-gtest
Test: booted MIPS32R2 in QEMU
Test: booted MIPS64R6 in QEMU
Test: testrunner.py --target --optimizing --32
      (on CI20 and MIPS32R6)
Test: test-art-target-gtest32
      (on CI20 and MIPS32R6)

Change-Id: I408b8ac063c9b1cc6f036dda095d1e3e1e2e1ef1
diff --git a/compiler/utils/mips/assembler_mips.cc b/compiler/utils/mips/assembler_mips.cc
index eb75f8b..2218ef9 100644
--- a/compiler/utils/mips/assembler_mips.cc
+++ b/compiler/utils/mips/assembler_mips.cc
@@ -42,26 +42,13 @@
 
 MipsAssembler::DelaySlot::DelaySlot()
     : instruction_(0),
-      gpr_outs_mask_(0),
-      gpr_ins_mask_(0),
-      fpr_outs_mask_(0),
-      fpr_ins_mask_(0),
-      cc_outs_mask_(0),
-      cc_ins_mask_(0),
       patcher_label_(nullptr) {}
 
-void MipsAssembler::DsFsmInstr(uint32_t instruction,
-                               uint32_t gpr_outs_mask,
-                               uint32_t gpr_ins_mask,
-                               uint32_t fpr_outs_mask,
-                               uint32_t fpr_ins_mask,
-                               uint32_t cc_outs_mask,
-                               uint32_t cc_ins_mask,
-                               MipsLabel* patcher_label) {
+InOutRegMasks& MipsAssembler::DsFsmInstr(uint32_t instruction, MipsLabel* patcher_label) {
   if (!reordering_) {
     CHECK_EQ(ds_fsm_state_, kExpectingLabel);
     CHECK_EQ(delay_slot_.instruction_, 0u);
-    return;
+    return delay_slot_.masks_;
   }
   switch (ds_fsm_state_) {
     case kExpectingLabel:
@@ -92,13 +79,9 @@
       break;
   }
   delay_slot_.instruction_ = instruction;
-  delay_slot_.gpr_outs_mask_ = gpr_outs_mask & ~1u;  // Ignore register ZERO.
-  delay_slot_.gpr_ins_mask_ = gpr_ins_mask & ~1u;  // Ignore register ZERO.
-  delay_slot_.fpr_outs_mask_ = fpr_outs_mask;
-  delay_slot_.fpr_ins_mask_ = fpr_ins_mask;
-  delay_slot_.cc_outs_mask_ = cc_outs_mask;
-  delay_slot_.cc_ins_mask_ = cc_ins_mask;
+  delay_slot_.masks_ = InOutRegMasks();
   delay_slot_.patcher_label_ = patcher_label;
+  return delay_slot_.masks_;
 }
 
 void MipsAssembler::DsFsmLabel() {
@@ -167,73 +150,7 @@
 }
 
 void MipsAssembler::DsFsmInstrNop(uint32_t instruction ATTRIBUTE_UNUSED) {
-  DsFsmInstr(0, 0, 0, 0, 0, 0, 0);
-}
-
-void MipsAssembler::DsFsmInstrRrr(uint32_t instruction,
-                                  Register out,
-                                  Register in1,
-                                  Register in2,
-                                  MipsLabel* patcher_label) {
-  DsFsmInstr(instruction, (1u << out), (1u << in1) | (1u << in2), 0, 0, 0, 0, patcher_label);
-}
-
-void MipsAssembler::DsFsmInstrRrrr(uint32_t instruction,
-                                   Register in1_out,
-                                   Register in2,
-                                   Register in3) {
-  DsFsmInstr(instruction, (1u << in1_out), (1u << in1_out) | (1u << in2) | (1u << in3), 0, 0, 0, 0);
-}
-
-void MipsAssembler::DsFsmInstrFff(uint32_t instruction,
-                                  FRegister out,
-                                  FRegister in1,
-                                  FRegister in2) {
-  DsFsmInstr(instruction, 0, 0, (1u << out), (1u << in1) | (1u << in2), 0, 0);
-}
-
-void MipsAssembler::DsFsmInstrFfff(uint32_t instruction,
-                                   FRegister in1_out,
-                                   FRegister in2,
-                                   FRegister in3) {
-  DsFsmInstr(instruction, 0, 0, (1u << in1_out), (1u << in1_out) | (1u << in2) | (1u << in3), 0, 0);
-}
-
-void MipsAssembler::DsFsmInstrFffr(uint32_t instruction,
-                                   FRegister in1_out,
-                                   FRegister in2,
-                                   Register in3) {
-  DsFsmInstr(instruction, 0, (1u << in3), (1u << in1_out), (1u << in1_out) | (1u << in2), 0, 0);
-}
-
-void MipsAssembler::DsFsmInstrRf(uint32_t instruction, Register out, FRegister in) {
-  DsFsmInstr(instruction, (1u << out), 0, 0, (1u << in), 0, 0);
-}
-
-void MipsAssembler::DsFsmInstrFr(uint32_t instruction, FRegister out, Register in) {
-  DsFsmInstr(instruction, 0, (1u << in), (1u << out), 0, 0, 0);
-}
-
-void MipsAssembler::DsFsmInstrFR(uint32_t instruction, FRegister in1, Register in2) {
-  DsFsmInstr(instruction, 0, (1u << in2), 0, (1u << in1), 0, 0);
-}
-
-void MipsAssembler::DsFsmInstrCff(uint32_t instruction, int cc_out, FRegister in1, FRegister in2) {
-  DsFsmInstr(instruction, 0, 0, 0, (1u << in1) | (1u << in2), (1 << cc_out), 0);
-}
-
-void MipsAssembler::DsFsmInstrRrrc(uint32_t instruction,
-                                   Register in1_out,
-                                   Register in2,
-                                   int cc_in) {
-  DsFsmInstr(instruction, (1u << in1_out), (1u << in1_out) | (1u << in2), 0, 0, 0, (1 << cc_in));
-}
-
-void MipsAssembler::DsFsmInstrFffc(uint32_t instruction,
-                                   FRegister in1_out,
-                                   FRegister in2,
-                                   int cc_in) {
-  DsFsmInstr(instruction, 0, 0, (1u << in1_out), (1u << in1_out) | (1u << in2), 0, (1 << cc_in));
+  DsFsmInstr(0);
 }
 
 void MipsAssembler::FinalizeCode() {
@@ -535,14 +452,14 @@
 }
 
 void MipsAssembler::Addu(Register rd, Register rs, Register rt) {
-  DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x21), rd, rs, rt);
+  DsFsmInstr(EmitR(0, rs, rt, rd, 0, 0x21)).GprOuts(rd).GprIns(rs, rt);
 }
 
 void MipsAssembler::Addiu(Register rt, Register rs, uint16_t imm16, MipsLabel* patcher_label) {
   if (patcher_label != nullptr) {
     Bind(patcher_label);
   }
-  DsFsmInstrRrr(EmitI(0x9, rs, rt, imm16), rt, rs, rs, patcher_label);
+  DsFsmInstr(EmitI(0x9, rs, rt, imm16), patcher_label).GprOuts(rt).GprIns(rs);
 }
 
 void MipsAssembler::Addiu(Register rt, Register rs, uint16_t imm16) {
@@ -550,32 +467,32 @@
 }
 
 void MipsAssembler::Subu(Register rd, Register rs, Register rt) {
-  DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x23), rd, rs, rt);
+  DsFsmInstr(EmitR(0, rs, rt, rd, 0, 0x23)).GprOuts(rd).GprIns(rs, rt);
 }
 
 void MipsAssembler::MultR2(Register rs, Register rt) {
   CHECK(!IsR6());
-  DsFsmInstrRrr(EmitR(0, rs, rt, static_cast<Register>(0), 0, 0x18), ZERO, rs, rt);
+  DsFsmInstr(EmitR(0, rs, rt, static_cast<Register>(0), 0, 0x18)).GprIns(rs, rt);
 }
 
 void MipsAssembler::MultuR2(Register rs, Register rt) {
   CHECK(!IsR6());
-  DsFsmInstrRrr(EmitR(0, rs, rt, static_cast<Register>(0), 0, 0x19), ZERO, rs, rt);
+  DsFsmInstr(EmitR(0, rs, rt, static_cast<Register>(0), 0, 0x19)).GprIns(rs, rt);
 }
 
 void MipsAssembler::DivR2(Register rs, Register rt) {
   CHECK(!IsR6());
-  DsFsmInstrRrr(EmitR(0, rs, rt, static_cast<Register>(0), 0, 0x1a), ZERO, rs, rt);
+  DsFsmInstr(EmitR(0, rs, rt, static_cast<Register>(0), 0, 0x1a)).GprIns(rs, rt);
 }
 
 void MipsAssembler::DivuR2(Register rs, Register rt) {
   CHECK(!IsR6());
-  DsFsmInstrRrr(EmitR(0, rs, rt, static_cast<Register>(0), 0, 0x1b), ZERO, rs, rt);
+  DsFsmInstr(EmitR(0, rs, rt, static_cast<Register>(0), 0, 0x1b)).GprIns(rs, rt);
 }
 
 void MipsAssembler::MulR2(Register rd, Register rs, Register rt) {
   CHECK(!IsR6());
-  DsFsmInstrRrr(EmitR(0x1c, rs, rt, rd, 0, 2), rd, rs, rt);
+  DsFsmInstr(EmitR(0x1c, rs, rt, rd, 0, 2)).GprOuts(rd).GprIns(rs, rt);
 }
 
 void MipsAssembler::DivR2(Register rd, Register rs, Register rt) {
@@ -604,179 +521,181 @@
 
 void MipsAssembler::MulR6(Register rd, Register rs, Register rt) {
   CHECK(IsR6());
-  DsFsmInstrRrr(EmitR(0, rs, rt, rd, 2, 0x18), rd, rs, rt);
+  DsFsmInstr(EmitR(0, rs, rt, rd, 2, 0x18)).GprOuts(rd).GprIns(rs, rt);
 }
 
 void MipsAssembler::MuhR6(Register rd, Register rs, Register rt) {
   CHECK(IsR6());
-  DsFsmInstrRrr(EmitR(0, rs, rt, rd, 3, 0x18), rd, rs, rt);
+  DsFsmInstr(EmitR(0, rs, rt, rd, 3, 0x18)).GprOuts(rd).GprIns(rs, rt);
 }
 
 void MipsAssembler::MuhuR6(Register rd, Register rs, Register rt) {
   CHECK(IsR6());
-  DsFsmInstrRrr(EmitR(0, rs, rt, rd, 3, 0x19), rd, rs, rt);
+  DsFsmInstr(EmitR(0, rs, rt, rd, 3, 0x19)).GprOuts(rd).GprIns(rs, rt);
 }
 
 void MipsAssembler::DivR6(Register rd, Register rs, Register rt) {
   CHECK(IsR6());
-  DsFsmInstrRrr(EmitR(0, rs, rt, rd, 2, 0x1a), rd, rs, rt);
+  DsFsmInstr(EmitR(0, rs, rt, rd, 2, 0x1a)).GprOuts(rd).GprIns(rs, rt);
 }
 
 void MipsAssembler::ModR6(Register rd, Register rs, Register rt) {
   CHECK(IsR6());
-  DsFsmInstrRrr(EmitR(0, rs, rt, rd, 3, 0x1a), rd, rs, rt);
+  DsFsmInstr(EmitR(0, rs, rt, rd, 3, 0x1a)).GprOuts(rd).GprIns(rs, rt);
 }
 
 void MipsAssembler::DivuR6(Register rd, Register rs, Register rt) {
   CHECK(IsR6());
-  DsFsmInstrRrr(EmitR(0, rs, rt, rd, 2, 0x1b), rd, rs, rt);
+  DsFsmInstr(EmitR(0, rs, rt, rd, 2, 0x1b)).GprOuts(rd).GprIns(rs, rt);
 }
 
 void MipsAssembler::ModuR6(Register rd, Register rs, Register rt) {
   CHECK(IsR6());
-  DsFsmInstrRrr(EmitR(0, rs, rt, rd, 3, 0x1b), rd, rs, rt);
+  DsFsmInstr(EmitR(0, rs, rt, rd, 3, 0x1b)).GprOuts(rd).GprIns(rs, rt);
 }
 
 void MipsAssembler::And(Register rd, Register rs, Register rt) {
-  DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x24), rd, rs, rt);
+  DsFsmInstr(EmitR(0, rs, rt, rd, 0, 0x24)).GprOuts(rd).GprIns(rs, rt);
 }
 
 void MipsAssembler::Andi(Register rt, Register rs, uint16_t imm16) {
-  DsFsmInstrRrr(EmitI(0xc, rs, rt, imm16), rt, rs, rs);
+  DsFsmInstr(EmitI(0xc, rs, rt, imm16)).GprOuts(rt).GprIns(rs);
 }
 
 void MipsAssembler::Or(Register rd, Register rs, Register rt) {
-  DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x25), rd, rs, rt);
+  DsFsmInstr(EmitR(0, rs, rt, rd, 0, 0x25)).GprOuts(rd).GprIns(rs, rt);
 }
 
 void MipsAssembler::Ori(Register rt, Register rs, uint16_t imm16) {
-  DsFsmInstrRrr(EmitI(0xd, rs, rt, imm16), rt, rs, rs);
+  DsFsmInstr(EmitI(0xd, rs, rt, imm16)).GprOuts(rt).GprIns(rs);
 }
 
 void MipsAssembler::Xor(Register rd, Register rs, Register rt) {
-  DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x26), rd, rs, rt);
+  DsFsmInstr(EmitR(0, rs, rt, rd, 0, 0x26)).GprOuts(rd).GprIns(rs, rt);
 }
 
 void MipsAssembler::Xori(Register rt, Register rs, uint16_t imm16) {
-  DsFsmInstrRrr(EmitI(0xe, rs, rt, imm16), rt, rs, rs);
+  DsFsmInstr(EmitI(0xe, rs, rt, imm16)).GprOuts(rt).GprIns(rs);
 }
 
 void MipsAssembler::Nor(Register rd, Register rs, Register rt) {
-  DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x27), rd, rs, rt);
+  DsFsmInstr(EmitR(0, rs, rt, rd, 0, 0x27)).GprOuts(rd).GprIns(rs, rt);
 }
 
 void MipsAssembler::Movz(Register rd, Register rs, Register rt) {
   CHECK(!IsR6());
-  DsFsmInstrRrrr(EmitR(0, rs, rt, rd, 0, 0x0A), rd, rs, rt);
+  DsFsmInstr(EmitR(0, rs, rt, rd, 0, 0x0A)).GprInOuts(rd).GprIns(rs, rt);
 }
 
 void MipsAssembler::Movn(Register rd, Register rs, Register rt) {
   CHECK(!IsR6());
-  DsFsmInstrRrrr(EmitR(0, rs, rt, rd, 0, 0x0B), rd, rs, rt);
+  DsFsmInstr(EmitR(0, rs, rt, rd, 0, 0x0B)).GprInOuts(rd).GprIns(rs, rt);
 }
 
 void MipsAssembler::Seleqz(Register rd, Register rs, Register rt) {
   CHECK(IsR6());
-  DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x35), rd, rs, rt);
+  DsFsmInstr(EmitR(0, rs, rt, rd, 0, 0x35)).GprOuts(rd).GprIns(rs, rt);
 }
 
 void MipsAssembler::Selnez(Register rd, Register rs, Register rt) {
   CHECK(IsR6());
-  DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x37), rd, rs, rt);
+  DsFsmInstr(EmitR(0, rs, rt, rd, 0, 0x37)).GprOuts(rd).GprIns(rs, rt);
 }
 
 void MipsAssembler::ClzR6(Register rd, Register rs) {
   CHECK(IsR6());
-  DsFsmInstrRrr(EmitR(0, rs, static_cast<Register>(0), rd, 0x01, 0x10), rd, rs, rs);
+  DsFsmInstr(EmitR(0, rs, static_cast<Register>(0), rd, 0x01, 0x10)).GprOuts(rd).GprIns(rs);
 }
 
 void MipsAssembler::ClzR2(Register rd, Register rs) {
   CHECK(!IsR6());
-  DsFsmInstrRrr(EmitR(0x1C, rs, rd, rd, 0, 0x20), rd, rs, rs);
+  DsFsmInstr(EmitR(0x1C, rs, rd, rd, 0, 0x20)).GprOuts(rd).GprIns(rs);
 }
 
 void MipsAssembler::CloR6(Register rd, Register rs) {
   CHECK(IsR6());
-  DsFsmInstrRrr(EmitR(0, rs, static_cast<Register>(0), rd, 0x01, 0x11), rd, rs, rs);
+  DsFsmInstr(EmitR(0, rs, static_cast<Register>(0), rd, 0x01, 0x11)).GprOuts(rd).GprIns(rs);
 }
 
 void MipsAssembler::CloR2(Register rd, Register rs) {
   CHECK(!IsR6());
-  DsFsmInstrRrr(EmitR(0x1C, rs, rd, rd, 0, 0x21), rd, rs, rs);
+  DsFsmInstr(EmitR(0x1C, rs, rd, rd, 0, 0x21)).GprOuts(rd).GprIns(rs);
 }
 
 void MipsAssembler::Seb(Register rd, Register rt) {
-  DsFsmInstrRrr(EmitR(0x1f, static_cast<Register>(0), rt, rd, 0x10, 0x20), rd, rt, rt);
+  DsFsmInstr(EmitR(0x1f, static_cast<Register>(0), rt, rd, 0x10, 0x20)).GprOuts(rd).GprIns(rt);
 }
 
 void MipsAssembler::Seh(Register rd, Register rt) {
-  DsFsmInstrRrr(EmitR(0x1f, static_cast<Register>(0), rt, rd, 0x18, 0x20), rd, rt, rt);
+  DsFsmInstr(EmitR(0x1f, static_cast<Register>(0), rt, rd, 0x18, 0x20)).GprOuts(rd).GprIns(rt);
 }
 
 void MipsAssembler::Wsbh(Register rd, Register rt) {
-  DsFsmInstrRrr(EmitR(0x1f, static_cast<Register>(0), rt, rd, 2, 0x20), rd, rt, rt);
+  DsFsmInstr(EmitR(0x1f, static_cast<Register>(0), rt, rd, 2, 0x20)).GprOuts(rd).GprIns(rt);
 }
 
 void MipsAssembler::Bitswap(Register rd, Register rt) {
   CHECK(IsR6());
-  DsFsmInstrRrr(EmitR(0x1f, static_cast<Register>(0), rt, rd, 0x0, 0x20), rd, rt, rt);
+  DsFsmInstr(EmitR(0x1f, static_cast<Register>(0), rt, rd, 0x0, 0x20)).GprOuts(rd).GprIns(rt);
 }
 
 void MipsAssembler::Sll(Register rd, Register rt, int shamt) {
   CHECK(IsUint<5>(shamt)) << shamt;
-  DsFsmInstrRrr(EmitR(0, static_cast<Register>(0), rt, rd, shamt, 0x00), rd, rt, rt);
+  DsFsmInstr(EmitR(0, static_cast<Register>(0), rt, rd, shamt, 0x00)).GprOuts(rd).GprIns(rt);
 }
 
 void MipsAssembler::Srl(Register rd, Register rt, int shamt) {
   CHECK(IsUint<5>(shamt)) << shamt;
-  DsFsmInstrRrr(EmitR(0, static_cast<Register>(0), rt, rd, shamt, 0x02), rd, rt, rt);
+  DsFsmInstr(EmitR(0, static_cast<Register>(0), rt, rd, shamt, 0x02)).GprOuts(rd).GprIns(rt);
 }
 
 void MipsAssembler::Rotr(Register rd, Register rt, int shamt) {
   CHECK(IsUint<5>(shamt)) << shamt;
-  DsFsmInstrRrr(EmitR(0, static_cast<Register>(1), rt, rd, shamt, 0x02), rd, rt, rt);
+  DsFsmInstr(EmitR(0, static_cast<Register>(1), rt, rd, shamt, 0x02)).GprOuts(rd).GprIns(rt);
 }
 
 void MipsAssembler::Sra(Register rd, Register rt, int shamt) {
   CHECK(IsUint<5>(shamt)) << shamt;
-  DsFsmInstrRrr(EmitR(0, static_cast<Register>(0), rt, rd, shamt, 0x03), rd, rt, rt);
+  DsFsmInstr(EmitR(0, static_cast<Register>(0), rt, rd, shamt, 0x03)).GprOuts(rd).GprIns(rt);
 }
 
 void MipsAssembler::Sllv(Register rd, Register rt, Register rs) {
-  DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x04), rd, rs, rt);
+  DsFsmInstr(EmitR(0, rs, rt, rd, 0, 0x04)).GprOuts(rd).GprIns(rs, rt);
 }
 
 void MipsAssembler::Srlv(Register rd, Register rt, Register rs) {
-  DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x06), rd, rs, rt);
+  DsFsmInstr(EmitR(0, rs, rt, rd, 0, 0x06)).GprOuts(rd).GprIns(rs, rt);
 }
 
 void MipsAssembler::Rotrv(Register rd, Register rt, Register rs) {
-  DsFsmInstrRrr(EmitR(0, rs, rt, rd, 1, 0x06), rd, rs, rt);
+  DsFsmInstr(EmitR(0, rs, rt, rd, 1, 0x06)).GprOuts(rd).GprIns(rs, rt);
 }
 
 void MipsAssembler::Srav(Register rd, Register rt, Register rs) {
-  DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x07), rd, rs, rt);
+  DsFsmInstr(EmitR(0, rs, rt, rd, 0, 0x07)).GprOuts(rd).GprIns(rs, rt);
 }
 
 void MipsAssembler::Ext(Register rd, Register rt, int pos, int size) {
   CHECK(IsUint<5>(pos)) << pos;
   CHECK(0 < size && size <= 32) << size;
   CHECK(0 < pos + size && pos + size <= 32) << pos << " + " << size;
-  DsFsmInstrRrr(EmitR(0x1f, rt, rd, static_cast<Register>(size - 1), pos, 0x00), rd, rt, rt);
+  DsFsmInstr(EmitR(0x1f, rt, rd, static_cast<Register>(size - 1), pos, 0x00))
+      .GprOuts(rd).GprIns(rt);
 }
 
 void MipsAssembler::Ins(Register rd, Register rt, int pos, int size) {
   CHECK(IsUint<5>(pos)) << pos;
   CHECK(0 < size && size <= 32) << size;
   CHECK(0 < pos + size && pos + size <= 32) << pos << " + " << size;
-  DsFsmInstrRrr(EmitR(0x1f, rt, rd, static_cast<Register>(pos + size - 1), pos, 0x04), rd, rd, rt);
+  DsFsmInstr(EmitR(0x1f, rt, rd, static_cast<Register>(pos + size - 1), pos, 0x04))
+      .GprInOuts(rd).GprIns(rt);
 }
 
 void MipsAssembler::Lsa(Register rd, Register rs, Register rt, int saPlusOne) {
   CHECK(IsR6() || HasMsa());
   CHECK(1 <= saPlusOne && saPlusOne <= 4) << saPlusOne;
   int sa = saPlusOne - 1;
-  DsFsmInstrRrr(EmitR(0x0, rs, rt, rd, sa, 0x05), rd, rs, rt);
+  DsFsmInstr(EmitR(0x0, rs, rt, rd, sa, 0x05)).GprOuts(rd).GprIns(rs, rt);
 }
 
 void MipsAssembler::ShiftAndAdd(Register dst,
@@ -798,18 +717,18 @@
 }
 
 void MipsAssembler::Lb(Register rt, Register rs, uint16_t imm16) {
-  DsFsmInstrRrr(EmitI(0x20, rs, rt, imm16), rt, rs, rs);
+  DsFsmInstr(EmitI(0x20, rs, rt, imm16)).GprOuts(rt).GprIns(rs);
 }
 
 void MipsAssembler::Lh(Register rt, Register rs, uint16_t imm16) {
-  DsFsmInstrRrr(EmitI(0x21, rs, rt, imm16), rt, rs, rs);
+  DsFsmInstr(EmitI(0x21, rs, rt, imm16)).GprOuts(rt).GprIns(rs);
 }
 
 void MipsAssembler::Lw(Register rt, Register rs, uint16_t imm16, MipsLabel* patcher_label) {
   if (patcher_label != nullptr) {
     Bind(patcher_label);
   }
-  DsFsmInstrRrr(EmitI(0x23, rs, rt, imm16), rt, rs, rs, patcher_label);
+  DsFsmInstr(EmitI(0x23, rs, rt, imm16), patcher_label).GprOuts(rt).GprIns(rs);
 }
 
 void MipsAssembler::Lw(Register rt, Register rs, uint16_t imm16) {
@@ -818,20 +737,20 @@
 
 void MipsAssembler::Lwl(Register rt, Register rs, uint16_t imm16) {
   CHECK(!IsR6());
-  DsFsmInstrRrr(EmitI(0x22, rs, rt, imm16), rt, rt, rs);
+  DsFsmInstr(EmitI(0x22, rs, rt, imm16)).GprInOuts(rt).GprIns(rs);
 }
 
 void MipsAssembler::Lwr(Register rt, Register rs, uint16_t imm16) {
   CHECK(!IsR6());
-  DsFsmInstrRrr(EmitI(0x26, rs, rt, imm16), rt, rt, rs);
+  DsFsmInstr(EmitI(0x26, rs, rt, imm16)).GprInOuts(rt).GprIns(rs);
 }
 
 void MipsAssembler::Lbu(Register rt, Register rs, uint16_t imm16) {
-  DsFsmInstrRrr(EmitI(0x24, rs, rt, imm16), rt, rs, rs);
+  DsFsmInstr(EmitI(0x24, rs, rt, imm16)).GprOuts(rt).GprIns(rs);
 }
 
 void MipsAssembler::Lhu(Register rt, Register rs, uint16_t imm16) {
-  DsFsmInstrRrr(EmitI(0x25, rs, rt, imm16), rt, rs, rs);
+  DsFsmInstr(EmitI(0x25, rs, rt, imm16)).GprOuts(rt).GprIns(rs);
 }
 
 void MipsAssembler::Lwpc(Register rs, uint32_t imm19) {
@@ -841,12 +760,12 @@
 }
 
 void MipsAssembler::Lui(Register rt, uint16_t imm16) {
-  DsFsmInstrRrr(EmitI(0xf, static_cast<Register>(0), rt, imm16), rt, ZERO, ZERO);
+  DsFsmInstr(EmitI(0xf, static_cast<Register>(0), rt, imm16)).GprOuts(rt);
 }
 
 void MipsAssembler::Aui(Register rt, Register rs, uint16_t imm16) {
   CHECK(IsR6());
-  DsFsmInstrRrr(EmitI(0xf, rs, rt, imm16), rt, rt, rs);
+  DsFsmInstr(EmitI(0xf, rs, rt, imm16)).GprOuts(rt).GprIns(rs);
 }
 
 void MipsAssembler::AddUpper(Register rt, Register rs, uint16_t imm16, Register tmp) {
@@ -871,27 +790,27 @@
 
 void MipsAssembler::Mfhi(Register rd) {
   CHECK(!IsR6());
-  DsFsmInstrRrr(EmitR(0, ZERO, ZERO, rd, 0, 0x10), rd, ZERO, ZERO);
+  DsFsmInstr(EmitR(0, ZERO, ZERO, rd, 0, 0x10)).GprOuts(rd);
 }
 
 void MipsAssembler::Mflo(Register rd) {
   CHECK(!IsR6());
-  DsFsmInstrRrr(EmitR(0, ZERO, ZERO, rd, 0, 0x12), rd, ZERO, ZERO);
+  DsFsmInstr(EmitR(0, ZERO, ZERO, rd, 0, 0x12)).GprOuts(rd);
 }
 
 void MipsAssembler::Sb(Register rt, Register rs, uint16_t imm16) {
-  DsFsmInstrRrr(EmitI(0x28, rs, rt, imm16), ZERO, rt, rs);
+  DsFsmInstr(EmitI(0x28, rs, rt, imm16)).GprIns(rt, rs);
 }
 
 void MipsAssembler::Sh(Register rt, Register rs, uint16_t imm16) {
-  DsFsmInstrRrr(EmitI(0x29, rs, rt, imm16), ZERO, rt, rs);
+  DsFsmInstr(EmitI(0x29, rs, rt, imm16)).GprIns(rt, rs);
 }
 
 void MipsAssembler::Sw(Register rt, Register rs, uint16_t imm16, MipsLabel* patcher_label) {
   if (patcher_label != nullptr) {
     Bind(patcher_label);
   }
-  DsFsmInstrRrr(EmitI(0x2b, rs, rt, imm16), ZERO, rt, rs, patcher_label);
+  DsFsmInstr(EmitI(0x2b, rs, rt, imm16), patcher_label).GprIns(rt, rs);
 }
 
 void MipsAssembler::Sw(Register rt, Register rs, uint16_t imm16) {
@@ -900,50 +819,50 @@
 
 void MipsAssembler::Swl(Register rt, Register rs, uint16_t imm16) {
   CHECK(!IsR6());
-  DsFsmInstrRrr(EmitI(0x2a, rs, rt, imm16), ZERO, rt, rs);
+  DsFsmInstr(EmitI(0x2a, rs, rt, imm16)).GprIns(rt, rs);
 }
 
 void MipsAssembler::Swr(Register rt, Register rs, uint16_t imm16) {
   CHECK(!IsR6());
-  DsFsmInstrRrr(EmitI(0x2e, rs, rt, imm16), ZERO, rt, rs);
+  DsFsmInstr(EmitI(0x2e, rs, rt, imm16)).GprIns(rt, rs);
 }
 
 void MipsAssembler::LlR2(Register rt, Register base, int16_t imm16) {
   CHECK(!IsR6());
-  DsFsmInstrRrr(EmitI(0x30, base, rt, imm16), rt, base, base);
+  DsFsmInstr(EmitI(0x30, base, rt, imm16)).GprOuts(rt).GprIns(base);
 }
 
 void MipsAssembler::ScR2(Register rt, Register base, int16_t imm16) {
   CHECK(!IsR6());
-  DsFsmInstrRrr(EmitI(0x38, base, rt, imm16), rt, rt, base);
+  DsFsmInstr(EmitI(0x38, base, rt, imm16)).GprInOuts(rt).GprIns(base);
 }
 
 void MipsAssembler::LlR6(Register rt, Register base, int16_t imm9) {
   CHECK(IsR6());
   CHECK(IsInt<9>(imm9));
-  DsFsmInstrRrr(EmitI(0x1f, base, rt, ((imm9 & 0x1ff) << 7) | 0x36), rt, base, base);
+  DsFsmInstr(EmitI(0x1f, base, rt, ((imm9 & 0x1ff) << 7) | 0x36)).GprOuts(rt).GprIns(base);
 }
 
 void MipsAssembler::ScR6(Register rt, Register base, int16_t imm9) {
   CHECK(IsR6());
   CHECK(IsInt<9>(imm9));
-  DsFsmInstrRrr(EmitI(0x1f, base, rt, ((imm9 & 0x1ff) << 7) | 0x26), rt, rt, base);
+  DsFsmInstr(EmitI(0x1f, base, rt, ((imm9 & 0x1ff) << 7) | 0x26)).GprInOuts(rt).GprIns(base);
 }
 
 void MipsAssembler::Slt(Register rd, Register rs, Register rt) {
-  DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x2a), rd, rs, rt);
+  DsFsmInstr(EmitR(0, rs, rt, rd, 0, 0x2a)).GprOuts(rd).GprIns(rs, rt);
 }
 
 void MipsAssembler::Sltu(Register rd, Register rs, Register rt) {
-  DsFsmInstrRrr(EmitR(0, rs, rt, rd, 0, 0x2b), rd, rs, rt);
+  DsFsmInstr(EmitR(0, rs, rt, rd, 0, 0x2b)).GprOuts(rd).GprIns(rs, rt);
 }
 
 void MipsAssembler::Slti(Register rt, Register rs, uint16_t imm16) {
-  DsFsmInstrRrr(EmitI(0xa, rs, rt, imm16), rt, rs, rs);
+  DsFsmInstr(EmitI(0xa, rs, rt, imm16)).GprOuts(rt).GprIns(rs);
 }
 
 void MipsAssembler::Sltiu(Register rt, Register rs, uint16_t imm16) {
-  DsFsmInstrRrr(EmitI(0xb, rs, rt, imm16), rt, rs, rs);
+  DsFsmInstr(EmitI(0xb, rs, rt, imm16)).GprOuts(rt).GprIns(rs);
 }
 
 void MipsAssembler::B(uint16_t imm16) {
@@ -1021,8 +940,8 @@
   uint32_t last_instruction = delay_slot_.instruction_;
   MipsLabel* patcher_label = delay_slot_.patcher_label_;
   bool exchange = (last_instruction != 0 &&
-      (delay_slot_.gpr_outs_mask_ & (1u << rs)) == 0 &&
-      ((delay_slot_.gpr_ins_mask_ | delay_slot_.gpr_outs_mask_) & (1u << rd)) == 0);
+      (delay_slot_.masks_.gpr_outs_ & (1u << rs)) == 0 &&
+      ((delay_slot_.masks_.gpr_ins_ | delay_slot_.masks_.gpr_outs_) & (1u << rd)) == 0);
   if (exchange) {
     // The last instruction cannot be used in a different delay slot,
     // do not commit the label before it (if any).
@@ -1305,67 +1224,67 @@
 }
 
 void MipsAssembler::AddS(FRegister fd, FRegister fs, FRegister ft) {
-  DsFsmInstrFff(EmitFR(0x11, 0x10, ft, fs, fd, 0x0), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x10, ft, fs, fd, 0x0)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::SubS(FRegister fd, FRegister fs, FRegister ft) {
-  DsFsmInstrFff(EmitFR(0x11, 0x10, ft, fs, fd, 0x1), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x10, ft, fs, fd, 0x1)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::MulS(FRegister fd, FRegister fs, FRegister ft) {
-  DsFsmInstrFff(EmitFR(0x11, 0x10, ft, fs, fd, 0x2), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x10, ft, fs, fd, 0x2)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::DivS(FRegister fd, FRegister fs, FRegister ft) {
-  DsFsmInstrFff(EmitFR(0x11, 0x10, ft, fs, fd, 0x3), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x10, ft, fs, fd, 0x3)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::AddD(FRegister fd, FRegister fs, FRegister ft) {
-  DsFsmInstrFff(EmitFR(0x11, 0x11, ft, fs, fd, 0x0), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x11, ft, fs, fd, 0x0)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::SubD(FRegister fd, FRegister fs, FRegister ft) {
-  DsFsmInstrFff(EmitFR(0x11, 0x11, ft, fs, fd, 0x1), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x11, ft, fs, fd, 0x1)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::MulD(FRegister fd, FRegister fs, FRegister ft) {
-  DsFsmInstrFff(EmitFR(0x11, 0x11, ft, fs, fd, 0x2), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x11, ft, fs, fd, 0x2)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::DivD(FRegister fd, FRegister fs, FRegister ft) {
-  DsFsmInstrFff(EmitFR(0x11, 0x11, ft, fs, fd, 0x3), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x11, ft, fs, fd, 0x3)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::SqrtS(FRegister fd, FRegister fs) {
-  DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x4), fd, fs, fs);
+  DsFsmInstr(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x4)).FprOuts(fd).FprIns(fs);
 }
 
 void MipsAssembler::SqrtD(FRegister fd, FRegister fs) {
-  DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x4), fd, fs, fs);
+  DsFsmInstr(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x4)).FprOuts(fd).FprIns(fs);
 }
 
 void MipsAssembler::AbsS(FRegister fd, FRegister fs) {
-  DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x5), fd, fs, fs);
+  DsFsmInstr(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x5)).FprOuts(fd).FprIns(fs);
 }
 
 void MipsAssembler::AbsD(FRegister fd, FRegister fs) {
-  DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x5), fd, fs, fs);
+  DsFsmInstr(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x5)).FprOuts(fd).FprIns(fs);
 }
 
 void MipsAssembler::MovS(FRegister fd, FRegister fs) {
-  DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x6), fd, fs, fs);
+  DsFsmInstr(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x6)).FprOuts(fd).FprIns(fs);
 }
 
 void MipsAssembler::MovD(FRegister fd, FRegister fs) {
-  DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x6), fd, fs, fs);
+  DsFsmInstr(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x6)).FprOuts(fd).FprIns(fs);
 }
 
 void MipsAssembler::NegS(FRegister fd, FRegister fs) {
-  DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x7), fd, fs, fs);
+  DsFsmInstr(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x7)).FprOuts(fd).FprIns(fs);
 }
 
 void MipsAssembler::NegD(FRegister fd, FRegister fs) {
-  DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x7), fd, fs, fs);
+  DsFsmInstr(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x7)).FprOuts(fd).FprIns(fs);
 }
 
 void MipsAssembler::CunS(FRegister fs, FRegister ft) {
@@ -1375,7 +1294,8 @@
 void MipsAssembler::CunS(int cc, FRegister fs, FRegister ft) {
   CHECK(!IsR6());
   CHECK(IsUint<3>(cc)) << cc;
-  DsFsmInstrCff(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x31), cc, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x31))
+      .CcOuts(cc).FprIns(fs, ft);
 }
 
 void MipsAssembler::CeqS(FRegister fs, FRegister ft) {
@@ -1385,7 +1305,8 @@
 void MipsAssembler::CeqS(int cc, FRegister fs, FRegister ft) {
   CHECK(!IsR6());
   CHECK(IsUint<3>(cc)) << cc;
-  DsFsmInstrCff(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x32), cc, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x32))
+      .CcOuts(cc).FprIns(fs, ft);
 }
 
 void MipsAssembler::CueqS(FRegister fs, FRegister ft) {
@@ -1395,7 +1316,8 @@
 void MipsAssembler::CueqS(int cc, FRegister fs, FRegister ft) {
   CHECK(!IsR6());
   CHECK(IsUint<3>(cc)) << cc;
-  DsFsmInstrCff(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x33), cc, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x33))
+      .CcOuts(cc).FprIns(fs, ft);
 }
 
 void MipsAssembler::ColtS(FRegister fs, FRegister ft) {
@@ -1405,7 +1327,8 @@
 void MipsAssembler::ColtS(int cc, FRegister fs, FRegister ft) {
   CHECK(!IsR6());
   CHECK(IsUint<3>(cc)) << cc;
-  DsFsmInstrCff(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x34), cc, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x34))
+      .CcOuts(cc).FprIns(fs, ft);
 }
 
 void MipsAssembler::CultS(FRegister fs, FRegister ft) {
@@ -1415,7 +1338,8 @@
 void MipsAssembler::CultS(int cc, FRegister fs, FRegister ft) {
   CHECK(!IsR6());
   CHECK(IsUint<3>(cc)) << cc;
-  DsFsmInstrCff(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x35), cc, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x35))
+      .CcOuts(cc).FprIns(fs, ft);
 }
 
 void MipsAssembler::ColeS(FRegister fs, FRegister ft) {
@@ -1425,7 +1349,8 @@
 void MipsAssembler::ColeS(int cc, FRegister fs, FRegister ft) {
   CHECK(!IsR6());
   CHECK(IsUint<3>(cc)) << cc;
-  DsFsmInstrCff(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x36), cc, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x36))
+      .CcOuts(cc).FprIns(fs, ft);
 }
 
 void MipsAssembler::CuleS(FRegister fs, FRegister ft) {
@@ -1435,7 +1360,8 @@
 void MipsAssembler::CuleS(int cc, FRegister fs, FRegister ft) {
   CHECK(!IsR6());
   CHECK(IsUint<3>(cc)) << cc;
-  DsFsmInstrCff(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x37), cc, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x37))
+      .CcOuts(cc).FprIns(fs, ft);
 }
 
 void MipsAssembler::CunD(FRegister fs, FRegister ft) {
@@ -1445,7 +1371,8 @@
 void MipsAssembler::CunD(int cc, FRegister fs, FRegister ft) {
   CHECK(!IsR6());
   CHECK(IsUint<3>(cc)) << cc;
-  DsFsmInstrCff(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x31), cc, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x31))
+      .CcOuts(cc).FprIns(fs, ft);
 }
 
 void MipsAssembler::CeqD(FRegister fs, FRegister ft) {
@@ -1455,7 +1382,8 @@
 void MipsAssembler::CeqD(int cc, FRegister fs, FRegister ft) {
   CHECK(!IsR6());
   CHECK(IsUint<3>(cc)) << cc;
-  DsFsmInstrCff(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x32), cc, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x32))
+      .CcOuts(cc).FprIns(fs, ft);
 }
 
 void MipsAssembler::CueqD(FRegister fs, FRegister ft) {
@@ -1465,7 +1393,8 @@
 void MipsAssembler::CueqD(int cc, FRegister fs, FRegister ft) {
   CHECK(!IsR6());
   CHECK(IsUint<3>(cc)) << cc;
-  DsFsmInstrCff(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x33), cc, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x33))
+      .CcOuts(cc).FprIns(fs, ft);
 }
 
 void MipsAssembler::ColtD(FRegister fs, FRegister ft) {
@@ -1475,7 +1404,8 @@
 void MipsAssembler::ColtD(int cc, FRegister fs, FRegister ft) {
   CHECK(!IsR6());
   CHECK(IsUint<3>(cc)) << cc;
-  DsFsmInstrCff(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x34), cc, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x34))
+      .CcOuts(cc).FprIns(fs, ft);
 }
 
 void MipsAssembler::CultD(FRegister fs, FRegister ft) {
@@ -1485,7 +1415,8 @@
 void MipsAssembler::CultD(int cc, FRegister fs, FRegister ft) {
   CHECK(!IsR6());
   CHECK(IsUint<3>(cc)) << cc;
-  DsFsmInstrCff(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x35), cc, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x35))
+      .CcOuts(cc).FprIns(fs, ft);
 }
 
 void MipsAssembler::ColeD(FRegister fs, FRegister ft) {
@@ -1495,7 +1426,8 @@
 void MipsAssembler::ColeD(int cc, FRegister fs, FRegister ft) {
   CHECK(!IsR6());
   CHECK(IsUint<3>(cc)) << cc;
-  DsFsmInstrCff(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x36), cc, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x36))
+      .CcOuts(cc).FprIns(fs, ft);
 }
 
 void MipsAssembler::CuleD(FRegister fs, FRegister ft) {
@@ -1505,301 +1437,323 @@
 void MipsAssembler::CuleD(int cc, FRegister fs, FRegister ft) {
   CHECK(!IsR6());
   CHECK(IsUint<3>(cc)) << cc;
-  DsFsmInstrCff(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x37), cc, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x37))
+      .CcOuts(cc).FprIns(fs, ft);
 }
 
 void MipsAssembler::CmpUnS(FRegister fd, FRegister fs, FRegister ft) {
   CHECK(IsR6());
-  DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x01), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x14, ft, fs, fd, 0x01)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::CmpEqS(FRegister fd, FRegister fs, FRegister ft) {
   CHECK(IsR6());
-  DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x02), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x14, ft, fs, fd, 0x02)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::CmpUeqS(FRegister fd, FRegister fs, FRegister ft) {
   CHECK(IsR6());
-  DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x03), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x14, ft, fs, fd, 0x03)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::CmpLtS(FRegister fd, FRegister fs, FRegister ft) {
   CHECK(IsR6());
-  DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x04), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x14, ft, fs, fd, 0x04)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::CmpUltS(FRegister fd, FRegister fs, FRegister ft) {
   CHECK(IsR6());
-  DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x05), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x14, ft, fs, fd, 0x05)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::CmpLeS(FRegister fd, FRegister fs, FRegister ft) {
   CHECK(IsR6());
-  DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x06), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x14, ft, fs, fd, 0x06)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::CmpUleS(FRegister fd, FRegister fs, FRegister ft) {
   CHECK(IsR6());
-  DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x07), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x14, ft, fs, fd, 0x07)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::CmpOrS(FRegister fd, FRegister fs, FRegister ft) {
   CHECK(IsR6());
-  DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x11), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x14, ft, fs, fd, 0x11)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::CmpUneS(FRegister fd, FRegister fs, FRegister ft) {
   CHECK(IsR6());
-  DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x12), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x14, ft, fs, fd, 0x12)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::CmpNeS(FRegister fd, FRegister fs, FRegister ft) {
   CHECK(IsR6());
-  DsFsmInstrFff(EmitFR(0x11, 0x14, ft, fs, fd, 0x13), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x14, ft, fs, fd, 0x13)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::CmpUnD(FRegister fd, FRegister fs, FRegister ft) {
   CHECK(IsR6());
-  DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x01), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x15, ft, fs, fd, 0x01)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::CmpEqD(FRegister fd, FRegister fs, FRegister ft) {
   CHECK(IsR6());
-  DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x02), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x15, ft, fs, fd, 0x02)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::CmpUeqD(FRegister fd, FRegister fs, FRegister ft) {
   CHECK(IsR6());
-  DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x03), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x15, ft, fs, fd, 0x03)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::CmpLtD(FRegister fd, FRegister fs, FRegister ft) {
   CHECK(IsR6());
-  DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x04), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x15, ft, fs, fd, 0x04)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::CmpUltD(FRegister fd, FRegister fs, FRegister ft) {
   CHECK(IsR6());
-  DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x05), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x15, ft, fs, fd, 0x05)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::CmpLeD(FRegister fd, FRegister fs, FRegister ft) {
   CHECK(IsR6());
-  DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x06), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x15, ft, fs, fd, 0x06)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::CmpUleD(FRegister fd, FRegister fs, FRegister ft) {
   CHECK(IsR6());
-  DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x07), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x15, ft, fs, fd, 0x07)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::CmpOrD(FRegister fd, FRegister fs, FRegister ft) {
   CHECK(IsR6());
-  DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x11), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x15, ft, fs, fd, 0x11)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::CmpUneD(FRegister fd, FRegister fs, FRegister ft) {
   CHECK(IsR6());
-  DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x12), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x15, ft, fs, fd, 0x12)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::CmpNeD(FRegister fd, FRegister fs, FRegister ft) {
   CHECK(IsR6());
-  DsFsmInstrFff(EmitFR(0x11, 0x15, ft, fs, fd, 0x13), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x15, ft, fs, fd, 0x13)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::Movf(Register rd, Register rs, int cc) {
   CHECK(!IsR6());
   CHECK(IsUint<3>(cc)) << cc;
-  DsFsmInstrRrrc(EmitR(0, rs, static_cast<Register>(cc << 2), rd, 0, 0x01), rd, rs, cc);
+  DsFsmInstr(EmitR(0, rs, static_cast<Register>(cc << 2), rd, 0, 0x01))
+      .GprInOuts(rd).GprIns(rs).CcIns(cc);
 }
 
 void MipsAssembler::Movt(Register rd, Register rs, int cc) {
   CHECK(!IsR6());
   CHECK(IsUint<3>(cc)) << cc;
-  DsFsmInstrRrrc(EmitR(0, rs, static_cast<Register>((cc << 2) | 1), rd, 0, 0x01), rd, rs, cc);
+  DsFsmInstr(EmitR(0, rs, static_cast<Register>((cc << 2) | 1), rd, 0, 0x01))
+      .GprInOuts(rd).GprIns(rs).CcIns(cc);
 }
 
 void MipsAssembler::MovfS(FRegister fd, FRegister fs, int cc) {
   CHECK(!IsR6());
   CHECK(IsUint<3>(cc)) << cc;
-  DsFsmInstrFffc(EmitFR(0x11, 0x10, static_cast<FRegister>(cc << 2), fs, fd, 0x11), fd, fs, cc);
+  DsFsmInstr(EmitFR(0x11, 0x10, static_cast<FRegister>(cc << 2), fs, fd, 0x11))
+      .FprInOuts(fd).FprIns(fs).CcIns(cc);
 }
 
 void MipsAssembler::MovfD(FRegister fd, FRegister fs, int cc) {
   CHECK(!IsR6());
   CHECK(IsUint<3>(cc)) << cc;
-  DsFsmInstrFffc(EmitFR(0x11, 0x11, static_cast<FRegister>(cc << 2), fs, fd, 0x11), fd, fs, cc);
+  DsFsmInstr(EmitFR(0x11, 0x11, static_cast<FRegister>(cc << 2), fs, fd, 0x11))
+      .FprInOuts(fd).FprIns(fs).CcIns(cc);
 }
 
 void MipsAssembler::MovtS(FRegister fd, FRegister fs, int cc) {
   CHECK(!IsR6());
   CHECK(IsUint<3>(cc)) << cc;
-  DsFsmInstrFffc(EmitFR(0x11, 0x10, static_cast<FRegister>((cc << 2) | 1), fs, fd, 0x11),
-                 fd,
-                 fs,
-                 cc);
+  DsFsmInstr(EmitFR(0x11, 0x10, static_cast<FRegister>((cc << 2) | 1), fs, fd, 0x11))
+      .FprInOuts(fd).FprIns(fs).CcIns(cc);
 }
 
 void MipsAssembler::MovtD(FRegister fd, FRegister fs, int cc) {
   CHECK(!IsR6());
   CHECK(IsUint<3>(cc)) << cc;
-  DsFsmInstrFffc(EmitFR(0x11, 0x11, static_cast<FRegister>((cc << 2) | 1), fs, fd, 0x11),
-                 fd,
-                 fs,
-                 cc);
+  DsFsmInstr(EmitFR(0x11, 0x11, static_cast<FRegister>((cc << 2) | 1), fs, fd, 0x11))
+      .FprInOuts(fd).FprIns(fs).CcIns(cc);
 }
 
 void MipsAssembler::MovzS(FRegister fd, FRegister fs, Register rt) {
   CHECK(!IsR6());
-  DsFsmInstrFffr(EmitFR(0x11, 0x10, static_cast<FRegister>(rt), fs, fd, 0x12), fd, fs, rt);
+  DsFsmInstr(EmitFR(0x11, 0x10, static_cast<FRegister>(rt), fs, fd, 0x12))
+      .FprInOuts(fd).FprIns(fs).GprIns(rt);
 }
 
 void MipsAssembler::MovzD(FRegister fd, FRegister fs, Register rt) {
   CHECK(!IsR6());
-  DsFsmInstrFffr(EmitFR(0x11, 0x11, static_cast<FRegister>(rt), fs, fd, 0x12), fd, fs, rt);
+  DsFsmInstr(EmitFR(0x11, 0x11, static_cast<FRegister>(rt), fs, fd, 0x12))
+      .FprInOuts(fd).FprIns(fs).GprIns(rt);
 }
 
 void MipsAssembler::MovnS(FRegister fd, FRegister fs, Register rt) {
   CHECK(!IsR6());
-  DsFsmInstrFffr(EmitFR(0x11, 0x10, static_cast<FRegister>(rt), fs, fd, 0x13), fd, fs, rt);
+  DsFsmInstr(EmitFR(0x11, 0x10, static_cast<FRegister>(rt), fs, fd, 0x13))
+      .FprInOuts(fd).FprIns(fs).GprIns(rt);
 }
 
 void MipsAssembler::MovnD(FRegister fd, FRegister fs, Register rt) {
   CHECK(!IsR6());
-  DsFsmInstrFffr(EmitFR(0x11, 0x11, static_cast<FRegister>(rt), fs, fd, 0x13), fd, fs, rt);
+  DsFsmInstr(EmitFR(0x11, 0x11, static_cast<FRegister>(rt), fs, fd, 0x13))
+      .FprInOuts(fd).FprIns(fs).GprIns(rt);
 }
 
 void MipsAssembler::SelS(FRegister fd, FRegister fs, FRegister ft) {
   CHECK(IsR6());
-  DsFsmInstrFfff(EmitFR(0x11, 0x10, ft, fs, fd, 0x10), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x10, ft, fs, fd, 0x10)).FprInOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::SelD(FRegister fd, FRegister fs, FRegister ft) {
   CHECK(IsR6());
-  DsFsmInstrFfff(EmitFR(0x11, 0x11, ft, fs, fd, 0x10), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x11, ft, fs, fd, 0x10)).FprInOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::SeleqzS(FRegister fd, FRegister fs, FRegister ft) {
   CHECK(IsR6());
-  DsFsmInstrFff(EmitFR(0x11, 0x10, ft, fs, fd, 0x14), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x10, ft, fs, fd, 0x14)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::SeleqzD(FRegister fd, FRegister fs, FRegister ft) {
   CHECK(IsR6());
-  DsFsmInstrFff(EmitFR(0x11, 0x11, ft, fs, fd, 0x14), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x11, ft, fs, fd, 0x14)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::SelnezS(FRegister fd, FRegister fs, FRegister ft) {
   CHECK(IsR6());
-  DsFsmInstrFff(EmitFR(0x11, 0x10, ft, fs, fd, 0x17), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x10, ft, fs, fd, 0x17)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::SelnezD(FRegister fd, FRegister fs, FRegister ft) {
   CHECK(IsR6());
-  DsFsmInstrFff(EmitFR(0x11, 0x11, ft, fs, fd, 0x17), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x11, ft, fs, fd, 0x17)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::ClassS(FRegister fd, FRegister fs) {
   CHECK(IsR6());
-  DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x1b), fd, fs, fs);
+  DsFsmInstr(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x1b)).FprOuts(fd).FprIns(fs);
 }
 
 void MipsAssembler::ClassD(FRegister fd, FRegister fs) {
   CHECK(IsR6());
-  DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x1b), fd, fs, fs);
+  DsFsmInstr(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x1b)).FprOuts(fd).FprIns(fs);
 }
 
 void MipsAssembler::MinS(FRegister fd, FRegister fs, FRegister ft) {
   CHECK(IsR6());
-  DsFsmInstrFff(EmitFR(0x11, 0x10, ft, fs, fd, 0x1c), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x10, ft, fs, fd, 0x1c)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::MinD(FRegister fd, FRegister fs, FRegister ft) {
   CHECK(IsR6());
-  DsFsmInstrFff(EmitFR(0x11, 0x11, ft, fs, fd, 0x1c), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x11, ft, fs, fd, 0x1c)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::MaxS(FRegister fd, FRegister fs, FRegister ft) {
   CHECK(IsR6());
-  DsFsmInstrFff(EmitFR(0x11, 0x10, ft, fs, fd, 0x1e), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x10, ft, fs, fd, 0x1e)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::MaxD(FRegister fd, FRegister fs, FRegister ft) {
   CHECK(IsR6());
-  DsFsmInstrFff(EmitFR(0x11, 0x11, ft, fs, fd, 0x1e), fd, fs, ft);
+  DsFsmInstr(EmitFR(0x11, 0x11, ft, fs, fd, 0x1e)).FprOuts(fd).FprIns(fs, ft);
 }
 
 void MipsAssembler::TruncLS(FRegister fd, FRegister fs) {
-  DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x09), fd, fs, fs);
+  DsFsmInstr(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x09)).FprOuts(fd).FprIns(fs);
 }
 
 void MipsAssembler::TruncLD(FRegister fd, FRegister fs) {
-  DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x09), fd, fs, fs);
+  DsFsmInstr(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x09)).FprOuts(fd).FprIns(fs);
 }
 
 void MipsAssembler::TruncWS(FRegister fd, FRegister fs) {
-  DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x0D), fd, fs, fs);
+  DsFsmInstr(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x0D)).FprOuts(fd).FprIns(fs);
 }
 
 void MipsAssembler::TruncWD(FRegister fd, FRegister fs) {
-  DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x0D), fd, fs, fs);
+  DsFsmInstr(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x0D)).FprOuts(fd).FprIns(fs);
 }
 
 void MipsAssembler::Cvtsw(FRegister fd, FRegister fs) {
-  DsFsmInstrFff(EmitFR(0x11, 0x14, static_cast<FRegister>(0), fs, fd, 0x20), fd, fs, fs);
+  DsFsmInstr(EmitFR(0x11, 0x14, static_cast<FRegister>(0), fs, fd, 0x20)).FprOuts(fd).FprIns(fs);
 }
 
 void MipsAssembler::Cvtdw(FRegister fd, FRegister fs) {
-  DsFsmInstrFff(EmitFR(0x11, 0x14, static_cast<FRegister>(0), fs, fd, 0x21), fd, fs, fs);
+  DsFsmInstr(EmitFR(0x11, 0x14, static_cast<FRegister>(0), fs, fd, 0x21)).FprOuts(fd).FprIns(fs);
 }
 
 void MipsAssembler::Cvtsd(FRegister fd, FRegister fs) {
-  DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x20), fd, fs, fs);
+  DsFsmInstr(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x20)).FprOuts(fd).FprIns(fs);
 }
 
 void MipsAssembler::Cvtds(FRegister fd, FRegister fs) {
-  DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x21), fd, fs, fs);
+  DsFsmInstr(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x21)).FprOuts(fd).FprIns(fs);
 }
 
 void MipsAssembler::Cvtsl(FRegister fd, FRegister fs) {
-  DsFsmInstrFff(EmitFR(0x11, 0x15, static_cast<FRegister>(0), fs, fd, 0x20), fd, fs, fs);
+  DsFsmInstr(EmitFR(0x11, 0x15, static_cast<FRegister>(0), fs, fd, 0x20)).FprOuts(fd).FprIns(fs);
 }
 
 void MipsAssembler::Cvtdl(FRegister fd, FRegister fs) {
-  DsFsmInstrFff(EmitFR(0x11, 0x15, static_cast<FRegister>(0), fs, fd, 0x21), fd, fs, fs);
+  DsFsmInstr(EmitFR(0x11, 0x15, static_cast<FRegister>(0), fs, fd, 0x21)).FprOuts(fd).FprIns(fs);
 }
 
 void MipsAssembler::FloorWS(FRegister fd, FRegister fs) {
-  DsFsmInstrFff(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0xf), fd, fs, fs);
+  DsFsmInstr(EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0xf)).FprOuts(fd).FprIns(fs);
 }
 
 void MipsAssembler::FloorWD(FRegister fd, FRegister fs) {
-  DsFsmInstrFff(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0xf), fd, fs, fs);
+  DsFsmInstr(EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0xf)).FprOuts(fd).FprIns(fs);
+}
+
+FRegister MipsAssembler::GetFpuRegLow(FRegister reg) {
+  // If FPRs are 32-bit (and get paired to hold 64-bit values), accesses to
+  // odd-numbered FPRs are reattributed to even-numbered FPRs. This lets us
+  // use only even-numbered FPRs irrespective of whether we're doing single-
+  // or double-precision arithmetic. (We don't use odd-numbered 32-bit FPRs
+  // to hold single-precision values).
+  return Is32BitFPU() ? static_cast<FRegister>(reg & ~1u) : reg;
 }
 
 void MipsAssembler::Mfc1(Register rt, FRegister fs) {
-  DsFsmInstrRf(EmitFR(0x11, 0x00, static_cast<FRegister>(rt), fs, static_cast<FRegister>(0), 0x0),
-               rt,
-               fs);
+  DsFsmInstr(EmitFR(0x11, 0x00, static_cast<FRegister>(rt), fs, static_cast<FRegister>(0), 0x0))
+      .GprOuts(rt).FprIns(GetFpuRegLow(fs));
 }
 
+// Note, the 32 LSBs of a 64-bit value must be loaded into an FPR before the 32 MSBs
+// when loading the value as 32-bit halves.
 void MipsAssembler::Mtc1(Register rt, FRegister fs) {
-  DsFsmInstrFr(EmitFR(0x11, 0x04, static_cast<FRegister>(rt), fs, static_cast<FRegister>(0), 0x0),
-               fs,
-               rt);
+  uint32_t encoding =
+      EmitFR(0x11, 0x04, static_cast<FRegister>(rt), fs, static_cast<FRegister>(0), 0x0);
+  if (Is32BitFPU() && (fs % 2 != 0)) {
+    // If mtc1 is used to simulate mthc1 by writing to the odd-numbered FPR in
+    // a pair of 32-bit FPRs, the associated even-numbered FPR is an in/out.
+    DsFsmInstr(encoding).FprInOuts(GetFpuRegLow(fs)).GprIns(rt);
+  } else {
+    // Otherwise (the FPR is 64-bit or even-numbered), the FPR is an out.
+    DsFsmInstr(encoding).FprOuts(fs).GprIns(rt);
+  }
 }
 
 void MipsAssembler::Mfhc1(Register rt, FRegister fs) {
-  DsFsmInstrRf(EmitFR(0x11, 0x03, static_cast<FRegister>(rt), fs, static_cast<FRegister>(0), 0x0),
-               rt,
-               fs);
+  DsFsmInstr(EmitFR(0x11, 0x03, static_cast<FRegister>(rt), fs, static_cast<FRegister>(0), 0x0))
+      .GprOuts(rt).FprIns(fs);
 }
 
+// Note, the 32 LSBs of a 64-bit value must be loaded into an FPR before the 32 MSBs
+// when loading the value as 32-bit halves.
 void MipsAssembler::Mthc1(Register rt, FRegister fs) {
-  DsFsmInstrFr(EmitFR(0x11, 0x07, static_cast<FRegister>(rt), fs, static_cast<FRegister>(0), 0x0),
-               fs,
-               rt);
+  DsFsmInstr(EmitFR(0x11, 0x07, static_cast<FRegister>(rt), fs, static_cast<FRegister>(0), 0x0))
+      .FprInOuts(fs).GprIns(rt);
 }
 
 void MipsAssembler::MoveFromFpuHigh(Register rt, FRegister fs) {
@@ -1820,20 +1774,30 @@
   }
 }
 
+// Note, the 32 LSBs of a 64-bit value must be loaded into an FPR before the 32 MSBs
+// when loading the value as 32-bit halves.
 void MipsAssembler::Lwc1(FRegister ft, Register rs, uint16_t imm16) {
-  DsFsmInstrFr(EmitI(0x31, rs, static_cast<Register>(ft), imm16), ft, rs);
+  uint32_t encoding = EmitI(0x31, rs, static_cast<Register>(ft), imm16);
+  if (Is32BitFPU() && (ft % 2 != 0)) {
+    // If lwc1 is used to load the odd-numbered FPR in a pair of 32-bit FPRs,
+    // the associated even-numbered FPR is an in/out.
+    DsFsmInstr(encoding).FprInOuts(GetFpuRegLow(ft)).GprIns(rs);
+  } else {
+    // Otherwise (the FPR is 64-bit or even-numbered), the FPR is an out.
+    DsFsmInstr(encoding).FprOuts(ft).GprIns(rs);
+  }
 }
 
 void MipsAssembler::Ldc1(FRegister ft, Register rs, uint16_t imm16) {
-  DsFsmInstrFr(EmitI(0x35, rs, static_cast<Register>(ft), imm16), ft, rs);
+  DsFsmInstr(EmitI(0x35, rs, static_cast<Register>(ft), imm16)).FprOuts(ft).GprIns(rs);
 }
 
 void MipsAssembler::Swc1(FRegister ft, Register rs, uint16_t imm16) {
-  DsFsmInstrFR(EmitI(0x39, rs, static_cast<Register>(ft), imm16), ft, rs);
+  DsFsmInstr(EmitI(0x39, rs, static_cast<Register>(ft), imm16)).FprIns(GetFpuRegLow(ft)).GprIns(rs);
 }
 
 void MipsAssembler::Sdc1(FRegister ft, Register rs, uint16_t imm16) {
-  DsFsmInstrFR(EmitI(0x3d, rs, static_cast<Register>(ft), imm16), ft, rs);
+  DsFsmInstr(EmitI(0x3d, rs, static_cast<Register>(ft), imm16)).FprIns(ft).GprIns(rs);
 }
 
 void MipsAssembler::Break() {
@@ -1882,1447 +1846,951 @@
 
 void MipsAssembler::AndV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x1e),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x1e)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::OrV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x1e),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x1e)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::NorV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x1e),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x1e)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::XorV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x1e),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x1e)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::AddvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x0, 0x0, wt, ws, wd, 0xe),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x0, 0x0, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::AddvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x0, 0x1, wt, ws, wd, 0xe),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x0, 0x1, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::AddvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x0, 0x2, wt, ws, wd, 0xe),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x0, 0x2, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::AddvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x0, 0x3, wt, ws, wd, 0xe),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x0, 0x3, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::SubvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x1, 0x0, wt, ws, wd, 0xe),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x1, 0x0, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::SubvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x1, 0x1, wt, ws, wd, 0xe),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x1, 0x1, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::SubvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x1, 0x2, wt, ws, wd, 0xe),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x1, 0x2, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::SubvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x1, 0x3, wt, ws, wd, 0xe),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x1, 0x3, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::MulvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x12),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::MulvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x12),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::MulvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x12),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::MulvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x12),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Div_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x12),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Div_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x12),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Div_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x12),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Div_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x12),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Div_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x12),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Div_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x12),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Div_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x12),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Div_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x12),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Mod_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x12),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Mod_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x12),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Mod_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x6, 0x2, wt, ws, wd, 0x12),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x6, 0x2, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Mod_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x6, 0x3, wt, ws, wd, 0x12),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x6, 0x3, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Mod_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x12),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Mod_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x12),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Mod_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x7, 0x2, wt, ws, wd, 0x12),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x7, 0x2, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Mod_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x7, 0x3, wt, ws, wd, 0x12),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x7, 0x3, wt, ws, wd, 0x12)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Add_aB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x10),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Add_aH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x10),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Add_aW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x10),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Add_aD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x10),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Ave_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x10),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Ave_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x10),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Ave_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x10),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Ave_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x10),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Ave_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x10),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Ave_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x10),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Ave_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x10),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Ave_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x10),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Aver_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x10),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Aver_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x10),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Aver_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x6, 0x2, wt, ws, wd, 0x10),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x6, 0x2, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Aver_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x6, 0x3, wt, ws, wd, 0x10),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x6, 0x3, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Aver_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x10),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Aver_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x10),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Aver_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x7, 0x2, wt, ws, wd, 0x10),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x7, 0x2, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Aver_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x7, 0x3, wt, ws, wd, 0x10),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x7, 0x3, wt, ws, wd, 0x10)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Max_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x2, 0x0, wt, ws, wd, 0xe),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x2, 0x0, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Max_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x2, 0x1, wt, ws, wd, 0xe),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x2, 0x1, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Max_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x2, 0x2, wt, ws, wd, 0xe),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x2, 0x2, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Max_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x2, 0x3, wt, ws, wd, 0xe),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x2, 0x3, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Max_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x3, 0x0, wt, ws, wd, 0xe),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x3, 0x0, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Max_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x3, 0x1, wt, ws, wd, 0xe),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x3, 0x1, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Max_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x3, 0x2, wt, ws, wd, 0xe),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x3, 0x2, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Max_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x3, 0x3, wt, ws, wd, 0xe),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x3, 0x3, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Min_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x4, 0x0, wt, ws, wd, 0xe),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x4, 0x0, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Min_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x4, 0x1, wt, ws, wd, 0xe),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x4, 0x1, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Min_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x4, 0x2, wt, ws, wd, 0xe),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x4, 0x2, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Min_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x4, 0x3, wt, ws, wd, 0xe),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x4, 0x3, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Min_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x5, 0x0, wt, ws, wd, 0xe),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x5, 0x0, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Min_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x5, 0x1, wt, ws, wd, 0xe),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x5, 0x1, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Min_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x5, 0x2, wt, ws, wd, 0xe),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x5, 0x2, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Min_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x5, 0x3, wt, ws, wd, 0xe),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x5, 0x3, wt, ws, wd, 0xe)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::FaddW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x1b),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x1b)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::FaddD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x1b),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x1b)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::FsubW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x1b),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x1b)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::FsubD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x1b),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x1b)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::FmulW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x1, 0x0, wt, ws, wd, 0x1b),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x1, 0x0, wt, ws, wd, 0x1b)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::FmulD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x1, 0x1, wt, ws, wd, 0x1b),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x1, 0x1, wt, ws, wd, 0x1b)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::FdivW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x1, 0x2, wt, ws, wd, 0x1b),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x1, 0x2, wt, ws, wd, 0x1b)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::FdivD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x1, 0x3, wt, ws, wd, 0x1b),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x1, 0x3, wt, ws, wd, 0x1b)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::FmaxW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x1b),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x1b)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::FmaxD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x1b),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x1b)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::FminW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x1b),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x1b)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::FminD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x1b),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x1b)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Ffint_sW(VectorRegister wd, VectorRegister ws) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa2RF(0x19e, 0x0, ws, wd, 0x1e),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(ws));
+  DsFsmInstr(EmitMsa2RF(0x19e, 0x0, ws, wd, 0x1e)).FprOuts(wd).FprIns(ws);
 }
 
 void MipsAssembler::Ffint_sD(VectorRegister wd, VectorRegister ws) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa2RF(0x19e, 0x1, ws, wd, 0x1e),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(ws));
+  DsFsmInstr(EmitMsa2RF(0x19e, 0x1, ws, wd, 0x1e)).FprOuts(wd).FprIns(ws);
 }
 
 void MipsAssembler::Ftint_sW(VectorRegister wd, VectorRegister ws) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa2RF(0x19c, 0x0, ws, wd, 0x1e),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(ws));
+  DsFsmInstr(EmitMsa2RF(0x19c, 0x0, ws, wd, 0x1e)).FprOuts(wd).FprIns(ws);
 }
 
 void MipsAssembler::Ftint_sD(VectorRegister wd, VectorRegister ws) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa2RF(0x19c, 0x1, ws, wd, 0x1e),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(ws));
+  DsFsmInstr(EmitMsa2RF(0x19c, 0x1, ws, wd, 0x1e)).FprOuts(wd).FprIns(ws);
 }
 
 void MipsAssembler::SllB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x0, 0x0, wt, ws, wd, 0xd),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x0, 0x0, wt, ws, wd, 0xd)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::SllH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x0, 0x1, wt, ws, wd, 0xd),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x0, 0x1, wt, ws, wd, 0xd)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::SllW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x0, 0x2, wt, ws, wd, 0xd),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x0, 0x2, wt, ws, wd, 0xd)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::SllD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x0, 0x3, wt, ws, wd, 0xd),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x0, 0x3, wt, ws, wd, 0xd)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::SraB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x1, 0x0, wt, ws, wd, 0xd),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x1, 0x0, wt, ws, wd, 0xd)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::SraH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x1, 0x1, wt, ws, wd, 0xd),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x1, 0x1, wt, ws, wd, 0xd)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::SraW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x1, 0x2, wt, ws, wd, 0xd),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x1, 0x2, wt, ws, wd, 0xd)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::SraD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x1, 0x3, wt, ws, wd, 0xd),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x1, 0x3, wt, ws, wd, 0xd)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::SrlB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x2, 0x0, wt, ws, wd, 0xd),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x2, 0x0, wt, ws, wd, 0xd)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::SrlH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x2, 0x1, wt, ws, wd, 0xd),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x2, 0x1, wt, ws, wd, 0xd)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::SrlW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x2, 0x2, wt, ws, wd, 0xd),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x2, 0x2, wt, ws, wd, 0xd)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::SrlD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x2, 0x3, wt, ws, wd, 0xd),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x2, 0x3, wt, ws, wd, 0xd)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::SlliB(VectorRegister wd, VectorRegister ws, int shamt3) {
   CHECK(HasMsa());
   CHECK(IsUint<3>(shamt3)) << shamt3;
-  DsFsmInstrFff(EmitMsaBIT(0x0, shamt3 | kMsaDfMByteMask, ws, wd, 0x9),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(ws));
+  DsFsmInstr(EmitMsaBIT(0x0, shamt3 | kMsaDfMByteMask, ws, wd, 0x9)).FprOuts(wd).FprIns(ws);
 }
 
 void MipsAssembler::SlliH(VectorRegister wd, VectorRegister ws, int shamt4) {
   CHECK(HasMsa());
   CHECK(IsUint<4>(shamt4)) << shamt4;
-  DsFsmInstrFff(EmitMsaBIT(0x0, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(ws));
+  DsFsmInstr(EmitMsaBIT(0x0, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9)).FprOuts(wd).FprIns(ws);
 }
 
 void MipsAssembler::SlliW(VectorRegister wd, VectorRegister ws, int shamt5) {
   CHECK(HasMsa());
   CHECK(IsUint<5>(shamt5)) << shamt5;
-  DsFsmInstrFff(EmitMsaBIT(0x0, shamt5 | kMsaDfMWordMask, ws, wd, 0x9),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(ws));
+  DsFsmInstr(EmitMsaBIT(0x0, shamt5 | kMsaDfMWordMask, ws, wd, 0x9)).FprOuts(wd).FprIns(ws);
 }
 
 void MipsAssembler::SlliD(VectorRegister wd, VectorRegister ws, int shamt6) {
   CHECK(HasMsa());
   CHECK(IsUint<6>(shamt6)) << shamt6;
-  DsFsmInstrFff(EmitMsaBIT(0x0, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(ws));
+  DsFsmInstr(EmitMsaBIT(0x0, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9)).FprOuts(wd).FprIns(ws);
 }
 
 void MipsAssembler::SraiB(VectorRegister wd, VectorRegister ws, int shamt3) {
   CHECK(HasMsa());
   CHECK(IsUint<3>(shamt3)) << shamt3;
-  DsFsmInstrFff(EmitMsaBIT(0x1, shamt3 | kMsaDfMByteMask, ws, wd, 0x9),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(ws));
+  DsFsmInstr(EmitMsaBIT(0x1, shamt3 | kMsaDfMByteMask, ws, wd, 0x9)).FprOuts(wd).FprIns(ws);
 }
 
 void MipsAssembler::SraiH(VectorRegister wd, VectorRegister ws, int shamt4) {
   CHECK(HasMsa());
   CHECK(IsUint<4>(shamt4)) << shamt4;
-  DsFsmInstrFff(EmitMsaBIT(0x1, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(ws));
+  DsFsmInstr(EmitMsaBIT(0x1, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9)).FprOuts(wd).FprIns(ws);
 }
 
 void MipsAssembler::SraiW(VectorRegister wd, VectorRegister ws, int shamt5) {
   CHECK(HasMsa());
   CHECK(IsUint<5>(shamt5)) << shamt5;
-  DsFsmInstrFff(EmitMsaBIT(0x1, shamt5 | kMsaDfMWordMask, ws, wd, 0x9),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(ws));
+  DsFsmInstr(EmitMsaBIT(0x1, shamt5 | kMsaDfMWordMask, ws, wd, 0x9)).FprOuts(wd).FprIns(ws);
 }
 
 void MipsAssembler::SraiD(VectorRegister wd, VectorRegister ws, int shamt6) {
   CHECK(HasMsa());
   CHECK(IsUint<6>(shamt6)) << shamt6;
-  DsFsmInstrFff(EmitMsaBIT(0x1, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(ws));
+  DsFsmInstr(EmitMsaBIT(0x1, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9)).FprOuts(wd).FprIns(ws);
 }
 
 void MipsAssembler::SrliB(VectorRegister wd, VectorRegister ws, int shamt3) {
   CHECK(HasMsa());
   CHECK(IsUint<3>(shamt3)) << shamt3;
-  DsFsmInstrFff(EmitMsaBIT(0x2, shamt3 | kMsaDfMByteMask, ws, wd, 0x9),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(ws));
+  DsFsmInstr(EmitMsaBIT(0x2, shamt3 | kMsaDfMByteMask, ws, wd, 0x9)).FprOuts(wd).FprIns(ws);
 }
 
 void MipsAssembler::SrliH(VectorRegister wd, VectorRegister ws, int shamt4) {
   CHECK(HasMsa());
   CHECK(IsUint<4>(shamt4)) << shamt4;
-  DsFsmInstrFff(EmitMsaBIT(0x2, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(ws));
+  DsFsmInstr(EmitMsaBIT(0x2, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9)).FprOuts(wd).FprIns(ws);
 }
 
 void MipsAssembler::SrliW(VectorRegister wd, VectorRegister ws, int shamt5) {
   CHECK(HasMsa());
   CHECK(IsUint<5>(shamt5)) << shamt5;
-  DsFsmInstrFff(EmitMsaBIT(0x2, shamt5 | kMsaDfMWordMask, ws, wd, 0x9),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(ws));
+  DsFsmInstr(EmitMsaBIT(0x2, shamt5 | kMsaDfMWordMask, ws, wd, 0x9)).FprOuts(wd).FprIns(ws);
 }
 
 void MipsAssembler::SrliD(VectorRegister wd, VectorRegister ws, int shamt6) {
   CHECK(HasMsa());
   CHECK(IsUint<6>(shamt6)) << shamt6;
-  DsFsmInstrFff(EmitMsaBIT(0x2, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(ws));
+  DsFsmInstr(EmitMsaBIT(0x2, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9)).FprOuts(wd).FprIns(ws);
 }
 
 void MipsAssembler::MoveV(VectorRegister wd, VectorRegister ws) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsaBIT(0x1, 0x3e, ws, wd, 0x19),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(ws));
+  DsFsmInstr(EmitMsaBIT(0x1, 0x3e, ws, wd, 0x19)).FprOuts(wd).FprIns(ws);
 }
 
 void MipsAssembler::SplatiB(VectorRegister wd, VectorRegister ws, int n4) {
   CHECK(HasMsa());
   CHECK(IsUint<4>(n4)) << n4;
-  DsFsmInstrFff(EmitMsaELM(0x1, n4 | kMsaDfNByteMask, ws, wd, 0x19),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(ws));
+  DsFsmInstr(EmitMsaELM(0x1, n4 | kMsaDfNByteMask, ws, wd, 0x19)).FprOuts(wd).FprIns(ws);
 }
 
 void MipsAssembler::SplatiH(VectorRegister wd, VectorRegister ws, int n3) {
   CHECK(HasMsa());
   CHECK(IsUint<3>(n3)) << n3;
-  DsFsmInstrFff(EmitMsaELM(0x1, n3 | kMsaDfNHalfwordMask, ws, wd, 0x19),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(ws));
+  DsFsmInstr(EmitMsaELM(0x1, n3 | kMsaDfNHalfwordMask, ws, wd, 0x19)).FprOuts(wd).FprIns(ws);
 }
 
 void MipsAssembler::SplatiW(VectorRegister wd, VectorRegister ws, int n2) {
   CHECK(HasMsa());
   CHECK(IsUint<2>(n2)) << n2;
-  DsFsmInstrFff(EmitMsaELM(0x1, n2 | kMsaDfNWordMask, ws, wd, 0x19),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(ws));
+  DsFsmInstr(EmitMsaELM(0x1, n2 | kMsaDfNWordMask, ws, wd, 0x19)).FprOuts(wd).FprIns(ws);
 }
 
 void MipsAssembler::SplatiD(VectorRegister wd, VectorRegister ws, int n1) {
   CHECK(HasMsa());
   CHECK(IsUint<1>(n1)) << n1;
-  DsFsmInstrFff(EmitMsaELM(0x1, n1 | kMsaDfNDoublewordMask, ws, wd, 0x19),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(ws));
+  DsFsmInstr(EmitMsaELM(0x1, n1 | kMsaDfNDoublewordMask, ws, wd, 0x19)).FprOuts(wd).FprIns(ws);
 }
 
 void MipsAssembler::Copy_sB(Register rd, VectorRegister ws, int n4) {
   CHECK(HasMsa());
   CHECK(IsUint<4>(n4)) << n4;
-  DsFsmInstrRf(EmitMsaELM(0x2, n4 | kMsaDfNByteMask, ws, static_cast<VectorRegister>(rd), 0x19),
-               rd,
-               static_cast<FRegister>(ws));
+  DsFsmInstr(EmitMsaELM(0x2, n4 | kMsaDfNByteMask, ws, static_cast<VectorRegister>(rd), 0x19))
+      .GprOuts(rd).FprIns(ws);
 }
 
 void MipsAssembler::Copy_sH(Register rd, VectorRegister ws, int n3) {
   CHECK(HasMsa());
   CHECK(IsUint<3>(n3)) << n3;
-  DsFsmInstrRf(EmitMsaELM(0x2, n3 | kMsaDfNHalfwordMask, ws, static_cast<VectorRegister>(rd), 0x19),
-               rd,
-               static_cast<FRegister>(ws));
+  DsFsmInstr(EmitMsaELM(0x2, n3 | kMsaDfNHalfwordMask, ws, static_cast<VectorRegister>(rd), 0x19))
+      .GprOuts(rd).FprIns(ws);
 }
 
 void MipsAssembler::Copy_sW(Register rd, VectorRegister ws, int n2) {
   CHECK(HasMsa());
   CHECK(IsUint<2>(n2)) << n2;
-  DsFsmInstrRf(EmitMsaELM(0x2, n2 | kMsaDfNWordMask, ws, static_cast<VectorRegister>(rd), 0x19),
-               rd,
-               static_cast<FRegister>(ws));
+  DsFsmInstr(EmitMsaELM(0x2, n2 | kMsaDfNWordMask, ws, static_cast<VectorRegister>(rd), 0x19))
+      .GprOuts(rd).FprIns(ws);
 }
 
 void MipsAssembler::Copy_uB(Register rd, VectorRegister ws, int n4) {
   CHECK(HasMsa());
   CHECK(IsUint<4>(n4)) << n4;
-  DsFsmInstrRf(EmitMsaELM(0x3, n4 | kMsaDfNByteMask, ws, static_cast<VectorRegister>(rd), 0x19),
-               rd,
-               static_cast<FRegister>(ws));
+  DsFsmInstr(EmitMsaELM(0x3, n4 | kMsaDfNByteMask, ws, static_cast<VectorRegister>(rd), 0x19))
+      .GprOuts(rd).FprIns(ws);
 }
 
 void MipsAssembler::Copy_uH(Register rd, VectorRegister ws, int n3) {
   CHECK(HasMsa());
   CHECK(IsUint<3>(n3)) << n3;
-  DsFsmInstrRf(EmitMsaELM(0x3, n3 | kMsaDfNHalfwordMask, ws, static_cast<VectorRegister>(rd), 0x19),
-               rd,
-               static_cast<FRegister>(ws));
+  DsFsmInstr(EmitMsaELM(0x3, n3 | kMsaDfNHalfwordMask, ws, static_cast<VectorRegister>(rd), 0x19))
+      .GprOuts(rd).FprIns(ws);
 }
 
 void MipsAssembler::InsertB(VectorRegister wd, Register rs, int n4) {
   CHECK(HasMsa());
   CHECK(IsUint<4>(n4)) << n4;
-  DsFsmInstrFffr(EmitMsaELM(0x4, n4 | kMsaDfNByteMask, static_cast<VectorRegister>(rs), wd, 0x19),
-                 static_cast<FRegister>(wd),
-                 static_cast<FRegister>(wd),
-                 rs);
+  DsFsmInstr(EmitMsaELM(0x4, n4 | kMsaDfNByteMask, static_cast<VectorRegister>(rs), wd, 0x19))
+      .FprInOuts(wd).GprIns(rs);
 }
 
 void MipsAssembler::InsertH(VectorRegister wd, Register rs, int n3) {
   CHECK(HasMsa());
   CHECK(IsUint<3>(n3)) << n3;
-  DsFsmInstrFffr(
-      EmitMsaELM(0x4, n3 | kMsaDfNHalfwordMask, static_cast<VectorRegister>(rs), wd, 0x19),
-      static_cast<FRegister>(wd),
-      static_cast<FRegister>(wd),
-      rs);
+  DsFsmInstr(EmitMsaELM(0x4, n3 | kMsaDfNHalfwordMask, static_cast<VectorRegister>(rs), wd, 0x19))
+      .FprInOuts(wd).GprIns(rs);
 }
 
 void MipsAssembler::InsertW(VectorRegister wd, Register rs, int n2) {
   CHECK(HasMsa());
   CHECK(IsUint<2>(n2)) << n2;
-  DsFsmInstrFffr(EmitMsaELM(0x4, n2 | kMsaDfNWordMask, static_cast<VectorRegister>(rs), wd, 0x19),
-                 static_cast<FRegister>(wd),
-                 static_cast<FRegister>(wd),
-                 rs);
+  DsFsmInstr(EmitMsaELM(0x4, n2 | kMsaDfNWordMask, static_cast<VectorRegister>(rs), wd, 0x19))
+      .FprInOuts(wd).GprIns(rs);
 }
 
 void MipsAssembler::FillB(VectorRegister wd, Register rs) {
   CHECK(HasMsa());
-  DsFsmInstrFr(EmitMsa2R(0xc0, 0x0, static_cast<VectorRegister>(rs), wd, 0x1e),
-               static_cast<FRegister>(wd),
-               rs);
+  DsFsmInstr(EmitMsa2R(0xc0, 0x0, static_cast<VectorRegister>(rs), wd, 0x1e))
+      .FprOuts(wd).GprIns(rs);
 }
 
 void MipsAssembler::FillH(VectorRegister wd, Register rs) {
   CHECK(HasMsa());
-  DsFsmInstrFr(EmitMsa2R(0xc0, 0x1, static_cast<VectorRegister>(rs), wd, 0x1e),
-               static_cast<FRegister>(wd),
-               rs);
+  DsFsmInstr(EmitMsa2R(0xc0, 0x1, static_cast<VectorRegister>(rs), wd, 0x1e))
+      .FprOuts(wd).GprIns(rs);
 }
 
 void MipsAssembler::FillW(VectorRegister wd, Register rs) {
   CHECK(HasMsa());
-  DsFsmInstrFr(EmitMsa2R(0xc0, 0x2, static_cast<VectorRegister>(rs), wd, 0x1e),
-               static_cast<FRegister>(wd),
-               rs);
+  DsFsmInstr(EmitMsa2R(0xc0, 0x2, static_cast<VectorRegister>(rs), wd, 0x1e))
+      .FprOuts(wd).GprIns(rs);
 }
 
 void MipsAssembler::LdiB(VectorRegister wd, int imm8) {
   CHECK(HasMsa());
   CHECK(IsInt<8>(imm8)) << imm8;
-  DsFsmInstrFr(EmitMsaI10(0x6, 0x0, imm8 & kMsaS10Mask, wd, 0x7),
-               static_cast<FRegister>(wd),
-               ZERO);
+  DsFsmInstr(EmitMsaI10(0x6, 0x0, imm8 & kMsaS10Mask, wd, 0x7)).FprOuts(wd);
 }
 
 void MipsAssembler::LdiH(VectorRegister wd, int imm10) {
   CHECK(HasMsa());
   CHECK(IsInt<10>(imm10)) << imm10;
-  DsFsmInstrFr(EmitMsaI10(0x6, 0x1, imm10 & kMsaS10Mask, wd, 0x7),
-               static_cast<FRegister>(wd),
-               ZERO);
+  DsFsmInstr(EmitMsaI10(0x6, 0x1, imm10 & kMsaS10Mask, wd, 0x7)).FprOuts(wd);
 }
 
 void MipsAssembler::LdiW(VectorRegister wd, int imm10) {
   CHECK(HasMsa());
   CHECK(IsInt<10>(imm10)) << imm10;
-  DsFsmInstrFr(EmitMsaI10(0x6, 0x2, imm10 & kMsaS10Mask, wd, 0x7),
-               static_cast<FRegister>(wd),
-               ZERO);
+  DsFsmInstr(EmitMsaI10(0x6, 0x2, imm10 & kMsaS10Mask, wd, 0x7)).FprOuts(wd);
 }
 
 void MipsAssembler::LdiD(VectorRegister wd, int imm10) {
   CHECK(HasMsa());
   CHECK(IsInt<10>(imm10)) << imm10;
-  DsFsmInstrFr(EmitMsaI10(0x6, 0x3, imm10 & kMsaS10Mask, wd, 0x7),
-               static_cast<FRegister>(wd),
-               ZERO);
+  DsFsmInstr(EmitMsaI10(0x6, 0x3, imm10 & kMsaS10Mask, wd, 0x7)).FprOuts(wd);
 }
 
 void MipsAssembler::LdB(VectorRegister wd, Register rs, int offset) {
   CHECK(HasMsa());
   CHECK(IsInt<10>(offset)) << offset;
-  DsFsmInstrFr(EmitMsaMI10(offset & kMsaS10Mask, rs, wd, 0x8, 0x0),
-               static_cast<FRegister>(wd),
-               rs);
+  DsFsmInstr(EmitMsaMI10(offset & kMsaS10Mask, rs, wd, 0x8, 0x0)).FprOuts(wd).GprIns(rs);
 }
 
 void MipsAssembler::LdH(VectorRegister wd, Register rs, int offset) {
   CHECK(HasMsa());
   CHECK(IsInt<11>(offset)) << offset;
   CHECK_ALIGNED(offset, kMipsHalfwordSize);
-  DsFsmInstrFr(EmitMsaMI10((offset >> TIMES_2) & kMsaS10Mask, rs, wd, 0x8, 0x1),
-               static_cast<FRegister>(wd),
-               rs);
+  DsFsmInstr(EmitMsaMI10((offset >> TIMES_2) & kMsaS10Mask, rs, wd, 0x8, 0x1))
+      .FprOuts(wd).GprIns(rs);
 }
 
 void MipsAssembler::LdW(VectorRegister wd, Register rs, int offset) {
   CHECK(HasMsa());
   CHECK(IsInt<12>(offset)) << offset;
   CHECK_ALIGNED(offset, kMipsWordSize);
-  DsFsmInstrFr(EmitMsaMI10((offset >> TIMES_4) & kMsaS10Mask, rs, wd, 0x8, 0x2),
-               static_cast<FRegister>(wd),
-               rs);
+  DsFsmInstr(EmitMsaMI10((offset >> TIMES_4) & kMsaS10Mask, rs, wd, 0x8, 0x2))
+      .FprOuts(wd).GprIns(rs);
 }
 
 void MipsAssembler::LdD(VectorRegister wd, Register rs, int offset) {
   CHECK(HasMsa());
   CHECK(IsInt<13>(offset)) << offset;
   CHECK_ALIGNED(offset, kMipsDoublewordSize);
-  DsFsmInstrFr(EmitMsaMI10((offset >> TIMES_8) & kMsaS10Mask, rs, wd, 0x8, 0x3),
-               static_cast<FRegister>(wd),
-               rs);
+  DsFsmInstr(EmitMsaMI10((offset >> TIMES_8) & kMsaS10Mask, rs, wd, 0x8, 0x3))
+      .FprOuts(wd).GprIns(rs);
 }
 
 void MipsAssembler::StB(VectorRegister wd, Register rs, int offset) {
   CHECK(HasMsa());
   CHECK(IsInt<10>(offset)) << offset;
-  DsFsmInstrFR(EmitMsaMI10(offset & kMsaS10Mask, rs, wd, 0x9, 0x0), static_cast<FRegister>(wd), rs);
+  DsFsmInstr(EmitMsaMI10(offset & kMsaS10Mask, rs, wd, 0x9, 0x0)).FprIns(wd).GprIns(rs);
 }
 
 void MipsAssembler::StH(VectorRegister wd, Register rs, int offset) {
   CHECK(HasMsa());
   CHECK(IsInt<11>(offset)) << offset;
   CHECK_ALIGNED(offset, kMipsHalfwordSize);
-  DsFsmInstrFR(EmitMsaMI10((offset >> TIMES_2) & kMsaS10Mask, rs, wd, 0x9, 0x1),
-               static_cast<FRegister>(wd),
-               rs);
+  DsFsmInstr(EmitMsaMI10((offset >> TIMES_2) & kMsaS10Mask, rs, wd, 0x9, 0x1))
+      .FprIns(wd).GprIns(rs);
 }
 
 void MipsAssembler::StW(VectorRegister wd, Register rs, int offset) {
   CHECK(HasMsa());
   CHECK(IsInt<12>(offset)) << offset;
   CHECK_ALIGNED(offset, kMipsWordSize);
-  DsFsmInstrFR(EmitMsaMI10((offset >> TIMES_4) & kMsaS10Mask, rs, wd, 0x9, 0x2),
-               static_cast<FRegister>(wd),
-               rs);
+  DsFsmInstr(EmitMsaMI10((offset >> TIMES_4) & kMsaS10Mask, rs, wd, 0x9, 0x2))
+      .FprIns(wd).GprIns(rs);
 }
 
 void MipsAssembler::StD(VectorRegister wd, Register rs, int offset) {
   CHECK(HasMsa());
   CHECK(IsInt<13>(offset)) << offset;
   CHECK_ALIGNED(offset, kMipsDoublewordSize);
-  DsFsmInstrFR(EmitMsaMI10((offset >> TIMES_8) & kMsaS10Mask, rs, wd, 0x9, 0x3),
-               static_cast<FRegister>(wd),
-               rs);
+  DsFsmInstr(EmitMsaMI10((offset >> TIMES_8) & kMsaS10Mask, rs, wd, 0x9, 0x3))
+      .FprIns(wd).GprIns(rs);
 }
 
 void MipsAssembler::IlvlB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x14),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x14)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::IlvlH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x14),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x14)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::IlvlW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x14),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x14)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::IlvlD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x14),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x14)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::IlvrB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x14),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x14)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::IlvrH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x14),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x14)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::IlvrW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x14),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x14)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::IlvrD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x14),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x14)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::IlvevB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x14),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x14)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::IlvevH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x14),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x14)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::IlvevW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x6, 0x2, wt, ws, wd, 0x14),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x6, 0x2, wt, ws, wd, 0x14)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::IlvevD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x6, 0x3, wt, ws, wd, 0x14),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x6, 0x3, wt, ws, wd, 0x14)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::IlvodB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x14),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x14)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::IlvodH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x14),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x14)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::IlvodW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x7, 0x2, wt, ws, wd, 0x14),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x7, 0x2, wt, ws, wd, 0x14)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::IlvodD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x7, 0x3, wt, ws, wd, 0x14),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x7, 0x3, wt, ws, wd, 0x14)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::MaddvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x1, 0x0, wt, ws, wd, 0x12),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x1, 0x0, wt, ws, wd, 0x12)).FprInOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::MaddvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x1, 0x1, wt, ws, wd, 0x12),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x1, 0x1, wt, ws, wd, 0x12)).FprInOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::MaddvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x1, 0x2, wt, ws, wd, 0x12),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x1, 0x2, wt, ws, wd, 0x12)).FprInOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::MaddvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x1, 0x3, wt, ws, wd, 0x12),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x1, 0x3, wt, ws, wd, 0x12)).FprInOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::MsubvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x2, 0x0, wt, ws, wd, 0x12),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x2, 0x0, wt, ws, wd, 0x12)).FprInOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::MsubvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x2, 0x1, wt, ws, wd, 0x12),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x2, 0x1, wt, ws, wd, 0x12)).FprInOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::MsubvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x2, 0x2, wt, ws, wd, 0x12),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x2, 0x2, wt, ws, wd, 0x12)).FprInOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::MsubvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x2, 0x3, wt, ws, wd, 0x12),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x2, 0x3, wt, ws, wd, 0x12)).FprInOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Asub_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x11),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x11)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Asub_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x11),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x11)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Asub_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x11),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x11)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Asub_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x11),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x11)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Asub_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x11),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x11)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Asub_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x11),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x11)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Asub_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x11),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x11)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Asub_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x11),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x11)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::FmaddW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x2, 0x0, wt, ws, wd, 0x1b),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x2, 0x0, wt, ws, wd, 0x1b)).FprInOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::FmaddD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x2, 0x1, wt, ws, wd, 0x1b),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x2, 0x1, wt, ws, wd, 0x1b)).FprInOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::FmsubW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x2, 0x2, wt, ws, wd, 0x1b),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x2, 0x2, wt, ws, wd, 0x1b)).FprInOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::FmsubD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x2, 0x3, wt, ws, wd, 0x1b),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x2, 0x3, wt, ws, wd, 0x1b)).FprInOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Hadd_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x15),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x15)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Hadd_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x15),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x15)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Hadd_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x15),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x15)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Hadd_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x15),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x15)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Hadd_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x15),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x15)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::Hadd_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
   CHECK(HasMsa());
-  DsFsmInstrFff(EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x15),
-                static_cast<FRegister>(wd),
-                static_cast<FRegister>(ws),
-                static_cast<FRegister>(wt));
+  DsFsmInstr(EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x15)).FprOuts(wd).FprIns(ws, wt);
 }
 
 void MipsAssembler::ReplicateFPToVectorRegister(VectorRegister dst,
@@ -4144,7 +3612,7 @@
     case kLongCall:
       // Instructions depending on or modifying RA should not be moved into delay slots
       // of branches modifying RA.
-      return ((delay_slot.gpr_ins_mask_ | delay_slot.gpr_outs_mask_) & (1u << RA)) == 0;
+      return ((delay_slot.masks_.gpr_ins_ | delay_slot.masks_.gpr_outs_) & (1u << RA)) == 0;
 
     // R2 conditional branches.
     case kCondBranch:
@@ -4157,17 +3625,17 @@
         case kCondGTZ:
         case kCondEQZ:
         case kCondNEZ:
-          return (delay_slot.gpr_outs_mask_ & (1u << lhs_reg_)) == 0;
+          return (delay_slot.masks_.gpr_outs_ & (1u << lhs_reg_)) == 0;
 
         // Branches with two GPR sources.
         case kCondEQ:
         case kCondNE:
-          return (delay_slot.gpr_outs_mask_ & ((1u << lhs_reg_) | (1u << rhs_reg_))) == 0;
+          return (delay_slot.masks_.gpr_outs_ & ((1u << lhs_reg_) | (1u << rhs_reg_))) == 0;
 
         // Branches with one FPU condition code source.
         case kCondF:
         case kCondT:
-          return (delay_slot.cc_outs_mask_ & (1u << lhs_reg_)) == 0;
+          return (delay_slot.masks_.cc_outs_ & (1u << lhs_reg_)) == 0;
 
         default:
           // We don't support synthetic R2 branches (preceded with slt[u]) at this level
@@ -4192,7 +3660,7 @@
         // Branches with one FPU register source.
         case kCondF:
         case kCondT:
-          return (delay_slot.fpr_outs_mask_ & (1u << lhs_reg_)) == 0;
+          return (delay_slot.masks_.fpr_outs_ & (1u << lhs_reg_)) == 0;
         // Others have a forbidden slot instead of a delay slot.
         default:
           return false;
@@ -4858,8 +4326,8 @@
   // Likewise, if the instruction depends on AT, it can't be exchanged with slt[u]
   // because slt[u] changes AT.
   return (delay_slot_.instruction_ != 0 &&
-      (delay_slot_.gpr_outs_mask_ & ((1u << AT) | (1u << rs) | (1u << rt))) == 0 &&
-      (delay_slot_.gpr_ins_mask_ & (1u << AT)) == 0);
+      (delay_slot_.masks_.gpr_outs_ & ((1u << AT) | (1u << rs) | (1u << rt))) == 0 &&
+      (delay_slot_.masks_.gpr_ins_ & (1u << AT)) == 0);
 }
 
 void MipsAssembler::ExchangeWithSlt(const DelaySlot& forwarded_slot) {
diff --git a/compiler/utils/mips/assembler_mips.h b/compiler/utils/mips/assembler_mips.h
index 1c3097a..7de8e2e 100644
--- a/compiler/utils/mips/assembler_mips.h
+++ b/compiler/utils/mips/assembler_mips.h
@@ -74,6 +74,81 @@
   kPositiveZero      = 0x200,
 };
 
+// Instruction description in terms of input and output registers.
+// Used for instruction reordering.
+struct InOutRegMasks {
+  InOutRegMasks()
+      : gpr_outs_(0), gpr_ins_(0), fpr_outs_(0), fpr_ins_(0), cc_outs_(0), cc_ins_(0) {}
+
+  inline InOutRegMasks& GprOuts(Register reg) {
+    gpr_outs_ |= (1u << reg);
+    gpr_outs_ &= ~1u;  // Ignore register ZERO.
+    return *this;
+  }
+  template<typename T, typename... Ts>
+  inline InOutRegMasks& GprOuts(T one, Ts... more) { GprOuts(one); GprOuts(more...); return *this; }
+
+  inline InOutRegMasks& GprIns(Register reg) {
+    gpr_ins_ |= (1u << reg);
+    gpr_ins_ &= ~1u;  // Ignore register ZERO.
+    return *this;
+  }
+  template<typename T, typename... Ts>
+  inline InOutRegMasks& GprIns(T one, Ts... more) { GprIns(one); GprIns(more...); return *this; }
+
+  inline InOutRegMasks& GprInOuts(Register reg) { GprIns(reg); GprOuts(reg); return *this; }
+  template<typename T, typename... Ts>
+  inline InOutRegMasks& GprInOuts(T one, Ts... more) {
+    GprInOuts(one);
+    GprInOuts(more...);
+    return *this;
+  }
+
+  inline InOutRegMasks& FprOuts(FRegister reg) { fpr_outs_ |= (1u << reg); return *this; }
+  inline InOutRegMasks& FprOuts(VectorRegister reg) { return FprOuts(static_cast<FRegister>(reg)); }
+  template<typename T, typename... Ts>
+  inline InOutRegMasks& FprOuts(T one, Ts... more) { FprOuts(one); FprOuts(more...); return *this; }
+
+  inline InOutRegMasks& FprIns(FRegister reg) { fpr_ins_ |= (1u << reg); return *this; }
+  inline InOutRegMasks& FprIns(VectorRegister reg) { return FprIns(static_cast<FRegister>(reg)); }
+  template<typename T, typename... Ts>
+  inline InOutRegMasks& FprIns(T one, Ts... more) { FprIns(one); FprIns(more...); return *this; }
+
+  inline InOutRegMasks& FprInOuts(FRegister reg) { FprIns(reg); FprOuts(reg); return *this; }
+  inline InOutRegMasks& FprInOuts(VectorRegister reg) {
+    return FprInOuts(static_cast<FRegister>(reg));
+  }
+  template<typename T, typename... Ts>
+  inline InOutRegMasks& FprInOuts(T one, Ts... more) {
+    FprInOuts(one);
+    FprInOuts(more...);
+    return *this;
+  }
+
+  inline InOutRegMasks& CcOuts(int cc) { cc_outs_ |= (1u << cc); return *this; }
+  template<typename T, typename... Ts>
+  inline InOutRegMasks& CcOuts(T one, Ts... more) { CcOuts(one); CcOuts(more...); return *this; }
+
+  inline InOutRegMasks& CcIns(int cc) { cc_ins_ |= (1u << cc); return *this; }
+  template<typename T, typename... Ts>
+  inline InOutRegMasks& CcIns(T one, Ts... more) { CcIns(one); CcIns(more...); return *this; }
+
+  // Mask of output GPRs for the instruction.
+  uint32_t gpr_outs_;
+  // Mask of input GPRs for the instruction.
+  uint32_t gpr_ins_;
+  // Mask of output FPRs for the instruction.
+  uint32_t fpr_outs_;
+  // Mask of input FPRs for the instruction.
+  uint32_t fpr_ins_;
+  // Mask of output FPU condition code flags for the instruction.
+  uint32_t cc_outs_;
+  // Mask of input FPU condition code flags for the instruction.
+  uint32_t cc_ins_;
+
+  // TODO: add LO and HI.
+};
+
 class MipsLabel : public Label {
  public:
   MipsLabel() : prev_branch_id_plus_one_(0) {}
@@ -462,6 +537,16 @@
   void FloorWS(FRegister fd, FRegister fs);
   void FloorWD(FRegister fd, FRegister fs);
 
+  // Note, the 32 LSBs of a 64-bit value must be loaded into an FPR before the 32 MSBs
+  // when loading the value as 32-bit halves. This applies to all 32-bit FPR loads:
+  // Mtc1(), Mthc1(), MoveToFpuHigh(), Lwc1(). Even if you need two Mtc1()'s or two
+  // Lwc1()'s to load a pair of 32-bit FPRs and these loads do not interfere with one
+  // another (unlike Mtc1() and Mthc1() with 64-bit FPRs), maintain the order:
+  // low then high.
+  //
+  // Also, prefer MoveFromFpuHigh()/MoveToFpuHigh() over Mfhc1()/Mthc1() and Mfc1()/Mtc1().
+  // This will save you some if statements.
+  FRegister GetFpuRegLow(FRegister reg);
   void Mfc1(Register rt, FRegister fs);
   void Mtc1(Register rt, FRegister fs);
   void Mfhc1(Register rt, FRegister fs);
@@ -1337,23 +1422,13 @@
   // Used to make the decision of moving the instruction into a delay slot.
   struct DelaySlot {
     DelaySlot();
+
     // Encoded instruction that may be used to fill the delay slot or 0
     // (0 conveniently represents NOP).
     uint32_t instruction_;
-    // Mask of output GPRs for the instruction.
-    uint32_t gpr_outs_mask_;
-    // Mask of input GPRs for the instruction.
-    uint32_t gpr_ins_mask_;
-    // Mask of output FPRs for the instruction.
-    uint32_t fpr_outs_mask_;
-    // Mask of input FPRs for the instruction.
-    uint32_t fpr_ins_mask_;
-    // Mask of output FPU condition code flags for the instruction.
-    uint32_t cc_outs_mask_;
-    // Mask of input FPU condition code flags for the instruction.
-    uint32_t cc_ins_mask_;
-    // Branches never operate on the LO and HI registers, hence there's
-    // no mask for LO and HI.
+
+    // Input/output register masks.
+    InOutRegMasks masks_;
 
     // Label for patchable instructions to allow moving them into delay slots.
     MipsLabel* patcher_label_;
@@ -1646,30 +1721,8 @@
   void FinalizeLabeledBranch(MipsLabel* label);
 
   // Various helpers for branch delay slot management.
-  void DsFsmInstr(uint32_t instruction,
-                  uint32_t gpr_outs_mask,
-                  uint32_t gpr_ins_mask,
-                  uint32_t fpr_outs_mask,
-                  uint32_t fpr_ins_mask,
-                  uint32_t cc_outs_mask,
-                  uint32_t cc_ins_mask,
-                  MipsLabel* patcher_label = nullptr);
+  InOutRegMasks& DsFsmInstr(uint32_t instruction, MipsLabel* patcher_label = nullptr);
   void DsFsmInstrNop(uint32_t instruction);
-  void DsFsmInstrRrr(uint32_t instruction,
-                     Register out,
-                     Register in1,
-                     Register in2,
-                     MipsLabel* patcher_label = nullptr);
-  void DsFsmInstrRrrr(uint32_t instruction, Register in1_out, Register in2, Register in3);
-  void DsFsmInstrFff(uint32_t instruction, FRegister out, FRegister in1, FRegister in2);
-  void DsFsmInstrFfff(uint32_t instruction, FRegister in1_out, FRegister in2, FRegister in3);
-  void DsFsmInstrFffr(uint32_t instruction, FRegister in1_out, FRegister in2, Register in3);
-  void DsFsmInstrRf(uint32_t instruction, Register out, FRegister in);
-  void DsFsmInstrFr(uint32_t instruction, FRegister out, Register in);
-  void DsFsmInstrFR(uint32_t instruction, FRegister in1, Register in2);
-  void DsFsmInstrCff(uint32_t instruction, int cc_out, FRegister in1, FRegister in2);
-  void DsFsmInstrRrrc(uint32_t instruction, Register in1_out, Register in2, int cc_in);
-  void DsFsmInstrFffc(uint32_t instruction, FRegister in1_out, FRegister in2, int cc_in);
   void DsFsmLabel();
   void DsFsmCommitLabel();
   void DsFsmDropLabel();