1ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// Copyright 2013 the V8 project authors. All rights reserved.
2ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// Rrdistribution and use in source and binary forms, with or without
3ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// modification, are permitted provided that the following conditions are
4ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// met:
5ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org//
6ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org//     * Rrdistributions of source code must retain the above copyright
7ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org//       notice, this list of conditions and the following disclaimer.
8ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org//     * Rrdistributions in binary form must reproduce the above
9ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org//       copyright notice, this list of conditions and the following
10ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org//       disclaimer in the documentation and/or other materials provided
11ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org//       with the distribution.
12ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org//     * Neither the name of Google Inc. nor the names of its
13ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org//       contributors may be used to endorse or promote products derived
14ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org//       from this software without specific prior written permission.
15ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org//
16ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
28ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org#include <stdlib.h>
29ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
30196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h"
31ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
325de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org#include "src/base/platform/platform.h"
33196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/code-stubs.h"
34196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/factory.h"
35196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/macro-assembler.h"
36196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "test/cctest/cctest.h"
37196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "test/cctest/test-code-stubs.h"
38ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
39ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.orgusing namespace v8::internal;
40ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
41ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
42ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org#define __ assm.
43ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
44ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.orgConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate,
45ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org                                              Register source_reg,
46ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org                                              Register destination_reg) {
47ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // Allocate an executable page of memory.
48ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  size_t actual_size;
495de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
505de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org      Assembler::kMinimalBufferSize, &actual_size, true));
51ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  CHECK(buffer);
52ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  HandleScope handles(isolate);
53ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  MacroAssembler assm(isolate, buffer, static_cast<int>(actual_size));
54ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  int offset =
55ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    source_reg.is(rsp) ? 0 : (HeapNumber::kValueOffset - kSmiTagSize);
56f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org  DoubleToIStub stub(isolate, source_reg, destination_reg, offset, true);
57f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org  byte* start = stub.GetCode()->instruction_start();
58ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
59763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ pushq(rbx);
60763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ pushq(rcx);
61763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ pushq(rdx);
62763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ pushq(rsi);
63763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ pushq(rdi);
64ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
65ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  if (!source_reg.is(rsp)) {
66935a7790c70d49e252069bc2d34eaa72f8c6677fmachenbach@chromium.org    // The argument we pass to the stub is not a heap number, but instead
67935a7790c70d49e252069bc2d34eaa72f8c6677fmachenbach@chromium.org    // stack-allocated and offset-wise made to look like a heap number for
68935a7790c70d49e252069bc2d34eaa72f8c6677fmachenbach@chromium.org    // the stub.  We create that "heap number" after pushing all allocatable
69935a7790c70d49e252069bc2d34eaa72f8c6677fmachenbach@chromium.org    // registers.
70935a7790c70d49e252069bc2d34eaa72f8c6677fmachenbach@chromium.org    int double_argument_slot =
71935a7790c70d49e252069bc2d34eaa72f8c6677fmachenbach@chromium.org        (Register::NumAllocatableRegisters() - 1) * kPointerSize + kDoubleSize;
72895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org    __ leaq(source_reg, MemOperand(rsp, -double_argument_slot - offset));
73ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  }
74ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
75ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // Save registers make sure they don't get clobbered.
76ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  int reg_num = 0;
77ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  for (;reg_num < Register::NumAllocatableRegisters(); ++reg_num) {
78935a7790c70d49e252069bc2d34eaa72f8c6677fmachenbach@chromium.org    Register reg = Register::FromAllocationIndex(reg_num);
79ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    if (!reg.is(rsp) && !reg.is(rbp) && !reg.is(destination_reg)) {
80763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ pushq(reg);
81ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    }
82ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  }
83ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
84935a7790c70d49e252069bc2d34eaa72f8c6677fmachenbach@chromium.org  // Put the double argument into the designated double argument slot.
85ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ subq(rsp, Immediate(kDoubleSize));
86ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ movsd(MemOperand(rsp, 0), xmm0);
87ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
88ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // Call through to the actual stub
89ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ Call(start, RelocInfo::EXTERNAL_REFERENCE);
90ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
91ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ addq(rsp, Immediate(kDoubleSize));
92ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
93ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // Make sure no registers have been unexpectedly clobbered
94ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  for (--reg_num; reg_num >= 0; --reg_num) {
95935a7790c70d49e252069bc2d34eaa72f8c6677fmachenbach@chromium.org    Register reg = Register::FromAllocationIndex(reg_num);
96ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    if (!reg.is(rsp) && !reg.is(rbp) && !reg.is(destination_reg)) {
97ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org      __ cmpq(reg, MemOperand(rsp, 0));
98594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org      __ Assert(equal, kRegisterWasClobbered);
99ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org      __ addq(rsp, Immediate(kPointerSize));
100ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    }
101ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  }
102ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
103ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ movq(rax, destination_reg);
104ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
105763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ popq(rdi);
106763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ popq(rsi);
107763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ popq(rdx);
108763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ popq(rcx);
109763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ popq(rbx);
110ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
111ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ ret(0);
112ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
113ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  CodeDesc desc;
114ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  assm.GetCode(&desc);
115ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  return reinterpret_cast<ConvertDToIFunc>(
116ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org      reinterpret_cast<intptr_t>(buffer));
117ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org}
118ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
119ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org#undef __
120ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
121ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
122ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.orgstatic Isolate* GetIsolateFrom(LocalContext* context) {
123ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  return reinterpret_cast<Isolate*>((*context)->GetIsolate());
124ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org}
125ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
126ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
127ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.orgTEST(ConvertDToI) {
128ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  CcTest::InitializeVM();
129ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  LocalContext context;
130ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  Isolate* isolate = GetIsolateFrom(&context);
131ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  HandleScope scope(isolate);
132ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
133ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org#if DEBUG
134ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // Verify that the tests actually work with the C version. In the release
135ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // code, the compiler optimizes it away because it's all constant, but does it
136ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // wrong, triggering an assert on gcc.
137ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  RunAllTruncationTests(&ConvertDToICVersion);
138ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org#endif
139ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
140ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  Register source_registers[] = {rsp, rax, rbx, rcx, rdx, rsi, rdi, r8, r9};
141ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  Register dest_registers[] = {rax, rbx, rcx, rdx, rsi, rdi, r8, r9};
142ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
143ebeba02c9ae4ffb0ceab36eb7239f143420f8607rossberg@chromium.org  for (size_t s = 0; s < sizeof(source_registers) / sizeof(Register); s++) {
144ebeba02c9ae4ffb0ceab36eb7239f143420f8607rossberg@chromium.org    for (size_t d = 0; d < sizeof(dest_registers) / sizeof(Register); d++) {
145ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org      RunAllTruncationTests(
146ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org          MakeConvertDToIFuncTrampoline(isolate,
147ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org                                        source_registers[s],
148ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org                                        dest_registers[d]));
149ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    }
150ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  }
151ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org}
152