Description: mips arch support backported to v8 3.14 branch
Origin: https://github.com/paul99/v8m-rb/tree/dm-mipsbe-3.14
Last-Update: 2014-04-09
Acked-by: Jérémy Lal <kapouer@melix.org>
--- a/Makefile
+++ b/Makefile
@@ -133,7 +133,7 @@
# Architectures and modes to be compiled. Consider these to be internal
# variables, don't override them (use the targets instead).
-ARCHES = ia32 x64 arm mipsel
+ARCHES = ia32 x64 arm mipsel mips
DEFAULT_ARCHES = ia32 x64 arm
MODES = release debug
ANDROID_ARCHES = android_ia32 android_arm
@@ -168,10 +168,6 @@
$(MAKE) -C "$(OUTDIR)" BUILDTYPE=$(BUILDTYPE) \
builddir="$(abspath $(OUTDIR))/$(BUILDTYPE)"
-mips mips.release mips.debug:
- @echo "V8 does not support big-endian MIPS builds at the moment," \
- "please use little-endian builds (mipsel)."
-
# Compile targets. MODES and ARCHES are convenience targets.
.SECONDEXPANSION:
$(MODES): $(addsuffix .$$@,$(DEFAULT_ARCHES))
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -176,7 +176,7 @@
'V8_TARGET_ARCH_IA32',
],
}], # v8_target_arch=="ia32"
- ['v8_target_arch=="mipsel"', {
+ ['v8_target_arch=="mipsel" or v8_target_arch=="mips"', {
'defines': [
'V8_TARGET_ARCH_MIPS',
],
@@ -187,12 +187,17 @@
['mipscompiler=="yes"', {
'target_conditions': [
['_toolset=="target"', {
- 'cflags': ['-EL'],
- 'ldflags': ['-EL'],
'conditions': [
+ ['v8_target_arch=="mipsel"', {
+ 'cflags': ['-EL'],
+ 'ldflags': ['-EL'],
+ }],
+ ['v8_target_arch=="mips"', {
+ 'cflags': ['-EB'],
+ 'ldflags': ['-EB'],
+ }],
[ 'v8_use_mips_abi_hardfloat=="true"', {
'cflags': ['-mhard-float'],
- 'ldflags': ['-mhard-float'],
}, {
'cflags': ['-msoft-float'],
'ldflags': ['-msoft-float'],
@@ -202,7 +207,8 @@
}],
['mips_arch_variant=="loongson"', {
'cflags': ['-mips3', '-Wa,-mips3'],
- }, {
+ }],
+ ['mips_arch_variant=="mips32r1"', {
'cflags': ['-mips32', '-Wa,-mips32'],
}],
],
@@ -290,7 +296,7 @@
['(OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris" \
or OS=="netbsd" or OS=="mac" or OS=="android") and \
(v8_target_arch=="arm" or v8_target_arch=="ia32" or \
- v8_target_arch=="mipsel")', {
+ v8_target_arch=="mipsel" or v8_target_arch=="mips")', {
# Check whether the host compiler and target compiler support the
# '-m32' option and set it if so.
'target_conditions': [
--- a/build/standalone.gypi
+++ b/build/standalone.gypi
@@ -68,6 +68,7 @@
'conditions': [
['(v8_target_arch=="arm" and host_arch!="arm") or \
(v8_target_arch=="mipsel" and host_arch!="mipsel") or \
+ (v8_target_arch=="mips" and host_arch!="mips") or \
(v8_target_arch=="x64" and host_arch!="x64") or \
(OS=="android")', {
'want_separate_host_toolset': 1,
--- a/src/conversions-inl.h
+++ b/src/conversions-inl.h
@@ -75,7 +75,11 @@
if (x < k2Pow52) {
x += k2Pow52;
uint32_t result;
+#ifndef BIG_ENDIAN_FLOATING_POINT
Address mantissa_ptr = reinterpret_cast<Address>(&x);
+#else
+ Address mantissa_ptr = reinterpret_cast<Address>(&x) + 4;
+#endif
// Copy least significant 32 bits of mantissa.
memcpy(&result, mantissa_ptr, sizeof(result));
return negative ? ~result + 1 : result;
--- a/src/globals.h
+++ b/src/globals.h
@@ -83,7 +83,7 @@
#if CAN_USE_UNALIGNED_ACCESSES
#define V8_HOST_CAN_READ_UNALIGNED 1
#endif
-#elif defined(__MIPSEL__)
+#elif defined(__MIPSEL__) || defined(__MIPSEB__)
#define V8_HOST_ARCH_MIPS 1
#define V8_HOST_ARCH_32_BIT 1
#else
@@ -101,13 +101,17 @@
#define V8_TARGET_ARCH_IA32 1
#elif defined(__ARMEL__)
#define V8_TARGET_ARCH_ARM 1
-#elif defined(__MIPSEL__)
+#elif defined(__MIPSEL__) || defined(__MIPSEB__)
#define V8_TARGET_ARCH_MIPS 1
#else
#error Target architecture was not detected as supported by v8
#endif
#endif
+#if defined(__MIPSEB__)
+#define BIG_ENDIAN_FLOATING_POINT 1
+#endif
+
// Check for supported combinations of host and target architectures.
#if defined(V8_TARGET_ARCH_IA32) && !defined(V8_HOST_ARCH_IA32)
#error Target architecture ia32 is only supported on ia32 host
--- a/src/mips/assembler-mips.cc
+++ b/src/mips/assembler-mips.cc
@@ -1631,10 +1631,17 @@
void Assembler::ldc1(FPURegister fd, const MemOperand& src) {
// Workaround for non-8-byte alignment of HeapNumber, convert 64-bit
// load to two 32-bit loads.
+#ifndef BIG_ENDIAN_FLOATING_POINT
GenInstrImmediate(LWC1, src.rm(), fd, src.offset_);
FPURegister nextfpreg;
nextfpreg.setcode(fd.code() + 1);
GenInstrImmediate(LWC1, src.rm(), nextfpreg, src.offset_ + 4);
+#else
+ GenInstrImmediate(LWC1, src.rm(), fd, src.offset_ + 4);
+ FPURegister nextfpreg;
+ nextfpreg.setcode(fd.code() + 1);
+ GenInstrImmediate(LWC1, src.rm(), nextfpreg, src.offset_);
+#endif
}
@@ -1646,10 +1653,17 @@
void Assembler::sdc1(FPURegister fd, const MemOperand& src) {
// Workaround for non-8-byte alignment of HeapNumber, convert 64-bit
// store to two 32-bit stores.
+#ifndef BIG_ENDIAN_FLOATING_POINT
GenInstrImmediate(SWC1, src.rm(), fd, src.offset_);
FPURegister nextfpreg;
nextfpreg.setcode(fd.code() + 1);
GenInstrImmediate(SWC1, src.rm(), nextfpreg, src.offset_ + 4);
+#else
+ GenInstrImmediate(SWC1, src.rm(), fd, src.offset_ + 4);
+ FPURegister nextfpreg;
+ nextfpreg.setcode(fd.code() + 1);
+ GenInstrImmediate(SWC1, src.rm(), nextfpreg, src.offset_ );
+#endif
}
--- a/src/mips/assembler-mips.h
+++ b/src/mips/assembler-mips.h
@@ -74,6 +74,13 @@
static const int kNumRegisters = v8::internal::kNumRegisters;
static const int kNumAllocatableRegisters = 14; // v0 through t7.
static const int kSizeInBytes = 4;
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ static const int kMantissaOffset = 0;
+ static const int kExponentOffset = 4;
+#else
+ static const int kMantissaOffset = 4;
+ static const int kExponentOffset = 0;
+#endif
static int ToAllocationIndex(Register reg) {
return reg.code() - 2; // zero_reg and 'at' are skipped.
--- a/src/mips/builtins-mips.cc
+++ b/src/mips/builtins-mips.cc
@@ -869,9 +869,7 @@
ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize);
__ LoadRoot(t7, Heap::kUndefinedValueRootIndex);
if (count_constructions) {
- __ lw(a0, FieldMemOperand(a2, Map::kInstanceSizesOffset));
- __ Ext(a0, a0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
- kBitsPerByte);
+ __ lbu(a0, FieldMemOperand(a2, Map::kPreAllocatedPropertyFieldsOffset));
__ sll(t0, a0, kPointerSizeLog2);
__ addu(a0, t5, t0);
// a0: offset of first field after pre-allocated fields
@@ -899,14 +897,12 @@
__ lbu(a3, FieldMemOperand(a2, Map::kUnusedPropertyFieldsOffset));
// The field instance sizes contains both pre-allocated property fields
// and in-object properties.
- __ lw(a0, FieldMemOperand(a2, Map::kInstanceSizesOffset));
- __ Ext(t6, a0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
- kBitsPerByte);
+ __ lbu(t6, FieldMemOperand(a2, Map::kPreAllocatedPropertyFieldsOffset));
__ Addu(a3, a3, Operand(t6));
- __ Ext(t6, a0, Map::kInObjectPropertiesByte * kBitsPerByte,
- kBitsPerByte);
+ __ lbu(t6, FieldMemOperand(a2, Map::kInObjectPropertiesOffset));
__ subu(a3, a3, t6);
+
// Done if no extra properties are to be allocated.
__ Branch(&allocated, eq, a3, Operand(zero_reg));
__ Assert(greater_equal, "Property allocation count failed.",
--- a/src/mips/code-stubs-mips.cc
+++ b/src/mips/code-stubs-mips.cc
@@ -536,13 +536,8 @@
void ConvertToDoubleStub::Generate(MacroAssembler* masm) {
-#ifndef BIG_ENDIAN_FLOATING_POINT
Register exponent = result1_;
Register mantissa = result2_;
-#else
- Register exponent = result2_;
- Register mantissa = result1_;
-#endif
Label not_special;
// Convert from Smi to integer.
__ sra(source_, source_, kSmiTagSize);
@@ -679,9 +674,8 @@
} else {
ASSERT(destination == kCoreRegisters);
// Load the double from heap number to dst1 and dst2 in double format.
- __ lw(dst1, FieldMemOperand(object, HeapNumber::kValueOffset));
- __ lw(dst2, FieldMemOperand(object,
- HeapNumber::kValueOffset + kPointerSize));
+ __ lw(dst1, FieldMemOperand(object, HeapNumber::kMantissaOffset));
+ __ lw(dst2, FieldMemOperand(object, HeapNumber::kExponentOffset));
}
__ Branch(&done);
@@ -1075,6 +1069,11 @@
// a0-a3 registers to f12/f14 register pairs.
__ Move(f12, a0, a1);
__ Move(f14, a2, a3);
+ } else {
+#ifdef BIG_ENDIAN_FLOATING_POINT
+ __ Swap(a0, a1);
+ __ Swap(a2, a3);
+#endif
}
{
AllowExternalCallThatCantCauseGC scope(masm);
@@ -1088,8 +1087,13 @@
__ sdc1(f0, FieldMemOperand(heap_number_result, HeapNumber::kValueOffset));
} else {
// Double returned in registers v0 and v1.
+#ifndef BIG_ENDIAN_FLOATING_POINT
__ sw(v1, FieldMemOperand(heap_number_result, HeapNumber::kExponentOffset));
__ sw(v0, FieldMemOperand(heap_number_result, HeapNumber::kMantissaOffset));
+#else
+ __ sw(v0, FieldMemOperand(heap_number_result, HeapNumber::kExponentOffset));
+ __ sw(v1, FieldMemOperand(heap_number_result, HeapNumber::kMantissaOffset));
+#endif
}
// Place heap_number_result in v0 and return to the pushed return address.
__ pop(ra);
@@ -1320,8 +1324,8 @@
__ ldc1(f12, FieldMemOperand(lhs, HeapNumber::kValueOffset));
} else {
// Load lhs to a double in a2, a3.
- __ lw(a3, FieldMemOperand(lhs, HeapNumber::kValueOffset + 4));
- __ lw(a2, FieldMemOperand(lhs, HeapNumber::kValueOffset));
+ __ lw(a3, FieldMemOperand(lhs, HeapNumber::kExponentOffset));
+ __ lw(a2, FieldMemOperand(lhs, HeapNumber::kMantissaOffset));
// Write Smi from rhs to a1 and a0 in double format. t5 is scratch.
__ mov(t6, rhs);
@@ -1366,11 +1370,11 @@
__ pop(ra);
// Load rhs to a double in a1, a0.
if (rhs.is(a0)) {
- __ lw(a1, FieldMemOperand(rhs, HeapNumber::kValueOffset + 4));
- __ lw(a0, FieldMemOperand(rhs, HeapNumber::kValueOffset));
+ __ lw(a1, FieldMemOperand(rhs, HeapNumber::kExponentOffset));
+ __ lw(a0, FieldMemOperand(rhs, HeapNumber::kMantissaOffset));
} else {
- __ lw(a0, FieldMemOperand(rhs, HeapNumber::kValueOffset));
- __ lw(a1, FieldMemOperand(rhs, HeapNumber::kValueOffset + 4));
+ __ lw(a0, FieldMemOperand(rhs, HeapNumber::kMantissaOffset));
+ __ lw(a1, FieldMemOperand(rhs, HeapNumber::kExponentOffset));
}
}
// Fall through to both_loaded_as_doubles.
@@ -1378,7 +1382,6 @@
void EmitNanCheck(MacroAssembler* masm, Condition cc) {
- bool exp_first = (HeapNumber::kExponentOffset == HeapNumber::kValueOffset);
if (CpuFeatures::IsSupported(FPU)) {
CpuFeatures::Scope scope(FPU);
// Lhs and rhs are already loaded to f12 and f14 register pairs.
@@ -1391,10 +1394,10 @@
__ mov(t2, a2); // a2 has LS 32 bits of lhs.
__ mov(t3, a3); // a3 has MS 32 bits of lhs.
}
- Register rhs_exponent = exp_first ? t0 : t1;
- Register lhs_exponent = exp_first ? t2 : t3;
- Register rhs_mantissa = exp_first ? t1 : t0;
- Register lhs_mantissa = exp_first ? t3 : t2;
+ Register rhs_exponent = t1;
+ Register lhs_exponent = t3;
+ Register rhs_mantissa = t0;
+ Register lhs_mantissa = t2;
Label one_is_nan, neither_is_nan;
Label lhs_not_nan_exp_mask_is_loaded;
@@ -1445,7 +1448,6 @@
if (cc == eq) {
// Doubles are not equal unless they have the same bit pattern.
// Exception: 0 and -0.
- bool exp_first = (HeapNumber::kExponentOffset == HeapNumber::kValueOffset);
if (CpuFeatures::IsSupported(FPU)) {
CpuFeatures::Scope scope(FPU);
// Lhs and rhs are already loaded to f12 and f14 register pairs.
@@ -1458,10 +1460,10 @@
__ mov(t2, a2); // a2 has LS 32 bits of lhs.
__ mov(t3, a3); // a3 has MS 32 bits of lhs.
}
- Register rhs_exponent = exp_first ? t0 : t1;
- Register lhs_exponent = exp_first ? t2 : t3;
- Register rhs_mantissa = exp_first ? t1 : t0;
- Register lhs_mantissa = exp_first ? t3 : t2;
+ Register rhs_exponent = t1;
+ Register lhs_exponent = t3;
+ Register rhs_mantissa = t0;
+ Register lhs_mantissa = t2;
__ xor_(v0, rhs_mantissa, lhs_mantissa);
__ Branch(&return_result_not_equal, ne, v0, Operand(zero_reg));
@@ -1495,6 +1497,11 @@
// a0-a3 registers to f12/f14 register pairs.
__ Move(f12, a0, a1);
__ Move(f14, a2, a3);
+ } else {
+#ifdef BIG_ENDIAN_FLOATING_POINT
+ __ Swap(a0, a1);
+ __ Swap(a2, a3);
+#endif
}
AllowExternalCallThatCantCauseGC scope(masm);
@@ -1582,14 +1589,14 @@
__ ldc1(f12, FieldMemOperand(lhs, HeapNumber::kValueOffset));
__ ldc1(f14, FieldMemOperand(rhs, HeapNumber::kValueOffset));
} else {
- __ lw(a2, FieldMemOperand(lhs, HeapNumber::kValueOffset));
- __ lw(a3, FieldMemOperand(lhs, HeapNumber::kValueOffset + 4));
+ __ lw(a2, FieldMemOperand(lhs, HeapNumber::kMantissaOffset));
+ __ lw(a3, FieldMemOperand(lhs, HeapNumber::kExponentOffset));
if (rhs.is(a0)) {
- __ lw(a1, FieldMemOperand(rhs, HeapNumber::kValueOffset + 4));
- __ lw(a0, FieldMemOperand(rhs, HeapNumber::kValueOffset));
+ __ lw(a1, FieldMemOperand(rhs, HeapNumber::kExponentOffset));
+ __ lw(a0, FieldMemOperand(rhs, HeapNumber::kMantissaOffset));
} else {
- __ lw(a0, FieldMemOperand(rhs, HeapNumber::kValueOffset));
- __ lw(a1, FieldMemOperand(rhs, HeapNumber::kValueOffset + 4));
+ __ lw(a0, FieldMemOperand(rhs, HeapNumber::kMantissaOffset));
+ __ lw(a1, FieldMemOperand(rhs, HeapNumber::kExponentOffset));
}
}
__ jmp(both_loaded_as_doubles);
@@ -5902,14 +5909,18 @@
__ Branch(&simple_loop, eq, scratch4, Operand(zero_reg));
// Loop for src/dst that are not aligned the same way.
- // This loop uses lwl and lwr instructions. These instructions
- // depend on the endianness, and the implementation assumes little-endian.
{
Label loop;
__ bind(&loop);
+#if __BYTE_ORDER == __BIG_ENDIAN
+ __ lwl(scratch1, MemOperand(src));
+ __ Addu(src, src, Operand(kReadAlignment));
+ __ lwr(scratch1, MemOperand(src, -1));
+#else
__ lwr(scratch1, MemOperand(src));
__ Addu(src, src, Operand(kReadAlignment));
__ lwl(scratch1, MemOperand(src, -1));
+#endif
__ sw(scratch1, MemOperand(dest));
__ Addu(dest, dest, Operand(kReadAlignment));
__ Subu(scratch2, limit, dest);
@@ -6616,6 +6627,11 @@
// in a little endian mode).
__ li(t2, Operand(2));
__ AllocateAsciiString(v0, t2, t0, t1, t5, &call_runtime);
+#if __BYTE_ORDER == __BIG_ENDIAN
+ __ sll(t0, a2, 8);
+ __ srl(t1, a2, 8);
+ __ or_(a2, t0, t1);
+#endif
__ sh(a2, FieldMemOperand(v0, SeqAsciiString::kHeaderSize));
__ IncrementCounter(counters->string_add_native(), 1, a2, a3);
__ DropAndRet(2);
--- a/src/mips/codegen-mips.cc
+++ b/src/mips/codegen-mips.cc
@@ -210,8 +210,8 @@
a1,
t7,
f0);
- __ sw(a0, MemOperand(t3)); // mantissa
- __ sw(a1, MemOperand(t3, kIntSize)); // exponent
+ __ sw(a0, MemOperand(t3, Register::kMantissaOffset)); // mantissa
+ __ sw(a1, MemOperand(t3, Register::kExponentOffset)); // exponent
__ Addu(t3, t3, kDoubleSize);
}
__ Branch(&entry);
@@ -225,8 +225,8 @@
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
__ Assert(eq, "object found in smi-only array", at, Operand(t5));
}
- __ sw(t0, MemOperand(t3)); // mantissa
- __ sw(t1, MemOperand(t3, kIntSize)); // exponent
+ __ sw(t0, MemOperand(t3, Register::kMantissaOffset)); // mantissa
+ __ sw(t1, MemOperand(t3, Register::kExponentOffset)); // exponent
__ Addu(t3, t3, kDoubleSize);
__ bind(&entry);
@@ -273,7 +273,7 @@
__ sw(t5, MemOperand(t2, HeapObject::kMapOffset));
// Prepare for conversion loop.
- __ Addu(t0, t0, Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag + 4));
+ __ Addu(t0, t0, Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag + Register::kExponentOffset));
__ Addu(a3, t2, Operand(FixedArray::kHeaderSize));
__ Addu(t2, t2, Operand(kHeapObjectTag));
__ sll(t1, t1, 1);
@@ -282,7 +282,7 @@
__ LoadRoot(t5, Heap::kHeapNumberMapRootIndex);
// Using offsetted addresses.
// a3: begin of destination FixedArray element fields, not tagged
- // t0: begin of source FixedDoubleArray element fields, not tagged, +4
+ // t0: begin of source FixedDoubleArray element fields, not tagged, points to the exponent
// t1: end of destination FixedArray, not tagged
// t2: destination FixedArray
// t3: the-hole pointer
@@ -296,7 +296,7 @@
__ Branch(fail);
__ bind(&loop);
- __ lw(a1, MemOperand(t0));
+ __ lw(a1, MemOperand(t0, 0)); // exponent
__ Addu(t0, t0, kDoubleSize);
// a1: current element's upper 32 bit
// t0: address of next element's upper 32 bit
@@ -305,7 +305,8 @@
// Non-hole double, copy value into a heap number.
__ AllocateHeapNumber(a2, a0, t6, t5, &gc_required);
// a2: new heap number
- __ lw(a0, MemOperand(t0, -12));
+ // Load mantissa of current element, t0 point to exponent of next element.
+ __ lw(a0, MemOperand(t0, (Register::kMantissaOffset - Register::kExponentOffset - kDoubleSize)));
__ sw(a0, FieldMemOperand(a2, HeapNumber::kMantissaOffset));
__ sw(a1, FieldMemOperand(a2, HeapNumber::kExponentOffset));
__ mov(a0, a3);
--- a/src/mips/constants-mips.h
+++ b/src/mips/constants-mips.h
@@ -69,6 +69,15 @@
#endif
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+const uint32_t kHoleNanUpper32Offset = 4;
+const uint32_t kHoleNanLower32Offset = 0;
+#else
+const uint32_t kHoleNanUpper32Offset = 0;
+const uint32_t kHoleNanLower32Offset = 4;
+#endif
+
+
// Defines constants and accessor classes to assemble, disassemble and
// simulate MIPS32 instructions.
//
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.cc
@@ -2699,7 +2699,7 @@
}
if (instr->hydrogen()->RequiresHoleCheck()) {
- __ lw(scratch, MemOperand(elements, sizeof(kHoleNanLower32)));
+ __ lw(scratch, MemOperand(elements, kHoleNanUpper32Offset));
DeoptimizeIf(eq, instr->environment(), scratch, Operand(kHoleNanUpper32));
}
@@ -4869,15 +4869,14 @@
Handle<FixedDoubleArray>::cast(elements);
for (int i = 0; i < elements_length; i++) {
int64_t value = double_array->get_representation(i);
- // We only support little endian mode...
int32_t value_low = static_cast<int32_t>(value & 0xFFFFFFFF);
int32_t value_high = static_cast<int32_t>(value >> 32);
int total_offset =
elements_offset + FixedDoubleArray::OffsetOfElementAt(i);
__ li(a2, Operand(value_low));
- __ sw(a2, FieldMemOperand(result, total_offset));
+ __ sw(a2, FieldMemOperand(result, total_offset + Register::kMantissaOffset));
__ li(a2, Operand(value_high));
- __ sw(a2, FieldMemOperand(result, total_offset + 4));
+ __ sw(a2, FieldMemOperand(result, total_offset + Register::kExponentOffset));
}
} else if (elements->IsFixedArray()) {
Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
--- a/src/mips/macro-assembler-mips.cc
+++ b/src/mips/macro-assembler-mips.cc
@@ -3300,6 +3300,7 @@
// TODO(kalmard) check if this can be optimized to use sw in most cases.
// Can't use unaligned access - copy byte by byte.
+#if __BYTE_ORDER == __LITTLE_ENDIAN
sb(scratch, MemOperand(dst, 0));
srl(scratch, scratch, 8);
sb(scratch, MemOperand(dst, 1));
@@ -3307,6 +3308,16 @@
sb(scratch, MemOperand(dst, 2));
srl(scratch, scratch, 8);
sb(scratch, MemOperand(dst, 3));
+#else
+ sb(scratch, MemOperand(dst, 3));
+ srl(scratch, scratch, 8);
+ sb(scratch, MemOperand(dst, 2));
+ srl(scratch, scratch, 8);
+ sb(scratch, MemOperand(dst, 1));
+ srl(scratch, scratch, 8);
+ sb(scratch, MemOperand(dst, 0));
+#endif
+
Addu(dst, dst, 4);
Subu(length, length, Operand(kPointerSize));
@@ -3412,9 +3423,8 @@
bind(&have_double_value);
sll(scratch1, key_reg, kDoubleSizeLog2 - kSmiTagSize);
Addu(scratch1, scratch1, elements_reg);
- sw(mantissa_reg, FieldMemOperand(scratch1, FixedDoubleArray::kHeaderSize));
- uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
- sw(exponent_reg, FieldMemOperand(scratch1, offset));
+ sw(mantissa_reg, FieldMemOperand(scratch1, FixedDoubleArray::kHeaderSize + kHoleNanLower32Offset));
+ sw(exponent_reg, FieldMemOperand(scratch1, FixedDoubleArray::kHeaderSize + kHoleNanUpper32Offset));
jmp(&done);
bind(&maybe_nan);
@@ -3459,8 +3469,8 @@
CpuFeatures::Scope scope(FPU);
sdc1(f0, MemOperand(scratch1, 0));
} else {
- sw(mantissa_reg, MemOperand(scratch1, 0));
- sw(exponent_reg, MemOperand(scratch1, Register::kSizeInBytes));
+ sw(mantissa_reg, MemOperand(scratch1, Register::kMantissaOffset));
+ sw(exponent_reg, MemOperand(scratch1, Register::kExponentOffset));
}
bind(&done);
}
--- a/src/mips/stub-cache-mips.cc
+++ b/src/mips/stub-cache-mips.cc
@@ -2195,7 +2195,7 @@
// Start checking for special cases.
// Get the argument exponent and clear the sign bit.
- __ lw(t1, FieldMemOperand(v0, HeapNumber::kValueOffset + kPointerSize));
+ __ lw(t1, FieldMemOperand(v0, HeapNumber::kExponentOffset));
__ And(t2, t1, Operand(~HeapNumber::kSignMask));
__ srl(t2, t2, HeapNumber::kMantissaBitsInTopWord);
@@ -3768,8 +3768,8 @@
__ ldc1(f0, MemOperand(t3, 0));
} else {
// t3: pointer to the beginning of the double we want to load.
- __ lw(a2, MemOperand(t3, 0));
- __ lw(a3, MemOperand(t3, Register::kSizeInBytes));
+ __ lw(a2, MemOperand(t3, Register::kMantissaOffset));
+ __ lw(a3, MemOperand(t3, Register::kExponentOffset));
}
break;
case FAST_ELEMENTS:
@@ -4132,8 +4132,8 @@
CpuFeatures::Scope scope(FPU);
__ sdc1(f0, MemOperand(a3, 0));
} else {
- __ sw(t2, MemOperand(a3, 0));
- __ sw(t3, MemOperand(a3, Register::kSizeInBytes));
+ __ sw(t2, MemOperand(a3, Register::kMantissaOffset));
+ __ sw(t3, MemOperand(a3, Register::kExponentOffset));
}
break;
case FAST_ELEMENTS:
@@ -4296,8 +4296,8 @@
__ sll(t8, key, 2);
__ addu(t8, a3, t8);
// t8: effective address of destination element.
- __ sw(t4, MemOperand(t8, 0));
- __ sw(t3, MemOperand(t8, Register::kSizeInBytes));
+ __ sw(t4, MemOperand(t8, Register::kMantissaOffset));
+ __ sw(t3, MemOperand(t8, Register::kExponentOffset));
__ mov(v0, a0);
__ Ret();
} else {
@@ -4497,11 +4497,11 @@
__ lw(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
__ Branch(&miss_force_generic, hs, key_reg, Operand(scratch));
- // Load the upper word of the double in the fixed array and test for NaN.
+ // Load the exponent in the fixed array and test for NaN.
__ sll(scratch2, key_reg, kDoubleSizeLog2 - kSmiTagSize);
__ Addu(indexed_double_offset, elements_reg, Operand(scratch2));
- uint32_t upper_32_offset = FixedArray::kHeaderSize + sizeof(kHoleNanLower32);
- __ lw(scratch, FieldMemOperand(indexed_double_offset, upper_32_offset));
+ __ lw(scratch, FieldMemOperand(indexed_double_offset,
+ FixedArray::kHeaderSize + kHoleNanUpper32Offset));
__ Branch(&miss_force_generic, eq, scratch, Operand(kHoleNanUpper32));
// Non-NaN. Allocate a new heap number and copy the double value into it.
@@ -4509,12 +4509,12 @@
__ AllocateHeapNumber(heap_number_reg, scratch2, scratch3,
heap_number_map, &slow_allocate_heapnumber);
- // Don't need to reload the upper 32 bits of the double, it's already in
+ // Don't need to reload the exponent (the upper 32 bits of the double), it's already in
// scratch.
__ sw(scratch, FieldMemOperand(heap_number_reg,
HeapNumber::kExponentOffset));
__ lw(scratch, FieldMemOperand(indexed_double_offset,
- FixedArray::kHeaderSize));
+ FixedArray::kHeaderSize + kHoleNanLower32Offset));
__ sw(scratch, FieldMemOperand(heap_number_reg,
HeapNumber::kMantissaOffset));
--- a/src/objects.h
+++ b/src/objects.h
@@ -1344,8 +1344,13 @@
// is a mixture of sign, exponent and mantissa. Our current platforms are all
// little endian apart from non-EABI arm which is little endian with big
// endian floating point word ordering!
+#ifndef BIG_ENDIAN_FLOATING_POINT
static const int kMantissaOffset = kValueOffset;
static const int kExponentOffset = kValueOffset + 4;
+#else
+ static const int kMantissaOffset = kValueOffset + 4;
+ static const int kExponentOffset = kValueOffset;
+#endif
static const int kSize = kValueOffset + kDoubleSize;
static const uint32_t kSignMask = 0x80000000u;
--- a/src/profile-generator.cc
+++ b/src/profile-generator.cc
@@ -1819,7 +1819,9 @@
Address field = obj->address() + offset;
ASSERT(!Memory::Object_at(field)->IsFailure());
ASSERT(Memory::Object_at(field)->IsHeapObject());
- *field |= kFailureTag;
+ Object* untagged = *reinterpret_cast<Object**>(field);
+ intptr_t tagged = reinterpret_cast<intptr_t>(untagged) | kFailureTag;
+ *reinterpret_cast<Object**>(field) = reinterpret_cast<Object*>(tagged);
}
private:
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -8553,8 +8553,15 @@
#else
typedef uint64_t ObjectPair;
static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
return reinterpret_cast<uint32_t>(x) |
(reinterpret_cast<ObjectPair>(y) << 32);
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ return reinterpret_cast<uint32_t>(y) |
+ (reinterpret_cast<ObjectPair>(x) << 32);
+#else
+#error Unknown endianess
+#endif
}
#endif
--- a/test/cctest/cctest.gyp
+++ b/test/cctest/cctest.gyp
@@ -118,7 +118,7 @@
'test-disasm-arm.cc'
],
}],
- ['v8_target_arch=="mipsel"', {
+ ['v8_target_arch=="mipsel" or v8_target_arch=="mips"', {
'sources': [
'test-assembler-mips.cc',
'test-disasm-mips.cc',
--- a/test/cctest/test-assembler-mips.cc
+++ b/test/cctest/test-assembler-mips.cc
@@ -537,11 +537,21 @@
USE(dummy);
CHECK_EQ(0x11223344, t.r1);
+#if __BYTE_ORDER == __LITTLE_ENDIAN
CHECK_EQ(0x3344, t.r2);
CHECK_EQ(0xffffbbcc, t.r3);
CHECK_EQ(0x0000bbcc, t.r4);
CHECK_EQ(0xffffffcc, t.r5);
CHECK_EQ(0x3333bbcc, t.r6);
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ CHECK_EQ(0x1122, t.r2);
+ CHECK_EQ(0xffff99aa, t.r3);
+ CHECK_EQ(0x000099aa, t.r4);
+ CHECK_EQ(0xffffff99, t.r5);
+ CHECK_EQ(0x99aa3333, t.r6);
+#else
+#error Unknown endianess
+#endif
}
@@ -955,6 +965,7 @@
Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
USE(dummy);
+#if __BYTE_ORDER == __LITTLE_ENDIAN
CHECK_EQ(0x44bbccdd, t.lwl_0);
CHECK_EQ(0x3344ccdd, t.lwl_1);
CHECK_EQ(0x223344dd, t.lwl_2);
@@ -974,6 +985,29 @@
CHECK_EQ(0xbbccdd44, t.swr_1);
CHECK_EQ(0xccdd3344, t.swr_2);
CHECK_EQ(0xdd223344, t.swr_3);
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ CHECK_EQ(0x11223344, t.lwl_0);
+ CHECK_EQ(0x223344dd, t.lwl_1);
+ CHECK_EQ(0x3344ccdd, t.lwl_2);
+ CHECK_EQ(0x44bbccdd, t.lwl_3);
+
+ CHECK_EQ(0xaabbcc11, t.lwr_0);
+ CHECK_EQ(0xaabb1122, t.lwr_1);
+ CHECK_EQ(0xaa112233, t.lwr_2);
+ CHECK_EQ(0x11223344, t.lwr_3);
+
+ CHECK_EQ(0xaabbccdd, t.swl_0);
+ CHECK_EQ(0x11aabbcc, t.swl_1);
+ CHECK_EQ(0x1122aabb, t.swl_2);
+ CHECK_EQ(0x112233aa, t.swl_3);
+
+ CHECK_EQ(0xdd223344, t.swr_0);
+ CHECK_EQ(0xccdd3344, t.swr_1);
+ CHECK_EQ(0xbbccdd44, t.swr_2);
+ CHECK_EQ(0xaabbccdd, t.swr_3);
+#else
+#error Unknown endianess
+#endif
}
--- a/test/mjsunit/mjsunit.status
+++ b/test/mjsunit/mjsunit.status
@@ -49,7 +49,7 @@
##############################################################################
# These use a built-in that's only present in debug mode. They take
# too long to run in debug mode on ARM and MIPS.
-fuzz-natives-part*: PASS, SKIP if ($mode == release || $arch == arm || $arch == android_arm || $arch == mipsel)
+fuzz-natives-part*: PASS, SKIP if ($mode == release || $arch == arm || $arch == android_arm || $arch == mipsel || $arch == mips)
big-object-literal: PASS, SKIP if ($arch == arm || $arch == android_arm)
@@ -57,7 +57,7 @@
array-constructor: PASS || TIMEOUT
# Very slow on ARM and MIPS, contains no architecture dependent code.
-unicode-case-overoptimization: PASS, TIMEOUT if ($arch == arm || $arch == android_arm || $arch == mipsel)
+unicode-case-overoptimization: PASS, TIMEOUT if ($arch == arm || $arch == android_arm || $arch == mipsel || $arch == mips)
##############################################################################
# This test sets the umask on a per-process basis and hence cannot be
@@ -127,7 +127,7 @@
math-floor-of-div-minus-zero: SKIP
##############################################################################
-[ $arch == mipsel ]
+[ $arch == mipsel || $arch == mips ]
# Slow tests which times out in debug mode.
try: PASS, SKIP if $mode == debug
--- a/test/mozilla/mozilla.status
+++ b/test/mozilla/mozilla.status
@@ -126,13 +126,13 @@
ecma/Date/15.9.2.2-6: PASS || FAIL
# 1026139: These date tests fail on arm and mips
-ecma/Date/15.9.5.29-1: PASS || FAIL if ($arch == arm || $arch == mipsel)
-ecma/Date/15.9.5.34-1: PASS || FAIL if ($arch == arm || $arch == mipsel)
-ecma/Date/15.9.5.28-1: PASS || FAIL if ($arch == arm || $arch == mipsel)
+ecma/Date/15.9.5.29-1: PASS || FAIL if ($arch == arm || $arch == mipsel || $arch == mips)
+ecma/Date/15.9.5.34-1: PASS || FAIL if ($arch == arm || $arch == mipsel || $arch == mips)
+ecma/Date/15.9.5.28-1: PASS || FAIL if ($arch == arm || $arch == mipsel || $arch == mips)
# 1050186: Arm/MIPS vm is broken; probably unrelated to dates
-ecma/Array/15.4.4.5-3: PASS || FAIL if ($arch == arm || $arch == mipsel)
-ecma/Date/15.9.5.22-2: PASS || FAIL if ($arch == arm || $arch == mipsel)
+ecma/Array/15.4.4.5-3: PASS || FAIL if ($arch == arm || $arch == mipsel || $arch == mips)
+ecma/Date/15.9.5.22-2: PASS || FAIL if ($arch == arm || $arch == mipsel || $arch == mips)
# Flaky test that fails due to what appears to be a bug in the test.
# Occurs depending on current time
@@ -854,6 +854,28 @@
# Times out and print so much output that we need to skip it to not
# hang the builder.
+js1_5/extensions/regress-342960: SKIP
+
+# BUG(3251229): Times out when running new crankshaft test script.
+ecma_3/RegExp/regress-311414: SKIP
+ecma/Date/15.9.5.8: SKIP
+ecma/Date/15.9.5.10-2: SKIP
+ecma/Date/15.9.5.11-2: SKIP
+ecma/Date/15.9.5.12-2: SKIP
+js1_5/Array/regress-99120-02: SKIP
+js1_5/extensions/regress-371636: SKIP
+js1_5/Regress/regress-203278-1: SKIP
+js1_5/Regress/regress-404755: SKIP
+js1_5/Regress/regress-451322: SKIP
+
+
+# BUG(1040): Allow this test to timeout.
+js1_5/GC/regress-203278-2: PASS || TIMEOUT
+
+[ $arch == mips ]
+
+# Times out and print so much output that we need to skip it to not
+# hang the builder.
js1_5/extensions/regress-342960: SKIP
# BUG(3251229): Times out when running new crankshaft test script.
--- a/test/sputnik/sputnik.status
+++ b/test/sputnik/sputnik.status
@@ -229,3 +229,17 @@
S15.1.3.4_A2.3_T1: SKIP
S15.1.3.1_A2.5_T1: SKIP
S15.1.3.2_A2.5_T1: SKIP
+
+[ $arch == mips ]
+
+# BUG(3251225): Tests that timeout with --nocrankshaft.
+S15.1.3.1_A2.5_T1: SKIP
+S15.1.3.2_A2.5_T1: SKIP
+S15.1.3.1_A2.4_T1: SKIP
+S15.1.3.1_A2.5_T1: SKIP
+S15.1.3.2_A2.4_T1: SKIP
+S15.1.3.2_A2.5_T1: SKIP
+S15.1.3.3_A2.3_T1: SKIP
+S15.1.3.4_A2.3_T1: SKIP
+S15.1.3.1_A2.5_T1: SKIP
+S15.1.3.2_A2.5_T1: SKIP
--- a/test/test262/test262.status
+++ b/test/test262/test262.status
@@ -74,7 +74,7 @@
S15.1.3.1_A2.5_T1: PASS, SKIP if $mode == debug
S15.1.3.2_A2.5_T1: PASS, SKIP if $mode == debug
-[ $arch == arm || $arch == mipsel ]
+[ $arch == arm || $arch == mipsel || $arch == mips ]
# TODO(mstarzinger): Causes stack overflow on simulators due to eager
# compilation of parenthesized function literals. Needs investigation.
--- a/tools/gyp/v8.gyp
+++ b/tools/gyp/v8.gyp
@@ -564,7 +564,7 @@
'../../src/ia32/stub-cache-ia32.cc',
],
}],
- ['v8_target_arch=="mipsel"', {
+ ['v8_target_arch=="mipsel" or v8_target_arch=="mips"', {
'sources': [
'../../src/mips/assembler-mips.cc',
'../../src/mips/assembler-mips.h',
--- a/tools/run-tests.py
+++ b/tools/run-tests.py
@@ -65,6 +65,7 @@
"arm",
"ia32",
"mipsel",
+ "mips",
"x64"]
@@ -268,7 +269,7 @@
timeout = options.timeout
if timeout == -1:
# Simulators are slow, therefore allow a longer default timeout.
- if arch in ["android", "arm", "mipsel"]:
+ if arch in ["android", "arm", "mipsel", "mips"]:
timeout = 2 * TIMEOUT_DEFAULT;
else:
timeout = TIMEOUT_DEFAULT;
--- a/tools/test-wrapper-gypbuild.py
+++ b/tools/test-wrapper-gypbuild.py
@@ -151,7 +151,7 @@
print "Unknown mode %s" % mode
return False
for arch in options.arch:
- if not arch in ['ia32', 'x64', 'arm', 'mipsel', 'android_arm',
+ if not arch in ['ia32', 'x64', 'arm', 'mipsel', 'mips', 'android_arm',
'android_ia32']:
print "Unknown architecture %s" % arch
return False
--- a/tools/test.py
+++ b/tools/test.py
@@ -1282,7 +1282,7 @@
options.scons_flags.append("arch=" + options.arch)
# Simulators are slow, therefore allow a longer default timeout.
if options.timeout == -1:
- if options.arch in ['android', 'arm', 'mipsel']:
+ if options.arch in ['android', 'arm', 'mipsel', 'mips']:
options.timeout = 2 * TIMEOUT_DEFAULT;
else:
options.timeout = TIMEOUT_DEFAULT;
--- a/tools/testrunner/local/statusfile.py
+++ b/tools/testrunner/local/statusfile.py
@@ -59,7 +59,7 @@
# Support arches, modes to be written as keywords instead of strings.
VARIABLES = {ALWAYS: True}
for var in ["debug", "release", "android_arm", "android_ia32", "arm", "ia32",
- "mipsel", "x64"]:
+ "mipsel", "mips", "x64"]:
VARIABLES[var] = var