Add MIPS floating point register mapping to DWARF.

Change-Id: I88508461412bc166549843744a3c6a4ee925b2c7
diff --git a/compiler/dwarf/register.h b/compiler/dwarf/register.h
index 35b3e15..aa3070a 100644
--- a/compiler/dwarf/register.h
+++ b/compiler/dwarf/register.h
@@ -42,6 +42,8 @@
   static Reg Arm64Fp(int num) { return Reg(64 + num); }  // V0-V31.
   static Reg MipsCore(int num) { return Reg(num); }
   static Reg Mips64Core(int num) { return Reg(num); }
+  static Reg MipsFp(int num) { return Reg(32 + num); }
+  static Reg Mips64Fp(int num) { return Reg(32 + num); }
   static Reg X86Core(int num) { return Reg(num); }
   static Reg X86Fp(int num) { return Reg(21 + num); }
   static Reg X86_64Core(int num) {
diff --git a/compiler/elf_writer_debug.cc b/compiler/elf_writer_debug.cc
index 5dbbbc7..b43b86e 100644
--- a/compiler/elf_writer_debug.cc
+++ b/compiler/elf_writer_debug.cc
@@ -90,6 +90,10 @@
       return Reg::X86Fp(machine_reg);
     case kX86_64:
       return Reg::X86_64Fp(machine_reg);
+    case kMips:
+      return Reg::MipsFp(machine_reg);
+    case kMips64:
+      return Reg::Mips64Fp(machine_reg);
     default:
       LOG(FATAL) << "Unknown instruction set: " << isa;
       UNREACHABLE();
@@ -162,6 +166,14 @@
           opcodes.SameValue(Reg::MipsCore(reg));
         }
       }
+      // fp registers.
+      for (int reg = 0; reg < 32; reg++) {
+        if (reg < 24) {
+          opcodes.Undefined(Reg::Mips64Fp(reg));
+        } else {
+          opcodes.SameValue(Reg::Mips64Fp(reg));
+        }
+      }
       auto return_reg = Reg::MipsCore(31);  // R31(RA).
       WriteCIE(is64bit, return_reg, opcodes, format, buffer);
       return;
@@ -860,10 +872,6 @@
               expr.WriteOpReg(Reg::ArmDp(value / 2).num());
               break;
             }
-            if (isa == kMips || isa == kMips64) {
-              // TODO: Find what the DWARF floating point register numbers are on MIPS.
-              break;
-            }
             expr.WriteOpReg(GetDwarfFpReg(isa, value).num());
             if (piece == 0 && reg_hi.GetKind() == Kind::kInFpuRegisterHigh &&
                 reg_hi.GetValue() == reg_lo.GetValue()) {
diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc
index cefcb95..3e1563c 100644
--- a/compiler/optimizing/code_generator_mips64.cc
+++ b/compiler/optimizing/code_generator_mips64.cc
@@ -523,7 +523,9 @@
   return dwarf::Reg::Mips64Core(static_cast<int>(reg));
 }
 
-// TODO: mapping of floating-point registers to DWARF
+static dwarf::Reg DWARFReg(FpuRegister reg) {
+  return dwarf::Reg::Mips64Fp(static_cast<int>(reg));
+}
 
 void CodeGeneratorMIPS64::GenerateFrameEntry() {
   __ Bind(&frame_entry_label_);
@@ -573,7 +575,7 @@
     if (allocated_registers_.ContainsFloatingPointRegister(reg)) {
       ofs -= kMips64DoublewordSize;
       __ Sdc1(reg, SP, ofs);
-      // TODO: __ cfi().RelOffset(DWARFReg(reg), ofs);
+      __ cfi().RelOffset(DWARFReg(reg), ofs);
     }
   }
 
@@ -610,7 +612,7 @@
       if (allocated_registers_.ContainsFloatingPointRegister(reg)) {
         __ Ldc1(reg, SP, ofs);
         ofs += kMips64DoublewordSize;
-        // TODO: __ cfi().Restore(DWARFReg(reg));
+        __ cfi().Restore(DWARFReg(reg));
       }
     }
 
diff --git a/compiler/optimizing/optimizing_cfi_test_expected.inc b/compiler/optimizing/optimizing_cfi_test_expected.inc
index de85729..fc66823 100644
--- a/compiler/optimizing/optimizing_cfi_test_expected.inc
+++ b/compiler/optimizing/optimizing_cfi_test_expected.inc
@@ -198,8 +198,9 @@
 };
 static constexpr uint8_t expected_cfi_kMips64[] = {
     0x44, 0x0E, 0x28, 0x44, 0x9F, 0x02, 0x44, 0x91, 0x04, 0x44, 0x90, 0x06,
-    0x4C, 0x0E, 0x40, 0x44, 0x0A, 0x44, 0x0E, 0x28, 0x4C, 0xD0, 0x44, 0xD1,
-    0x44, 0xDF, 0x44, 0x0E, 0x00, 0x48, 0x0B, 0x0E, 0x40,
+    0x44, 0xB9, 0x08, 0x44, 0xB8, 0x0A, 0x44, 0x0E, 0x40, 0x44, 0x0A, 0x44,
+    0x0E, 0x28, 0x44, 0xF8, 0x44, 0xF9, 0x44, 0xD0, 0x44, 0xD1, 0x44, 0xDF,
+    0x44, 0x0E, 0x00, 0x48, 0x0B, 0x0E, 0x40,
 };
 // 0x00000000: daddiu r29, r29, -40
 // 0x00000004: .cfi_def_cfa_offset: 40
@@ -210,7 +211,9 @@
 // 0x0000000c: sd r16, +16(r29)
 // 0x00000010: .cfi_offset: r16 at cfa-24
 // 0x00000010: sdc1 f25, +8(r29)
+// 0x00000014: .cfi_offset: r57 at cfa-32
 // 0x00000014: sdc1 f24, +0(r29)
+// 0x00000018: .cfi_offset: r56 at cfa-40
 // 0x00000018: daddiu r29, r29, -24
 // 0x0000001c: .cfi_def_cfa_offset: 64
 // 0x0000001c: sd r4, +0(r29)
@@ -218,7 +221,9 @@
 // 0x00000020: daddiu r29, r29, 24
 // 0x00000024: .cfi_def_cfa_offset: 40
 // 0x00000024: ldc1 f24, +0(r29)
+// 0x00000028: .cfi_restore: r56
 // 0x00000028: ldc1 f25, +8(r29)
+// 0x0000002c: .cfi_restore: r57
 // 0x0000002c: ld r16, +16(r29)
 // 0x00000030: .cfi_restore: r16
 // 0x00000030: ld r17, +24(r29)
@@ -427,9 +432,9 @@
 };
 static constexpr uint8_t expected_cfi_kMips64_adjust[] = {
     0x44, 0x0E, 0x28, 0x44, 0x9F, 0x02, 0x44, 0x91, 0x04, 0x44, 0x90, 0x06,
-    0x4C, 0x0E, 0x40, 0x04, 0x14, 0x00, 0x02, 0x00, 0x0A, 0x44, 0x0E, 0x28,
-    0x4C, 0xD0, 0x44, 0xD1, 0x44, 0xDF, 0x44, 0x0E, 0x00, 0x48, 0x0B, 0x0E,
-    0x40,
+    0x44, 0xB9, 0x08, 0x44, 0xB8, 0x0A, 0x44, 0x0E, 0x40, 0x04, 0x14, 0x00,
+    0x02, 0x00, 0x0A, 0x44, 0x0E, 0x28, 0x44, 0xF8, 0x44, 0xF9, 0x44, 0xD0,
+    0x44, 0xD1, 0x44, 0xDF, 0x44, 0x0E, 0x00, 0x48, 0x0B, 0x0E, 0x40,
 };
 // 0x00000000: daddiu r29, r29, -40
 // 0x00000004: .cfi_def_cfa_offset: 40
@@ -440,7 +445,9 @@
 // 0x0000000c: sd r16, +16(r29)
 // 0x00000010: .cfi_offset: r16 at cfa-24
 // 0x00000010: sdc1 f25, +8(r29)
+// 0x00000014: .cfi_offset: r57 at cfa-32
 // 0x00000014: sdc1 f24, +0(r29)
+// 0x00000018: .cfi_offset: r56 at cfa-40
 // 0x00000018: daddiu r29, r29, -24
 // 0x0000001c: .cfi_def_cfa_offset: 64
 // 0x0000001c: sd r4, +0(r29)
@@ -454,7 +461,9 @@
 // 0x00020030: daddiu r29, r29, 24
 // 0x00020034: .cfi_def_cfa_offset: 40
 // 0x00020034: ldc1 f24, +0(r29)
+// 0x00020038: .cfi_restore: r56
 // 0x00020038: ldc1 f25, +8(r29)
+// 0x0002003c: .cfi_restore: r57
 // 0x0002003c: ld r16, +16(r29)
 // 0x00020040: .cfi_restore: r16
 // 0x00020040: ld r17, +24(r29)