Home | History | Annotate | Download | only in cctest
      1 // Copyright 2011 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #include <stdlib.h>
     29 
     30 #include "v8.h"
     31 
     32 #include "debug.h"
     33 #include "disasm.h"
     34 #include "disassembler.h"
     35 #include "macro-assembler.h"
     36 #include "serialize.h"
     37 #include "cctest.h"
     38 
     39 using namespace v8::internal;
     40 
     41 static v8::Persistent<v8::Context> env;
     42 
     43 static void InitializeVM() {
     44   if (env.IsEmpty()) {
     45     env = v8::Context::New();
     46   }
     47 }
     48 
     49 
     50 #define __ assm.
     51 
     52 
     53 static void DummyStaticFunction(Object* result) {
     54 }
     55 
     56 
     57 TEST(DisasmX64) {
     58   InitializeVM();
     59   v8::HandleScope scope;
     60   v8::internal::byte buffer[2048];
     61   Assembler assm(Isolate::Current(), buffer, sizeof buffer);
     62   DummyStaticFunction(NULL);  // just bloody use it (DELETE; debugging)
     63 
     64   // Short immediate instructions
     65   __ addq(rax, Immediate(12345678));
     66   __ or_(rax, Immediate(12345678));
     67   __ subq(rax, Immediate(12345678));
     68   __ xor_(rax, Immediate(12345678));
     69   __ and_(rax, Immediate(12345678));
     70 
     71   // ---- This one caused crash
     72   __ movq(rbx,  Operand(rsp, rcx, times_2, 0));  // [rsp+rcx*4]
     73 
     74   // ---- All instructions that I can think of
     75   __ addq(rdx, rbx);
     76   __ addq(rdx, Operand(rbx, 0));
     77   __ addq(rdx, Operand(rbx, 16));
     78   __ addq(rdx, Operand(rbx, 1999));
     79   __ addq(rdx, Operand(rsp, 0));
     80   __ addq(rdx, Operand(rsp, 16));
     81   __ addq(rdx, Operand(rsp, 1999));
     82   __ nop();
     83   __ addq(rdi, Operand(rbp, rcx, times_4, 0));
     84   __ addq(rdi, Operand(rbp, rcx, times_4, 12));
     85   __ addq(Operand(rbp, rcx, times_4, 12), Immediate(12));
     86 
     87   __ nop();
     88   __ addq(rbx, Immediate(12));
     89   __ nop();
     90   __ nop();
     91   __ and_(rdx, Immediate(3));
     92   __ and_(rdx, Operand(rsp, 4));
     93   __ cmpq(rdx, Immediate(3));
     94   __ cmpq(rdx, Operand(rsp, 4));
     95   __ cmpq(Operand(rbp, rcx, times_4, 0), Immediate(1000));
     96   __ cmpb(rbx, Operand(rbp, rcx, times_2, 0));
     97   __ cmpb(Operand(rbp, rcx, times_2, 0), rbx);
     98   __ or_(rdx, Immediate(3));
     99   __ xor_(rdx, Immediate(3));
    100   __ nop();
    101   {
    102     CHECK(CpuFeatures::IsSupported(CPUID));
    103     CpuFeatures::Scope fscope(CPUID);
    104     __ cpuid();
    105   }
    106   {
    107     CHECK(CpuFeatures::IsSupported(RDTSC));
    108     CpuFeatures::Scope fscope(RDTSC);
    109     __ rdtsc();
    110   }
    111   __ movsxbq(rdx, Operand(rcx, 0));
    112   __ movsxwq(rdx, Operand(rcx, 0));
    113   __ movzxbl(rdx, Operand(rcx, 0));
    114   __ movzxwl(rdx, Operand(rcx, 0));
    115   __ movzxbq(rdx, Operand(rcx, 0));
    116   __ movzxwq(rdx, Operand(rcx, 0));
    117 
    118   __ nop();
    119   __ imul(rdx, rcx);
    120   __ shld(rdx, rcx);
    121   __ shrd(rdx, rcx);
    122   __ bts(Operand(rdx, 0), rcx);
    123   __ bts(Operand(rbx, rcx, times_4, 0), rcx);
    124   __ nop();
    125   __ push(Immediate(12));
    126   __ push(Immediate(23456));
    127   __ push(rcx);
    128   __ push(rsi);
    129   __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
    130   __ push(Operand(rbx, rcx, times_4, 0));
    131   __ push(Operand(rbx, rcx, times_4, 0));
    132   __ push(Operand(rbx, rcx, times_4, 10000));
    133   __ pop(rdx);
    134   __ pop(rax);
    135   __ pop(Operand(rbx, rcx, times_4, 0));
    136   __ nop();
    137 
    138   __ addq(rdx, Operand(rsp, 16));
    139   __ addq(rdx, rcx);
    140   __ movb(rdx, Operand(rcx, 0));
    141   __ movb(rcx, Immediate(6));
    142   __ movb(Operand(rsp, 16), rdx);
    143   __ movw(Operand(rsp, 16), rdx);
    144   __ nop();
    145   __ movsxwq(rdx, Operand(rsp, 12));
    146   __ movsxbq(rdx, Operand(rsp, 12));
    147   __ movsxlq(rdx, Operand(rsp, 12));
    148   __ movzxwq(rdx, Operand(rsp, 12));
    149   __ movzxbq(rdx, Operand(rsp, 12));
    150   __ nop();
    151   __ movq(rdx, Immediate(1234567));
    152   __ movq(rdx, Operand(rsp, 12));
    153   __ movq(Operand(rbx, rcx, times_4, 10000), Immediate(12345));
    154   __ movq(Operand(rbx, rcx, times_4, 10000), rdx);
    155   __ nop();
    156   __ decb(rdx);
    157   __ decb(Operand(rax, 10));
    158   __ decb(Operand(rbx, rcx, times_4, 10000));
    159   __ decq(rdx);
    160   __ cdq();
    161 
    162   __ nop();
    163   __ idivq(rdx);
    164   __ mul(rdx);
    165   __ neg(rdx);
    166   __ not_(rdx);
    167   __ testq(Operand(rbx, rcx, times_4, 10000), rdx);
    168 
    169   __ imul(rdx, Operand(rbx, rcx, times_4, 10000));
    170   __ imul(rdx, rcx, Immediate(12));
    171   __ imul(rdx, rcx, Immediate(1000));
    172 
    173   __ incq(rdx);
    174   __ incq(Operand(rbx, rcx, times_4, 10000));
    175   __ push(Operand(rbx, rcx, times_4, 10000));
    176   __ pop(Operand(rbx, rcx, times_4, 10000));
    177   __ jmp(Operand(rbx, rcx, times_4, 10000));
    178 
    179   __ lea(rdx, Operand(rbx, rcx, times_4, 10000));
    180   __ or_(rdx, Immediate(12345));
    181   __ or_(rdx, Operand(rbx, rcx, times_4, 10000));
    182 
    183   __ nop();
    184 
    185   __ rcl(rdx, Immediate(1));
    186   __ rcl(rdx, Immediate(7));
    187   __ rcr(rdx, Immediate(1));
    188   __ rcr(rdx, Immediate(7));
    189   __ sar(rdx, Immediate(1));
    190   __ sar(rdx, Immediate(6));
    191   __ sar_cl(rdx);
    192   __ sbbq(rdx, rbx);
    193   __ shld(rdx, rbx);
    194   __ shl(rdx, Immediate(1));
    195   __ shl(rdx, Immediate(6));
    196   __ shl_cl(rdx);
    197   __ shrd(rdx, rbx);
    198   __ shr(rdx, Immediate(1));
    199   __ shr(rdx, Immediate(7));
    200   __ shr_cl(rdx);
    201 
    202 
    203   // Immediates
    204 
    205   __ addq(rbx, Immediate(12));
    206   __ addq(Operand(rdx, rcx, times_4, 10000), Immediate(12));
    207 
    208   __ and_(rbx, Immediate(12345));
    209 
    210   __ cmpq(rbx, Immediate(12345));
    211   __ cmpq(rbx, Immediate(12));
    212   __ cmpq(Operand(rdx, rcx, times_4, 10000), Immediate(12));
    213   __ cmpb(rax, Immediate(100));
    214 
    215   __ or_(rbx, Immediate(12345));
    216 
    217   __ subq(rbx, Immediate(12));
    218   __ subq(Operand(rdx, rcx, times_4, 10000), Immediate(12));
    219 
    220   __ xor_(rbx, Immediate(12345));
    221 
    222   __ imul(rdx, rcx, Immediate(12));
    223   __ imul(rdx, rcx, Immediate(1000));
    224 
    225   __ cld();
    226 
    227   __ subq(rdx, Operand(rbx, rcx, times_4, 10000));
    228   __ subq(rdx, rbx);
    229 
    230   __ testq(rdx, Immediate(12345));
    231   __ testq(Operand(rbx, rcx, times_8, 10000), rdx);
    232   __ testb(Operand(rcx, rbx, times_2, 1000), rdx);
    233   __ testb(Operand(rax, -20), Immediate(0x9A));
    234   __ nop();
    235 
    236   __ xor_(rdx, Immediate(12345));
    237   __ xor_(rdx, Operand(rbx, rcx, times_8, 10000));
    238   __ bts(Operand(rbx, rcx, times_8, 10000), rdx);
    239   __ hlt();
    240   __ int3();
    241   __ ret(0);
    242   __ ret(8);
    243 
    244   // Calls
    245 
    246   Label L1, L2;
    247   __ bind(&L1);
    248   __ nop();
    249   __ call(&L1);
    250   __ call(&L2);
    251   __ nop();
    252   __ bind(&L2);
    253   __ call(Operand(rbx, rcx, times_4, 10000));
    254   __ nop();
    255   Handle<Code> ic(Isolate::Current()->builtins()->builtin(
    256       Builtins::kLoadIC_Initialize));
    257   __ call(ic, RelocInfo::CODE_TARGET);
    258   __ nop();
    259   __ nop();
    260 
    261   __ jmp(&L1);
    262   __ jmp(Operand(rbx, rcx, times_4, 10000));
    263 #ifdef ENABLE_DEBUGGER_SUPPORT
    264   ExternalReference after_break_target =
    265       ExternalReference(Debug_Address::AfterBreakTarget(),
    266                         assm.isolate());
    267 #endif  // ENABLE_DEBUGGER_SUPPORT
    268   __ jmp(ic, RelocInfo::CODE_TARGET);
    269   __ nop();
    270 
    271 
    272   Label Ljcc;
    273   __ nop();
    274   // long jumps
    275   __ j(overflow, &Ljcc);
    276   __ j(no_overflow, &Ljcc);
    277   __ j(below, &Ljcc);
    278   __ j(above_equal, &Ljcc);
    279   __ j(equal, &Ljcc);
    280   __ j(not_equal, &Ljcc);
    281   __ j(below_equal, &Ljcc);
    282   __ j(above, &Ljcc);
    283   __ j(sign, &Ljcc);
    284   __ j(not_sign, &Ljcc);
    285   __ j(parity_even, &Ljcc);
    286   __ j(parity_odd, &Ljcc);
    287   __ j(less, &Ljcc);
    288   __ j(greater_equal, &Ljcc);
    289   __ j(less_equal, &Ljcc);
    290   __ j(greater, &Ljcc);
    291   __ nop();
    292   __ bind(&Ljcc);
    293   // short jumps
    294   __ j(overflow, &Ljcc);
    295   __ j(no_overflow, &Ljcc);
    296   __ j(below, &Ljcc);
    297   __ j(above_equal, &Ljcc);
    298   __ j(equal, &Ljcc);
    299   __ j(not_equal, &Ljcc);
    300   __ j(below_equal, &Ljcc);
    301   __ j(above, &Ljcc);
    302   __ j(sign, &Ljcc);
    303   __ j(not_sign, &Ljcc);
    304   __ j(parity_even, &Ljcc);
    305   __ j(parity_odd, &Ljcc);
    306   __ j(less, &Ljcc);
    307   __ j(greater_equal, &Ljcc);
    308   __ j(less_equal, &Ljcc);
    309   __ j(greater, &Ljcc);
    310 
    311   // 0xD9 instructions
    312   __ nop();
    313 
    314   __ fld(1);
    315   __ fld1();
    316   __ fldz();
    317   __ fldpi();
    318   __ fabs();
    319   __ fchs();
    320   __ fprem();
    321   __ fprem1();
    322   __ fincstp();
    323   __ ftst();
    324   __ fxch(3);
    325   __ fld_s(Operand(rbx, rcx, times_4, 10000));
    326   __ fstp_s(Operand(rbx, rcx, times_4, 10000));
    327   __ ffree(3);
    328   __ fld_d(Operand(rbx, rcx, times_4, 10000));
    329   __ fstp_d(Operand(rbx, rcx, times_4, 10000));
    330   __ nop();
    331 
    332   __ fild_s(Operand(rbx, rcx, times_4, 10000));
    333   __ fistp_s(Operand(rbx, rcx, times_4, 10000));
    334   __ fild_d(Operand(rbx, rcx, times_4, 10000));
    335   __ fistp_d(Operand(rbx, rcx, times_4, 10000));
    336   __ fnstsw_ax();
    337   __ nop();
    338   __ fadd(3);
    339   __ fsub(3);
    340   __ fmul(3);
    341   __ fdiv(3);
    342 
    343   __ faddp(3);
    344   __ fsubp(3);
    345   __ fmulp(3);
    346   __ fdivp(3);
    347   __ fcompp();
    348   __ fwait();
    349   __ nop();
    350   {
    351     if (CpuFeatures::IsSupported(SSE2)) {
    352       CpuFeatures::Scope fscope(SSE2);
    353       __ cvttss2si(rdx, Operand(rbx, rcx, times_4, 10000));
    354       __ cvttss2si(rdx, xmm1);
    355       __ cvttsd2si(rdx, Operand(rbx, rcx, times_4, 10000));
    356       __ cvttsd2si(rdx, xmm1);
    357       __ cvttsd2siq(rdx, xmm1);
    358       __ addsd(xmm1, xmm0);
    359       __ mulsd(xmm1, xmm0);
    360       __ subsd(xmm1, xmm0);
    361       __ divsd(xmm1, xmm0);
    362       __ movsd(xmm1, Operand(rbx, rcx, times_4, 10000));
    363       __ movsd(Operand(rbx, rcx, times_4, 10000), xmm1);
    364       __ ucomisd(xmm0, xmm1);
    365 
    366       // 128 bit move instructions.
    367       __ movdqa(xmm0, Operand(rbx, rcx, times_4, 10000));
    368       __ movdqa(Operand(rbx, rcx, times_4, 10000), xmm0);
    369     }
    370   }
    371 
    372   // cmov.
    373   {
    374     if (CpuFeatures::IsSupported(CMOV)) {
    375       CpuFeatures::Scope use_cmov(CMOV);
    376       __ cmovq(overflow, rax, Operand(rax, 0));
    377       __ cmovq(no_overflow, rax, Operand(rax, 1));
    378       __ cmovq(below, rax, Operand(rax, 2));
    379       __ cmovq(above_equal, rax, Operand(rax, 3));
    380       __ cmovq(equal, rax, Operand(rbx, 0));
    381       __ cmovq(not_equal, rax, Operand(rbx, 1));
    382       __ cmovq(below_equal, rax, Operand(rbx, 2));
    383       __ cmovq(above, rax, Operand(rbx, 3));
    384       __ cmovq(sign, rax, Operand(rcx, 0));
    385       __ cmovq(not_sign, rax, Operand(rcx, 1));
    386       __ cmovq(parity_even, rax, Operand(rcx, 2));
    387       __ cmovq(parity_odd, rax, Operand(rcx, 3));
    388       __ cmovq(less, rax, Operand(rdx, 0));
    389       __ cmovq(greater_equal, rax, Operand(rdx, 1));
    390       __ cmovq(less_equal, rax, Operand(rdx, 2));
    391       __ cmovq(greater, rax, Operand(rdx, 3));
    392     }
    393   }
    394 
    395   // andpd, etc.
    396   {
    397     if (CpuFeatures::IsSupported(SSE2)) {
    398       CpuFeatures::Scope fscope(SSE2);
    399       __ andpd(xmm0, xmm1);
    400       __ andpd(xmm1, xmm2);
    401 
    402       __ movaps(xmm0, xmm1);
    403       __ movaps(xmm1, xmm2);
    404     }
    405   }
    406 
    407   // Nop instructions
    408   for (int i = 0; i < 16; i++) {
    409     __ Nop(i);
    410   }
    411 
    412   __ ret(0);
    413 
    414   CodeDesc desc;
    415   assm.GetCode(&desc);
    416   Object* code = HEAP->CreateCode(
    417       desc,
    418       Code::ComputeFlags(Code::STUB),
    419       Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
    420   CHECK(code->IsCode());
    421 #ifdef OBJECT_PRINT
    422   Code::cast(code)->Print();
    423   byte* begin = Code::cast(code)->instruction_start();
    424   byte* end = begin + Code::cast(code)->instruction_size();
    425   disasm::Disassembler::Disassemble(stdout, begin, end);
    426 #endif
    427 }
    428 
    429 #undef __
    430