• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
InitializeVM()43 static void InitializeVM() {
44   if (env.IsEmpty()) {
45     env = v8::Context::New();
46   }
47 }
48 
49 
50 #define __ assm.
51 
52 
DummyStaticFunction(Object * result)53 static void DummyStaticFunction(Object* result) {
54 }
55 
56 
TEST(DisasmIa320)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