From 787aa693e344e38f6a70f0793c359b869cc98986 Mon Sep 17 00:00:00 2001 From: "palfia@homejinni.com" Date: Wed, 22 Jan 2014 13:44:00 +0000 Subject: [PATCH] MIPS: Add missing cctests of DoubleToIStub (r16322). BUG= R=jkummerow@chromium.org, plind44@gmail.com Review URL: https://codereview.chromium.org/143453003 Patch from Balazs Kilvady . git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18751 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/mips/code-stubs-mips.cc | 10 +- test/cctest/cctest.gyp | 2 + test/cctest/test-code-stubs-mips.cc | 188 ++++++++++++++++++++++++++++ 3 files changed, 197 insertions(+), 3 deletions(-) create mode 100644 test/cctest/test-code-stubs-mips.cc diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc index c7010c9c23..f44f1147ef 100644 --- a/src/mips/code-stubs-mips.cc +++ b/src/mips/code-stubs-mips.cc @@ -683,7 +683,7 @@ void DoubleToIStub::Generate(MacroAssembler* masm) { // Try a conversion to a signed integer. __ Trunc_w_d(double_scratch, double_scratch); // Move the converted value into the result register. - __ mfc1(result_reg, double_scratch); + __ mfc1(scratch3, double_scratch); // Retrieve and restore the FCSR. __ cfc1(scratch, FCSR); @@ -694,8 +694,12 @@ void DoubleToIStub::Generate(MacroAssembler* masm) { scratch, scratch, kFCSROverflowFlagMask | kFCSRUnderflowFlagMask | kFCSRInvalidOpFlagMask); - // If we had no exceptions we are done. - __ Branch(&done, eq, scratch, Operand(zero_reg)); + // If we had no exceptions then set result_reg and we are done. + Label error; + __ Branch(&error, ne, scratch, Operand(zero_reg)); + __ Move(result_reg, scratch3); + __ Branch(&done); + __ bind(&error); } // Load the double value and perform a manual truncation. diff --git a/test/cctest/cctest.gyp b/test/cctest/cctest.gyp index 921c1a4248..d735c60eec 100644 --- a/test/cctest/cctest.gyp +++ b/test/cctest/cctest.gyp @@ -153,6 +153,8 @@ ['v8_target_arch=="mipsel"', { 'sources': [ 'test-assembler-mips.cc', + 'test-code-stubs.cc', + 'test-code-stubs-mips.cc', 'test-disasm-mips.cc', 'test-macro-assembler-mips.cc' ], diff --git a/test/cctest/test-code-stubs-mips.cc b/test/cctest/test-code-stubs-mips.cc new file mode 100644 index 0000000000..8dce89694e --- /dev/null +++ b/test/cctest/test-code-stubs-mips.cc @@ -0,0 +1,188 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Rrdistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Rrdistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Rrdistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +#include "v8.h" + +#include "cctest.h" +#include "code-stubs.h" +#include "test-code-stubs.h" +#include "mips/constants-mips.h" +#include "factory.h" +#include "macro-assembler.h" +#include "platform.h" +#include "simulator.h" + +using namespace v8::internal; + +#define __ masm. + +ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate, + Register source_reg, + Register destination_reg, + bool inline_fastpath) { + // Allocate an executable page of memory. + size_t actual_size; + byte* buffer = static_cast(OS::Allocate(Assembler::kMinimalBufferSize, + &actual_size, + true)); + CHECK(buffer); + HandleScope handles(isolate); + MacroAssembler masm(isolate, buffer, static_cast(actual_size)); + DoubleToIStub stub(source_reg, destination_reg, 0, true, inline_fastpath); + + byte* start = stub.GetCode(isolate)->instruction_start(); + Label done; + + // Save callee save registers. + __ MultiPush(kCalleeSaved | ra.bit()); + + // For softfp, move the input value into f12. + if (IsMipsSoftFloatABI) { + __ Move(f12, a0, a1); + } + // Push the double argument. + __ Subu(sp, sp, Operand(kDoubleSize)); + __ sdc1(f12, MemOperand(sp)); + __ Move(source_reg, sp); + + // Save registers make sure they don't get clobbered. + int source_reg_offset = kDoubleSize; + int reg_num = 2; + for (;reg_num < Register::NumAllocatableRegisters(); ++reg_num) { + Register reg = Register::from_code(reg_num); + if (!reg.is(destination_reg)) { + __ push(reg); + source_reg_offset += kPointerSize; + } + } + + // Re-push the double argument. + __ Subu(sp, sp, Operand(kDoubleSize)); + __ sdc1(f12, MemOperand(sp)); + + // Call through to the actual stub + if (inline_fastpath) { + __ ldc1(f12, MemOperand(source_reg)); + __ TryInlineTruncateDoubleToI(destination_reg, f12, &done); + if (destination_reg.is(source_reg) && !source_reg.is(sp)) { + // Restore clobbered source_reg. + __ Addu(source_reg, sp, Operand(source_reg_offset)); + } + } + __ Call(start, RelocInfo::EXTERNAL_REFERENCE); + __ bind(&done); + + __ Addu(sp, sp, Operand(kDoubleSize)); + + // Make sure no registers have been unexpectedly clobbered + for (--reg_num; reg_num >= 2; --reg_num) { + Register reg = Register::from_code(reg_num); + if (!reg.is(destination_reg)) { + __ lw(at, MemOperand(sp, 0)); + __ Assert(eq, kRegisterWasClobbered, reg, Operand(at)); + __ Addu(sp, sp, Operand(kPointerSize)); + } + } + + __ Addu(sp, sp, Operand(kDoubleSize)); + + __ Move(v0, destination_reg); + Label ok; + __ Branch(&ok, eq, v0, Operand(zero_reg)); + __ bind(&ok); + + // Restore callee save registers. + __ MultiPop(kCalleeSaved | ra.bit()); + + Label ok1; + __ Branch(&ok1, eq, v0, Operand(zero_reg)); + __ bind(&ok1); + __ Ret(); + + CodeDesc desc; + masm.GetCode(&desc); + CPU::FlushICache(buffer, actual_size); + return (reinterpret_cast( + reinterpret_cast(buffer))); +} + +#undef __ + + +static Isolate* GetIsolateFrom(LocalContext* context) { + return reinterpret_cast((*context)->GetIsolate()); +} + + +int32_t RunGeneratedCodeCallWrapper(ConvertDToIFunc func, + double from) { +#ifdef USE_SIMULATOR + Simulator::current(Isolate::Current())->CallFP(FUNCTION_ADDR(func), from, 0.); + return Simulator::current(Isolate::Current())->get_register(v0.code()); +#else + return (*func)(from); +#endif +} + + +TEST(ConvertDToI) { + CcTest::InitializeVM(); + LocalContext context; + Isolate* isolate = GetIsolateFrom(&context); + HandleScope scope(isolate); + +#if DEBUG + // Verify that the tests actually work with the C version. In the release + // code, the compiler optimizes it away because it's all constant, but does it + // wrong, triggering an assert on gcc. + RunAllTruncationTests(&ConvertDToICVersion); +#endif + + Register source_registers[] = { + sp, v0, v1, a0, a1, a2, a3, t0, t1, t2, t3, t4, t5}; + Register dest_registers[] = { + v0, v1, a0, a1, a2, a3, t0, t1, t2, t3, t4, t5}; + + for (size_t s = 0; s < sizeof(source_registers) / sizeof(Register); s++) { + for (size_t d = 0; d < sizeof(dest_registers) / sizeof(Register); d++) { + RunAllTruncationTests( + RunGeneratedCodeCallWrapper, + MakeConvertDToIFuncTrampoline(isolate, + source_registers[s], + dest_registers[d], + false)); + RunAllTruncationTests( + RunGeneratedCodeCallWrapper, + MakeConvertDToIFuncTrampoline(isolate, + source_registers[s], + dest_registers[d], + true)); + } + } +}