deps: update v8 to 4.3.61.21
[platform/upstream/nodejs.git] / deps / v8 / test / cctest / test-assembler-x87.cc
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/base/platform/platform.h"
33 #include "src/disassembler.h"
34 #include "src/factory.h"
35 #include "src/macro-assembler.h"
36 #include "src/ostreams.h"
37 #include "test/cctest/cctest.h"
38
39 using namespace v8::internal;
40
41
42 typedef int (*F0)();
43 typedef int (*F1)(int x);
44 typedef int (*F2)(int x, int y);
45
46
47 #define __ assm.
48
49 TEST(AssemblerIa320) {
50   CcTest::InitializeVM();
51   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
52   HandleScope scope(isolate);
53
54   v8::internal::byte buffer[256];
55   Assembler assm(isolate, buffer, sizeof buffer);
56
57   __ mov(eax, Operand(esp, 4));
58   __ add(eax, Operand(esp, 8));
59   __ ret(0);
60
61   CodeDesc desc;
62   assm.GetCode(&desc);
63   Handle<Code> code = isolate->factory()->NewCode(
64       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
65 #ifdef OBJECT_PRINT
66   OFStream os(stdout);
67   code->Print(os);
68 #endif
69   F2 f = FUNCTION_CAST<F2>(code->entry());
70   int res = f(3, 4);
71   ::printf("f() = %d\n", res);
72   CHECK_EQ(7, res);
73 }
74
75
76 TEST(AssemblerIa321) {
77   CcTest::InitializeVM();
78   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
79   HandleScope scope(isolate);
80
81   v8::internal::byte buffer[256];
82   Assembler assm(isolate, buffer, sizeof buffer);
83   Label L, C;
84
85   __ mov(edx, Operand(esp, 4));
86   __ xor_(eax, eax);  // clear eax
87   __ jmp(&C);
88
89   __ bind(&L);
90   __ add(eax, edx);
91   __ sub(edx, Immediate(1));
92
93   __ bind(&C);
94   __ test(edx, edx);
95   __ j(not_zero, &L);
96   __ ret(0);
97
98   CodeDesc desc;
99   assm.GetCode(&desc);
100   Handle<Code> code = isolate->factory()->NewCode(
101       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
102 #ifdef OBJECT_PRINT
103   OFStream os(stdout);
104   code->Print(os);
105 #endif
106   F1 f = FUNCTION_CAST<F1>(code->entry());
107   int res = f(100);
108   ::printf("f() = %d\n", res);
109   CHECK_EQ(5050, res);
110 }
111
112
113 TEST(AssemblerIa322) {
114   CcTest::InitializeVM();
115   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
116   HandleScope scope(isolate);
117
118   v8::internal::byte buffer[256];
119   Assembler assm(isolate, buffer, sizeof buffer);
120   Label L, C;
121
122   __ mov(edx, Operand(esp, 4));
123   __ mov(eax, 1);
124   __ jmp(&C);
125
126   __ bind(&L);
127   __ imul(eax, edx);
128   __ sub(edx, Immediate(1));
129
130   __ bind(&C);
131   __ test(edx, edx);
132   __ j(not_zero, &L);
133   __ ret(0);
134
135   // some relocated stuff here, not executed
136   __ mov(eax, isolate->factory()->true_value());
137   __ jmp(NULL, RelocInfo::RUNTIME_ENTRY);
138
139   CodeDesc desc;
140   assm.GetCode(&desc);
141   Handle<Code> code = isolate->factory()->NewCode(
142       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
143 #ifdef OBJECT_PRINT
144   OFStream os(stdout);
145   code->Print(os);
146 #endif
147   F1 f = FUNCTION_CAST<F1>(code->entry());
148   int res = f(10);
149   ::printf("f() = %d\n", res);
150   CHECK_EQ(3628800, res);
151 }
152
153
154 typedef int (*F3)(float x);
155
156 typedef int (*F4)(double x);
157
158 static int baz = 42;
159 TEST(AssemblerIa325) {
160   CcTest::InitializeVM();
161   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
162   HandleScope scope(isolate);
163
164   v8::internal::byte buffer[256];
165   Assembler assm(isolate, buffer, sizeof buffer);
166
167   __ mov(eax, Operand(reinterpret_cast<intptr_t>(&baz), RelocInfo::NONE32));
168   __ ret(0);
169
170   CodeDesc desc;
171   assm.GetCode(&desc);
172   Handle<Code> code = isolate->factory()->NewCode(
173       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
174   F0 f = FUNCTION_CAST<F0>(code->entry());
175   int res = f();
176   CHECK_EQ(42, res);
177 }
178
179
180 typedef int (*F7)(double x, double y);
181
182 TEST(AssemblerIa329) {
183   CcTest::InitializeVM();
184   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
185   HandleScope scope(isolate);
186   v8::internal::byte buffer[256];
187   MacroAssembler assm(isolate, buffer, sizeof buffer);
188   enum { kEqual = 0, kGreater = 1, kLess = 2, kNaN = 3, kUndefined = 4 };
189   Label equal_l, less_l, greater_l, nan_l;
190   __ fld_d(Operand(esp, 3 * kPointerSize));
191   __ fld_d(Operand(esp, 1 * kPointerSize));
192   __ FCmp();
193   __ j(parity_even, &nan_l);
194   __ j(equal, &equal_l);
195   __ j(below, &less_l);
196   __ j(above, &greater_l);
197
198   __ mov(eax, kUndefined);
199   __ ret(0);
200
201   __ bind(&equal_l);
202   __ mov(eax, kEqual);
203   __ ret(0);
204
205   __ bind(&greater_l);
206   __ mov(eax, kGreater);
207   __ ret(0);
208
209   __ bind(&less_l);
210   __ mov(eax, kLess);
211   __ ret(0);
212
213   __ bind(&nan_l);
214   __ mov(eax, kNaN);
215   __ ret(0);
216
217
218   CodeDesc desc;
219   assm.GetCode(&desc);
220   Handle<Code> code = isolate->factory()->NewCode(
221       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
222 #ifdef OBJECT_PRINT
223   OFStream os(stdout);
224   code->Print(os);
225 #endif
226
227   F7 f = FUNCTION_CAST<F7>(code->entry());
228   CHECK_EQ(kLess, f(1.1, 2.2));
229   CHECK_EQ(kEqual, f(2.2, 2.2));
230   CHECK_EQ(kGreater, f(3.3, 2.2));
231   CHECK_EQ(kNaN, f(std::numeric_limits<double>::quiet_NaN(), 1.1));
232 }
233
234
235 TEST(AssemblerIa3210) {
236   // Test chaining of label usages within instructions (issue 1644).
237   CcTest::InitializeVM();
238   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
239   HandleScope scope(isolate);
240   Assembler assm(isolate, NULL, 0);
241
242   Label target;
243   __ j(equal, &target);
244   __ j(not_equal, &target);
245   __ bind(&target);
246   __ nop();
247 }
248
249
250 TEST(AssemblerMultiByteNop) {
251   CcTest::InitializeVM();
252   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
253   HandleScope scope(isolate);
254   v8::internal::byte buffer[1024];
255   Assembler assm(isolate, buffer, sizeof(buffer));
256   __ push(ebx);
257   __ push(ecx);
258   __ push(edx);
259   __ push(edi);
260   __ push(esi);
261   __ mov(eax, 1);
262   __ mov(ebx, 2);
263   __ mov(ecx, 3);
264   __ mov(edx, 4);
265   __ mov(edi, 5);
266   __ mov(esi, 6);
267   for (int i = 0; i < 16; i++) {
268     int before = assm.pc_offset();
269     __ Nop(i);
270     CHECK_EQ(assm.pc_offset() - before, i);
271   }
272
273   Label fail;
274   __ cmp(eax, 1);
275   __ j(not_equal, &fail);
276   __ cmp(ebx, 2);
277   __ j(not_equal, &fail);
278   __ cmp(ecx, 3);
279   __ j(not_equal, &fail);
280   __ cmp(edx, 4);
281   __ j(not_equal, &fail);
282   __ cmp(edi, 5);
283   __ j(not_equal, &fail);
284   __ cmp(esi, 6);
285   __ j(not_equal, &fail);
286   __ mov(eax, 42);
287   __ pop(esi);
288   __ pop(edi);
289   __ pop(edx);
290   __ pop(ecx);
291   __ pop(ebx);
292   __ ret(0);
293   __ bind(&fail);
294   __ mov(eax, 13);
295   __ pop(esi);
296   __ pop(edi);
297   __ pop(edx);
298   __ pop(ecx);
299   __ pop(ebx);
300   __ ret(0);
301
302   CodeDesc desc;
303   assm.GetCode(&desc);
304   Handle<Code> code = isolate->factory()->NewCode(
305       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
306   CHECK(code->IsCode());
307
308   F0 f = FUNCTION_CAST<F0>(code->entry());
309   int res = f();
310   CHECK_EQ(42, res);
311 }
312
313
314 TEST(AssemblerIa32JumpTables1) {
315   // Test jump tables with forward jumps.
316   CcTest::InitializeVM();
317   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
318   HandleScope scope(isolate);
319   Assembler assm(isolate, nullptr, 0);
320
321   const int kNumCases = 512;
322   int values[kNumCases];
323   isolate->random_number_generator()->NextBytes(values, sizeof(values));
324   Label labels[kNumCases];
325
326   Label done, table;
327   __ mov(eax, Operand(esp, 4));
328   __ jmp(Operand::JumpTable(eax, times_4, &table));
329   __ ud2();
330   __ bind(&table);
331   for (int i = 0; i < kNumCases; ++i) {
332     __ dd(&labels[i]);
333   }
334
335   for (int i = 0; i < kNumCases; ++i) {
336     __ bind(&labels[i]);
337     __ mov(eax, Immediate(values[i]));
338     __ jmp(&done);
339   }
340
341   __ bind(&done);
342   __ ret(0);
343
344   CodeDesc desc;
345   assm.GetCode(&desc);
346   Handle<Code> code = isolate->factory()->NewCode(
347       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
348 #ifdef OBJECT_PRINT
349   OFStream os(stdout);
350   code->Print(os);
351 #endif
352   F1 f = FUNCTION_CAST<F1>(code->entry());
353   for (int i = 0; i < kNumCases; ++i) {
354     int res = f(i);
355     ::printf("f(%d) = %d\n", i, res);
356     CHECK_EQ(values[i], res);
357   }
358 }
359
360
361 TEST(AssemblerIa32JumpTables2) {
362   // Test jump tables with backward jumps.
363   CcTest::InitializeVM();
364   Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
365   HandleScope scope(isolate);
366   Assembler assm(isolate, nullptr, 0);
367
368   const int kNumCases = 512;
369   int values[kNumCases];
370   isolate->random_number_generator()->NextBytes(values, sizeof(values));
371   Label labels[kNumCases];
372
373   Label done, table;
374   __ mov(eax, Operand(esp, 4));
375   __ jmp(Operand::JumpTable(eax, times_4, &table));
376   __ ud2();
377
378   for (int i = 0; i < kNumCases; ++i) {
379     __ bind(&labels[i]);
380     __ mov(eax, Immediate(values[i]));
381     __ jmp(&done);
382   }
383
384   __ bind(&table);
385   for (int i = 0; i < kNumCases; ++i) {
386     __ dd(&labels[i]);
387   }
388
389   __ bind(&done);
390   __ ret(0);
391
392   CodeDesc desc;
393   assm.GetCode(&desc);
394   Handle<Code> code = isolate->factory()->NewCode(
395       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
396 #ifdef OBJECT_PRINT
397   OFStream os(stdout);
398   code->Print(os);
399 #endif
400   F1 f = FUNCTION_CAST<F1>(code->entry());
401   for (int i = 0; i < kNumCases; ++i) {
402     int res = f(i);
403     ::printf("f(%d) = %d\n", i, res);
404     CHECK_EQ(values[i], res);
405   }
406 }
407
408 #undef __