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 "src/v8.h"
31
32#include "src/debug.h"
33#include "src/disasm.h"
34#include "src/disassembler.h"
35#include "src/ic/ic.h"
36#include "src/macro-assembler.h"
37#include "src/serialize.h"
38#include "test/cctest/cctest.h"
39
40using namespace v8::internal;
41
42
43#define __ assm.
44
45
46static void DummyStaticFunction(Object* result) {
47}
48
49
50TEST(DisasmIa320) {
51  CcTest::InitializeVM();
52  Isolate* isolate = CcTest::i_isolate();
53  HandleScope scope(isolate);
54  v8::internal::byte buffer[2048];
55  Assembler assm(isolate, buffer, sizeof buffer);
56  DummyStaticFunction(NULL);  // just bloody use it (DELETE; debugging)
57
58  // Short immediate instructions
59  __ adc(eax, 12345678);
60  __ add(eax, Immediate(12345678));
61  __ or_(eax, 12345678);
62  __ sub(eax, Immediate(12345678));
63  __ xor_(eax, 12345678);
64  __ and_(eax, 12345678);
65  Handle<FixedArray> foo = isolate->factory()->NewFixedArray(10, TENURED);
66  __ cmp(eax, foo);
67
68  // ---- This one caused crash
69  __ mov(ebx,  Operand(esp, ecx, times_2, 0));  // [esp+ecx*4]
70
71  // ---- All instructions that I can think of
72  __ add(edx, ebx);
73  __ add(edx, Operand(12, RelocInfo::NONE32));
74  __ add(edx, Operand(ebx, 0));
75  __ add(edx, Operand(ebx, 16));
76  __ add(edx, Operand(ebx, 1999));
77  __ add(edx, Operand(ebx, -4));
78  __ add(edx, Operand(ebx, -1999));
79  __ add(edx, Operand(esp, 0));
80  __ add(edx, Operand(esp, 16));
81  __ add(edx, Operand(esp, 1999));
82  __ add(edx, Operand(esp, -4));
83  __ add(edx, Operand(esp, -1999));
84  __ nop();
85  __ add(esi, Operand(ecx, times_4, 0));
86  __ add(esi, Operand(ecx, times_4, 24));
87  __ add(esi, Operand(ecx, times_4, -4));
88  __ add(esi, Operand(ecx, times_4, -1999));
89  __ nop();
90  __ add(edi, Operand(ebp, ecx, times_4, 0));
91  __ add(edi, Operand(ebp, ecx, times_4, 12));
92  __ add(edi, Operand(ebp, ecx, times_4, -8));
93  __ add(edi, Operand(ebp, ecx, times_4, -3999));
94  __ add(Operand(ebp, ecx, times_4, 12), Immediate(12));
95
96  __ nop();
97  __ add(ebx, Immediate(12));
98  __ nop();
99  __ adc(ecx, 12);
100  __ adc(ecx, 1000);
101  __ nop();
102  __ and_(edx, 3);
103  __ and_(edx, Operand(esp, 4));
104  __ cmp(edx, 3);
105  __ cmp(edx, Operand(esp, 4));
106  __ cmp(Operand(ebp, ecx, times_4, 0), Immediate(1000));
107  Handle<FixedArray> foo2 = isolate->factory()->NewFixedArray(10, TENURED);
108  __ cmp(ebx, foo2);
109  __ cmpb(ebx, Operand(ebp, ecx, times_2, 0));
110  __ cmpb(Operand(ebp, ecx, times_2, 0), ebx);
111  __ or_(edx, 3);
112  __ xor_(edx, 3);
113  __ nop();
114  __ cpuid();
115  __ movsx_b(edx, ecx);
116  __ movsx_w(edx, ecx);
117  __ movzx_b(edx, ecx);
118  __ movzx_w(edx, ecx);
119
120  __ nop();
121  __ imul(edx, ecx);
122  __ shld(edx, ecx);
123  __ shrd(edx, ecx);
124  __ bts(edx, ecx);
125  __ bts(Operand(ebx, ecx, times_4, 0), ecx);
126  __ nop();
127  __ pushad();
128  __ popad();
129  __ pushfd();
130  __ popfd();
131  __ push(Immediate(12));
132  __ push(Immediate(23456));
133  __ push(ecx);
134  __ push(esi);
135  __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
136  __ push(Operand(ebx, ecx, times_4, 0));
137  __ push(Operand(ebx, ecx, times_4, 0));
138  __ push(Operand(ebx, ecx, times_4, 10000));
139  __ pop(edx);
140  __ pop(eax);
141  __ pop(Operand(ebx, ecx, times_4, 0));
142  __ nop();
143
144  __ add(edx, Operand(esp, 16));
145  __ add(edx, ecx);
146  __ mov_b(edx, ecx);
147  __ mov_b(ecx, 6);
148  __ mov_b(Operand(ebx, ecx, times_4, 10000), 6);
149  __ mov_b(Operand(esp, 16), edx);
150  __ mov_w(edx, Operand(esp, 16));
151  __ mov_w(Operand(esp, 16), edx);
152  __ nop();
153  __ movsx_w(edx, Operand(esp, 12));
154  __ movsx_b(edx, Operand(esp, 12));
155  __ movzx_w(edx, Operand(esp, 12));
156  __ movzx_b(edx, Operand(esp, 12));
157  __ nop();
158  __ mov(edx, 1234567);
159  __ mov(edx, Operand(esp, 12));
160  __ mov(Operand(ebx, ecx, times_4, 10000), Immediate(12345));
161  __ mov(Operand(ebx, ecx, times_4, 10000), edx);
162  __ nop();
163  __ dec_b(edx);
164  __ dec_b(Operand(eax, 10));
165  __ dec_b(Operand(ebx, ecx, times_4, 10000));
166  __ dec(edx);
167  __ cdq();
168
169  __ nop();
170  __ idiv(edx);
171  __ idiv(Operand(edx, ecx, times_1, 1));
172  __ idiv(Operand(esp, 12));
173  __ div(edx);
174  __ div(Operand(edx, ecx, times_1, 1));
175  __ div(Operand(esp, 12));
176  __ mul(edx);
177  __ neg(edx);
178  __ not_(edx);
179  __ test(Operand(ebx, ecx, times_4, 10000), Immediate(123456));
180
181  __ imul(edx, Operand(ebx, ecx, times_4, 10000));
182  __ imul(edx, ecx, 12);
183  __ imul(edx, Operand(edx, eax, times_2, 42), 8);
184  __ imul(edx, ecx, 1000);
185  __ imul(edx, Operand(ebx, ecx, times_4, 1), 9000);
186
187  __ inc(edx);
188  __ inc(Operand(ebx, ecx, times_4, 10000));
189  __ push(Operand(ebx, ecx, times_4, 10000));
190  __ pop(Operand(ebx, ecx, times_4, 10000));
191  __ call(Operand(ebx, ecx, times_4, 10000));
192  __ jmp(Operand(ebx, ecx, times_4, 10000));
193
194  __ lea(edx, Operand(ebx, ecx, times_4, 10000));
195  __ or_(edx, 12345);
196  __ or_(edx, Operand(ebx, ecx, times_4, 10000));
197
198  __ nop();
199
200  __ rcl(edx, 1);
201  __ rcl(edx, 7);
202  __ rcr(edx, 1);
203  __ rcr(edx, 7);
204  __ sar(edx, 1);
205  __ sar(edx, 6);
206  __ sar_cl(edx);
207  __ sar(Operand(ebx, ecx, times_4, 10000), 1);
208  __ sar(Operand(ebx, ecx, times_4, 10000), 6);
209  __ sar_cl(Operand(ebx, ecx, times_4, 10000));
210  __ sbb(edx, Operand(ebx, ecx, times_4, 10000));
211  __ shld(edx, Operand(ebx, ecx, times_4, 10000));
212  __ shl(edx, 1);
213  __ shl(edx, 6);
214  __ shl_cl(edx);
215  __ shl(Operand(ebx, ecx, times_4, 10000), 1);
216  __ shl(Operand(ebx, ecx, times_4, 10000), 6);
217  __ shl_cl(Operand(ebx, ecx, times_4, 10000));
218  __ shrd(edx, Operand(ebx, ecx, times_4, 10000));
219  __ shr(edx, 1);
220  __ shr(edx, 7);
221  __ shr_cl(edx);
222  __ shr(Operand(ebx, ecx, times_4, 10000), 1);
223  __ shr(Operand(ebx, ecx, times_4, 10000), 6);
224  __ shr_cl(Operand(ebx, ecx, times_4, 10000));
225
226
227  // Immediates
228
229  __ adc(edx, 12345);
230
231  __ add(ebx, Immediate(12));
232  __ add(Operand(edx, ecx, times_4, 10000), Immediate(12));
233
234  __ and_(ebx, 12345);
235
236  __ cmp(ebx, 12345);
237  __ cmp(ebx, Immediate(12));
238  __ cmp(Operand(edx, ecx, times_4, 10000), Immediate(12));
239  __ cmpb(eax, 100);
240
241  __ or_(ebx, 12345);
242
243  __ sub(ebx, Immediate(12));
244  __ sub(Operand(edx, ecx, times_4, 10000), Immediate(12));
245
246  __ xor_(ebx, 12345);
247
248  __ imul(edx, ecx, 12);
249  __ imul(edx, ecx, 1000);
250
251  __ cld();
252  __ rep_movs();
253  __ rep_stos();
254  __ stos();
255
256  __ sub(edx, Operand(ebx, ecx, times_4, 10000));
257  __ sub(edx, ebx);
258
259  __ test(edx, Immediate(12345));
260  __ test(edx, Operand(ebx, ecx, times_8, 10000));
261  __ test(Operand(esi, edi, times_1, -20000000), Immediate(300000000));
262  __ test_b(edx, Operand(ecx, ebx, times_2, 1000));
263  __ test_b(Operand(eax, -20), 0x9A);
264  __ nop();
265
266  __ xor_(edx, 12345);
267  __ xor_(edx, Operand(ebx, ecx, times_8, 10000));
268  __ bts(Operand(ebx, ecx, times_8, 10000), edx);
269  __ hlt();
270  __ int3();
271  __ ret(0);
272  __ ret(8);
273
274  // Calls
275
276  Label L1, L2;
277  __ bind(&L1);
278  __ nop();
279  __ call(&L1);
280  __ call(&L2);
281  __ nop();
282  __ bind(&L2);
283  __ call(Operand(ebx, ecx, times_4, 10000));
284  __ nop();
285  Handle<Code> ic(LoadIC::initialize_stub(isolate, NOT_CONTEXTUAL));
286  __ call(ic, RelocInfo::CODE_TARGET);
287  __ nop();
288  __ call(FUNCTION_ADDR(DummyStaticFunction), RelocInfo::RUNTIME_ENTRY);
289  __ nop();
290
291  __ jmp(&L1);
292  __ jmp(Operand(ebx, ecx, times_4, 10000));
293  ExternalReference after_break_target =
294      ExternalReference::debug_after_break_target_address(isolate);
295  __ jmp(Operand::StaticVariable(after_break_target));
296  __ jmp(ic, RelocInfo::CODE_TARGET);
297  __ nop();
298
299
300  Label Ljcc;
301  __ nop();
302  // long jumps
303  __ j(overflow, &Ljcc);
304  __ j(no_overflow, &Ljcc);
305  __ j(below, &Ljcc);
306  __ j(above_equal, &Ljcc);
307  __ j(equal, &Ljcc);
308  __ j(not_equal, &Ljcc);
309  __ j(below_equal, &Ljcc);
310  __ j(above, &Ljcc);
311  __ j(sign, &Ljcc);
312  __ j(not_sign, &Ljcc);
313  __ j(parity_even, &Ljcc);
314  __ j(parity_odd, &Ljcc);
315  __ j(less, &Ljcc);
316  __ j(greater_equal, &Ljcc);
317  __ j(less_equal, &Ljcc);
318  __ j(greater, &Ljcc);
319  __ nop();
320  __ bind(&Ljcc);
321  // short jumps
322  __ j(overflow, &Ljcc);
323  __ j(no_overflow, &Ljcc);
324  __ j(below, &Ljcc);
325  __ j(above_equal, &Ljcc);
326  __ j(equal, &Ljcc);
327  __ j(not_equal, &Ljcc);
328  __ j(below_equal, &Ljcc);
329  __ j(above, &Ljcc);
330  __ j(sign, &Ljcc);
331  __ j(not_sign, &Ljcc);
332  __ j(parity_even, &Ljcc);
333  __ j(parity_odd, &Ljcc);
334  __ j(less, &Ljcc);
335  __ j(greater_equal, &Ljcc);
336  __ j(less_equal, &Ljcc);
337  __ j(greater, &Ljcc);
338
339  // 0xD9 instructions
340  __ nop();
341
342  __ fld(1);
343  __ fld1();
344  __ fldz();
345  __ fldpi();
346  __ fabs();
347  __ fchs();
348  __ fprem();
349  __ fprem1();
350  __ fincstp();
351  __ ftst();
352  __ fxam();
353  __ fxch(3);
354  __ fld_s(Operand(ebx, ecx, times_4, 10000));
355  __ fstp_s(Operand(ebx, ecx, times_4, 10000));
356  __ ffree(3);
357  __ fld_d(Operand(ebx, ecx, times_4, 10000));
358  __ fstp_d(Operand(ebx, ecx, times_4, 10000));
359  __ nop();
360
361  __ fild_s(Operand(ebx, ecx, times_4, 10000));
362  __ fistp_s(Operand(ebx, ecx, times_4, 10000));
363  __ fild_d(Operand(ebx, ecx, times_4, 10000));
364  __ fistp_d(Operand(ebx, ecx, times_4, 10000));
365  __ fnstsw_ax();
366  __ nop();
367  __ fadd(3);
368  __ fsub(3);
369  __ fmul(3);
370  __ fdiv(3);
371
372  __ faddp(3);
373  __ fsubp(3);
374  __ fmulp(3);
375  __ fdivp(3);
376  __ fcompp();
377  __ fwait();
378  __ frndint();
379  __ fninit();
380  __ nop();
381
382  __ fldcw(Operand(ebx, ecx, times_4, 10000));
383  __ fnstcw(Operand(ebx, ecx, times_4, 10000));
384  __ fadd_d(Operand(ebx, ecx, times_4, 10000));
385  __ fnsave(Operand(ebx, ecx, times_4, 10000));
386  __ frstor(Operand(ebx, ecx, times_4, 10000));
387
388  // xchg.
389  {
390    __ xchg(eax, eax);
391    __ xchg(eax, ebx);
392    __ xchg(ebx, ebx);
393    __ xchg(ebx, Operand(esp, 12));
394  }
395
396  // Nop instructions
397  for (int i = 0; i < 16; i++) {
398    __ Nop(i);
399  }
400
401  __ ret(0);
402
403  CodeDesc desc;
404  assm.GetCode(&desc);
405  Handle<Code> code = isolate->factory()->NewCode(
406      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
407  USE(code);
408#ifdef OBJECT_PRINT
409  OFStream os(stdout);
410  code->Print(os);
411  byte* begin = code->instruction_start();
412  byte* end = begin + code->instruction_size();
413  disasm::Disassembler::Disassemble(stdout, begin, end);
414#endif
415}
416
417#undef __
418