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(DisasmIa320) {
     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   __ adc(eax, 12345678);
     66   __ add(eax, Immediate(12345678));
     67   __ or_(eax, 12345678);
     68   __ sub(eax, Immediate(12345678));
     69   __ xor_(eax, 12345678);
     70   __ and_(eax, 12345678);
     71   Handle<FixedArray> foo = FACTORY->NewFixedArray(10, TENURED);
     72   __ cmp(eax, foo);
     73 
     74   // ---- This one caused crash
     75   __ mov(ebx,  Operand(esp, ecx, times_2, 0));  // [esp+ecx*4]
     76 
     77   // ---- All instructions that I can think of
     78   __ add(edx, ebx);
     79   __ add(edx, Operand(12, RelocInfo::NONE));
     80   __ add(edx, Operand(ebx, 0));
     81   __ add(edx, Operand(ebx, 16));
     82   __ add(edx, Operand(ebx, 1999));
     83   __ add(edx, Operand(esp, 0));
     84   __ add(edx, Operand(esp, 16));
     85   __ add(edx, Operand(esp, 1999));
     86   __ nop();
     87   __ add(edi, Operand(ebp, ecx, times_4, 0));
     88   __ add(edi, Operand(ebp, ecx, times_4, 12));
     89   __ add(Operand(ebp, ecx, times_4, 12), Immediate(12));
     90 
     91   __ nop();
     92   __ add(ebx, Immediate(12));
     93   __ nop();
     94   __ adc(ecx, 12);
     95   __ adc(ecx, 1000);
     96   __ nop();
     97   __ and_(edx, 3);
     98   __ and_(edx, Operand(esp, 4));
     99   __ cmp(edx, 3);
    100   __ cmp(edx, Operand(esp, 4));
    101   __ cmp(Operand(ebp, ecx, times_4, 0), Immediate(1000));
    102   Handle<FixedArray> foo2 = FACTORY->NewFixedArray(10, TENURED);
    103   __ cmp(ebx, foo2);
    104   __ cmpb(ebx, Operand(ebp, ecx, times_2, 0));
    105   __ cmpb(Operand(ebp, ecx, times_2, 0), ebx);
    106   __ or_(edx, 3);
    107   __ xor_(edx, 3);
    108   __ nop();
    109   {
    110     CHECK(CpuFeatures::IsSupported(CPUID));
    111     CpuFeatures::Scope fscope(CPUID);
    112     __ cpuid();
    113   }
    114   {
    115     CHECK(CpuFeatures::IsSupported(RDTSC));
    116     CpuFeatures::Scope fscope(RDTSC);
    117     __ rdtsc();
    118   }
    119   __ movsx_b(edx, ecx);
    120   __ movsx_w(edx, ecx);
    121   __ movzx_b(edx, ecx);
    122   __ movzx_w(edx, ecx);
    123 
    124   __ nop();
    125   __ imul(edx, ecx);
    126   __ shld(edx, ecx);
    127   __ shrd(edx, ecx);
    128   __ bts(edx, ecx);
    129   __ bts(Operand(ebx, ecx, times_4, 0), ecx);
    130   __ nop();
    131   __ pushad();
    132   __ popad();
    133   __ pushfd();
    134   __ popfd();
    135   __ push(Immediate(12));
    136   __ push(Immediate(23456));
    137   __ push(ecx);
    138   __ push(esi);
    139   __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
    140   __ push(Operand(ebx, ecx, times_4, 0));
    141   __ push(Operand(ebx, ecx, times_4, 0));
    142   __ push(Operand(ebx, ecx, times_4, 10000));
    143   __ pop(edx);
    144   __ pop(eax);
    145   __ pop(Operand(ebx, ecx, times_4, 0));
    146   __ nop();
    147 
    148   __ add(edx, Operand(esp, 16));
    149   __ add(edx, ecx);
    150   __ mov_b(edx, ecx);
    151   __ mov_b(ecx, 6);
    152   __ mov_b(Operand(ebx, ecx, times_4, 10000), 6);
    153   __ mov_b(Operand(esp, 16), edx);
    154   __ mov_w(edx, Operand(esp, 16));
    155   __ mov_w(Operand(esp, 16), edx);
    156   __ nop();
    157   __ movsx_w(edx, Operand(esp, 12));
    158   __ movsx_b(edx, Operand(esp, 12));
    159   __ movzx_w(edx, Operand(esp, 12));
    160   __ movzx_b(edx, Operand(esp, 12));
    161   __ nop();
    162   __ mov(edx, 1234567);
    163   __ mov(edx, Operand(esp, 12));
    164   __ mov(Operand(ebx, ecx, times_4, 10000), Immediate(12345));
    165   __ mov(Operand(ebx, ecx, times_4, 10000), edx);
    166   __ nop();
    167   __ dec_b(edx);
    168   __ dec_b(Operand(eax, 10));
    169   __ dec_b(Operand(ebx, ecx, times_4, 10000));
    170   __ dec(edx);
    171   __ cdq();
    172 
    173   __ nop();
    174   __ idiv(edx);
    175   __ mul(edx);
    176   __ neg(edx);
    177   __ not_(edx);
    178   __ test(Operand(ebx, ecx, times_4, 10000), Immediate(123456));
    179 
    180   __ imul(edx, Operand(ebx, ecx, times_4, 10000));
    181   __ imul(edx, ecx, 12);
    182   __ imul(edx, ecx, 1000);
    183 
    184   __ inc(edx);
    185   __ inc(Operand(ebx, ecx, times_4, 10000));
    186   __ push(Operand(ebx, ecx, times_4, 10000));
    187   __ pop(Operand(ebx, ecx, times_4, 10000));
    188   __ call(Operand(ebx, ecx, times_4, 10000));
    189   __ jmp(Operand(ebx, ecx, times_4, 10000));
    190 
    191   __ lea(edx, Operand(ebx, ecx, times_4, 10000));
    192   __ or_(edx, 12345);
    193   __ or_(edx, Operand(ebx, ecx, times_4, 10000));
    194 
    195   __ nop();
    196 
    197   __ rcl(edx, 1);
    198   __ rcl(edx, 7);
    199   __ rcr(edx, 1);
    200   __ rcr(edx, 7);
    201   __ sar(edx, 1);
    202   __ sar(edx, 6);
    203   __ sar_cl(edx);
    204   __ sbb(edx, Operand(ebx, ecx, times_4, 10000));
    205   __ shld(edx, Operand(ebx, ecx, times_4, 10000));
    206   __ shl(edx, 1);
    207   __ shl(edx, 6);
    208   __ shl_cl(edx);
    209   __ shrd(edx, Operand(ebx, ecx, times_4, 10000));
    210   __ shr(edx, 1);
    211   __ shr(edx, 7);
    212   __ shr_cl(edx);
    213 
    214 
    215   // Immediates
    216 
    217   __ adc(edx, 12345);
    218 
    219   __ add(ebx, Immediate(12));
    220   __ add(Operand(edx, ecx, times_4, 10000), Immediate(12));
    221 
    222   __ and_(ebx, 12345);
    223 
    224   __ cmp(ebx, 12345);
    225   __ cmp(ebx, Immediate(12));
    226   __ cmp(Operand(edx, ecx, times_4, 10000), Immediate(12));
    227   __ cmpb(eax, 100);
    228 
    229   __ or_(ebx, 12345);
    230 
    231   __ sub(ebx, Immediate(12));
    232   __ sub(Operand(edx, ecx, times_4, 10000), Immediate(12));
    233 
    234   __ xor_(ebx, 12345);
    235 
    236   __ imul(edx, ecx, 12);
    237   __ imul(edx, ecx, 1000);
    238 
    239   __ cld();
    240   __ rep_movs();
    241   __ rep_stos();
    242   __ stos();
    243 
    244   __ sub(edx, Operand(ebx, ecx, times_4, 10000));
    245   __ sub(edx, ebx);
    246 
    247   __ test(edx, Immediate(12345));
    248   __ test(edx, Operand(ebx, ecx, times_8, 10000));
    249   __ test(Operand(esi, edi, times_1, -20000000), Immediate(300000000));
    250   __ test_b(edx, Operand(ecx, ebx, times_2, 1000));
    251   __ test_b(Operand(eax, -20), 0x9A);
    252   __ nop();
    253 
    254   __ xor_(edx, 12345);
    255   __ xor_(edx, Operand(ebx, ecx, times_8, 10000));
    256   __ bts(Operand(ebx, ecx, times_8, 10000), edx);
    257   __ hlt();
    258   __ int3();
    259   __ ret(0);
    260   __ ret(8);
    261 
    262   // Calls
    263 
    264   Label L1, L2;
    265   __ bind(&L1);
    266   __ nop();
    267   __ call(&L1);
    268   __ call(&L2);
    269   __ nop();
    270   __ bind(&L2);
    271   __ call(Operand(ebx, ecx, times_4, 10000));
    272   __ nop();
    273   Handle<Code> ic(Isolate::Current()->builtins()->builtin(
    274       Builtins::kLoadIC_Initialize));
    275   __ call(ic, RelocInfo::CODE_TARGET);
    276   __ nop();
    277   __ call(FUNCTION_ADDR(DummyStaticFunction), RelocInfo::RUNTIME_ENTRY);
    278   __ nop();
    279 
    280   __ jmp(&L1);
    281   __ jmp(Operand(ebx, ecx, times_4, 10000));
    282 #ifdef ENABLE_DEBUGGER_SUPPORT
    283   ExternalReference after_break_target =
    284       ExternalReference(Debug_Address::AfterBreakTarget(),
    285                         assm.isolate());
    286   __ jmp(Operand::StaticVariable(after_break_target));
    287 #endif  // ENABLE_DEBUGGER_SUPPORT
    288   __ jmp(ic, RelocInfo::CODE_TARGET);
    289   __ nop();
    290 
    291 
    292   Label Ljcc;
    293   __ nop();
    294   // long jumps
    295   __ j(overflow, &Ljcc);
    296   __ j(no_overflow, &Ljcc);
    297   __ j(below, &Ljcc);
    298   __ j(above_equal, &Ljcc);
    299   __ j(equal, &Ljcc);
    300   __ j(not_equal, &Ljcc);
    301   __ j(below_equal, &Ljcc);
    302   __ j(above, &Ljcc);
    303   __ j(sign, &Ljcc);
    304   __ j(not_sign, &Ljcc);
    305   __ j(parity_even, &Ljcc);
    306   __ j(parity_odd, &Ljcc);
    307   __ j(less, &Ljcc);
    308   __ j(greater_equal, &Ljcc);
    309   __ j(less_equal, &Ljcc);
    310   __ j(greater, &Ljcc);
    311   __ nop();
    312   __ bind(&Ljcc);
    313   // short jumps
    314   __ j(overflow, &Ljcc);
    315   __ j(no_overflow, &Ljcc);
    316   __ j(below, &Ljcc);
    317   __ j(above_equal, &Ljcc);
    318   __ j(equal, &Ljcc);
    319   __ j(not_equal, &Ljcc);
    320   __ j(below_equal, &Ljcc);
    321   __ j(above, &Ljcc);
    322   __ j(sign, &Ljcc);
    323   __ j(not_sign, &Ljcc);
    324   __ j(parity_even, &Ljcc);
    325   __ j(parity_odd, &Ljcc);
    326   __ j(less, &Ljcc);
    327   __ j(greater_equal, &Ljcc);
    328   __ j(less_equal, &Ljcc);
    329   __ j(greater, &Ljcc);
    330 
    331   // 0xD9 instructions
    332   __ nop();
    333 
    334   __ fld(1);
    335   __ fld1();
    336   __ fldz();
    337   __ fldpi();
    338   __ fabs();
    339   __ fchs();
    340   __ fprem();
    341   __ fprem1();
    342   __ fincstp();
    343   __ ftst();
    344   __ fxch(3);
    345   __ fld_s(Operand(ebx, ecx, times_4, 10000));
    346   __ fstp_s(Operand(ebx, ecx, times_4, 10000));
    347   __ ffree(3);
    348   __ fld_d(Operand(ebx, ecx, times_4, 10000));
    349   __ fstp_d(Operand(ebx, ecx, times_4, 10000));
    350   __ nop();
    351 
    352   __ fild_s(Operand(ebx, ecx, times_4, 10000));
    353   __ fistp_s(Operand(ebx, ecx, times_4, 10000));
    354   __ fild_d(Operand(ebx, ecx, times_4, 10000));
    355   __ fistp_d(Operand(ebx, ecx, times_4, 10000));
    356   __ fnstsw_ax();
    357   __ nop();
    358   __ fadd(3);
    359   __ fsub(3);
    360   __ fmul(3);
    361   __ fdiv(3);
    362 
    363   __ faddp(3);
    364   __ fsubp(3);
    365   __ fmulp(3);
    366   __ fdivp(3);
    367   __ fcompp();
    368   __ fwait();
    369   __ nop();
    370   {
    371     if (CpuFeatures::IsSupported(SSE2)) {
    372       CpuFeatures::Scope fscope(SSE2);
    373       __ cvttss2si(edx, Operand(ebx, ecx, times_4, 10000));
    374       __ cvtsi2sd(xmm1, Operand(ebx, ecx, times_4, 10000));
    375       __ addsd(xmm1, xmm0);
    376       __ mulsd(xmm1, xmm0);
    377       __ subsd(xmm1, xmm0);
    378       __ divsd(xmm1, xmm0);
    379       __ movdbl(xmm1, Operand(ebx, ecx, times_4, 10000));
    380       __ movdbl(Operand(ebx, ecx, times_4, 10000), xmm1);
    381       __ ucomisd(xmm0, xmm1);
    382 
    383       // 128 bit move instructions.
    384       __ movdqa(xmm0, Operand(ebx, ecx, times_4, 10000));
    385       __ movdqa(Operand(ebx, ecx, times_4, 10000), xmm0);
    386       __ movdqu(xmm0, Operand(ebx, ecx, times_4, 10000));
    387       __ movdqu(Operand(ebx, ecx, times_4, 10000), xmm0);
    388     }
    389   }
    390 
    391   // cmov.
    392   {
    393     if (CpuFeatures::IsSupported(CMOV)) {
    394       CpuFeatures::Scope use_cmov(CMOV);
    395       __ cmov(overflow, eax, Operand(eax, 0));
    396       __ cmov(no_overflow, eax, Operand(eax, 1));
    397       __ cmov(below, eax, Operand(eax, 2));
    398       __ cmov(above_equal, eax, Operand(eax, 3));
    399       __ cmov(equal, eax, Operand(ebx, 0));
    400       __ cmov(not_equal, eax, Operand(ebx, 1));
    401       __ cmov(below_equal, eax, Operand(ebx, 2));
    402       __ cmov(above, eax, Operand(ebx, 3));
    403       __ cmov(sign, eax, Operand(ecx, 0));
    404       __ cmov(not_sign, eax, Operand(ecx, 1));
    405       __ cmov(parity_even, eax, Operand(ecx, 2));
    406       __ cmov(parity_odd, eax, Operand(ecx, 3));
    407       __ cmov(less, eax, Operand(edx, 0));
    408       __ cmov(greater_equal, eax, Operand(edx, 1));
    409       __ cmov(less_equal, eax, Operand(edx, 2));
    410       __ cmov(greater, eax, Operand(edx, 3));
    411     }
    412   }
    413 
    414   // andpd, cmpltsd, movaps, psllq, psrlq, por.
    415   {
    416     if (CpuFeatures::IsSupported(SSE2)) {
    417       CpuFeatures::Scope fscope(SSE2);
    418       __ andpd(xmm0, xmm1);
    419       __ andpd(xmm1, xmm2);
    420 
    421       __ cmpltsd(xmm0, xmm1);
    422       __ cmpltsd(xmm1, xmm2);
    423 
    424       __ movaps(xmm0, xmm1);
    425       __ movaps(xmm1, xmm2);
    426 
    427       __ psllq(xmm0, 17);
    428       __ psllq(xmm1, 42);
    429 
    430       __ psllq(xmm0, xmm1);
    431       __ psllq(xmm1, xmm2);
    432 
    433       __ psrlq(xmm0, 17);
    434       __ psrlq(xmm1, 42);
    435 
    436       __ psrlq(xmm0, xmm1);
    437       __ psrlq(xmm1, xmm2);
    438 
    439       __ por(xmm0, xmm1);
    440       __ por(xmm1, xmm2);
    441     }
    442   }
    443 
    444   {
    445     if (CpuFeatures::IsSupported(SSE4_1)) {
    446       CpuFeatures::Scope scope(SSE4_1);
    447       __ pextrd(eax, xmm0, 1);
    448       __ pinsrd(xmm1, eax, 0);
    449     }
    450   }
    451 
    452   // Nop instructions
    453   for (int i = 0; i < 16; i++) {
    454     __ Nop(i);
    455   }
    456 
    457   __ ret(0);
    458 
    459   CodeDesc desc;
    460   assm.GetCode(&desc);
    461   Object* code = HEAP->CreateCode(
    462       desc,
    463       Code::ComputeFlags(Code::STUB),
    464       Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
    465   CHECK(code->IsCode());
    466 #ifdef OBJECT_PRINT
    467   Code::cast(code)->Print();
    468   byte* begin = Code::cast(code)->instruction_start();
    469   byte* end = begin + Code::cast(code)->instruction_size();
    470   disasm::Disassembler::Disassemble(stdout, begin, end);
    471 #endif
    472 }
    473 
    474 #undef __
    475