Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / v8 / test / cctest / test-code-stubs-arm.cc
1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Rrdistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Rrdistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Rrdistributions 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/code-stubs.h"
34 #include "src/factory.h"
35 #include "src/macro-assembler.h"
36 #include "src/simulator.h"
37 #include "test/cctest/cctest.h"
38 #include "test/cctest/test-code-stubs.h"
39
40 using namespace v8::internal;
41
42 #define __ masm.
43
44 ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate,
45                                               Register source_reg,
46                                               Register destination_reg,
47                                               bool inline_fastpath) {
48   // Allocate an executable page of memory.
49   size_t actual_size;
50   byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
51       Assembler::kMinimalBufferSize, &actual_size, true));
52   CHECK(buffer);
53   HandleScope handles(isolate);
54   MacroAssembler masm(isolate, buffer, static_cast<int>(actual_size));
55   DoubleToIStub stub(isolate, source_reg, destination_reg, 0, true,
56                      inline_fastpath);
57
58   byte* start = stub.GetCode()->instruction_start();
59   Label done;
60
61   // Save callee save registers.
62   __ Push(r7, r6, r5, r4);
63   __ Push(lr);
64
65   // For softfp, move the input value into d0.
66   if (!masm.use_eabi_hardfloat()) {
67     __ vmov(d0, r0, r1);
68   }
69   // Push the double argument.
70   __ sub(sp, sp, Operand(kDoubleSize));
71   __ vstr(d0, sp, 0);
72   if (!source_reg.is(sp)) {
73     __ mov(source_reg, sp);
74   }
75
76   // Save registers make sure they don't get clobbered.
77   int source_reg_offset = kDoubleSize;
78   int reg_num = 0;
79   for (;reg_num < Register::NumAllocatableRegisters(); ++reg_num) {
80     Register reg = Register::from_code(reg_num);
81     if (!reg.is(destination_reg)) {
82       __ push(reg);
83       source_reg_offset += kPointerSize;
84     }
85   }
86
87   // Re-push the double argument.
88   __ sub(sp, sp, Operand(kDoubleSize));
89   __ vstr(d0, sp, 0);
90
91   // Call through to the actual stub
92   if (inline_fastpath) {
93     __ vldr(d0, MemOperand(source_reg));
94     __ TryInlineTruncateDoubleToI(destination_reg, d0, &done);
95     if (destination_reg.is(source_reg) && !source_reg.is(sp)) {
96       // Restore clobbered source_reg.
97       __ add(source_reg, sp, Operand(source_reg_offset));
98     }
99   }
100   __ Call(start, RelocInfo::EXTERNAL_REFERENCE);
101   __ bind(&done);
102
103   __ add(sp, sp, Operand(kDoubleSize));
104
105   // Make sure no registers have been unexpectedly clobbered
106   for (--reg_num; reg_num >= 0; --reg_num) {
107     Register reg = Register::from_code(reg_num);
108     if (!reg.is(destination_reg)) {
109       __ ldr(ip, MemOperand(sp, 0));
110       __ cmp(reg, ip);
111       __ Assert(eq, kRegisterWasClobbered);
112       __ add(sp, sp, Operand(kPointerSize));
113     }
114   }
115
116   __ add(sp, sp, Operand(kDoubleSize));
117
118   if (!destination_reg.is(r0))
119     __ mov(r0, destination_reg);
120
121   // Restore callee save registers.
122   __ Pop(lr);
123   __ Pop(r7, r6, r5, r4);
124
125   __ Ret(0);
126
127   CodeDesc desc;
128   masm.GetCode(&desc);
129   CpuFeatures::FlushICache(buffer, actual_size);
130   return (reinterpret_cast<ConvertDToIFunc>(
131       reinterpret_cast<intptr_t>(buffer)));
132 }
133
134 #undef __
135
136
137 static Isolate* GetIsolateFrom(LocalContext* context) {
138   return reinterpret_cast<Isolate*>((*context)->GetIsolate());
139 }
140
141
142 int32_t RunGeneratedCodeCallWrapper(ConvertDToIFunc func,
143                                     double from) {
144 #ifdef USE_SIMULATOR
145   return CALL_GENERATED_FP_INT(func, from, 0);
146 #else
147   return (*func)(from);
148 #endif
149 }
150
151
152 TEST(ConvertDToI) {
153   CcTest::InitializeVM();
154   LocalContext context;
155   Isolate* isolate = GetIsolateFrom(&context);
156   HandleScope scope(isolate);
157
158 #if DEBUG
159   // Verify that the tests actually work with the C version. In the release
160   // code, the compiler optimizes it away because it's all constant, but does it
161   // wrong, triggering an assert on gcc.
162   RunAllTruncationTests(&ConvertDToICVersion);
163 #endif
164
165   Register source_registers[] = {sp, r0, r1, r2, r3, r4, r5, r6, r7};
166   Register dest_registers[] = {r0, r1, r2, r3, r4, r5, r6, r7};
167
168   for (size_t s = 0; s < sizeof(source_registers) / sizeof(Register); s++) {
169     for (size_t d = 0; d < sizeof(dest_registers) / sizeof(Register); d++) {
170       RunAllTruncationTests(
171           RunGeneratedCodeCallWrapper,
172           MakeConvertDToIFuncTrampoline(isolate,
173                                         source_registers[s],
174                                         dest_registers[d],
175                                         false));
176       RunAllTruncationTests(
177           RunGeneratedCodeCallWrapper,
178           MakeConvertDToIFuncTrampoline(isolate,
179                                         source_registers[s],
180                                         dest_registers[d],
181                                         true));
182     }
183   }
184 }