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/mips64/constants-mips64.h" 37014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/register-configuration.h" 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/simulator.h" 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "test/cctest/cctest.h" 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "test/cctest/test-code-stubs.h" 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochusing namespace v8::internal; 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define __ masm. 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate, 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register source_reg, 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register destination_reg, 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool inline_fastpath) { 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Allocate an executable page of memory. 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch size_t actual_size; 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch byte* buffer = static_cast<byte*>(v8::base::OS::Allocate( 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::kMinimalBufferSize, &actual_size, true)); 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(buffer); 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HandleScope handles(isolate); 56014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MacroAssembler masm(isolate, buffer, static_cast<int>(actual_size), 57014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch v8::internal::CodeObjectRequired::kYes); 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DoubleToIStub stub(isolate, source_reg, destination_reg, 0, true, 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline_fastpath); 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch byte* start = stub.GetCode()->instruction_start(); 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save callee save registers. 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ MultiPush(kCalleeSaved | ra.bit()); 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 67014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Save callee-saved FPU registers. 68014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ MultiPushFPU(kCalleeSavedFPU); 69014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Set up the reserved register for 0.0. 70014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Move(kDoubleRegZero, 0.0); 71014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // For softfp, move the input value into f12. 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IsMipsSoftFloatABI) { 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(f12, a0, a1); 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the double argument. 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Dsubu(sp, sp, Operand(kDoubleSize)); 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sdc1(f12, MemOperand(sp)); 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(source_reg, sp); 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save registers make sure they don't get clobbered. 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int source_reg_offset = kDoubleSize; 83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int reg_num = 2; 8421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch const RegisterConfiguration* config = RegisterConfiguration::Crankshaft(); 85014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (; reg_num < config->num_allocatable_general_registers(); ++reg_num) { 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg = Register::from_code(reg_num); 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!reg.is(destination_reg)) { 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(reg); 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch source_reg_offset += kPointerSize; 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Re-push the double argument. 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Dsubu(sp, sp, Operand(kDoubleSize)); 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sdc1(f12, MemOperand(sp)); 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call through to the actual stub 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (inline_fastpath) { 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldc1(f12, MemOperand(source_reg)); 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TryInlineTruncateDoubleToI(destination_reg, f12, &done); 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (destination_reg.is(source_reg) && !source_reg.is(sp)) { 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore clobbered source_reg. 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Daddu(source_reg, sp, Operand(source_reg_offset)); 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Call(start, RelocInfo::EXTERNAL_REFERENCE); 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Daddu(sp, sp, Operand(kDoubleSize)); 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Make sure no registers have been unexpectedly clobbered 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (--reg_num; reg_num >= 2; --reg_num) { 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg = Register::from_code(reg_num); 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!reg.is(destination_reg)) { 115958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ld(at, MemOperand(sp, 0)); 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(eq, kRegisterWasClobbered, reg, Operand(at)); 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Daddu(sp, sp, Operand(kPointerSize)); 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Daddu(sp, sp, Operand(kDoubleSize)); 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(v0, destination_reg); 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label ok; 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(&ok, eq, v0, Operand(zero_reg)); 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&ok); 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Restore callee-saved FPU registers. 129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ MultiPopFPU(kCalleeSavedFPU); 130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore callee save registers. 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ MultiPop(kCalleeSaved | ra.bit()); 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label ok1; 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(&ok1, eq, v0, Operand(zero_reg)); 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&ok1); 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodeDesc desc; 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm.GetCode(&desc); 141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Assembler::FlushICache(isolate, buffer, actual_size); 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return (reinterpret_cast<ConvertDToIFunc>( 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<intptr_t>(buffer))); 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef __ 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic Isolate* GetIsolateFrom(LocalContext* context) { 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return reinterpret_cast<Isolate*>((*context)->GetIsolate()); 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint32_t RunGeneratedCodeCallWrapper(ConvertDToIFunc func, 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch double from) { 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef USE_SIMULATOR 157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Simulator::current(CcTest::i_isolate()) 158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ->CallFP(FUNCTION_ADDR(func), from, 0.); 159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return static_cast<int32_t>( 160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Simulator::current(CcTest::i_isolate())->get_register(v0.code())); 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return (*func)(from); 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(ConvertDToI) { 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CcTest::InitializeVM(); 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LocalContext context; 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate = GetIsolateFrom(&context); 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HandleScope scope(isolate); 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if DEBUG 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Verify that the tests actually work with the C version. In the release 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // code, the compiler optimizes it away because it's all constant, but does it 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // wrong, triggering an assert on gcc. 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RunAllTruncationTests(&ConvertDToICVersion); 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register source_registers[] = { 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sp, v0, v1, a0, a1, a2, a3, a4, a5, a6, a7, t0, t1}; 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register dest_registers[] = { 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v0, v1, a0, a1, a2, a3, a4, a5, a6, a7, t0, t1}; 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (size_t s = 0; s < sizeof(source_registers) / sizeof(Register); s++) { 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (size_t d = 0; d < sizeof(dest_registers) / sizeof(Register); d++) { 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RunAllTruncationTests( 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RunGeneratedCodeCallWrapper, 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MakeConvertDToIFuncTrampoline(isolate, 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch source_registers[s], 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch dest_registers[d], 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch false)); 193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RunAllTruncationTests( 194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RunGeneratedCodeCallWrapper, 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MakeConvertDToIFuncTrampoline(isolate, 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch source_registers[s], 197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch dest_registers[d], 198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch true)); 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 202