v8  3.14.5(node0.10.28)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
test-disasm-ia32.cc
Go to the documentation of this file.
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 
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  {
111  CpuFeatures::Scope fscope(CPUID);
112  __ cpuid();
113  }
114  {
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);
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  {
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  {
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  {
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  {
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 __
static void Disassemble(FILE *f, byte *begin, byte *end)
Isolate * isolate() const
Definition: assembler.h:61
const Register esp
static bool IsSupported(CpuFeature f)
#define CHECK(condition)
Definition: checks.h:56
static Code * cast(Object *obj)
const Register edi
int foo
uint8_t byte
Definition: globals.h:156
const Register ebp
const Register eax
const XMMRegister xmm1
byte * instruction_start()
Definition: objects-inl.h:4649
void GetCode(CodeDesc *desc)
const Register ecx
#define __
static Flags ComputeFlags(Kind kind, InlineCacheState ic_state=UNINITIALIZED, ExtraICState extra_ic_state=kNoExtraICState, StubType type=NORMAL, int argc=-1, InlineCacheHolderFlag holder=OWN_MAP)
Definition: objects-inl.h:3491
const Register ebx
#define HEAP
Definition: isolate.h:1433
const Register esi
bool IsEmpty() const
Definition: v8.h:209
#define FACTORY
Definition: isolate.h:1434
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
Definition: flags.cc:301
static Persistent< Context > New(ExtensionConfiguration *extensions=NULL, Handle< ObjectTemplate > global_template=Handle< ObjectTemplate >(), Handle< Value > global_object=Handle< Value >())
Definition: api.cc:4411
#define RUNTIME_ENTRY(name, nargs, ressize)
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
const XMMRegister xmm2
const Register edx
#define FUNCTION_ADDR(f)
Definition: globals.h:293
const XMMRegister xmm0