From 8bd431de92d4032c67f51be750987967691a77c1 Mon Sep 17 00:00:00 2001 From: "dusan.m.milosavljevic" Date: Tue, 29 Sep 2015 10:23:44 -0700 Subject: [PATCH] MIPS64: Add big-endian support for mips64. TEST= BUG= Review URL: https://codereview.chromium.org/1334793004 Cr-Commit-Position: refs/heads/master@{#31011} --- Makefile | 2 +- build/toolchain.gypi | 25 +- src/base/build_config.h | 4 + src/ic/mips64/handler-compiler-mips64.cc | 2 +- src/ic/mips64/ic-mips64.cc | 2 +- src/mips64/assembler-mips64.h | 10 + src/mips64/code-stubs-mips64.cc | 24 +- src/mips64/codegen-mips64.cc | 342 ++++++++++++++------- src/mips64/constants-mips64.h | 10 + src/mips64/lithium-codegen-mips64.cc | 8 +- src/mips64/macro-assembler-mips64.cc | 139 +++++++-- src/mips64/macro-assembler-mips64.h | 14 +- src/mips64/simulator-mips64.cc | 16 +- src/mips64/simulator-mips64.h | 7 +- src/regexp/mips64/regexp-macro-assembler-mips64.cc | 10 +- test/cctest/cctest.status | 4 +- test/cctest/test-assembler-mips64.cc | 78 +++-- test/mjsunit/mjsunit.status | 8 +- test/mozilla/mozilla.status | 4 +- test/test262/test262.status | 2 +- tools/gyp/v8.gyp | 2 +- tools/run-tests.py | 4 +- tools/testrunner/local/statusfile.py | 2 +- 23 files changed, 497 insertions(+), 222 deletions(-) diff --git a/Makefile b/Makefile index 761b6fc..28c1af2 100644 --- a/Makefile +++ b/Makefile @@ -244,7 +244,7 @@ endif # Architectures and modes to be compiled. Consider these to be internal # variables, don't override them (use the targets instead). -ARCHES = ia32 x64 x32 arm arm64 mips mipsel mips64el x87 ppc ppc64 +ARCHES = ia32 x64 x32 arm arm64 mips mipsel mips64 mips64el x87 ppc ppc64 DEFAULT_ARCHES = ia32 x64 arm MODES = release debug optdebug DEFAULT_MODES = release debug diff --git a/build/toolchain.gypi b/build/toolchain.gypi index 2163171..bd081e1 100644 --- a/build/toolchain.gypi +++ b/build/toolchain.gypi @@ -341,7 +341,8 @@ 'cflags': ['-march=i586'], }], # v8_target_arch=="x87" ['(v8_target_arch=="mips" or v8_target_arch=="mipsel" \ - or v8_target_arch=="mips64el") and v8_target_arch==target_arch', { + or v8_target_arch=="mips64" or v8_target_arch=="mips64el") \ + and v8_target_arch==target_arch', { 'target_conditions': [ ['_toolset=="target"', { # Target built with a Mips CXX compiler. @@ -743,7 +744,7 @@ }], ], }], # v8_target_arch=="mipsel" - ['v8_target_arch=="mips64el"', { + ['v8_target_arch=="mips64el" or v8_target_arch=="mips64"', { 'defines': [ 'V8_TARGET_ARCH_MIPS64', ], @@ -753,6 +754,16 @@ 'CAN_USE_FPU_INSTRUCTIONS', ], }], + [ 'v8_host_byteorder=="little"', { + 'defines': [ + 'V8_TARGET_ARCH_MIPS64_LE', + ], + }], + [ 'v8_host_byteorder=="big"', { + 'defines': [ + 'V8_TARGET_ARCH_MIPS64_BE', + ], + }], [ 'v8_use_mips_abi_hardfloat=="true"', { 'defines': [ '__mips_hard_float=1', @@ -769,11 +780,17 @@ 'conditions': [ ['v8_target_arch==target_arch', { 'cflags': [ - '-EL', '-Wno-error=array-bounds', # Workaround https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56273 ], - 'ldflags': ['-EL'], 'conditions': [ + ['v8_target_arch=="mips64el"', { + 'cflags': ['-EL'], + 'ldflags': ['-EL'], + }], + ['v8_target_arch=="mips64"', { + 'cflags': ['-EB'], + 'ldflags': ['-EB'], + }], [ 'v8_use_mips_abi_hardfloat=="true"', { 'cflags': ['-mhard-float'], 'ldflags': ['-mhard-float'], diff --git a/src/base/build_config.h b/src/base/build_config.h index b8ba4eb..8016218 100644 --- a/src/base/build_config.h +++ b/src/base/build_config.h @@ -164,7 +164,11 @@ #define V8_TARGET_LITTLE_ENDIAN 1 #endif #elif V8_TARGET_ARCH_MIPS64 +#if defined(__MIPSEB__) || defined(V8_TARGET_ARCH_MIPS64_BE) +#define V8_TARGET_BIG_ENDIAN 1 +#else #define V8_TARGET_LITTLE_ENDIAN 1 +#endif #elif V8_TARGET_ARCH_X87 #define V8_TARGET_LITTLE_ENDIAN 1 #elif V8_TARGET_ARCH_PPC_LE diff --git a/src/ic/mips64/handler-compiler-mips64.cc b/src/ic/mips64/handler-compiler-mips64.cc index e905506..9c3a5b3 100644 --- a/src/ic/mips64/handler-compiler-mips64.cc +++ b/src/ic/mips64/handler-compiler-mips64.cc @@ -361,7 +361,7 @@ void NamedStoreHandlerCompiler::GenerateRestoreMap(Handle transition, DCHECK(!map_reg.is(scratch)); __ LoadWeakValue(map_reg, cell, miss); if (transition->CanBeDeprecated()) { - __ ld(scratch, FieldMemOperand(map_reg, Map::kBitField3Offset)); + __ lwu(scratch, FieldMemOperand(map_reg, Map::kBitField3Offset)); __ And(at, scratch, Operand(Map::Deprecated::kMask)); __ Branch(miss, ne, at, Operand(zero_reg)); } diff --git a/src/ic/mips64/ic-mips64.cc b/src/ic/mips64/ic-mips64.cc index cacc95c..0d7af56 100644 --- a/src/ic/mips64/ic-mips64.cc +++ b/src/ic/mips64/ic-mips64.cc @@ -551,7 +551,7 @@ static void KeyedStoreGenerateMegamorphicHelper( // We have to see if the double version of the hole is present. If so // go to the runtime. __ Daddu(address, elements, - Operand(FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32) - + Operand(FixedDoubleArray::kHeaderSize + Register::kExponentOffset - kHeapObjectTag)); __ SmiScale(at, key, kPointerSizeLog2); __ daddu(address, address, at); diff --git a/src/mips64/assembler-mips64.h b/src/mips64/assembler-mips64.h index 2036aa7..be57f29 100644 --- a/src/mips64/assembler-mips64.h +++ b/src/mips64/assembler-mips64.h @@ -79,6 +79,16 @@ struct Register { static const int kSizeInBytes = 8; static const int kCpRegister = 23; // cp (s7) is the 23rd register. +#if defined(V8_TARGET_LITTLE_ENDIAN) + static const int kMantissaOffset = 0; + static const int kExponentOffset = 4; +#elif defined(V8_TARGET_BIG_ENDIAN) + static const int kMantissaOffset = 4; + static const int kExponentOffset = 0; +#else +#error Unknown endianness +#endif + inline static int NumAllocatableRegisters(); static int ToAllocationIndex(Register reg) { diff --git a/src/mips64/code-stubs-mips64.cc b/src/mips64/code-stubs-mips64.cc index c447a79..d0c05ad 100644 --- a/src/mips64/code-stubs-mips64.cc +++ b/src/mips64/code-stubs-mips64.cc @@ -182,8 +182,10 @@ void DoubleToIStub::Generate(MacroAssembler* masm) { Register input_high = scratch2; Register input_low = scratch3; - __ lw(input_low, MemOperand(input_reg, double_offset)); - __ lw(input_high, MemOperand(input_reg, double_offset + kIntSize)); + __ lw(input_low, + MemOperand(input_reg, double_offset + Register::kMantissaOffset)); + __ lw(input_high, + MemOperand(input_reg, double_offset + Register::kExponentOffset)); Label normal_exponent, restore_sign; // Extract the biased exponent in result. @@ -3309,7 +3311,7 @@ void ToNumberStub::Generate(MacroAssembler* masm) { Label not_string, slow_string; __ Branch(¬_string, hs, a1, Operand(FIRST_NONSTRING_TYPE)); // Check if string has a cached array index. - __ ld(a2, FieldMemOperand(a0, String::kHashFieldOffset)); + __ lwu(a2, FieldMemOperand(a0, String::kHashFieldOffset)); __ And(at, a2, Operand(String::kContainsCachedArrayIndexMask)); __ Branch(&slow_string, ne, at, Operand(zero_reg)); __ IndexFromHash(a2, a0); @@ -5602,8 +5604,8 @@ static void CallApiFunctionStubHelper(MacroAssembler* masm, // -- // -- sp[0] : last argument // -- ... - // -- sp[(argc - 1)* 4] : first argument - // -- sp[argc * 4] : receiver + // -- sp[(argc - 1)* 8] : first argument + // -- sp[argc * 8] : receiver // ----------------------------------- Register callee = a0; @@ -5662,10 +5664,12 @@ static void CallApiFunctionStubHelper(MacroAssembler* masm, Operand((FCA::kArgsLength - 1 + argc.immediate()) * kPointerSize)); __ sd(at, MemOperand(a0, 1 * kPointerSize)); // FunctionCallbackInfo::length_ = argc + // Stored as int field, 32-bit integers within struct on stack always left + // justified by n64 ABI. __ li(at, Operand(argc.immediate())); - __ sd(at, MemOperand(a0, 2 * kPointerSize)); + __ sw(at, MemOperand(a0, 2 * kPointerSize)); // FunctionCallbackInfo::is_construct_call_ = 0 - __ sd(zero_reg, MemOperand(a0, 3 * kPointerSize)); + __ sw(zero_reg, MemOperand(a0, 2 * kPointerSize + kIntSize)); } else { // FunctionCallbackInfo::values_ __ dsll(at, argc.reg(), kPointerSizeLog2); @@ -5673,11 +5677,13 @@ static void CallApiFunctionStubHelper(MacroAssembler* masm, __ Daddu(at, at, Operand((FCA::kArgsLength - 1) * kPointerSize)); __ sd(at, MemOperand(a0, 1 * kPointerSize)); // FunctionCallbackInfo::length_ = argc - __ sd(argc.reg(), MemOperand(a0, 2 * kPointerSize)); + // Stored as int field, 32-bit integers within struct on stack always left + // justified by n64 ABI. + __ sw(argc.reg(), MemOperand(a0, 2 * kPointerSize)); // FunctionCallbackInfo::is_construct_call_ __ Daddu(argc.reg(), argc.reg(), Operand(FCA::kArgsLength + 1)); __ dsll(at, argc.reg(), kPointerSizeLog2); - __ sd(at, MemOperand(a0, 3 * kPointerSize)); + __ sw(at, MemOperand(a0, 2 * kPointerSize + kIntSize)); } ExternalReference thunk_ref = diff --git a/src/mips64/codegen-mips64.cc b/src/mips64/codegen-mips64.cc index 9a5cdb3..d30bdbb 100644 --- a/src/mips64/codegen-mips64.cc +++ b/src/mips64/codegen-mips64.cc @@ -45,21 +45,13 @@ UnaryMathFunction CreateExpFunction() { Register temp2 = a5; Register temp3 = a6; - if (!IsMipsSoftFloatABI) { - // Input value is in f12 anyway, nothing to do. - } else { - __ Move(input, a0, a1); - } + __ MovFromFloatParameter(input); __ Push(temp3, temp2, temp1); MathExpGenerator::EmitMathExp( &masm, input, result, double_scratch1, double_scratch2, temp1, temp2, temp3); __ Pop(temp3, temp2, temp1); - if (!IsMipsSoftFloatABI) { - // Result is already in f0, nothing to do. - } else { - __ Move(v0, v1, result); - } + __ MovToFloatResult(result); __ Ret(); } @@ -141,10 +133,17 @@ MemCopyUint8Function CreateMemCopyUint8Function(MemCopyUint8Function stub) { __ beq(a3, zero_reg, &aligned); // Already aligned. __ subu(a2, a2, a3); // In delay slot. a2 is the remining bytes count. - __ lwr(t8, MemOperand(a1)); - __ addu(a1, a1, a3); - __ swr(t8, MemOperand(a0)); - __ addu(a0, a0, a3); + if (kArchEndian == kLittle) { + __ lwr(t8, MemOperand(a1)); + __ addu(a1, a1, a3); + __ swr(t8, MemOperand(a0)); + __ addu(a0, a0, a3); + } else { + __ lwl(t8, MemOperand(a1)); + __ addu(a1, a1, a3); + __ swl(t8, MemOperand(a0)); + __ addu(a0, a0, a3); + } // Now dst/src are both aligned to (word) aligned addresses. Set a2 to // count how many bytes we have to copy after all the 64 byte chunks are @@ -297,12 +296,21 @@ MemCopyUint8Function CreateMemCopyUint8Function(MemCopyUint8Function stub) { __ beq(a3, zero_reg, &ua_chk16w); __ subu(a2, a2, a3); // In delay slot. - __ lwr(v1, MemOperand(a1)); - __ lwl(v1, - MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one)); - __ addu(a1, a1, a3); - __ swr(v1, MemOperand(a0)); - __ addu(a0, a0, a3); + if (kArchEndian == kLittle) { + __ lwr(v1, MemOperand(a1)); + __ lwl(v1, + MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one)); + __ addu(a1, a1, a3); + __ swr(v1, MemOperand(a0)); + __ addu(a0, a0, a3); + } else { + __ lwl(v1, MemOperand(a1)); + __ lwr(v1, + MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one)); + __ addu(a1, a1, a3); + __ swl(v1, MemOperand(a0)); + __ addu(a0, a0, a3); + } // Now the dst (but not the source) is aligned. Set a2 to count how many // bytes we have to copy after all the 64 byte chunks are copied and a3 to @@ -330,41 +338,79 @@ MemCopyUint8Function CreateMemCopyUint8Function(MemCopyUint8Function stub) { } __ bind(&ua_loop16w); - __ Pref(pref_hint_load, MemOperand(a1, 3 * pref_chunk)); - __ lwr(a4, MemOperand(a1)); - __ lwr(a5, MemOperand(a1, 1, loadstore_chunk)); - __ lwr(a6, MemOperand(a1, 2, loadstore_chunk)); - - if (pref_hint_store == kPrefHintPrepareForStore) { - __ sltu(v1, t9, a0); - __ Branch(USE_DELAY_SLOT, &ua_skip_pref, gt, v1, Operand(zero_reg)); + if (kArchEndian == kLittle) { + __ Pref(pref_hint_load, MemOperand(a1, 3 * pref_chunk)); + __ lwr(a4, MemOperand(a1)); + __ lwr(a5, MemOperand(a1, 1, loadstore_chunk)); + __ lwr(a6, MemOperand(a1, 2, loadstore_chunk)); + + if (pref_hint_store == kPrefHintPrepareForStore) { + __ sltu(v1, t9, a0); + __ Branch(USE_DELAY_SLOT, &ua_skip_pref, gt, v1, Operand(zero_reg)); + } + __ lwr(a7, MemOperand(a1, 3, loadstore_chunk)); // Maybe in delay slot. + + __ Pref(pref_hint_store, MemOperand(a0, 4 * pref_chunk)); + __ Pref(pref_hint_store, MemOperand(a0, 5 * pref_chunk)); + + __ bind(&ua_skip_pref); + __ lwr(t0, MemOperand(a1, 4, loadstore_chunk)); + __ lwr(t1, MemOperand(a1, 5, loadstore_chunk)); + __ lwr(t2, MemOperand(a1, 6, loadstore_chunk)); + __ lwr(t3, MemOperand(a1, 7, loadstore_chunk)); + __ lwl(a4, + MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwl(a5, + MemOperand(a1, 2, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwl(a6, + MemOperand(a1, 3, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwl(a7, + MemOperand(a1, 4, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwl(t0, + MemOperand(a1, 5, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwl(t1, + MemOperand(a1, 6, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwl(t2, + MemOperand(a1, 7, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwl(t3, + MemOperand(a1, 8, loadstore_chunk, MemOperand::offset_minus_one)); + } else { + __ Pref(pref_hint_load, MemOperand(a1, 3 * pref_chunk)); + __ lwl(a4, MemOperand(a1)); + __ lwl(a5, MemOperand(a1, 1, loadstore_chunk)); + __ lwl(a6, MemOperand(a1, 2, loadstore_chunk)); + + if (pref_hint_store == kPrefHintPrepareForStore) { + __ sltu(v1, t9, a0); + __ Branch(USE_DELAY_SLOT, &ua_skip_pref, gt, v1, Operand(zero_reg)); + } + __ lwl(a7, MemOperand(a1, 3, loadstore_chunk)); // Maybe in delay slot. + + __ Pref(pref_hint_store, MemOperand(a0, 4 * pref_chunk)); + __ Pref(pref_hint_store, MemOperand(a0, 5 * pref_chunk)); + + __ bind(&ua_skip_pref); + __ lwl(t0, MemOperand(a1, 4, loadstore_chunk)); + __ lwl(t1, MemOperand(a1, 5, loadstore_chunk)); + __ lwl(t2, MemOperand(a1, 6, loadstore_chunk)); + __ lwl(t3, MemOperand(a1, 7, loadstore_chunk)); + __ lwr(a4, + MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwr(a5, + MemOperand(a1, 2, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwr(a6, + MemOperand(a1, 3, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwr(a7, + MemOperand(a1, 4, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwr(t0, + MemOperand(a1, 5, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwr(t1, + MemOperand(a1, 6, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwr(t2, + MemOperand(a1, 7, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwr(t3, + MemOperand(a1, 8, loadstore_chunk, MemOperand::offset_minus_one)); } - __ lwr(a7, MemOperand(a1, 3, loadstore_chunk)); // Maybe in delay slot. - - __ Pref(pref_hint_store, MemOperand(a0, 4 * pref_chunk)); - __ Pref(pref_hint_store, MemOperand(a0, 5 * pref_chunk)); - - __ bind(&ua_skip_pref); - __ lwr(t0, MemOperand(a1, 4, loadstore_chunk)); - __ lwr(t1, MemOperand(a1, 5, loadstore_chunk)); - __ lwr(t2, MemOperand(a1, 6, loadstore_chunk)); - __ lwr(t3, MemOperand(a1, 7, loadstore_chunk)); - __ lwl(a4, - MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one)); - __ lwl(a5, - MemOperand(a1, 2, loadstore_chunk, MemOperand::offset_minus_one)); - __ lwl(a6, - MemOperand(a1, 3, loadstore_chunk, MemOperand::offset_minus_one)); - __ lwl(a7, - MemOperand(a1, 4, loadstore_chunk, MemOperand::offset_minus_one)); - __ lwl(t0, - MemOperand(a1, 5, loadstore_chunk, MemOperand::offset_minus_one)); - __ lwl(t1, - MemOperand(a1, 6, loadstore_chunk, MemOperand::offset_minus_one)); - __ lwl(t2, - MemOperand(a1, 7, loadstore_chunk, MemOperand::offset_minus_one)); - __ lwl(t3, - MemOperand(a1, 8, loadstore_chunk, MemOperand::offset_minus_one)); __ Pref(pref_hint_load, MemOperand(a1, 4 * pref_chunk)); __ sw(a4, MemOperand(a0)); __ sw(a5, MemOperand(a0, 1, loadstore_chunk)); @@ -374,30 +420,57 @@ MemCopyUint8Function CreateMemCopyUint8Function(MemCopyUint8Function stub) { __ sw(t1, MemOperand(a0, 5, loadstore_chunk)); __ sw(t2, MemOperand(a0, 6, loadstore_chunk)); __ sw(t3, MemOperand(a0, 7, loadstore_chunk)); - __ lwr(a4, MemOperand(a1, 8, loadstore_chunk)); - __ lwr(a5, MemOperand(a1, 9, loadstore_chunk)); - __ lwr(a6, MemOperand(a1, 10, loadstore_chunk)); - __ lwr(a7, MemOperand(a1, 11, loadstore_chunk)); - __ lwr(t0, MemOperand(a1, 12, loadstore_chunk)); - __ lwr(t1, MemOperand(a1, 13, loadstore_chunk)); - __ lwr(t2, MemOperand(a1, 14, loadstore_chunk)); - __ lwr(t3, MemOperand(a1, 15, loadstore_chunk)); - __ lwl(a4, - MemOperand(a1, 9, loadstore_chunk, MemOperand::offset_minus_one)); - __ lwl(a5, - MemOperand(a1, 10, loadstore_chunk, MemOperand::offset_minus_one)); - __ lwl(a6, - MemOperand(a1, 11, loadstore_chunk, MemOperand::offset_minus_one)); - __ lwl(a7, - MemOperand(a1, 12, loadstore_chunk, MemOperand::offset_minus_one)); - __ lwl(t0, - MemOperand(a1, 13, loadstore_chunk, MemOperand::offset_minus_one)); - __ lwl(t1, - MemOperand(a1, 14, loadstore_chunk, MemOperand::offset_minus_one)); - __ lwl(t2, - MemOperand(a1, 15, loadstore_chunk, MemOperand::offset_minus_one)); - __ lwl(t3, - MemOperand(a1, 16, loadstore_chunk, MemOperand::offset_minus_one)); + if (kArchEndian == kLittle) { + __ lwr(a4, MemOperand(a1, 8, loadstore_chunk)); + __ lwr(a5, MemOperand(a1, 9, loadstore_chunk)); + __ lwr(a6, MemOperand(a1, 10, loadstore_chunk)); + __ lwr(a7, MemOperand(a1, 11, loadstore_chunk)); + __ lwr(t0, MemOperand(a1, 12, loadstore_chunk)); + __ lwr(t1, MemOperand(a1, 13, loadstore_chunk)); + __ lwr(t2, MemOperand(a1, 14, loadstore_chunk)); + __ lwr(t3, MemOperand(a1, 15, loadstore_chunk)); + __ lwl(a4, + MemOperand(a1, 9, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwl(a5, + MemOperand(a1, 10, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwl(a6, + MemOperand(a1, 11, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwl(a7, + MemOperand(a1, 12, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwl(t0, + MemOperand(a1, 13, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwl(t1, + MemOperand(a1, 14, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwl(t2, + MemOperand(a1, 15, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwl(t3, + MemOperand(a1, 16, loadstore_chunk, MemOperand::offset_minus_one)); + } else { + __ lwl(a4, MemOperand(a1, 8, loadstore_chunk)); + __ lwl(a5, MemOperand(a1, 9, loadstore_chunk)); + __ lwl(a6, MemOperand(a1, 10, loadstore_chunk)); + __ lwl(a7, MemOperand(a1, 11, loadstore_chunk)); + __ lwl(t0, MemOperand(a1, 12, loadstore_chunk)); + __ lwl(t1, MemOperand(a1, 13, loadstore_chunk)); + __ lwl(t2, MemOperand(a1, 14, loadstore_chunk)); + __ lwl(t3, MemOperand(a1, 15, loadstore_chunk)); + __ lwr(a4, + MemOperand(a1, 9, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwr(a5, + MemOperand(a1, 10, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwr(a6, + MemOperand(a1, 11, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwr(a7, + MemOperand(a1, 12, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwr(t0, + MemOperand(a1, 13, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwr(t1, + MemOperand(a1, 14, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwr(t2, + MemOperand(a1, 15, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwr(t3, + MemOperand(a1, 16, loadstore_chunk, MemOperand::offset_minus_one)); + } __ Pref(pref_hint_load, MemOperand(a1, 5 * pref_chunk)); __ sw(a4, MemOperand(a0, 8, loadstore_chunk)); __ sw(a5, MemOperand(a0, 9, loadstore_chunk)); @@ -421,30 +494,57 @@ MemCopyUint8Function CreateMemCopyUint8Function(MemCopyUint8Function stub) { __ beq(a2, t8, &ua_chk1w); __ nop(); // In delay slot. - __ lwr(a4, MemOperand(a1)); - __ lwr(a5, MemOperand(a1, 1, loadstore_chunk)); - __ lwr(a6, MemOperand(a1, 2, loadstore_chunk)); - __ lwr(a7, MemOperand(a1, 3, loadstore_chunk)); - __ lwr(t0, MemOperand(a1, 4, loadstore_chunk)); - __ lwr(t1, MemOperand(a1, 5, loadstore_chunk)); - __ lwr(t2, MemOperand(a1, 6, loadstore_chunk)); - __ lwr(t3, MemOperand(a1, 7, loadstore_chunk)); - __ lwl(a4, - MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one)); - __ lwl(a5, - MemOperand(a1, 2, loadstore_chunk, MemOperand::offset_minus_one)); - __ lwl(a6, - MemOperand(a1, 3, loadstore_chunk, MemOperand::offset_minus_one)); - __ lwl(a7, - MemOperand(a1, 4, loadstore_chunk, MemOperand::offset_minus_one)); - __ lwl(t0, - MemOperand(a1, 5, loadstore_chunk, MemOperand::offset_minus_one)); - __ lwl(t1, - MemOperand(a1, 6, loadstore_chunk, MemOperand::offset_minus_one)); - __ lwl(t2, - MemOperand(a1, 7, loadstore_chunk, MemOperand::offset_minus_one)); - __ lwl(t3, - MemOperand(a1, 8, loadstore_chunk, MemOperand::offset_minus_one)); + if (kArchEndian == kLittle) { + __ lwr(a4, MemOperand(a1)); + __ lwr(a5, MemOperand(a1, 1, loadstore_chunk)); + __ lwr(a6, MemOperand(a1, 2, loadstore_chunk)); + __ lwr(a7, MemOperand(a1, 3, loadstore_chunk)); + __ lwr(t0, MemOperand(a1, 4, loadstore_chunk)); + __ lwr(t1, MemOperand(a1, 5, loadstore_chunk)); + __ lwr(t2, MemOperand(a1, 6, loadstore_chunk)); + __ lwr(t3, MemOperand(a1, 7, loadstore_chunk)); + __ lwl(a4, + MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwl(a5, + MemOperand(a1, 2, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwl(a6, + MemOperand(a1, 3, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwl(a7, + MemOperand(a1, 4, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwl(t0, + MemOperand(a1, 5, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwl(t1, + MemOperand(a1, 6, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwl(t2, + MemOperand(a1, 7, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwl(t3, + MemOperand(a1, 8, loadstore_chunk, MemOperand::offset_minus_one)); + } else { + __ lwl(a4, MemOperand(a1)); + __ lwl(a5, MemOperand(a1, 1, loadstore_chunk)); + __ lwl(a6, MemOperand(a1, 2, loadstore_chunk)); + __ lwl(a7, MemOperand(a1, 3, loadstore_chunk)); + __ lwl(t0, MemOperand(a1, 4, loadstore_chunk)); + __ lwl(t1, MemOperand(a1, 5, loadstore_chunk)); + __ lwl(t2, MemOperand(a1, 6, loadstore_chunk)); + __ lwl(t3, MemOperand(a1, 7, loadstore_chunk)); + __ lwr(a4, + MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwr(a5, + MemOperand(a1, 2, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwr(a6, + MemOperand(a1, 3, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwr(a7, + MemOperand(a1, 4, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwr(t0, + MemOperand(a1, 5, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwr(t1, + MemOperand(a1, 6, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwr(t2, + MemOperand(a1, 7, loadstore_chunk, MemOperand::offset_minus_one)); + __ lwr(t3, + MemOperand(a1, 8, loadstore_chunk, MemOperand::offset_minus_one)); + } __ addiu(a1, a1, 8 * loadstore_chunk); __ sw(a4, MemOperand(a0)); __ sw(a5, MemOperand(a0, 1, loadstore_chunk)); @@ -465,9 +565,15 @@ MemCopyUint8Function CreateMemCopyUint8Function(MemCopyUint8Function stub) { __ addu(a3, a0, a3); __ bind(&ua_wordCopy_loop); - __ lwr(v1, MemOperand(a1)); - __ lwl(v1, - MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one)); + if (kArchEndian == kLittle) { + __ lwr(v1, MemOperand(a1)); + __ lwl(v1, + MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one)); + } else { + __ lwl(v1, MemOperand(a1)); + __ lwr(v1, + MemOperand(a1, 1, loadstore_chunk, MemOperand::offset_minus_one)); + } __ addiu(a0, a0, loadstore_chunk); __ addiu(a1, a1, loadstore_chunk); __ bne(a0, a3, &ua_wordCopy_loop); @@ -696,7 +802,7 @@ void ElementsTransitionGenerator::GenerateSmiToDouble( // Convert and copy elements. __ bind(&loop); __ ld(scratch2, MemOperand(scratch1)); - __ Daddu(scratch1, scratch1, kIntSize); + __ Daddu(scratch1, scratch1, kPointerSize); // scratch2: current element __ JumpIfNotSmi(scratch2, &convert_hole); __ SmiUntag(scratch2); @@ -717,9 +823,9 @@ void ElementsTransitionGenerator::GenerateSmiToDouble( __ Assert(eq, kObjectFoundInSmiOnlyArray, at, Operand(scratch2)); } // mantissa - __ sw(hole_lower, MemOperand(scratch3)); + __ sw(hole_lower, MemOperand(scratch3, Register::kMantissaOffset)); // exponent - __ sw(hole_upper, MemOperand(scratch3, kIntSize)); + __ sw(hole_upper, MemOperand(scratch3, Register::kExponentOffset)); __ Daddu(scratch3, scratch3, kDoubleSize); __ bind(&entry); @@ -786,7 +892,7 @@ void ElementsTransitionGenerator::GenerateDoubleToObject( Register dst_end = length; Register heap_number_map = scratch; __ Daddu(src_elements, src_elements, - Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag + 4)); + Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag)); __ Daddu(dst_elements, array, Operand(FixedArray::kHeaderSize)); __ SmiScale(dst_end, dst_end, kPointerSizeLog2); __ Daddu(dst_end, dst_elements, dst_end); @@ -824,10 +930,10 @@ void ElementsTransitionGenerator::GenerateDoubleToObject( __ bind(&loop); Register upper_bits = key; - __ lw(upper_bits, MemOperand(src_elements)); + __ lw(upper_bits, MemOperand(src_elements, Register::kExponentOffset)); __ Daddu(src_elements, src_elements, kDoubleSize); // upper_bits: current element's upper 32 bit - // src_elements: address of next element's upper 32 bit + // src_elements: address of next element __ Branch(&convert_hole, eq, a1, Operand(kHoleNanUpper32)); // Non-hole double, copy value into a heap number. @@ -837,11 +943,11 @@ void ElementsTransitionGenerator::GenerateDoubleToObject( __ AllocateHeapNumber(heap_number, scratch2, scratch3, heap_number_map, &gc_required); // heap_number: new heap number - // Load mantissa of current element, src_elements - // point to exponent of next element. - __ lw(scratch2, MemOperand(heap_number, -12)); - __ sw(scratch2, FieldMemOperand(heap_number, HeapNumber::kMantissaOffset)); - __ sw(upper_bits, FieldMemOperand(heap_number, HeapNumber::kExponentOffset)); + // Load current element, src_elements point to next element. + + __ ld(scratch2, MemOperand(src_elements, -kDoubleSize)); + __ sd(scratch2, FieldMemOperand(heap_number, HeapNumber::kValueOffset)); + __ mov(scratch2, dst_elements); __ sd(heap_number, MemOperand(dst_elements)); __ Daddu(dst_elements, dst_elements, kPointerSize); @@ -1045,8 +1151,8 @@ void MathExpGenerator::EmitMathExp(MacroAssembler* masm, __ li(temp3, Operand(ExternalReference::math_exp_log_table())); __ dsll(at, temp2, 3); __ Daddu(temp3, temp3, Operand(at)); - __ lwu(temp2, MemOperand(temp3, 0)); - __ lwu(temp3, MemOperand(temp3, kIntSize)); + __ lwu(temp2, MemOperand(temp3, Register::kMantissaOffset)); + __ lwu(temp3, MemOperand(temp3, Register::kExponentOffset)); // The first word is loaded is the lower number register. if (temp2.code() < temp3.code()) { __ dsll(at, temp1, 20); diff --git a/src/mips64/constants-mips64.h b/src/mips64/constants-mips64.h index 51e665f..f23f103 100644 --- a/src/mips64/constants-mips64.h +++ b/src/mips64/constants-mips64.h @@ -35,6 +35,16 @@ enum ArchVariants { #endif + enum Endianness { kLittle, kBig }; + +#if defined(V8_TARGET_LITTLE_ENDIAN) + static const Endianness kArchEndian = kLittle; +#elif defined(V8_TARGET_BIG_ENDIAN) + static const Endianness kArchEndian = kBig; +#else +#error Unknown endianness +#endif + // TODO(plind): consider deriving ABI from compiler flags or build system. // ABI-dependent definitions are made with #define in simulator-mips64.h, diff --git a/src/mips64/lithium-codegen-mips64.cc b/src/mips64/lithium-codegen-mips64.cc index 014847e..a26d099 100644 --- a/src/mips64/lithium-codegen-mips64.cc +++ b/src/mips64/lithium-codegen-mips64.cc @@ -2981,7 +2981,7 @@ void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { // Read int value directly from upper half of the smi. STATIC_ASSERT(kSmiTag == 0); STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32); - offset += kPointerSize / 2; + offset = SmiWordOffset(offset); representation = Representation::Integer32(); } __ Load(result, FieldMemOperand(object, offset), representation); @@ -3255,7 +3255,7 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { // Read int value directly from upper half of the smi. STATIC_ASSERT(kSmiTag == 0); STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32); - offset += kPointerSize / 2; + offset = SmiWordOffset(offset); } __ Load(result, MemOperand(store_base, offset), representation); @@ -4202,7 +4202,7 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { __ AssertSmi(scratch2); } // Store int value directly to upper half of the smi. - offset += kPointerSize / 2; + offset = SmiWordOffset(offset); representation = Representation::Integer32(); } MemOperand operand = FieldMemOperand(destination, offset); @@ -4468,7 +4468,7 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { // Store int value directly to upper half of the smi. STATIC_ASSERT(kSmiTag == 0); STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32); - offset += kPointerSize / 2; + offset = SmiWordOffset(offset); representation = Representation::Integer32(); } diff --git a/src/mips64/macro-assembler-mips64.cc b/src/mips64/macro-assembler-mips64.cc index 1a2829d..26229c9 100644 --- a/src/mips64/macro-assembler-mips64.cc +++ b/src/mips64/macro-assembler-mips64.cc @@ -1209,7 +1209,24 @@ void MacroAssembler::Uld(Register rd, const MemOperand& rs, Register scratch) { // Assert fail if the offset from start of object IS actually aligned. // ONLY use with known misalignment, since there is performance cost. DCHECK((rs.offset() + kHeapObjectTag) & (kPointerSize - 1)); - // TODO(plind): endian dependency. + if (kArchEndian == kLittle) { + lwu(rd, rs); + lw(scratch, MemOperand(rs.rm(), rs.offset() + kPointerSize / 2)); + dsll32(scratch, scratch, 0); + } else { + lw(rd, rs); + lwu(scratch, MemOperand(rs.rm(), rs.offset() + kPointerSize / 2)); + dsll32(rd, rd, 0); + } + Daddu(rd, rd, scratch); +} + + +// Load consequent 32-bit word pair in 64-bit reg. and put first word in low +// bits, +// second word in high bits. +void MacroAssembler::LoadWordPair(Register rd, const MemOperand& rs, + Register scratch) { lwu(rd, rs); lw(scratch, MemOperand(rs.rm(), rs.offset() + kPointerSize / 2)); dsll32(scratch, scratch, 0); @@ -1223,7 +1240,21 @@ void MacroAssembler::Usd(Register rd, const MemOperand& rs, Register scratch) { // Assert fail if the offset from start of object IS actually aligned. // ONLY use with known misalignment, since there is performance cost. DCHECK((rs.offset() + kHeapObjectTag) & (kPointerSize - 1)); - // TODO(plind): endian dependency. + if (kArchEndian == kLittle) { + sw(rd, rs); + dsrl32(scratch, rd, 0); + sw(scratch, MemOperand(rs.rm(), rs.offset() + kPointerSize / 2)); + } else { + sw(rd, MemOperand(rs.rm(), rs.offset() + kPointerSize / 2)); + dsrl32(scratch, rd, 0); + sw(scratch, rs); + } +} + + +// Do 64-bit store as two consequent 32-bit stores to unaligned address. +void MacroAssembler::StoreWordPair(Register rd, const MemOperand& rs, + Register scratch) { sw(rd, rs); dsrl32(scratch, rd, 0); sw(scratch, MemOperand(rs.rm(), rs.offset() + kPointerSize / 2)); @@ -3774,21 +3805,39 @@ void MacroAssembler::CopyBytes(Register src, // TODO(kalmard) check if this can be optimized to use sw in most cases. // Can't use unaligned access - copy byte by byte. - sb(scratch, MemOperand(dst, 0)); - dsrl(scratch, scratch, 8); - sb(scratch, MemOperand(dst, 1)); - dsrl(scratch, scratch, 8); - sb(scratch, MemOperand(dst, 2)); - dsrl(scratch, scratch, 8); - sb(scratch, MemOperand(dst, 3)); - dsrl(scratch, scratch, 8); - sb(scratch, MemOperand(dst, 4)); - dsrl(scratch, scratch, 8); - sb(scratch, MemOperand(dst, 5)); - dsrl(scratch, scratch, 8); - sb(scratch, MemOperand(dst, 6)); - dsrl(scratch, scratch, 8); - sb(scratch, MemOperand(dst, 7)); + if (kArchEndian == kLittle) { + sb(scratch, MemOperand(dst, 0)); + dsrl(scratch, scratch, 8); + sb(scratch, MemOperand(dst, 1)); + dsrl(scratch, scratch, 8); + sb(scratch, MemOperand(dst, 2)); + dsrl(scratch, scratch, 8); + sb(scratch, MemOperand(dst, 3)); + dsrl(scratch, scratch, 8); + sb(scratch, MemOperand(dst, 4)); + dsrl(scratch, scratch, 8); + sb(scratch, MemOperand(dst, 5)); + dsrl(scratch, scratch, 8); + sb(scratch, MemOperand(dst, 6)); + dsrl(scratch, scratch, 8); + sb(scratch, MemOperand(dst, 7)); + } else { + sb(scratch, MemOperand(dst, 7)); + dsrl(scratch, scratch, 8); + sb(scratch, MemOperand(dst, 6)); + dsrl(scratch, scratch, 8); + sb(scratch, MemOperand(dst, 5)); + dsrl(scratch, scratch, 8); + sb(scratch, MemOperand(dst, 4)); + dsrl(scratch, scratch, 8); + sb(scratch, MemOperand(dst, 3)); + dsrl(scratch, scratch, 8); + sb(scratch, MemOperand(dst, 2)); + dsrl(scratch, scratch, 8); + sb(scratch, MemOperand(dst, 1)); + dsrl(scratch, scratch, 8); + sb(scratch, MemOperand(dst, 0)); + } Daddu(dst, dst, 8); Dsubu(length, length, Operand(kPointerSize)); @@ -3986,7 +4035,11 @@ void MacroAssembler::LoadWeakValue(Register value, Handle cell, void MacroAssembler::MovFromFloatResult(const DoubleRegister dst) { if (IsMipsSoftFloatABI) { - Move(dst, v0, v1); + if (kArchEndian == kLittle) { + Move(dst, v0, v1); + } else { + Move(dst, v1, v0); + } } else { Move(dst, f0); // Reg f0 is o32 ABI FP return value. } @@ -3995,9 +4048,13 @@ void MacroAssembler::MovFromFloatResult(const DoubleRegister dst) { void MacroAssembler::MovFromFloatParameter(const DoubleRegister dst) { if (IsMipsSoftFloatABI) { - Move(dst, a0, a1); + if (kArchEndian == kLittle) { + Move(dst, a0, a1); + } else { + Move(dst, a1, a0); + } } else { - Move(dst, f12); // Reg f12 is o32 ABI FP first argument value. + Move(dst, f12); // Reg f12 is n64 ABI FP first argument value. } } @@ -4006,7 +4063,11 @@ void MacroAssembler::MovToFloatParameter(DoubleRegister src) { if (!IsMipsSoftFloatABI) { Move(f12, src); } else { - Move(a0, a1, src); + if (kArchEndian == kLittle) { + Move(a0, a1, src); + } else { + Move(a1, a0, src); + } } } @@ -4015,7 +4076,11 @@ void MacroAssembler::MovToFloatResult(DoubleRegister src) { if (!IsMipsSoftFloatABI) { Move(f0, src); } else { - Move(v0, v1, src); + if (kArchEndian == kLittle) { + Move(v0, v1, src); + } else { + Move(v1, v0, src); + } } } @@ -4033,8 +4098,13 @@ void MacroAssembler::MovToFloatParameters(DoubleRegister src1, Move(fparg2, src2); } } else { - Move(a0, a1, src1); - Move(a2, a3, src2); + if (kArchEndian == kLittle) { + Move(a0, a1, src1); + Move(a2, a3, src2); + } else { + Move(a1, a0, src1); + Move(a3, a2, src2); + } } } @@ -5121,7 +5191,7 @@ void MacroAssembler::InitializeNewString(Register string, sd(scratch1, FieldMemOperand(string, String::kLengthOffset)); li(scratch1, Operand(String::kEmptyHashField)); sd(scratch2, FieldMemOperand(string, HeapObject::kMapOffset)); - sd(scratch1, FieldMemOperand(string, String::kHashFieldOffset)); + sw(scratch1, FieldMemOperand(string, String::kHashFieldOffset)); } @@ -5650,8 +5720,8 @@ void MacroAssembler::HasColor(Register object, GetMarkBits(object, bitmap_scratch, mask_scratch); Label other_color; - // Note that we are using a 4-byte aligned 8-byte load. - Uld(t9, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); + // Note that we are using two 4-byte aligned loads. + LoadWordPair(t9, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); And(t8, t9, Operand(mask_scratch)); Branch(&other_color, first_bit == 1 ? eq : ne, t8, Operand(zero_reg)); // Shift left 1 by adding. @@ -5724,7 +5794,8 @@ void MacroAssembler::EnsureNotWhite( // Since both black and grey have a 1 in the first position and white does // not have a 1 there we only need to check one bit. // Note that we are using a 4-byte aligned 8-byte load. - Uld(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); + LoadWordPair(load_scratch, + MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); And(t8, mask_scratch, load_scratch); Branch(&done, ne, t8, Operand(zero_reg)); @@ -5803,14 +5874,14 @@ void MacroAssembler::EnsureNotWhite( bind(&is_data_object); // Value is a data object, and it is white. Mark it black. Since we know // that the object is white we can make it black by flipping one bit. - Uld(t8, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); + LoadWordPair(t8, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); Or(t8, t8, Operand(mask_scratch)); - Usd(t8, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); + StoreWordPair(t8, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); And(bitmap_scratch, bitmap_scratch, Operand(~Page::kPageAlignmentMask)); - Uld(t8, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset)); + LoadWordPair(t8, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset)); Daddu(t8, t8, Operand(length)); - Usd(t8, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset)); + StoreWordPair(t8, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset)); bind(&done); } @@ -5823,14 +5894,14 @@ void MacroAssembler::LoadInstanceDescriptors(Register map, void MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) { - ld(dst, FieldMemOperand(map, Map::kBitField3Offset)); + lwu(dst, FieldMemOperand(map, Map::kBitField3Offset)); DecodeField(dst); } void MacroAssembler::EnumLength(Register dst, Register map) { STATIC_ASSERT(Map::EnumLengthBits::kShift == 0); - ld(dst, FieldMemOperand(map, Map::kBitField3Offset)); + lwu(dst, FieldMemOperand(map, Map::kBitField3Offset)); And(dst, dst, Operand(Map::EnumLengthBits::kMask)); SmiTag(dst); } diff --git a/src/mips64/macro-assembler-mips64.h b/src/mips64/macro-assembler-mips64.h index 2de0ad2..5dfee07 100644 --- a/src/mips64/macro-assembler-mips64.h +++ b/src/mips64/macro-assembler-mips64.h @@ -116,6 +116,13 @@ bool AreAliased(Register reg1, // ----------------------------------------------------------------------------- // Static helper functions. +#if defined(V8_TARGET_LITTLE_ENDIAN) +#define SmiWordOffset(offset) (offset + kPointerSize / 2) +#else +#define SmiWordOffset(offset) offset +#endif + + inline MemOperand ContextOperand(Register context, int index) { return MemOperand(context, Context::SlotOffset(index)); } @@ -133,9 +140,9 @@ inline MemOperand FieldMemOperand(Register object, int offset) { inline MemOperand UntagSmiMemOperand(Register rm, int offset) { - // Assumes that Smis are shifted by 32 bits and little endianness. + // Assumes that Smis are shifted by 32 bits. STATIC_ASSERT(kSmiShift == 32); - return MemOperand(rm, offset + (kSmiShift / kBitsPerByte)); + return MemOperand(rm, SmiWordOffset(offset)); } @@ -682,6 +689,9 @@ class MacroAssembler: public Assembler { void Uld(Register rd, const MemOperand& rs, Register scratch = at); void Usd(Register rd, const MemOperand& rs, Register scratch = at); + void LoadWordPair(Register rd, const MemOperand& rs, Register scratch = at); + void StoreWordPair(Register rd, const MemOperand& rs, Register scratch = at); + // Load int32 in the rd register. void li(Register rd, Operand j, LiFlags mode = OPTIMIZE_SIZE); inline void li(Register rd, int64_t j, LiFlags mode = OPTIMIZE_SIZE) { diff --git a/src/mips64/simulator-mips64.cc b/src/mips64/simulator-mips64.cc index 00db0c8..b82b2d9 100644 --- a/src/mips64/simulator-mips64.cc +++ b/src/mips64/simulator-mips64.cc @@ -1052,18 +1052,26 @@ void Simulator::set_fpu_register(int fpureg, int64_t value) { void Simulator::set_fpu_register_word(int fpureg, int32_t value) { // Set ONLY lower 32-bits, leaving upper bits untouched. - // TODO(plind): big endian issue. DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); - int32_t *pword = reinterpret_cast(&FPUregisters_[fpureg]); + int32_t* pword; + if (kArchEndian == kLittle) { + pword = reinterpret_cast(&FPUregisters_[fpureg]); + } else { + pword = reinterpret_cast(&FPUregisters_[fpureg]) + 1; + } *pword = value; } void Simulator::set_fpu_register_hi_word(int fpureg, int32_t value) { // Set ONLY upper 32-bits, leaving lower bits untouched. - // TODO(plind): big endian issue. DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); - int32_t *phiword = (reinterpret_cast(&FPUregisters_[fpureg])) + 1; + int32_t* phiword; + if (kArchEndian == kLittle) { + phiword = (reinterpret_cast(&FPUregisters_[fpureg])) + 1; + } else { + phiword = reinterpret_cast(&FPUregisters_[fpureg]); + } *phiword = value; } diff --git a/src/mips64/simulator-mips64.h b/src/mips64/simulator-mips64.h index 75d4935..e45cbd4 100644 --- a/src/mips64/simulator-mips64.h +++ b/src/mips64/simulator-mips64.h @@ -493,9 +493,10 @@ class Simulator { #ifdef MIPS_ABI_N64 #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7, p8) \ - static_cast( \ - Simulator::current(Isolate::Current()) \ - ->Call(entry, 10, p0, p1, p2, p3, p4, p5, p6, p7, NULL, p8)) + static_cast(Simulator::current(Isolate::Current()) \ + ->Call(entry, 10, p0, p1, p2, p3, p4, \ + reinterpret_cast(p5), p6, p7, NULL, \ + p8)) #else // Must be O32 Abi. #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7, p8) \ static_cast( \ diff --git a/src/regexp/mips64/regexp-macro-assembler-mips64.cc b/src/regexp/mips64/regexp-macro-assembler-mips64.cc index 838fc68..869cbc4 100644 --- a/src/regexp/mips64/regexp-macro-assembler-mips64.cc +++ b/src/regexp/mips64/regexp-macro-assembler-mips64.cc @@ -219,7 +219,7 @@ void RegExpMacroAssemblerMIPS::CheckCharacterGT(uc16 limit, Label* on_greater) { void RegExpMacroAssemblerMIPS::CheckAtStart(Label* on_at_start) { Label not_at_start; // Did we start the match at the start of the string at all? - __ lw(a0, MemOperand(frame_pointer(), kStartIndex)); + __ ld(a0, MemOperand(frame_pointer(), kStartIndex)); BranchOrBacktrack(¬_at_start, ne, a0, Operand(zero_reg)); // If we did, are we still at the start of the input? @@ -232,7 +232,7 @@ void RegExpMacroAssemblerMIPS::CheckAtStart(Label* on_at_start) { void RegExpMacroAssemblerMIPS::CheckNotAtStart(Label* on_not_at_start) { // Did we start the match at the start of the string at all? - __ lw(a0, MemOperand(frame_pointer(), kStartIndex)); + __ ld(a0, MemOperand(frame_pointer(), kStartIndex)); BranchOrBacktrack(on_not_at_start, ne, a0, Operand(zero_reg)); // If we did, are we still at the start of the input? __ ld(a1, MemOperand(frame_pointer(), kInputStart)); @@ -779,7 +779,7 @@ Handle RegExpMacroAssemblerMIPS::GetCode(Handle source) { if (global()) { // Restart matching if the regular expression is flagged as global. __ ld(a0, MemOperand(frame_pointer(), kSuccessfulCaptures)); - __ lw(a1, MemOperand(frame_pointer(), kNumOutputRegisters)); + __ ld(a1, MemOperand(frame_pointer(), kNumOutputRegisters)); __ ld(a2, MemOperand(frame_pointer(), kRegisterOutput)); // Increment success counter. __ Daddu(a0, a0, 1); @@ -1155,8 +1155,8 @@ int64_t RegExpMacroAssemblerMIPS::CheckStackGuardState(Address* return_address, Address re_frame) { return NativeRegExpMacroAssembler::CheckStackGuardState( frame_entry(re_frame, kIsolate), - frame_entry(re_frame, kStartIndex), - frame_entry(re_frame, kDirectCall) == 1, return_address, re_code, + static_cast(frame_entry(re_frame, kStartIndex)), + frame_entry(re_frame, kDirectCall) == 1, return_address, re_code, frame_entry_address(re_frame, kInputString), frame_entry_address(re_frame, kInputStart), frame_entry_address(re_frame, kInputEnd)); diff --git a/test/cctest/cctest.status b/test/cctest/cctest.status index 718a65a..eb67611 100644 --- a/test/cctest/cctest.status +++ b/test/cctest/cctest.status @@ -276,7 +276,7 @@ }], # 'arch == mips' ############################################################################## -['arch == mips64el', { +['arch == mips64el or arch == mips64', { 'test-cpu-profiler/CollectDeoptEvents': [PASS, FAIL], # BUG(v8:3154). @@ -287,7 +287,7 @@ 'test-serialize/DeserializeFromSecondSerializationAndRunScript2': [SKIP], 'test-serialize/DeserializeAndRunScript2': [SKIP], 'test-serialize/DeserializeFromSecondSerialization': [SKIP], -}], # 'arch == mips64el' +}], # 'arch == mips64el or arch == mips64' ############################################################################## ['arch == x87', { diff --git a/test/cctest/test-assembler-mips64.cc b/test/cctest/test-assembler-mips64.cc index 90e31d4..ee6755f 100644 --- a/test/cctest/test-assembler-mips64.cc +++ b/test/cctest/test-assembler-mips64.cc @@ -590,11 +590,19 @@ TEST(MIPS6) { USE(dummy); CHECK_EQ(static_cast(0x11223344), t.r1); - CHECK_EQ(static_cast(0x3344), t.r2); - CHECK_EQ(static_cast(0xffffbbcc), t.r3); - CHECK_EQ(static_cast(0x0000bbcc), t.r4); - CHECK_EQ(static_cast(0xffffffcc), t.r5); - CHECK_EQ(static_cast(0x3333bbcc), t.r6); + if (kArchEndian == kLittle) { + CHECK_EQ(static_cast(0x3344), t.r2); + CHECK_EQ(static_cast(0xffffbbcc), t.r3); + CHECK_EQ(static_cast(0x0000bbcc), t.r4); + CHECK_EQ(static_cast(0xffffffcc), t.r5); + CHECK_EQ(static_cast(0x3333bbcc), t.r6); + } else { + CHECK_EQ(static_cast(0x1122), t.r2); + CHECK_EQ(static_cast(0xffff99aa), t.r3); + CHECK_EQ(static_cast(0x000099aa), t.r4); + CHECK_EQ(static_cast(0xffffff99), t.r5); + CHECK_EQ(static_cast(0x99aa3333), t.r6); + } } @@ -1026,25 +1034,47 @@ TEST(MIPS11) { Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); USE(dummy); - CHECK_EQ(static_cast(0x44bbccdd), t.lwl_0); - CHECK_EQ(static_cast(0x3344ccdd), t.lwl_1); - CHECK_EQ(static_cast(0x223344dd), t.lwl_2); - CHECK_EQ(static_cast(0x11223344), t.lwl_3); - - CHECK_EQ(static_cast(0x11223344), t.lwr_0); - CHECK_EQ(static_cast(0xaa112233), t.lwr_1); - CHECK_EQ(static_cast(0xaabb1122), t.lwr_2); - CHECK_EQ(static_cast(0xaabbcc11), t.lwr_3); - - CHECK_EQ(static_cast(0x112233aa), t.swl_0); - CHECK_EQ(static_cast(0x1122aabb), t.swl_1); - CHECK_EQ(static_cast(0x11aabbcc), t.swl_2); - CHECK_EQ(static_cast(0xaabbccdd), t.swl_3); - - CHECK_EQ(static_cast(0xaabbccdd), t.swr_0); - CHECK_EQ(static_cast(0xbbccdd44), t.swr_1); - CHECK_EQ(static_cast(0xccdd3344), t.swr_2); - CHECK_EQ(static_cast(0xdd223344), t.swr_3); + if (kArchEndian == kLittle) { + CHECK_EQ(static_cast(0x44bbccdd), t.lwl_0); + CHECK_EQ(static_cast(0x3344ccdd), t.lwl_1); + CHECK_EQ(static_cast(0x223344dd), t.lwl_2); + CHECK_EQ(static_cast(0x11223344), t.lwl_3); + + CHECK_EQ(static_cast(0x11223344), t.lwr_0); + CHECK_EQ(static_cast(0xaa112233), t.lwr_1); + CHECK_EQ(static_cast(0xaabb1122), t.lwr_2); + CHECK_EQ(static_cast(0xaabbcc11), t.lwr_3); + + CHECK_EQ(static_cast(0x112233aa), t.swl_0); + CHECK_EQ(static_cast(0x1122aabb), t.swl_1); + CHECK_EQ(static_cast(0x11aabbcc), t.swl_2); + CHECK_EQ(static_cast(0xaabbccdd), t.swl_3); + + CHECK_EQ(static_cast(0xaabbccdd), t.swr_0); + CHECK_EQ(static_cast(0xbbccdd44), t.swr_1); + CHECK_EQ(static_cast(0xccdd3344), t.swr_2); + CHECK_EQ(static_cast(0xdd223344), t.swr_3); + } else { + CHECK_EQ(static_cast(0x11223344), t.lwl_0); + CHECK_EQ(static_cast(0x223344dd), t.lwl_1); + CHECK_EQ(static_cast(0x3344ccdd), t.lwl_2); + CHECK_EQ(static_cast(0x44bbccdd), t.lwl_3); + + CHECK_EQ(static_cast(0xaabbcc11), t.lwr_0); + CHECK_EQ(static_cast(0xaabb1122), t.lwr_1); + CHECK_EQ(static_cast(0xaa112233), t.lwr_2); + CHECK_EQ(static_cast(0x11223344), t.lwr_3); + + CHECK_EQ(static_cast(0xaabbccdd), t.swl_0); + CHECK_EQ(static_cast(0x11aabbcc), t.swl_1); + CHECK_EQ(static_cast(0x1122aabb), t.swl_2); + CHECK_EQ(static_cast(0x112233aa), t.swl_3); + + CHECK_EQ(static_cast(0xdd223344), t.swr_0); + CHECK_EQ(static_cast(0xccdd3344), t.swr_1); + CHECK_EQ(static_cast(0xbbccdd44), t.swr_2); + CHECK_EQ(static_cast(0xaabbccdd), t.swr_3); + } } } diff --git a/test/mjsunit/mjsunit.status b/test/mjsunit/mjsunit.status index 2a616b0..f549718 100644 --- a/test/mjsunit/mjsunit.status +++ b/test/mjsunit/mjsunit.status @@ -184,8 +184,8 @@ 'array-constructor': [PASS, TIMEOUT], # Very slow on ARM and MIPS, contains no architecture dependent code. - 'unicode-case-overoptimization': [PASS, NO_VARIANTS, ['arch == arm or arch == arm64 or arch == android_arm or arch == android_arm64 or arch == mipsel or arch == mips64el or arch == mips', TIMEOUT]], - 'regress/regress-3976': [PASS, NO_VARIANTS, ['arch == arm or arch == arm64 or arch == android_arm or arch == android_arm64 or arch == mipsel or arch == mips64el or arch == mips', SKIP]], + 'unicode-case-overoptimization': [PASS, NO_VARIANTS, ['arch == arm or arch == arm64 or arch == android_arm or arch == android_arm64 or arch == mipsel or arch == mips64el or arch == mips64 or arch == mips', TIMEOUT]], + 'regress/regress-3976': [PASS, NO_VARIANTS, ['arch == arm or arch == arm64 or arch == android_arm or arch == android_arm64 or arch == mipsel or arch == mips64el or arch == mips64 or arch == mips', SKIP]], 'regress/regress-crbug-482998': [PASS, NO_VARIANTS, ['arch == arm or arch == arm64 or arch == android_arm or arch == android_arm64 or arch == mipsel or arch == mips64el or arch == mips', SKIP]], ############################################################################## @@ -543,7 +543,7 @@ }], # 'arch == mips' ############################################################################## -['arch == mips64el', { +['arch == mips64el or arch == mips64', { # Slow tests which times out in debug mode. 'try': [PASS, ['mode == debug', SKIP]], @@ -591,7 +591,7 @@ # Currently always deopt on minus zero 'math-floor-of-div-minus-zero': [SKIP], -}], # 'arch == mips64el' +}], # 'arch == mips64el or arch == mips64' ############################################################################## ['system == windows', { diff --git a/test/mozilla/mozilla.status b/test/mozilla/mozilla.status index 70bbd36..d70c922 100644 --- a/test/mozilla/mozilla.status +++ b/test/mozilla/mozilla.status @@ -887,7 +887,7 @@ }], # 'arch == arm64' -['arch == mipsel or arch == mips64el', { +['arch == mipsel or arch == mips64el or arch == mips64', { # BUG(3251229): Times out when running new crankshaft test script. 'ecma_3/RegExp/regress-311414': [SKIP], @@ -904,7 +904,7 @@ # BUG(1040): Allow this test to timeout. 'js1_5/GC/regress-203278-2': [PASS, TIMEOUT, NO_VARIANTS], -}], # 'arch == mipsel or arch == mips64el' +}], # 'arch == mipsel or arch == mips64el or arch == mips64' ['arch == mipsel and simulator_run == True', { # Crashes due to C stack overflow. diff --git a/test/test262/test262.status b/test/test262/test262.status index 1e8bf5e..802a7d8 100644 --- a/test/test262/test262.status +++ b/test/test262/test262.status @@ -746,7 +746,7 @@ }], # no_i18n == True and mode == debug -['arch == arm or arch == mipsel or arch == mips or arch == arm64 or arch == mips64el', { +['arch == arm or arch == mipsel or arch == mips or arch == arm64 or arch == mips64 or arch == mips64el', { # TODO(mstarzinger): Causes stack overflow on simulators due to eager # compilation of parenthesized function literals. Needs investigation. diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp index 3412b68..bcb5801 100644 --- a/tools/gyp/v8.gyp +++ b/tools/gyp/v8.gyp @@ -1255,7 +1255,7 @@ '../../src/regexp/mips/regexp-macro-assembler-mips.h', ], }], - ['v8_target_arch=="mips64el"', { + ['v8_target_arch=="mips64" or v8_target_arch=="mips64el"', { 'sources': [ ### gcmole(arch:mips64el) ### '../../src/mips64/assembler-mips64.cc', '../../src/mips64/assembler-mips64.h', diff --git a/tools/run-tests.py b/tools/run-tests.py index c54c32d..f596c84 100755 --- a/tools/run-tests.py +++ b/tools/run-tests.py @@ -146,6 +146,7 @@ SUPPORTED_ARCHS = ["android_arm", "x87", "mips", "mipsel", + "mips64", "mips64el", "nacl_ia32", "nacl_x64", @@ -162,6 +163,7 @@ SLOW_ARCHS = ["android_arm", "arm", "mips", "mipsel", + "mips64", "mips64el", "nacl_ia32", "nacl_x64", @@ -591,7 +593,7 @@ def Execute(arch, mode, args, options, suites, workspace): # TODO(all): Combine "simulator" and "simulator_run". simulator_run = not options.dont_skip_simulator_slow_tests and \ - arch in ['arm64', 'arm', 'mipsel', 'mips', 'mips64el', \ + arch in ['arm64', 'arm', 'mipsel', 'mips', 'mips64', 'mips64el', \ 'ppc', 'ppc64'] and \ ARCH_GUESS and arch != ARCH_GUESS # Find available test suites and read test cases from them. diff --git a/tools/testrunner/local/statusfile.py b/tools/testrunner/local/statusfile.py index 62c959b..bfa53c5 100644 --- a/tools/testrunner/local/statusfile.py +++ b/tools/testrunner/local/statusfile.py @@ -56,7 +56,7 @@ DEFS = {FAIL_OK: [FAIL, OKAY], VARIABLES = {ALWAYS: True} for var in ["debug", "release", "big", "little", "android_arm", "android_arm64", "android_ia32", "android_x87", - "android_x64", "arm", "arm64", "ia32", "mips", "mipsel", + "android_x64", "arm", "arm64", "ia32", "mips", "mipsel", "mips64", "mips64el", "x64", "x87", "nacl_ia32", "nacl_x64", "ppc", "ppc64", "macos", "windows", "linux", "aix"]: VARIABLES[var] = var -- 2.7.4