1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2013 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Rrdistribution and use in source and binary forms, with or without
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// modification, are permitted provided that the following conditions are
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// met:
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//     * Rrdistributions of source code must retain the above copyright
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//       notice, this list of conditions and the following disclaimer.
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//     * Rrdistributions in binary form must reproduce the above
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//       copyright notice, this list of conditions and the following
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//       disclaimer in the documentation and/or other materials provided
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//       with the distribution.
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//     * Neither the name of Google Inc. nor the names of its
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//       contributors may be used to endorse or promote products derived
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//       from this software without specific prior written permission.
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <stdlib.h>
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8.h"
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/platform/platform.h"
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-stubs.h"
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/factory.h"
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/macro-assembler.h"
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/simulator.h"
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "test/cctest/cctest.h"
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "test/cctest/test-code-stubs.h"
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochusing namespace v8::internal;
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define __ masm.
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate,
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              Register source_reg,
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              Register destination_reg,
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              bool inline_fastpath) {
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocate an executable page of memory.
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_t actual_size;
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Assembler::kMinimalBufferSize, &actual_size, true));
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(buffer);
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope handles(isolate);
54014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  MacroAssembler masm(isolate, buffer, static_cast<int>(actual_size),
55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                      v8::internal::CodeObjectRequired::kYes);
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleToIStub stub(isolate, source_reg, destination_reg, 0, true,
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     inline_fastpath);
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  byte* start = stub.GetCode()->instruction_start();
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Save callee save registers.
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(r7, r6, r5, r4);
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(lr);
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // For softfp, move the input value into d0.
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!masm.use_eabi_hardfloat()) {
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vmov(d0, r0, r1);
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Push the double argument.
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sub(sp, sp, Operand(kDoubleSize));
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vstr(d0, sp, 0);
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!source_reg.is(sp)) {
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(source_reg, sp);
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Save registers make sure they don't get clobbered.
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int source_reg_offset = kDoubleSize;
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int reg_num = 0;
80014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  for (; reg_num < Register::kNumRegisters; ++reg_num) {
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register reg = Register::from_code(reg_num);
82014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (reg.IsAllocatable()) {
83014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (!reg.is(destination_reg)) {
84014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ push(reg);
85014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        source_reg_offset += kPointerSize;
86014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Re-push the double argument.
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sub(sp, sp, Operand(kDoubleSize));
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vstr(d0, sp, 0);
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Call through to the actual stub
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (inline_fastpath) {
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vldr(d0, MemOperand(source_reg));
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ TryInlineTruncateDoubleToI(destination_reg, d0, &done);
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (destination_reg.is(source_reg) && !source_reg.is(sp)) {
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Restore clobbered source_reg.
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ add(source_reg, sp, Operand(source_reg_offset));
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Call(start, RelocInfo::EXTERNAL_REFERENCE);
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(sp, sp, Operand(kDoubleSize));
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Make sure no registers have been unexpectedly clobbered
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (--reg_num; reg_num >= 0; --reg_num) {
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register reg = Register::from_code(reg_num);
111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (reg.IsAllocatable()) {
112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (!reg.is(destination_reg)) {
113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ ldr(ip, MemOperand(sp, 0));
114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ cmp(reg, ip);
115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ Assert(eq, kRegisterWasClobbered);
116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ add(sp, sp, Operand(kPointerSize));
117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(sp, sp, Operand(kDoubleSize));
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!destination_reg.is(r0))
124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(r0, destination_reg);
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Restore callee save registers.
127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(lr);
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(r7, r6, r5, r4);
129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Ret(0);
131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeDesc desc;
133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  masm.GetCode(&desc);
134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Assembler::FlushICache(isolate, buffer, actual_size);
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return (reinterpret_cast<ConvertDToIFunc>(
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reinterpret_cast<intptr_t>(buffer)));
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef __
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic Isolate* GetIsolateFrom(LocalContext* context) {
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return reinterpret_cast<Isolate*>((*context)->GetIsolate());
144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint32_t RunGeneratedCodeCallWrapper(ConvertDToIFunc func,
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    double from) {
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef USE_SIMULATOR
150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return CALL_GENERATED_FP_INT(CcTest::i_isolate(), func, from, 0);
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else
152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return (*func)(from);
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(ConvertDToI) {
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::InitializeVM();
159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LocalContext context;
160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = GetIsolateFrom(&context);
161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate);
162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if DEBUG
164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Verify that the tests actually work with the C version. In the release
165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // code, the compiler optimizes it away because it's all constant, but does it
166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // wrong, triggering an assert on gcc.
167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RunAllTruncationTests(&ConvertDToICVersion);
168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register source_registers[] = {sp, r0, r1, r2, r3, r4, r5, r6, r7};
171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register dest_registers[] = {r0, r1, r2, r3, r4, r5, r6, r7};
172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (size_t s = 0; s < sizeof(source_registers) / sizeof(Register); s++) {
174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (size_t d = 0; d < sizeof(dest_registers) / sizeof(Register); d++) {
175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      RunAllTruncationTests(
176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          RunGeneratedCodeCallWrapper,
177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          MakeConvertDToIFuncTrampoline(isolate,
178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        source_registers[s],
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        dest_registers[d],
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        false));
181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      RunAllTruncationTests(
182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          RunGeneratedCodeCallWrapper,
183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          MakeConvertDToIFuncTrampoline(isolate,
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        source_registers[s],
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        dest_registers[d],
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        true));
187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
190