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