test-disasm-ia32.cc revision d0582a6c46733687d045e4188a1bcd0123c758a1
1// Copyright 2007-2008 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
39using namespace v8::internal;
40
41static v8::Persistent<v8::Context> env;
42
43static void InitializeVM() {
44  if (env.IsEmpty()) {
45    env = v8::Context::New();
46  }
47}
48
49
50#define __ assm.
51
52
53static void DummyStaticFunction(Object* result) {
54}
55
56
57TEST(DisasmIa320) {
58  InitializeVM();
59  v8::HandleScope scope;
60  v8::internal::byte buffer[1024];
61  Assembler assm(buffer, sizeof buffer);
62  DummyStaticFunction(NULL);  // just bloody use it (DELETE; debugging)
63
64  // Short immediate instructions
65  __ adc(eax, 12345678);
66  __ add(Operand(eax), Immediate(12345678));
67  __ or_(eax, 12345678);
68  __ sub(Operand(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, Operand(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(Operand(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  __ or_(edx, 3);
105  __ xor_(edx, 3);
106  __ nop();
107  {
108    CHECK(CpuFeatures::IsSupported(CPUID));
109    CpuFeatures::Scope fscope(CPUID);
110    __ cpuid();
111  }
112  {
113    CHECK(CpuFeatures::IsSupported(RDTSC));
114    CpuFeatures::Scope fscope(RDTSC);
115    __ rdtsc();
116  }
117  __ movsx_b(edx, Operand(ecx));
118  __ movsx_w(edx, Operand(ecx));
119  __ movzx_b(edx, Operand(ecx));
120  __ movzx_w(edx, Operand(ecx));
121
122  __ nop();
123  __ imul(edx, Operand(ecx));
124  __ shld(edx, Operand(ecx));
125  __ shrd(edx, Operand(ecx));
126  __ bts(Operand(edx), ecx);
127  __ bts(Operand(ebx, ecx, times_4, 0), ecx);
128  __ nop();
129  __ pushad();
130  __ popad();
131  __ pushfd();
132  __ popfd();
133  __ push(Immediate(12));
134  __ push(Immediate(23456));
135  __ push(ecx);
136  __ push(esi);
137  __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
138  __ push(Operand(ebx, ecx, times_4, 0));
139  __ push(Operand(ebx, ecx, times_4, 0));
140  __ push(Operand(ebx, ecx, times_4, 10000));
141  __ pop(edx);
142  __ pop(eax);
143  __ pop(Operand(ebx, ecx, times_4, 0));
144  __ nop();
145
146  __ add(edx, Operand(esp, 16));
147  __ add(edx, Operand(ecx));
148  __ mov_b(edx, Operand(ecx));
149  __ mov_b(Operand(ecx), 6);
150  __ mov_b(Operand(ebx, ecx, times_4, 10000), 6);
151  __ mov_b(Operand(esp, 16), edx);
152  __ mov_w(edx, Operand(esp, 16));
153  __ mov_w(Operand(esp, 16), edx);
154  __ nop();
155  __ movsx_w(edx, Operand(esp, 12));
156  __ movsx_b(edx, Operand(esp, 12));
157  __ movzx_w(edx, Operand(esp, 12));
158  __ movzx_b(edx, Operand(esp, 12));
159  __ nop();
160  __ mov(edx, 1234567);
161  __ mov(edx, Operand(esp, 12));
162  __ mov(Operand(ebx, ecx, times_4, 10000), Immediate(12345));
163  __ mov(Operand(ebx, ecx, times_4, 10000), edx);
164  __ nop();
165  __ dec_b(edx);
166  __ dec(edx);
167  __ cdq();
168
169  __ nop();
170  __ idiv(edx);
171  __ mul(edx);
172  __ neg(edx);
173  __ not_(edx);
174  __ test(Operand(ebx, ecx, times_4, 10000), Immediate(123456));
175
176  __ imul(edx, Operand(ebx, ecx, times_4, 10000));
177  __ imul(edx, ecx, 12);
178  __ imul(edx, ecx, 1000);
179
180  __ inc(edx);
181  __ inc(Operand(ebx, ecx, times_4, 10000));
182  __ push(Operand(ebx, ecx, times_4, 10000));
183  __ pop(Operand(ebx, ecx, times_4, 10000));
184  __ call(Operand(ebx, ecx, times_4, 10000));
185  __ jmp(Operand(ebx, ecx, times_4, 10000));
186
187  __ lea(edx, Operand(ebx, ecx, times_4, 10000));
188  __ or_(edx, 12345);
189  __ or_(edx, Operand(ebx, ecx, times_4, 10000));
190
191  __ nop();
192
193  __ rcl(edx, 1);
194  __ rcl(edx, 7);
195  __ sar(edx, 1);
196  __ sar(edx, 6);
197  __ sar_cl(edx);
198  __ sbb(edx, Operand(ebx, ecx, times_4, 10000));
199  __ shld(edx, Operand(ebx, ecx, times_4, 10000));
200  __ shl(edx, 1);
201  __ shl(edx, 6);
202  __ shl_cl(edx);
203  __ shrd(edx, Operand(ebx, ecx, times_4, 10000));
204  __ shr(edx, 1);
205  __ shr(edx, 7);
206  __ shr_cl(edx);
207
208
209  // Immediates
210
211  __ adc(edx, 12345);
212
213  __ add(Operand(ebx), Immediate(12));
214  __ add(Operand(edx, ecx, times_4, 10000), Immediate(12));
215
216  __ and_(ebx, 12345);
217
218  __ cmp(ebx, 12345);
219  __ cmp(Operand(ebx), Immediate(12));
220  __ cmp(Operand(edx, ecx, times_4, 10000), Immediate(12));
221
222  __ or_(ebx, 12345);
223
224  __ sub(Operand(ebx), Immediate(12));
225  __ sub(Operand(edx, ecx, times_4, 10000), Immediate(12));
226
227  __ xor_(ebx, 12345);
228
229  __ imul(edx, ecx, 12);
230  __ imul(edx, ecx, 1000);
231
232
233
234  __ sub(edx, Operand(ebx, ecx, times_4, 10000));
235  __ sub(edx, Operand(ebx));
236
237  __ test(edx, Immediate(12345));
238  __ test(edx, Operand(ebx, ecx, times_8, 10000));
239  __ nop();
240
241  __ xor_(edx, 12345);
242  __ xor_(edx, Operand(ebx, ecx, times_8, 10000));
243  __ bts(Operand(ebx, ecx, times_8, 10000), edx);
244  __ hlt();
245  __ int3();
246  __ ret(0);
247  __ ret(8);
248
249  // Calls
250
251  Label L1, L2;
252  __ bind(&L1);
253  __ nop();
254  __ call(&L1);
255  __ call(&L2);
256  __ nop();
257  __ bind(&L2);
258  __ call(Operand(ebx, ecx, times_4, 10000));
259  __ nop();
260  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
261  __ call(ic, RelocInfo::CODE_TARGET);
262  __ nop();
263  __ call(FUNCTION_ADDR(DummyStaticFunction), RelocInfo::RUNTIME_ENTRY);
264  __ nop();
265
266  __ jmp(&L1);
267  __ jmp(Operand(ebx, ecx, times_4, 10000));
268  ExternalReference after_break_target =
269      ExternalReference(Debug_Address::AfterBreakTarget());
270  __ jmp(Operand::StaticVariable(after_break_target));
271  __ jmp(ic, RelocInfo::CODE_TARGET);
272  __ nop();
273
274
275  Label Ljcc;
276  __ nop();
277  // long jumps
278  __ j(overflow, &Ljcc);
279  __ j(no_overflow, &Ljcc);
280  __ j(below, &Ljcc);
281  __ j(above_equal, &Ljcc);
282  __ j(equal, &Ljcc);
283  __ j(not_equal, &Ljcc);
284  __ j(below_equal, &Ljcc);
285  __ j(above, &Ljcc);
286  __ j(sign, &Ljcc);
287  __ j(not_sign, &Ljcc);
288  __ j(parity_even, &Ljcc);
289  __ j(parity_odd, &Ljcc);
290  __ j(less, &Ljcc);
291  __ j(greater_equal, &Ljcc);
292  __ j(less_equal, &Ljcc);
293  __ j(greater, &Ljcc);
294  __ nop();
295  __ bind(&Ljcc);
296  // short jumps
297  __ j(overflow, &Ljcc);
298  __ j(no_overflow, &Ljcc);
299  __ j(below, &Ljcc);
300  __ j(above_equal, &Ljcc);
301  __ j(equal, &Ljcc);
302  __ j(not_equal, &Ljcc);
303  __ j(below_equal, &Ljcc);
304  __ j(above, &Ljcc);
305  __ j(sign, &Ljcc);
306  __ j(not_sign, &Ljcc);
307  __ j(parity_even, &Ljcc);
308  __ j(parity_odd, &Ljcc);
309  __ j(less, &Ljcc);
310  __ j(greater_equal, &Ljcc);
311  __ j(less_equal, &Ljcc);
312  __ j(greater, &Ljcc);
313
314  // checking hints
315  __ j(zero, &Ljcc, taken);
316  __ j(zero, &Ljcc, not_taken);
317
318  // __ mov(Operand::StaticVariable(Top::handler_address()), eax);
319  // 0xD9 instructions
320  __ nop();
321
322  __ fld1();
323  __ fldz();
324  __ fabs();
325  __ fchs();
326  __ fprem();
327  __ fprem1();
328  __ fincstp();
329  __ ftst();
330  __ fxch(3);
331  __ fld_s(Operand(ebx, ecx, times_4, 10000));
332  __ fstp_s(Operand(ebx, ecx, times_4, 10000));
333  __ ffree(3);
334  __ fld_d(Operand(ebx, ecx, times_4, 10000));
335  __ fstp_d(Operand(ebx, ecx, times_4, 10000));
336  __ nop();
337
338  __ fild_s(Operand(ebx, ecx, times_4, 10000));
339  __ fistp_s(Operand(ebx, ecx, times_4, 10000));
340  __ fild_d(Operand(ebx, ecx, times_4, 10000));
341  __ fistp_d(Operand(ebx, ecx, times_4, 10000));
342  __ fnstsw_ax();
343  __ nop();
344  __ fadd(3);
345  __ fsub(3);
346  __ fmul(3);
347  __ fdiv(3);
348
349  __ faddp(3);
350  __ fsubp(3);
351  __ fmulp(3);
352  __ fdivp(3);
353  __ fcompp();
354  __ fwait();
355  __ nop();
356  {
357    CHECK(CpuFeatures::IsSupported(SSE2));
358    CpuFeatures::Scope fscope(SSE2);
359    __ cvttss2si(edx, Operand(ebx, ecx, times_4, 10000));
360    __ cvtsi2sd(xmm1, Operand(ebx, ecx, times_4, 10000));
361    __ addsd(xmm1, xmm0);
362    __ mulsd(xmm1, xmm0);
363    __ subsd(xmm1, xmm0);
364    __ divsd(xmm1, xmm0);
365    __ movdbl(xmm1, Operand(ebx, ecx, times_4, 10000));
366    __ movdbl(Operand(ebx, ecx, times_4, 10000), xmm1);
367    __ comisd(xmm0, xmm1);
368  }
369
370  // cmov.
371  {
372    CHECK(CpuFeatures::IsSupported(CMOV));
373    CpuFeatures::Scope use_cmov(CMOV);
374    __ cmov(overflow, eax, Operand(eax, 0));
375    __ cmov(no_overflow, eax, Operand(eax, 1));
376    __ cmov(below, eax, Operand(eax, 2));
377    __ cmov(above_equal, eax, Operand(eax, 3));
378    __ cmov(equal, eax, Operand(ebx, 0));
379    __ cmov(not_equal, eax, Operand(ebx, 1));
380    __ cmov(below_equal, eax, Operand(ebx, 2));
381    __ cmov(above, eax, Operand(ebx, 3));
382    __ cmov(sign, eax, Operand(ecx, 0));
383    __ cmov(not_sign, eax, Operand(ecx, 1));
384    __ cmov(parity_even, eax, Operand(ecx, 2));
385    __ cmov(parity_odd, eax, Operand(ecx, 3));
386    __ cmov(less, eax, Operand(edx, 0));
387    __ cmov(greater_equal, eax, Operand(edx, 1));
388    __ cmov(less_equal, eax, Operand(edx, 2));
389    __ cmov(greater, eax, Operand(edx, 3));
390  }
391
392  __ ret(0);
393
394  CodeDesc desc;
395  assm.GetCode(&desc);
396  Object* code = Heap::CreateCode(desc,
397                                  NULL,
398                                  Code::ComputeFlags(Code::STUB),
399                                  Handle<Object>(Heap::undefined_value()));
400  CHECK(code->IsCode());
401#ifdef DEBUG
402  Code::cast(code)->Print();
403  byte* begin = Code::cast(code)->instruction_start();
404  byte* end = begin + Code::cast(code)->instruction_size();
405  disasm::Disassembler::Disassemble(stdout, begin, end);
406#endif
407}
408
409#undef __
410