Index: test/cctest/test-disasm-x64.cc |
=================================================================== |
--- test/cctest/test-disasm-x64.cc (revision 0) |
+++ test/cctest/test-disasm-x64.cc (revision 0) |
@@ -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 __ |