Add repeat support for memory addresses.

Rationale:
This enables exhaustive testing of instructions
that use memory addresses. First use case of
the generics is x86.

Bug: 18380245
Bug: 18380559
Bug: 18380348

Test: assembler_x86[_64]_test

Change-Id: Ib0ad6fa65477b0c6fc04642ff980a4b9543d16d5
diff --git a/compiler/utils/x86/assembler_x86.cc b/compiler/utils/x86/assembler_x86.cc
index b89af10..3162a32 100644
--- a/compiler/utils/x86/assembler_x86.cc
+++ b/compiler/utils/x86/assembler_x86.cc
@@ -32,6 +32,33 @@
   return os << "ST" << static_cast<int>(reg);
 }
 
+std::ostream& operator<<(std::ostream& os, const Address& addr) {
+  switch (addr.mod()) {
+    case 0:
+      if (addr.rm() == ESP && addr.index() != ESP) {
+        return os << "(%" << addr.base() << ",%"
+                  << addr.index() << "," << (1 << addr.scale()) << ")";
+      }
+      return os << "(%" << addr.rm() << ")";
+    case 1:
+      if (addr.rm() == ESP && addr.index() != ESP) {
+        return os << static_cast<int>(addr.disp8())
+                  << "(%" << addr.base() << ",%"
+                  << addr.index() << "," << (1 << addr.scale()) << ")";
+      }
+      return os << static_cast<int>(addr.disp8()) << "(%" << addr.rm() << ")";
+    case 2:
+      if (addr.rm() == ESP && addr.index() != ESP) {
+        return os << static_cast<int>(addr.disp32())
+                  << "(%" << addr.base() << ",%"
+                  << addr.index() << "," << (1 << addr.scale()) << ")";
+      }
+      return os << static_cast<int>(addr.disp32()) << "(%" << addr.rm() << ")";
+    default:
+      return os << "<address?>";
+  }
+}
+
 void X86Assembler::call(Register reg) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0xFF);