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);