Clean up multi byte nop support on x64 to more closely match IA32.
authorerik.corry@gmail.com <erik.corry@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 5 Dec 2011 08:58:01 +0000 (08:58 +0000)
committererik.corry@gmail.com <erik.corry@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 5 Dec 2011 08:58:01 +0000 (08:58 +0000)
Fix missing instruction in disassembler.
Fix wrong disassembly of multi-byte NOP on x64
Add test of disassembler on 64 bit!
Review URL: http://codereview.chromium.org/8773039

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10147 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/x64/assembler-x64.cc
src/x64/assembler-x64.h
src/x64/debug-x64.cc
src/x64/deoptimizer-x64.cc
src/x64/disasm-x64.cc
src/x64/lithium-codegen-x64.cc
test/cctest/SConscript
test/cctest/test-assembler-x64.cc
test/cctest/test-disasm-x64.cc [new file with mode: 0644]

index 26b449c524690ee69b4a71a227b7790f8a0faa06..f07a0ddee592faeb6cb7f117a8642a7516036e3a 100644 (file)
@@ -426,13 +426,7 @@ void Assembler::GetCode(CodeDesc* desc) {
 void Assembler::Align(int m) {
   ASSERT(IsPowerOf2(m));
   int delta = (m - (pc_offset() & (m - 1))) & (m - 1);
-  while (delta >= 9) {
-    nop(9);
-    delta -= 9;
-  }
-  if (delta > 0) {
-    nop(delta);
-  }
+  Nop(delta);
 }
 
 
@@ -441,6 +435,15 @@ void Assembler::CodeTargetAlign() {
 }
 
 
+bool Assembler::IsNop(Address addr) {
+  Address a = addr;
+  while (*a == 0x66) a++;
+  if (*a == 0x90) return true;
+  if (a[0] == 0xf && a[1] == 0x1f) return true;
+  return false;
+}
+
+
 void Assembler::bind_to(Label* L, int pos) {
   ASSERT(!L->is_bound());  // Label may only be bound once.
   ASSERT(0 <= pos && pos <= pc_offset());  // Position must be valid.
@@ -1763,7 +1766,7 @@ void Assembler::notl(Register dst) {
 }
 
 
-void Assembler::nop(int n) {
+void Assembler::Nop(int n) {
   // The recommended muti-byte sequences of NOP instructions from the Intel 64
   // and IA-32 Architectures Software Developer's Manual.
   //
@@ -1778,73 +1781,64 @@ void Assembler::nop(int n) {
   // 9 bytes  66 NOP DWORD ptr [EAX + EAX*1 +         66 0F 1F 84 00 00 00 00
   //          00000000H]                              00H
 
-  ASSERT(1 <= n);
-  ASSERT(n <= 9);
   EnsureSpace ensure_space(this);
-  switch (n) {
-  case 1:
-    emit(0x90);
-    return;
-  case 2:
-    emit(0x66);
-    emit(0x90);
-    return;
-  case 3:
-    emit(0x0f);
-    emit(0x1f);
-    emit(0x00);
-    return;
-  case 4:
-    emit(0x0f);
-    emit(0x1f);
-    emit(0x40);
-    emit(0x00);
-    return;
-  case 5:
-    emit(0x0f);
-    emit(0x1f);
-    emit(0x44);
-    emit(0x00);
-    emit(0x00);
-    return;
-  case 6:
-    emit(0x66);
-    emit(0x0f);
-    emit(0x1f);
-    emit(0x44);
-    emit(0x00);
-    emit(0x00);
-    return;
-  case 7:
-    emit(0x0f);
-    emit(0x1f);
-    emit(0x80);
-    emit(0x00);
-    emit(0x00);
-    emit(0x00);
-    emit(0x00);
-    return;
-  case 8:
-    emit(0x0f);
-    emit(0x1f);
-    emit(0x84);
-    emit(0x00);
-    emit(0x00);
-    emit(0x00);
-    emit(0x00);
-    emit(0x00);
-    return;
-  case 9:
-    emit(0x66);
-    emit(0x0f);
-    emit(0x1f);
-    emit(0x84);
-    emit(0x00);
-    emit(0x00);
-    emit(0x00);
-    emit(0x00);
-    emit(0x00);
-    return;
+  while (n > 0) {
+    switch (n) {
+      case 2:
+        emit(0x66);
+      case 1:
+        emit(0x90);
+        return;
+      case 3:
+        emit(0x0f);
+        emit(0x1f);
+        emit(0x00);
+        return;
+      case 4:
+        emit(0x0f);
+        emit(0x1f);
+        emit(0x40);
+        emit(0x00);
+        return;
+      case 6:
+        emit(0x66);
+      case 5:
+        emit(0x0f);
+        emit(0x1f);
+        emit(0x44);
+        emit(0x00);
+        emit(0x00);
+        return;
+      case 7:
+        emit(0x0f);
+        emit(0x1f);
+        emit(0x80);
+        emit(0x00);
+        emit(0x00);
+        emit(0x00);
+        emit(0x00);
+        return;
+      default:
+      case 11:
+        emit(0x66);
+        n--;
+      case 10:
+        emit(0x66);
+        n--;
+      case 9:
+        emit(0x66);
+        n--;
+      case 8:
+        emit(0x0f);
+        emit(0x1f);
+        emit(0x84);
+        emit(0x00);
+        emit(0x00);
+        emit(0x00);
+        emit(0x00);
+        emit(0x00);
+        n -= 8;
+    }
   }
 }
 
index 1db5273b2962c36a7be18bedad4131795df73316..1501d230b9fa4fbf3db949027129ffe833f10314 100644 (file)
@@ -636,6 +636,7 @@ class Assembler : public AssemblerBase {
   // possible to align the pc offset to a multiple
   // of m, where m must be a power of 2.
   void Align(int m);
+  void Nop(int bytes = 1);
   // Aligns code to something that's optimal for a jump target for the platform.
   void CodeTargetAlign();
 
@@ -1154,7 +1155,6 @@ class Assembler : public AssemblerBase {
   void hlt();
   void int3();
   void nop();
-  void nop(int n);
   void rdtsc();
   void ret(int imm16);
   void setcc(Condition cc, Register reg);
@@ -1398,7 +1398,7 @@ class Assembler : public AssemblerBase {
     return static_cast<int>(reloc_info_writer.pos() - pc_);
   }
 
-  static bool IsNop(Address addr) { return *addr == 0x90; }
+  static bool IsNop(Address addr);
 
   // Avoid overflows for displacements etc.
   static const int kMaximalBufferSize = 512*MB;
index 339b961fe2c8a743c1271b49f1c6213ca2544403..f84772eb9fd57a537a115dc4b3e7584df06c8188 100644 (file)
@@ -264,9 +264,7 @@ void Debug::GenerateSlot(MacroAssembler* masm) {
   Label check_codesize;
   __ bind(&check_codesize);
   __ RecordDebugBreakSlot();
-  for (int i = 0; i < Assembler::kDebugBreakSlotLength; i++) {
-    __ nop();
-  }
+  __ Nop(Assembler::kDebugBreakSlotLength);
   ASSERT_EQ(Assembler::kDebugBreakSlotLength,
             masm->SizeOfCodeGeneratedSince(&check_codesize));
 }
index 1fd78fc5789531709c898a672d8d5bfbbc704756..d684ad713f49d322923fd75d872df2a1427b5b5e 100644 (file)
@@ -138,8 +138,8 @@ void Deoptimizer::PatchStackCheckCodeAt(Code* unoptimized_code,
   ASSERT(*(call_target_address - 3) == 0x73 &&  // jae
          *(call_target_address - 2) == 0x07 &&  // offset
          *(call_target_address - 1) == 0xe8);   // call
-  *(call_target_address - 3) = 0x90;  // nop
-  *(call_target_address - 2) = 0x90;  // nop
+  *(call_target_address - 3) = 0x66;  // 2 byte nop part 1
+  *(call_target_address - 2) = 0x90;  // 2 byte nop part 2
   Assembler::set_target_address_at(call_target_address,
                                    replacement_code->entry());
 
@@ -157,8 +157,8 @@ void Deoptimizer::RevertStackCheckCodeAt(Code* unoptimized_code,
          Assembler::target_address_at(call_target_address));
   // Replace the nops from patching (Deoptimizer::PatchStackCheckCode) to
   // restore the conditional branch.
-  ASSERT(*(call_target_address - 3) == 0x90 &&  // nop
-         *(call_target_address - 2) == 0x90 &&  // nop
+  ASSERT(*(call_target_address - 3) == 0x66 &&  // 2 byte nop part 1
+         *(call_target_address - 2) == 0x90 &&  // 2 byte nop part 2
          *(call_target_address - 1) == 0xe8);   // call
   *(call_target_address - 3) = 0x73;  // jae
   *(call_target_address - 2) = 0x07;  // offset
index 1b8871fd473cb1956453e1b679cc7b9ea38b1a3d..a88a13353ebc80a437009f09d0f317832d4bfcc6 100644 (file)
@@ -109,6 +109,7 @@ static const ByteMnemonic zero_operands_instr[] = {
   { 0xC3, UNSET_OP_ORDER, "ret" },
   { 0xC9, UNSET_OP_ORDER, "leave" },
   { 0xF4, UNSET_OP_ORDER, "hlt" },
+  { 0xFC, UNSET_OP_ORDER, "cld" },
   { 0xCC, UNSET_OP_ORDER, "int3" },
   { 0x60, UNSET_OP_ORDER, "pushad" },
   { 0x61, UNSET_OP_ORDER, "popad" },
@@ -1034,7 +1035,18 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
       }
     } else {
       get_modrm(*current, &mod, &regop, &rm);
-      if (opcode == 0x28) {
+      if (opcode == 0x1f) {
+        current++;
+        if (rm == 4) {  // SIB byte present.
+          current++;
+        }
+        if (mod == 1) {  // Byte displacement.
+          current += 1;
+        } else if (mod == 2) {  // 32-bit displacement.
+          current += 4;
+        }  // else no immediate displacement.
+        AppendToBuffer("nop");
+      } else if (opcode == 0x28) {
         AppendToBuffer("movapd %s, ", NameOfXMMRegister(regop));
         current += PrintRightXMMOperand(current);
       } else if (opcode == 0x29) {
@@ -1178,7 +1190,7 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
     int mod, regop, rm;
     get_modrm(*current, &mod, &regop, &rm);
     current++;
-    if (regop == 4) {  // SIB byte present.
+    if (rm == 4) {  // SIB byte present.
       current++;
     }
     if (mod == 1) {  // Byte displacement.
index cdbc717e4f168310922b72af64af7e684e965993..ce2cddfab75791594aaef96e0fa9c3ffcf999da2 100644 (file)
@@ -4201,11 +4201,7 @@ void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) {
   int current_pc = masm()->pc_offset();
   if (current_pc < last_lazy_deopt_pc_ + space_needed) {
     int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc;
-    while (padding_size > 0) {
-      int nop_size = padding_size > 9 ? 9 : padding_size;
-      __ nop(nop_size);
-      padding_size -= nop_size;
-    }
+    __ Nop(padding_size);
   }
 }
 
index 621d8ecf65b0205375644ec8fb8417b8bd9f34c7..5fc9188ee9d3012ac875303697bc18ad5692f4c4 100644 (file)
@@ -110,7 +110,8 @@ SOURCES = {
   ],
   'arch:x64': ['test-assembler-x64.cc',
                'test-macro-assembler-x64.cc',
-               'test-log-stack-tracer.cc'],
+               'test-log-stack-tracer.cc',
+               'test-disasm-x64.cc'],
   'arch:mips': ['test-assembler-mips.cc',
                 'test-disasm-mips.cc'],
   'os:linux':  ['test-platform-linux.cc'],
index 28f7c9b703f27a72bbba0178a34cd690423574dc..959cf3fe52a3476411df6d440024a91729a0c438 100644 (file)
@@ -36,6 +36,7 @@
 #include "cctest.h"
 
 using v8::internal::Assembler;
+using v8::internal::Code;
 using v8::internal::CodeDesc;
 using v8::internal::FUNCTION_CAST;
 using v8::internal::Immediate;
@@ -53,6 +54,7 @@ using v8::internal::r15;
 using v8::internal::r8;
 using v8::internal::r9;
 using v8::internal::rax;
+using v8::internal::rbx;
 using v8::internal::rbp;
 using v8::internal::rcx;
 using v8::internal::rdi;
@@ -86,6 +88,16 @@ static const v8::internal::Register arg2 = rsi;
 #define __ assm.
 
 
+static v8::Persistent<v8::Context> env;
+
+
+static void InitializeVM() {
+  if (env.IsEmpty()) {
+    env = v8::Context::New();
+  }
+}
+
+
 TEST(AssemblerX64ReturnOperation) {
   OS::Setup();
   // Allocate an executable page of memory.
@@ -359,4 +371,73 @@ TEST(AssemblerX64LabelChaining) {
   __ nop();
 }
 
+
+TEST(AssemblerMultiByteNop) {
+  InitializeVM();
+  v8::HandleScope scope;
+  v8::internal::byte buffer[1024];
+  Assembler assm(Isolate::Current(), buffer, sizeof(buffer));
+  __ push(rbx);
+  __ push(rcx);
+  __ push(rdx);
+  __ push(rdi);
+  __ push(rsi);
+  __ movq(rax, Immediate(1));
+  __ movq(rbx, Immediate(2));
+  __ movq(rcx, Immediate(3));
+  __ movq(rdx, Immediate(4));
+  __ movq(rdi, Immediate(5));
+  __ movq(rsi, Immediate(6));
+  for (int i = 0; i < 16; i++) {
+    int before = assm.pc_offset();
+    __ Nop(i);
+    CHECK_EQ(assm.pc_offset() - before, i);
+  }
+
+  Label fail;
+  __ cmpq(rax, Immediate(1));
+  __ j(not_equal, &fail);
+  __ cmpq(rbx, Immediate(2));
+  __ j(not_equal, &fail);
+  __ cmpq(rcx, Immediate(3));
+  __ j(not_equal, &fail);
+  __ cmpq(rdx, Immediate(4));
+  __ j(not_equal, &fail);
+  __ cmpq(rdi, Immediate(5));
+  __ j(not_equal, &fail);
+  __ cmpq(rsi, Immediate(6));
+  __ j(not_equal, &fail);
+  __ movq(rax, Immediate(42));
+  __ pop(rsi);
+  __ pop(rdi);
+  __ pop(rdx);
+  __ pop(rcx);
+  __ pop(rbx);
+  __ ret(0);
+  __ bind(&fail);
+  __ movq(rax, Immediate(13));
+  __ pop(rsi);
+  __ pop(rdi);
+  __ pop(rdx);
+  __ pop(rcx);
+  __ pop(rbx);
+  __ ret(0);
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Code* code = Code::cast(HEAP->CreateCode(
+      desc,
+      Code::ComputeFlags(Code::STUB),
+      v8::internal::Handle<v8::internal::Object>(
+          HEAP->undefined_value()))->ToObjectChecked());
+  CHECK(code->IsCode());
+
+  F0 f = FUNCTION_CAST<F0>(code->entry());
+  int res = f();
+  CHECK_EQ(42, res);
+}
+
+
+
+
 #undef __
diff --git a/test/cctest/test-disasm-x64.cc b/test/cctest/test-disasm-x64.cc
new file mode 100644 (file)
index 0000000..da85eb9
--- /dev/null
@@ -0,0 +1,429 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <stdlib.h>
+
+#include "v8.h"
+
+#include "debug.h"
+#include "disasm.h"
+#include "disassembler.h"
+#include "macro-assembler.h"
+#include "serialize.h"
+#include "cctest.h"
+
+using namespace v8::internal;
+
+static v8::Persistent<v8::Context> env;
+
+static void InitializeVM() {
+  if (env.IsEmpty()) {
+    env = v8::Context::New();
+  }
+}
+
+
+#define __ assm.
+
+
+static void DummyStaticFunction(Object* result) {
+}
+
+
+TEST(DisasmX64) {
+  InitializeVM();
+  v8::HandleScope scope;
+  v8::internal::byte buffer[2048];
+  Assembler assm(Isolate::Current(), buffer, sizeof buffer);
+  DummyStaticFunction(NULL);  // just bloody use it (DELETE; debugging)
+
+  // Short immediate instructions
+  __ addq(rax, Immediate(12345678));
+  __ or_(rax, Immediate(12345678));
+  __ subq(rax, Immediate(12345678));
+  __ xor_(rax, Immediate(12345678));
+  __ and_(rax, Immediate(12345678));
+
+  // ---- This one caused crash
+  __ movq(rbx,  Operand(rsp, rcx, times_2, 0));  // [rsp+rcx*4]
+
+  // ---- All instructions that I can think of
+  __ addq(rdx, rbx);
+  __ addq(rdx, Operand(rbx, 0));
+  __ addq(rdx, Operand(rbx, 16));
+  __ addq(rdx, Operand(rbx, 1999));
+  __ addq(rdx, Operand(rsp, 0));
+  __ addq(rdx, Operand(rsp, 16));
+  __ addq(rdx, Operand(rsp, 1999));
+  __ nop();
+  __ addq(rdi, Operand(rbp, rcx, times_4, 0));
+  __ addq(rdi, Operand(rbp, rcx, times_4, 12));
+  __ addq(Operand(rbp, rcx, times_4, 12), Immediate(12));
+
+  __ nop();
+  __ addq(rbx, Immediate(12));
+  __ nop();
+  __ nop();
+  __ and_(rdx, Immediate(3));
+  __ and_(rdx, Operand(rsp, 4));
+  __ cmpq(rdx, Immediate(3));
+  __ cmpq(rdx, Operand(rsp, 4));
+  __ cmpq(Operand(rbp, rcx, times_4, 0), Immediate(1000));
+  __ cmpb(rbx, Operand(rbp, rcx, times_2, 0));
+  __ cmpb(Operand(rbp, rcx, times_2, 0), rbx);
+  __ or_(rdx, Immediate(3));
+  __ xor_(rdx, Immediate(3));
+  __ nop();
+  {
+    CHECK(CpuFeatures::IsSupported(CPUID));
+    CpuFeatures::Scope fscope(CPUID);
+    __ cpuid();
+  }
+  {
+    CHECK(CpuFeatures::IsSupported(RDTSC));
+    CpuFeatures::Scope fscope(RDTSC);
+    __ rdtsc();
+  }
+  __ movsxbq(rdx, Operand(rcx, 0));
+  __ movsxwq(rdx, Operand(rcx, 0));
+  __ movzxbl(rdx, Operand(rcx, 0));
+  __ movzxwl(rdx, Operand(rcx, 0));
+  __ movzxbq(rdx, Operand(rcx, 0));
+  __ movzxwq(rdx, Operand(rcx, 0));
+
+  __ nop();
+  __ imul(rdx, rcx);
+  __ shld(rdx, rcx);
+  __ shrd(rdx, rcx);
+  __ bts(Operand(rdx, 0), rcx);
+  __ bts(Operand(rbx, rcx, times_4, 0), rcx);
+  __ nop();
+  __ push(Immediate(12));
+  __ push(Immediate(23456));
+  __ push(rcx);
+  __ push(rsi);
+  __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
+  __ push(Operand(rbx, rcx, times_4, 0));
+  __ push(Operand(rbx, rcx, times_4, 0));
+  __ push(Operand(rbx, rcx, times_4, 10000));
+  __ pop(rdx);
+  __ pop(rax);
+  __ pop(Operand(rbx, rcx, times_4, 0));
+  __ nop();
+
+  __ addq(rdx, Operand(rsp, 16));
+  __ addq(rdx, rcx);
+  __ movb(rdx, Operand(rcx, 0));
+  __ movb(rcx, Immediate(6));
+  __ movb(Operand(rsp, 16), rdx);
+  __ movw(Operand(rsp, 16), rdx);
+  __ nop();
+  __ movsxwq(rdx, Operand(rsp, 12));
+  __ movsxbq(rdx, Operand(rsp, 12));
+  __ movsxlq(rdx, Operand(rsp, 12));
+  __ movzxwq(rdx, Operand(rsp, 12));
+  __ movzxbq(rdx, Operand(rsp, 12));
+  __ nop();
+  __ movq(rdx, Immediate(1234567));
+  __ movq(rdx, Operand(rsp, 12));
+  __ movq(Operand(rbx, rcx, times_4, 10000), Immediate(12345));
+  __ movq(Operand(rbx, rcx, times_4, 10000), rdx);
+  __ nop();
+  __ decb(rdx);
+  __ decb(Operand(rax, 10));
+  __ decb(Operand(rbx, rcx, times_4, 10000));
+  __ decq(rdx);
+  __ cdq();
+
+  __ nop();
+  __ idivq(rdx);
+  __ mul(rdx);
+  __ neg(rdx);
+  __ not_(rdx);
+  __ testq(Operand(rbx, rcx, times_4, 10000), rdx);
+
+  __ imul(rdx, Operand(rbx, rcx, times_4, 10000));
+  __ imul(rdx, rcx, Immediate(12));
+  __ imul(rdx, rcx, Immediate(1000));
+
+  __ incq(rdx);
+  __ incq(Operand(rbx, rcx, times_4, 10000));
+  __ push(Operand(rbx, rcx, times_4, 10000));
+  __ pop(Operand(rbx, rcx, times_4, 10000));
+  __ jmp(Operand(rbx, rcx, times_4, 10000));
+
+  __ lea(rdx, Operand(rbx, rcx, times_4, 10000));
+  __ or_(rdx, Immediate(12345));
+  __ or_(rdx, Operand(rbx, rcx, times_4, 10000));
+
+  __ nop();
+
+  __ rcl(rdx, Immediate(1));
+  __ rcl(rdx, Immediate(7));
+  __ rcr(rdx, Immediate(1));
+  __ rcr(rdx, Immediate(7));
+  __ sar(rdx, Immediate(1));
+  __ sar(rdx, Immediate(6));
+  __ sar_cl(rdx);
+  __ sbbq(rdx, rbx);
+  __ shld(rdx, rbx);
+  __ shl(rdx, Immediate(1));
+  __ shl(rdx, Immediate(6));
+  __ shl_cl(rdx);
+  __ shrd(rdx, rbx);
+  __ shr(rdx, Immediate(1));
+  __ shr(rdx, Immediate(7));
+  __ shr_cl(rdx);
+
+
+  // Immediates
+
+  __ addq(rbx, Immediate(12));
+  __ addq(Operand(rdx, rcx, times_4, 10000), Immediate(12));
+
+  __ and_(rbx, Immediate(12345));
+
+  __ cmpq(rbx, Immediate(12345));
+  __ cmpq(rbx, Immediate(12));
+  __ cmpq(Operand(rdx, rcx, times_4, 10000), Immediate(12));
+  __ cmpb(rax, Immediate(100));
+
+  __ or_(rbx, Immediate(12345));
+
+  __ subq(rbx, Immediate(12));
+  __ subq(Operand(rdx, rcx, times_4, 10000), Immediate(12));
+
+  __ xor_(rbx, Immediate(12345));
+
+  __ imul(rdx, rcx, Immediate(12));
+  __ imul(rdx, rcx, Immediate(1000));
+
+  __ cld();
+
+  __ subq(rdx, Operand(rbx, rcx, times_4, 10000));
+  __ subq(rdx, rbx);
+
+  __ testq(rdx, Immediate(12345));
+  __ testq(Operand(rbx, rcx, times_8, 10000), rdx);
+  __ testb(Operand(rcx, rbx, times_2, 1000), rdx);
+  __ testb(Operand(rax, -20), Immediate(0x9A));
+  __ nop();
+
+  __ xor_(rdx, Immediate(12345));
+  __ xor_(rdx, Operand(rbx, rcx, times_8, 10000));
+  __ bts(Operand(rbx, rcx, times_8, 10000), rdx);
+  __ hlt();
+  __ int3();
+  __ ret(0);
+  __ ret(8);
+
+  // Calls
+
+  Label L1, L2;
+  __ bind(&L1);
+  __ nop();
+  __ call(&L1);
+  __ call(&L2);
+  __ nop();
+  __ bind(&L2);
+  __ call(Operand(rbx, rcx, times_4, 10000));
+  __ nop();
+  Handle<Code> ic(Isolate::Current()->builtins()->builtin(
+      Builtins::kLoadIC_Initialize));
+  __ call(ic, RelocInfo::CODE_TARGET);
+  __ nop();
+  __ nop();
+
+  __ jmp(&L1);
+  __ jmp(Operand(rbx, rcx, times_4, 10000));
+#ifdef ENABLE_DEBUGGER_SUPPORT
+  ExternalReference after_break_target =
+      ExternalReference(Debug_Address::AfterBreakTarget(),
+                        assm.isolate());
+#endif  // ENABLE_DEBUGGER_SUPPORT
+  __ jmp(ic, RelocInfo::CODE_TARGET);
+  __ nop();
+
+
+  Label Ljcc;
+  __ nop();
+  // long jumps
+  __ j(overflow, &Ljcc);
+  __ j(no_overflow, &Ljcc);
+  __ j(below, &Ljcc);
+  __ j(above_equal, &Ljcc);
+  __ j(equal, &Ljcc);
+  __ j(not_equal, &Ljcc);
+  __ j(below_equal, &Ljcc);
+  __ j(above, &Ljcc);
+  __ j(sign, &Ljcc);
+  __ j(not_sign, &Ljcc);
+  __ j(parity_even, &Ljcc);
+  __ j(parity_odd, &Ljcc);
+  __ j(less, &Ljcc);
+  __ j(greater_equal, &Ljcc);
+  __ j(less_equal, &Ljcc);
+  __ j(greater, &Ljcc);
+  __ nop();
+  __ bind(&Ljcc);
+  // short jumps
+  __ j(overflow, &Ljcc);
+  __ j(no_overflow, &Ljcc);
+  __ j(below, &Ljcc);
+  __ j(above_equal, &Ljcc);
+  __ j(equal, &Ljcc);
+  __ j(not_equal, &Ljcc);
+  __ j(below_equal, &Ljcc);
+  __ j(above, &Ljcc);
+  __ j(sign, &Ljcc);
+  __ j(not_sign, &Ljcc);
+  __ j(parity_even, &Ljcc);
+  __ j(parity_odd, &Ljcc);
+  __ j(less, &Ljcc);
+  __ j(greater_equal, &Ljcc);
+  __ j(less_equal, &Ljcc);
+  __ j(greater, &Ljcc);
+
+  // 0xD9 instructions
+  __ nop();
+
+  __ fld(1);
+  __ fld1();
+  __ fldz();
+  __ fldpi();
+  __ fabs();
+  __ fchs();
+  __ fprem();
+  __ fprem1();
+  __ fincstp();
+  __ ftst();
+  __ fxch(3);
+  __ fld_s(Operand(rbx, rcx, times_4, 10000));
+  __ fstp_s(Operand(rbx, rcx, times_4, 10000));
+  __ ffree(3);
+  __ fld_d(Operand(rbx, rcx, times_4, 10000));
+  __ fstp_d(Operand(rbx, rcx, times_4, 10000));
+  __ nop();
+
+  __ fild_s(Operand(rbx, rcx, times_4, 10000));
+  __ fistp_s(Operand(rbx, rcx, times_4, 10000));
+  __ fild_d(Operand(rbx, rcx, times_4, 10000));
+  __ fistp_d(Operand(rbx, rcx, times_4, 10000));
+  __ fnstsw_ax();
+  __ nop();
+  __ fadd(3);
+  __ fsub(3);
+  __ fmul(3);
+  __ fdiv(3);
+
+  __ faddp(3);
+  __ fsubp(3);
+  __ fmulp(3);
+  __ fdivp(3);
+  __ fcompp();
+  __ fwait();
+  __ nop();
+  {
+    if (CpuFeatures::IsSupported(SSE2)) {
+      CpuFeatures::Scope fscope(SSE2);
+      __ cvttss2si(rdx, Operand(rbx, rcx, times_4, 10000));
+      __ cvttss2si(rdx, xmm1);
+      __ cvttsd2si(rdx, Operand(rbx, rcx, times_4, 10000));
+      __ cvttsd2si(rdx, xmm1);
+      __ cvttsd2siq(rdx, xmm1);
+      __ addsd(xmm1, xmm0);
+      __ mulsd(xmm1, xmm0);
+      __ subsd(xmm1, xmm0);
+      __ divsd(xmm1, xmm0);
+      __ movsd(xmm1, Operand(rbx, rcx, times_4, 10000));
+      __ movsd(Operand(rbx, rcx, times_4, 10000), xmm1);
+      __ ucomisd(xmm0, xmm1);
+
+      // 128 bit move instructions.
+      __ movdqa(xmm0, Operand(rbx, rcx, times_4, 10000));
+      __ movdqa(Operand(rbx, rcx, times_4, 10000), xmm0);
+    }
+  }
+
+  // cmov.
+  {
+    if (CpuFeatures::IsSupported(CMOV)) {
+      CpuFeatures::Scope use_cmov(CMOV);
+      __ cmovq(overflow, rax, Operand(rax, 0));
+      __ cmovq(no_overflow, rax, Operand(rax, 1));
+      __ cmovq(below, rax, Operand(rax, 2));
+      __ cmovq(above_equal, rax, Operand(rax, 3));
+      __ cmovq(equal, rax, Operand(rbx, 0));
+      __ cmovq(not_equal, rax, Operand(rbx, 1));
+      __ cmovq(below_equal, rax, Operand(rbx, 2));
+      __ cmovq(above, rax, Operand(rbx, 3));
+      __ cmovq(sign, rax, Operand(rcx, 0));
+      __ cmovq(not_sign, rax, Operand(rcx, 1));
+      __ cmovq(parity_even, rax, Operand(rcx, 2));
+      __ cmovq(parity_odd, rax, Operand(rcx, 3));
+      __ cmovq(less, rax, Operand(rdx, 0));
+      __ cmovq(greater_equal, rax, Operand(rdx, 1));
+      __ cmovq(less_equal, rax, Operand(rdx, 2));
+      __ cmovq(greater, rax, Operand(rdx, 3));
+    }
+  }
+
+  // andpd, etc.
+  {
+    if (CpuFeatures::IsSupported(SSE2)) {
+      CpuFeatures::Scope fscope(SSE2);
+      __ andpd(xmm0, xmm1);
+      __ andpd(xmm1, xmm2);
+
+      __ movaps(xmm0, xmm1);
+      __ movaps(xmm1, xmm2);
+    }
+  }
+
+  // Nop instructions
+  for (int i = 0; i < 16; i++) {
+    __ Nop(i);
+  }
+
+  __ ret(0);
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Object* code = HEAP->CreateCode(
+      desc,
+      Code::ComputeFlags(Code::STUB),
+      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
+  CHECK(code->IsCode());
+#ifdef OBJECT_PRINT
+  Code::cast(code)->Print();
+  byte* begin = Code::cast(code)->instruction_start();
+  byte* end = begin + Code::cast(code)->instruction_size();
+  disasm::Disassembler::Disassemble(stdout, begin, end);
+#endif
+}
+
+#undef __