v8  3.11.10(node0.8.26)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
test-disasm-x64.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(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  {
103  CpuFeatures::Scope fscope(CPUID);
104  __ cpuid();
105  }
106  {
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);
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  USE(after_break_target);
268 #endif // ENABLE_DEBUGGER_SUPPORT
269  __ jmp(ic, RelocInfo::CODE_TARGET);
270  __ nop();
271 
272 
273  Label Ljcc;
274  __ nop();
275  // long jumps
276  __ j(overflow, &Ljcc);
277  __ j(no_overflow, &Ljcc);
278  __ j(below, &Ljcc);
279  __ j(above_equal, &Ljcc);
280  __ j(equal, &Ljcc);
281  __ j(not_equal, &Ljcc);
282  __ j(below_equal, &Ljcc);
283  __ j(above, &Ljcc);
284  __ j(sign, &Ljcc);
285  __ j(not_sign, &Ljcc);
286  __ j(parity_even, &Ljcc);
287  __ j(parity_odd, &Ljcc);
288  __ j(less, &Ljcc);
289  __ j(greater_equal, &Ljcc);
290  __ j(less_equal, &Ljcc);
291  __ j(greater, &Ljcc);
292  __ nop();
293  __ bind(&Ljcc);
294  // short 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 
312  // 0xD9 instructions
313  __ nop();
314 
315  __ fld(1);
316  __ fld1();
317  __ fldz();
318  __ fldpi();
319  __ fabs();
320  __ fchs();
321  __ fprem();
322  __ fprem1();
323  __ fincstp();
324  __ ftst();
325  __ fxch(3);
326  __ fld_s(Operand(rbx, rcx, times_4, 10000));
327  __ fstp_s(Operand(rbx, rcx, times_4, 10000));
328  __ ffree(3);
329  __ fld_d(Operand(rbx, rcx, times_4, 10000));
330  __ fstp_d(Operand(rbx, rcx, times_4, 10000));
331  __ nop();
332 
333  __ fild_s(Operand(rbx, rcx, times_4, 10000));
334  __ fistp_s(Operand(rbx, rcx, times_4, 10000));
335  __ fild_d(Operand(rbx, rcx, times_4, 10000));
336  __ fistp_d(Operand(rbx, rcx, times_4, 10000));
337  __ fnstsw_ax();
338  __ nop();
339  __ fadd(3);
340  __ fsub(3);
341  __ fmul(3);
342  __ fdiv(3);
343 
344  __ faddp(3);
345  __ fsubp(3);
346  __ fmulp(3);
347  __ fdivp(3);
348  __ fcompp();
349  __ fwait();
350  __ nop();
351  {
353  CpuFeatures::Scope fscope(SSE2);
354  __ cvttss2si(rdx, Operand(rbx, rcx, times_4, 10000));
355  __ cvttss2si(rdx, xmm1);
356  __ cvttsd2si(rdx, Operand(rbx, rcx, times_4, 10000));
357  __ cvttsd2si(rdx, xmm1);
358  __ cvttsd2siq(rdx, xmm1);
359  __ addsd(xmm1, xmm0);
360  __ mulsd(xmm1, xmm0);
361  __ subsd(xmm1, xmm0);
362  __ divsd(xmm1, xmm0);
363  __ movsd(xmm1, Operand(rbx, rcx, times_4, 10000));
364  __ movsd(Operand(rbx, rcx, times_4, 10000), xmm1);
365  __ ucomisd(xmm0, xmm1);
366 
367  // 128 bit move instructions.
368  __ movdqa(xmm0, Operand(rbx, rcx, times_4, 10000));
369  __ movdqa(Operand(rbx, rcx, times_4, 10000), xmm0);
370  }
371  }
372 
373  // cmov.
374  {
376  CpuFeatures::Scope use_cmov(CMOV);
377  __ cmovq(overflow, rax, Operand(rax, 0));
378  __ cmovq(no_overflow, rax, Operand(rax, 1));
379  __ cmovq(below, rax, Operand(rax, 2));
380  __ cmovq(above_equal, rax, Operand(rax, 3));
381  __ cmovq(equal, rax, Operand(rbx, 0));
382  __ cmovq(not_equal, rax, Operand(rbx, 1));
383  __ cmovq(below_equal, rax, Operand(rbx, 2));
384  __ cmovq(above, rax, Operand(rbx, 3));
385  __ cmovq(sign, rax, Operand(rcx, 0));
386  __ cmovq(not_sign, rax, Operand(rcx, 1));
387  __ cmovq(parity_even, rax, Operand(rcx, 2));
388  __ cmovq(parity_odd, rax, Operand(rcx, 3));
389  __ cmovq(less, rax, Operand(rdx, 0));
390  __ cmovq(greater_equal, rax, Operand(rdx, 1));
391  __ cmovq(less_equal, rax, Operand(rdx, 2));
392  __ cmovq(greater, rax, Operand(rdx, 3));
393  }
394  }
395 
396  // andpd, etc.
397  {
399  CpuFeatures::Scope fscope(SSE2);
400  __ andpd(xmm0, xmm1);
401  __ andpd(xmm1, xmm2);
402 
403  __ movaps(xmm0, xmm1);
404  __ movaps(xmm1, xmm2);
405  }
406  }
407 
408  // Nop instructions
409  for (int i = 0; i < 16; i++) {
410  __ Nop(i);
411  }
412 
413  __ ret(0);
414 
415  CodeDesc desc;
416  assm.GetCode(&desc);
417  Object* code = HEAP->CreateCode(
418  desc,
420  Handle<Object>(HEAP->undefined_value()))->ToObjectChecked();
421  CHECK(code->IsCode());
422 #ifdef OBJECT_PRINT
423  Code::cast(code)->Print();
424  byte* begin = Code::cast(code)->instruction_start();
425  byte* end = begin + Code::cast(code)->instruction_size();
426  disasm::Disassembler::Disassemble(stdout, begin, end);
427 #endif
428 }
429 
430 #undef __
#define __
const Register rdx
static void Disassemble(FILE *f, byte *begin, byte *end)
Isolate * isolate() const
Definition: assembler.h:62
const Register rbp
const Register rsi
static bool IsSupported(CpuFeature f)
#define CHECK(condition)
Definition: checks.h:56
static Code * cast(Object *obj)
uint8_t byte
Definition: globals.h:171
const XMMRegister xmm1
byte * instruction_start()
Definition: objects-inl.h:4376
void GetCode(CodeDesc *desc)
const Register rbx
const Register rsp
const Register rax
const Register rdi
static Flags ComputeFlags(Kind kind, InlineCacheState ic_state=UNINITIALIZED, ExtraICState extra_ic_state=kNoExtraICState, PropertyType type=NORMAL, int argc=-1, InlineCacheHolderFlag holder=OWN_MAP)
Definition: objects-inl.h:3312
const Register rcx
#define HEAP
Definition: isolate.h:1408
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 trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt 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 enable use of ARMv7 instructions if enable use of MIPS FPU instructions if NULL
Definition: flags.cc:274
void USE(T)
Definition: globals.h:303
bool IsEmpty() const
Definition: v8.h:208
static Persistent< Context > New(ExtensionConfiguration *extensions=NULL, Handle< ObjectTemplate > global_template=Handle< ObjectTemplate >(), Handle< Value > global_object=Handle< Value >())
Definition: api.cc:4308
const XMMRegister xmm2
const XMMRegister xmm0