13d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org// Copyright 2013 the V8 project authors. All rights reserved.
23d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org// Redistribution and use in source and binary forms, with or without
33d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org// modification, are permitted provided that the following conditions are
43d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org// met:
53d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org//
63d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org//     * Redistributions of source code must retain the above copyright
73d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org//       notice, this list of conditions and the following disclaimer.
83d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org//     * Redistributions in binary form must reproduce the above
93d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org//       copyright notice, this list of conditions and the following
103d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org//       disclaimer in the documentation and/or other materials provided
113d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org//       with the distribution.
123d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org//     * Neither the name of Google Inc. nor the names of its
133d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org//       contributors may be used to endorse or promote products derived
143d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org//       from this software without specific prior written permission.
153d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org//
163d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
173d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
183d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
193d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
203d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
213d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
223d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
233d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
243d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
253d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
263d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
273d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
283d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org#include <stdlib.h>
293d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
30196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h"
314b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org#include "test/cctest/cctest.h"
324b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org
33196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/macro-assembler.h"
34196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/mips/macro-assembler-mips.h"
35196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/mips/simulator-mips.h"
363d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
373d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
383d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.orgusing namespace v8::internal;
393d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
403d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.orgtypedef void* (*F)(int x, int y, int p2, int p3, int p4);
413d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
423d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org#define __ masm->
433d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
443d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
453d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.orgstatic byte to_non_zero(int n) {
463d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  return static_cast<unsigned>(n) % 255 + 1;
473d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org}
483d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
493d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
503d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.orgstatic bool all_zeroes(const byte* beg, const byte* end) {
513d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  CHECK(beg);
523d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  CHECK(beg <= end);
533d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  while (beg < end) {
543d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org    if (*beg++ != 0)
553d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org      return false;
563d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  }
573d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  return true;
583d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org}
593d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
603d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
613d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.orgTEST(CopyBytes) {
623d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  CcTest::InitializeVM();
633d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  Isolate* isolate = Isolate::Current();
643d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  HandleScope handles(isolate);
653d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
663d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  const int data_size = 1 * KB;
673d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  size_t act_size;
683d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
693d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  // Allocate two blocks to copy data between.
705de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  byte* src_buffer =
715de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org      static_cast<byte*>(v8::base::OS::Allocate(data_size, &act_size, 0));
723d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  CHECK(src_buffer);
733d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  CHECK(act_size >= static_cast<size_t>(data_size));
745de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  byte* dest_buffer =
755de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org      static_cast<byte*>(v8::base::OS::Allocate(data_size, &act_size, 0));
763d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  CHECK(dest_buffer);
773d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  CHECK(act_size >= static_cast<size_t>(data_size));
783d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
793d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  // Storage for a0 and a1.
803d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  byte* a0_;
813d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  byte* a1_;
823d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
833d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  MacroAssembler assembler(isolate, NULL, 0);
843d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  MacroAssembler* masm = &assembler;
853d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
863d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  // Code to be generated: The stuff in CopyBytes followed by a store of a0 and
873d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  // a1, respectively.
883d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  __ CopyBytes(a0, a1, a2, a3);
893d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  __ li(a2, Operand(reinterpret_cast<int>(&a0_)));
903d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  __ li(a3, Operand(reinterpret_cast<int>(&a1_)));
913d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  __ sw(a0, MemOperand(a2));
923d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  __ jr(ra);
933d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  __ sw(a1, MemOperand(a3));
943d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
953d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  CodeDesc desc;
963d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  masm->GetCode(&desc);
979fa619507474a4c1c21c6935b3209070bc13a218machenbach@chromium.org  Handle<Code> code = isolate->factory()->NewCode(
989fa619507474a4c1c21c6935b3209070bc13a218machenbach@chromium.org      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
993d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
1009fa619507474a4c1c21c6935b3209070bc13a218machenbach@chromium.org  ::F f = FUNCTION_CAST< ::F>(code->entry());
1013d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
1023d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  // Initialise source data with non-zero bytes.
1033d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  for (int i = 0; i < data_size; i++) {
1043d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org    src_buffer[i] = to_non_zero(i);
1053d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  }
1063d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
1073d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  const int fuzz = 11;
1083d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
1093d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  for (int size = 0; size < 600; size++) {
1103d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org    for (const byte* src = src_buffer; src < src_buffer + fuzz; src++) {
1113d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org      for (byte* dest = dest_buffer; dest < dest_buffer + fuzz; dest++) {
1123d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org        memset(dest_buffer, 0, data_size);
1133d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org        CHECK(dest + size < dest_buffer + data_size);
1143d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org        (void) CALL_GENERATED_CODE(f, reinterpret_cast<int>(src),
1153d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org                                      reinterpret_cast<int>(dest), size, 0, 0);
1163d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org        // a0 and a1 should point at the first byte after the copied data.
1173d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org        CHECK_EQ(src + size, a0_);
1183d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org        CHECK_EQ(dest + size, a1_);
1193d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org        // Check that we haven't written outside the target area.
1203d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org        CHECK(all_zeroes(dest_buffer, dest));
1213d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org        CHECK(all_zeroes(dest + size, dest_buffer + data_size));
1223d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org        // Check the target area.
1233d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org        CHECK_EQ(0, memcmp(src, dest, size));
1243d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org      }
1253d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org    }
1263d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  }
1273d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
1283d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  // Check that the source data hasn't been clobbered.
1293d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  for (int i = 0; i < data_size; i++) {
1303d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org    CHECK(src_buffer[i] == to_non_zero(i));
1313d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  }
1323d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org}
1333d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
1343d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
135f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgstatic void TestNaN(const char *code) {
136f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // NaN value is different on MIPS and x86 architectures, and TEST(NaNx)
137f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // tests checks the case where a x86 NaN value is serialized into the
138f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // snapshot on the simulator during cross compilation.
139f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  v8::HandleScope scope(CcTest::isolate());
140f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  v8::Local<v8::Context> context = CcTest::NewContext(PRINT_EXTENSION);
141f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  v8::Context::Scope context_scope(context);
142f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
143f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  v8::Local<v8::Script> script = v8::Script::Compile(v8_str(code));
144f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  v8::Local<v8::Object> result = v8::Local<v8::Object>::Cast(script->Run());
145f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Have to populate the handle manually, as it's not Cast-able.
146f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  i::Handle<i::JSObject> o =
147f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      v8::Utils::OpenHandle<v8::Object, i::JSObject>(result);
148f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  i::Handle<i::JSArray> array1(reinterpret_cast<i::JSArray*>(*o));
149f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  i::FixedDoubleArray* a = i::FixedDoubleArray::cast(array1->elements());
150f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  double value = a->get_scalar(0);
151f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  CHECK(std::isnan(value) &&
152e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org        bit_cast<uint64_t>(value) ==
153e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org            bit_cast<uint64_t>(
154e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org                i::FixedDoubleArray::canonical_not_the_hole_nan_as_double()));
155f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
156f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
157f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
158f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgTEST(NaN0) {
159f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  TestNaN(
160f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org          "var result;"
161f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org          "for (var i = 0; i < 2; i++) {"
162f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org          "  result = new Array(Number.NaN, Number.POSITIVE_INFINITY);"
163f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org          "}"
164f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org          "result;");
165f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
166f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
167f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
168f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgTEST(NaN1) {
169f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  TestNaN(
170f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org          "var result;"
171f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org          "for (var i = 0; i < 2; i++) {"
172f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org          "  result = [NaN];"
173f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org          "}"
174f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org          "result;");
175f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
176f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1773d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
1783d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org#undef __
179