1f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Copyright 2013 the V8 project authors. All rights reserved. 2f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Rrdistribution and use in source and binary forms, with or without 3f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// modification, are permitted provided that the following conditions are 4f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// met: 5f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// 6f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// * Rrdistributions of source code must retain the above copyright 7f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// notice, this list of conditions and the following disclaimer. 8f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// * Rrdistributions in binary form must reproduce the above 9f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// copyright notice, this list of conditions and the following 10f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// disclaimer in the documentation and/or other materials provided 11f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// with the distribution. 12f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// * Neither the name of Google Inc. nor the names of its 13f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// contributors may be used to endorse or promote products derived 14f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// from this software without specific prior written permission. 15f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// 16f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 28f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#include <stdlib.h> 29f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 30196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h" 31f5a24546072ecdbbd6372c85c42157e01e913561titzer@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" 39f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 40f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgusing namespace v8::internal; 41f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 42f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#define __ masm. 43f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 44f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate, 45f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register source_reg, 46f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register destination_reg, 47f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org bool inline_fastpath) { 48f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Allocate an executable page of memory. 493c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org size_t actual_size = 4 * Assembler::kMinimalBufferSize; 505de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org byte* buffer = static_cast<byte*>( 515de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org v8::base::OS::Allocate(actual_size, &actual_size, true)); 52f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CHECK(buffer); 53f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org HandleScope handles(isolate); 54f5a24546072ecdbbd6372c85c42157e01e913561titzer@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); 57f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 58f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org byte* start = stub.GetCode()->instruction_start(); 59f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Label done; 60f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 61f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ SetStackPointer(csp); 62f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ PushCalleeSavedRegisters(); 63f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Mov(jssp, csp); 64f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ SetStackPointer(jssp); 65f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 66f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Push the double argument. 67f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Push(d0); 68f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Mov(source_reg, jssp); 69f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 70f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org MacroAssembler::PushPopQueue queue(&masm); 71f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 72f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Save registers make sure they don't get clobbered. 73f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int source_reg_offset = kDoubleSize; 74f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int reg_num = 0; 75f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (;reg_num < Register::NumAllocatableRegisters(); ++reg_num) { 76f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register reg = Register::from_code(reg_num); 77f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (!reg.is(destination_reg)) { 78f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org queue.Queue(reg); 79f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org source_reg_offset += kPointerSize; 80f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 81f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 82f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Re-push the double argument. 83f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org queue.Queue(d0); 84f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 85f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org queue.PushQueued(); 86f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 87f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Call through to the actual stub 88f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (inline_fastpath) { 89f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ldr(d0, MemOperand(source_reg)); 90f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ TryConvertDoubleToInt64(destination_reg, d0, &done); 91f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (destination_reg.is(source_reg)) { 92f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Restore clobbered source_reg. 93f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ add(source_reg, jssp, Operand(source_reg_offset)); 94f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 95f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 96f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Call(start, RelocInfo::EXTERNAL_REFERENCE); 97f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ bind(&done); 98f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 99f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Drop(1, kDoubleSize); 100f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 101f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // // Make sure no registers have been unexpectedly clobbered 102f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (--reg_num; reg_num >= 0; --reg_num) { 103f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register reg = Register::from_code(reg_num); 104f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (!reg.is(destination_reg)) { 105f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Pop(ip0); 106f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ cmp(reg, ip0); 107f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Assert(eq, kRegisterWasClobbered); 108f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 109f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 110f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 111f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Drop(1, kDoubleSize); 112f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 113f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (!destination_reg.is(x0)) 114f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Mov(x0, destination_reg); 115f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 116f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Restore callee save registers. 117f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Mov(csp, jssp); 118f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ SetStackPointer(csp); 119f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ PopCalleeSavedRegisters(); 120f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 121f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __ Ret(); 122f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 123f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CodeDesc desc; 124f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org masm.GetCode(&desc); 1255de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org CpuFeatures::FlushICache(buffer, actual_size); 126f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return (reinterpret_cast<ConvertDToIFunc>( 127f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org reinterpret_cast<intptr_t>(buffer))); 128f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 129f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 130f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#undef __ 131f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 132f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 133f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgstatic Isolate* GetIsolateFrom(LocalContext* context) { 134f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return reinterpret_cast<Isolate*>((*context)->GetIsolate()); 135f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 136f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 137f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 138f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgint32_t RunGeneratedCodeCallWrapper(ConvertDToIFunc func, 139f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org double from) { 140f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#ifdef USE_SIMULATOR 141f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Simulator::CallArgument args[] = { 142f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Simulator::CallArgument(from), 143f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Simulator::CallArgument::End() 144f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org }; 145f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return Simulator::current(Isolate::Current())->CallInt64( 146f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FUNCTION_ADDR(func), args); 147f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#else 148f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return (*func)(from); 149f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#endif 150f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 151f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 152f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 153f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgTEST(ConvertDToI) { 154f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CcTest::InitializeVM(); 155f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LocalContext context; 156f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Isolate* isolate = GetIsolateFrom(&context); 157f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org HandleScope scope(isolate); 158f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 159f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#if DEBUG 160f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Verify that the tests actually work with the C version. In the release 161f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // code, the compiler optimizes it away because it's all constant, but does it 162f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // wrong, triggering an assert on gcc. 163f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org RunAllTruncationTests(&ConvertDToICVersion); 164f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#endif 165f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 166f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register source_registers[] = {jssp, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, 167f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org x10, x11, x12, x13, x14, x15, x18, x19, x20, 168f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org x21, x22, x23, x24}; 169f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Register dest_registers[] = {x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, 170f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org x12, x13, x14, x15, x18, x19, x20, x21, x22, x23, 171f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org x24}; 172f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 173f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (size_t s = 0; s < sizeof(source_registers) / sizeof(Register); s++) { 174f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (size_t d = 0; d < sizeof(dest_registers) / sizeof(Register); d++) { 175f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org RunAllTruncationTests( 176f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org RunGeneratedCodeCallWrapper, 177f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org MakeConvertDToIFuncTrampoline(isolate, 178f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org source_registers[s], 179f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org dest_registers[d], 180f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org false)); 181f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org RunAllTruncationTests( 182f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org RunGeneratedCodeCallWrapper, 183f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org MakeConvertDToIFuncTrampoline(isolate, 184f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org source_registers[s], 185f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org dest_registers[d], 186f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org true)); 187f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 188f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 189f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 190