11e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org// Copyright 2013 the V8 project authors. All rights reserved.
21e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org// Rrdistribution and use in source and binary forms, with or without
31e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org// modification, are permitted provided that the following conditions are
41e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org// met:
51e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org//
61e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org//     * Rrdistributions of source code must retain the above copyright
71e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org//       notice, this list of conditions and the following disclaimer.
81e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org//     * Rrdistributions in binary form must reproduce the above
91e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org//       copyright notice, this list of conditions and the following
101e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org//       disclaimer in the documentation and/or other materials provided
111e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org//       with the distribution.
121e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org//     * Neither the name of Google Inc. nor the names of its
131e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org//       contributors may be used to endorse or promote products derived
141e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org//       from this software without specific prior written permission.
151e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org//
161e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
171e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
181e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
191e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
201e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
211e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
221e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
231e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
241e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
251e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
261e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
271e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
281e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org#include <stdlib.h>
291e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
30196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h"
311e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@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 "src/simulator.h"
37196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "test/cctest/cctest.h"
38196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "test/cctest/test-code-stubs.h"
391e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
401e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.orgusing namespace v8::internal;
411e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
421e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org#define __ masm.
431e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
441e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.orgConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate,
451e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org                                              Register source_reg,
461e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org                                              Register destination_reg,
471e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org                                              bool inline_fastpath) {
481e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // Allocate an executable page of memory.
491e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  size_t actual_size;
505de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
515de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org      Assembler::kMinimalBufferSize, &actual_size, true));
521e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  CHECK(buffer);
531e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  HandleScope handles(isolate);
541e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  MacroAssembler masm(isolate, buffer, static_cast<int>(actual_size));
55f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org  DoubleToIStub stub(isolate, source_reg, destination_reg, 0, true,
56f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org                     inline_fastpath);
571e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
58f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org  byte* start = stub.GetCode()->instruction_start();
591e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  Label done;
601e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
611e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // Save callee save registers.
621e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ Push(r7, r6, r5, r4);
631e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ Push(lr);
641e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
652c9426bdda5e95459527292063d885c98180cb0fjkummerow@chromium.org  // For softfp, move the input value into d0.
662c9426bdda5e95459527292063d885c98180cb0fjkummerow@chromium.org  if (!masm.use_eabi_hardfloat()) {
672c9426bdda5e95459527292063d885c98180cb0fjkummerow@chromium.org    __ vmov(d0, r0, r1);
682c9426bdda5e95459527292063d885c98180cb0fjkummerow@chromium.org  }
691e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // Push the double argument.
701e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ sub(sp, sp, Operand(kDoubleSize));
711e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ vstr(d0, sp, 0);
721e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  if (!source_reg.is(sp)) {
731e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org    __ mov(source_reg, sp);
741e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  }
751e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
761e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // Save registers make sure they don't get clobbered.
771e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  int source_reg_offset = kDoubleSize;
781e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  int reg_num = 0;
791e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  for (;reg_num < Register::NumAllocatableRegisters(); ++reg_num) {
801e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org    Register reg = Register::from_code(reg_num);
811e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org    if (!reg.is(destination_reg)) {
821e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org      __ push(reg);
831e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org      source_reg_offset += kPointerSize;
841e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org    }
851e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  }
861e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
871e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // Re-push the double argument.
881e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ sub(sp, sp, Operand(kDoubleSize));
891e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ vstr(d0, sp, 0);
901e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
911e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // Call through to the actual stub
921e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  if (inline_fastpath) {
931e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org    __ vldr(d0, MemOperand(source_reg));
941e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org    __ TryInlineTruncateDoubleToI(destination_reg, d0, &done);
951e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org    if (destination_reg.is(source_reg) && !source_reg.is(sp)) {
961e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org      // Restore clobbered source_reg.
971e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org      __ add(source_reg, sp, Operand(source_reg_offset));
981e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org    }
991e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  }
1001e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ Call(start, RelocInfo::EXTERNAL_REFERENCE);
1011e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ bind(&done);
1021e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
1031e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ add(sp, sp, Operand(kDoubleSize));
1041e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
1051e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // Make sure no registers have been unexpectedly clobbered
1061e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  for (--reg_num; reg_num >= 0; --reg_num) {
1071e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org    Register reg = Register::from_code(reg_num);
1081e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org    if (!reg.is(destination_reg)) {
1091e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org      __ ldr(ip, MemOperand(sp, 0));
1101e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org      __ cmp(reg, ip);
1111e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org      __ Assert(eq, kRegisterWasClobbered);
1121e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org      __ add(sp, sp, Operand(kPointerSize));
1131e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org    }
1141e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  }
1151e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
1161e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ add(sp, sp, Operand(kDoubleSize));
1171e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
1181e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  if (!destination_reg.is(r0))
1191e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org    __ mov(r0, destination_reg);
1201e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
1211e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // Restore callee save registers.
1221e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ Pop(lr);
1231e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ Pop(r7, r6, r5, r4);
1241e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
1251e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  __ Ret(0);
1261e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
1271e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  CodeDesc desc;
1281e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  masm.GetCode(&desc);
1295de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  CpuFeatures::FlushICache(buffer, actual_size);
1301e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  return (reinterpret_cast<ConvertDToIFunc>(
1311e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org      reinterpret_cast<intptr_t>(buffer)));
1321e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org}
1331e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
1341e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org#undef __
1351e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
1361e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
1371e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.orgstatic Isolate* GetIsolateFrom(LocalContext* context) {
1381e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  return reinterpret_cast<Isolate*>((*context)->GetIsolate());
1391e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org}
1401e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
1411e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
1421e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.orgint32_t RunGeneratedCodeCallWrapper(ConvertDToIFunc func,
1431e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org                                    double from) {
1441e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org#ifdef USE_SIMULATOR
145528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  return CALL_GENERATED_FP_INT(func, from, 0);
1461e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org#else
1471e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  return (*func)(from);
1481e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org#endif
1491e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org}
1501e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
1511e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
1521e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.orgTEST(ConvertDToI) {
1531e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  CcTest::InitializeVM();
1541e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  LocalContext context;
1551e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  Isolate* isolate = GetIsolateFrom(&context);
1561e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  HandleScope scope(isolate);
1571e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
1581e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org#if DEBUG
1591e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // Verify that the tests actually work with the C version. In the release
1601e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // code, the compiler optimizes it away because it's all constant, but does it
1611e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // wrong, triggering an assert on gcc.
1621e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  RunAllTruncationTests(&ConvertDToICVersion);
1631e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org#endif
1641e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
1651e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  Register source_registers[] = {sp, r0, r1, r2, r3, r4, r5, r6, r7};
1661e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  Register dest_registers[] = {r0, r1, r2, r3, r4, r5, r6, r7};
1671e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org
1681e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  for (size_t s = 0; s < sizeof(source_registers) / sizeof(Register); s++) {
1691e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org    for (size_t d = 0; d < sizeof(dest_registers) / sizeof(Register); d++) {
1701e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org      RunAllTruncationTests(
1711e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org          RunGeneratedCodeCallWrapper,
1721e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org          MakeConvertDToIFuncTrampoline(isolate,
1731e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org                                        source_registers[s],
1741e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org                                        dest_registers[d],
1751e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org                                        false));
1761e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org      RunAllTruncationTests(
1771e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org          RunGeneratedCodeCallWrapper,
1781e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org          MakeConvertDToIFuncTrampoline(isolate,
1791e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org                                        source_registers[s],
1801e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org                                        dest_registers[d],
1811e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org                                        true));
1821e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org    }
1831e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  }
1841e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org}
185