Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1044)

Unified Diff: src/mips64/lithium-codegen-mips64.cc

Issue 371923006: Add mips64 port. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rebase Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/mips64/lithium-codegen-mips64.h ('k') | src/mips64/lithium-gap-resolver-mips64.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/mips64/lithium-codegen-mips64.cc
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips64/lithium-codegen-mips64.cc
similarity index 89%
copy from src/mips/lithium-codegen-mips.cc
copy to src/mips64/lithium-codegen-mips64.cc
index 247572abc2eb75b48030069a8e8cdbe4f03d3544..bf856b4c6634904519b87c8092b752b665746dbb 100644
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips64/lithium-codegen-mips64.cc
@@ -1,36 +1,13 @@
-// Copyright 2012 the V8 project authors. All rights reserved.7
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// Copyright 2012 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
#include "src/v8.h"
#include "src/code-stubs.h"
#include "src/hydrogen-osr.h"
-#include "src/mips/lithium-codegen-mips.h"
-#include "src/mips/lithium-gap-resolver-mips.h"
+#include "src/mips64/lithium-codegen-mips64.h"
+#include "src/mips64/lithium-gap-resolver-mips64.h"
#include "src/stub-cache.h"
namespace v8 {
@@ -148,13 +125,13 @@ bool LCodeGen::GeneratePrologue() {
Label ok;
int receiver_offset = info_->scope()->num_parameters() * kPointerSize;
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
- __ lw(a2, MemOperand(sp, receiver_offset));
+ __ ld(a2, MemOperand(sp, receiver_offset));
__ Branch(&ok, ne, a2, Operand(at));
- __ lw(a2, GlobalObjectOperand());
- __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalProxyOffset));
+ __ ld(a2, GlobalObjectOperand());
+ __ ld(a2, FieldMemOperand(a2, GlobalObject::kGlobalProxyOffset));
- __ sw(a2, MemOperand(sp, receiver_offset));
+ __ sd(a2, MemOperand(sp, receiver_offset));
__ bind(&ok);
}
@@ -175,18 +152,18 @@ bool LCodeGen::GeneratePrologue() {
int slots = GetStackSlotCount();
if (slots > 0) {
if (FLAG_debug_code) {
- __ Subu(sp, sp, Operand(slots * kPointerSize));
+ __ Dsubu(sp, sp, Operand(slots * kPointerSize));
__ Push(a0, a1);
- __ Addu(a0, sp, Operand(slots * kPointerSize));
+ __ Daddu(a0, sp, Operand(slots * kPointerSize));
__ li(a1, Operand(kSlotsZapValue));
Label loop;
__ bind(&loop);
- __ Subu(a0, a0, Operand(kPointerSize));
- __ sw(a1, MemOperand(a0, 2 * kPointerSize));
+ __ Dsubu(a0, a0, Operand(kPointerSize));
+ __ sd(a1, MemOperand(a0, 2 * kPointerSize));
__ Branch(&loop, ne, a0, Operand(sp));
__ Pop(a0, a1);
} else {
- __ Subu(sp, sp, Operand(slots * kPointerSize));
+ __ Dsubu(sp, sp, Operand(slots * kPointerSize));
}
}
@@ -213,7 +190,7 @@ bool LCodeGen::GeneratePrologue() {
// Context is returned in both v0. It replaces the context passed to us.
// It's saved in the stack and kept live in cp.
__ mov(cp, v0);
- __ sw(v0, MemOperand(fp, StandardFrameConstants::kContextOffset));
+ __ sd(v0, MemOperand(fp, StandardFrameConstants::kContextOffset));
// Copy any necessary parameters into the context.
int num_parameters = scope()->num_parameters();
for (int i = 0; i < num_parameters; i++) {
@@ -222,10 +199,10 @@ bool LCodeGen::GeneratePrologue() {
int parameter_offset = StandardFrameConstants::kCallerSPOffset +
(num_parameters - 1 - i) * kPointerSize;
// Load parameter from stack.
- __ lw(a0, MemOperand(fp, parameter_offset));
+ __ ld(a0, MemOperand(fp, parameter_offset));
// Store it in the context.
MemOperand target = ContextOperand(cp, var->index());
- __ sw(a0, target);
+ __ sd(a0, target);
// Update the write barrier. This clobbers a3 and a0.
if (need_write_barrier) {
__ RecordWriteContextSlot(
@@ -262,7 +239,7 @@ void LCodeGen::GenerateOsrPrologue() {
// optimized frame.
int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots();
ASSERT(slots >= 0);
- __ Subu(sp, sp, Operand(slots * kPointerSize));
+ __ Dsubu(sp, sp, Operand(slots * kPointerSize));
}
@@ -301,7 +278,8 @@ bool LCodeGen::GenerateDeferredCode() {
__ MultiPush(cp.bit() | fp.bit() | ra.bit());
__ li(scratch0(), Operand(Smi::FromInt(StackFrame::STUB)));
__ push(scratch0());
- __ Addu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
+ __ Daddu(fp, sp,
+ Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
Comment(";;; Deferred code");
}
code->Generate();
@@ -354,7 +332,8 @@ bool LCodeGen::GenerateDeoptJumpTable() {
ASSERT(info()->IsStub());
__ li(scratch0(), Operand(Smi::FromInt(StackFrame::STUB)));
__ push(scratch0());
- __ Addu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
+ __ Daddu(fp, sp,
+ Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
__ Call(t9);
}
} else {
@@ -419,7 +398,7 @@ Register LCodeGen::EmitLoadRegister(LOperand* op, Register scratch) {
}
return scratch;
} else if (op->IsStackSlot()) {
- __ lw(scratch, ToMemOperand(op));
+ __ ld(scratch, ToMemOperand(op));
return scratch;
}
UNREACHABLE();
@@ -482,17 +461,19 @@ bool LCodeGen::IsSmi(LConstantOperand* op) const {
int32_t LCodeGen::ToInteger32(LConstantOperand* op) const {
- return ToRepresentation(op, Representation::Integer32());
+ // return ToRepresentation(op, Representation::Integer32());
+ HConstant* constant = chunk_->LookupConstant(op);
+ return constant->Integer32Value();
}
-int32_t LCodeGen::ToRepresentation(LConstantOperand* op,
+int32_t LCodeGen::ToRepresentation_donotuse(LConstantOperand* op,
const Representation& r) const {
HConstant* constant = chunk_->LookupConstant(op);
int32_t value = constant->Integer32Value();
if (r.IsInteger32()) return value;
ASSERT(r.IsSmiOrTagged());
- return reinterpret_cast<int32_t>(Smi::FromInt(value));
+ return reinterpret_cast<int64_t>(Smi::FromInt(value));
}
@@ -529,11 +510,11 @@ Operand LCodeGen::ToOperand(LOperand* op) {
return Operand(ToRegister(op));
} else if (op->IsDoubleRegister()) {
Abort(kToOperandIsDoubleRegisterUnimplemented);
- return Operand(0);
+ return Operand((int64_t)0);
}
// Stack slots not implemented, use ToMemOperand instead.
UNREACHABLE();
- return Operand(0);
+ return Operand((int64_t)0);
}
@@ -560,12 +541,15 @@ MemOperand LCodeGen::ToMemOperand(LOperand* op) const {
MemOperand LCodeGen::ToHighMemOperand(LOperand* op) const {
ASSERT(op->IsDoubleStackSlot());
if (NeedsEagerFrame()) {
- return MemOperand(fp, StackSlotOffset(op->index()) + kPointerSize);
+ // return MemOperand(fp, StackSlotOffset(op->index()) + kPointerSize);
+ return MemOperand(fp, StackSlotOffset(op->index()) + kIntSize);
} else {
// Retrieve parameter without eager stack-frame relative to the
// stack-pointer.
+ // return MemOperand(
+ // sp, ArgumentsOffsetWithoutFrame(op->index()) + kPointerSize);
return MemOperand(
- sp, ArgumentsOffsetWithoutFrame(op->index()) + kPointerSize);
+ sp, ArgumentsOffsetWithoutFrame(op->index()) + kIntSize);
}
}
@@ -727,7 +711,7 @@ void LCodeGen::LoadContextFromDeferred(LOperand* context) {
if (context->IsRegister()) {
__ Move(cp, ToRegister(context));
} else if (context->IsStackSlot()) {
- __ lw(cp, ToMemOperand(context));
+ __ ld(cp, ToMemOperand(context));
} else if (context->IsConstantOperand()) {
HConstant* constant =
chunk_->LookupConstant(LConstantOperand::cast(context));
@@ -1096,13 +1080,13 @@ void LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) {
if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) {
__ Branch(&dividend_is_not_negative, ge, dividend, Operand(zero_reg));
// Note: The code below even works when right contains kMinInt.
- __ subu(dividend, zero_reg, dividend);
+ __ dsubu(dividend, zero_reg, dividend);
__ And(dividend, dividend, Operand(mask));
if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(eq, instr->environment(), dividend, Operand(zero_reg));
}
__ Branch(USE_DELAY_SLOT, &done);
- __ subu(dividend, zero_reg, dividend);
+ __ dsubu(dividend, zero_reg, dividend);
}
__ bind(&dividend_is_not_negative);
@@ -1123,8 +1107,8 @@ void LCodeGen::DoModByConstI(LModByConstI* instr) {
}
__ TruncatingDiv(result, dividend, Abs(divisor));
- __ Mul(result, result, Operand(Abs(divisor)));
- __ Subu(result, dividend, Operand(result));
+ __ Dmul(result, result, Operand(Abs(divisor)));
+ __ Dsubu(result, dividend, Operand(result));
// Check for negative zero.
HMod* hmod = instr->hydrogen();
@@ -1144,7 +1128,7 @@ void LCodeGen::DoModI(LModI* instr) {
const Register result_reg = ToRegister(instr->result());
// div runs in the background while we check for special cases.
- __ div(left_reg, right_reg);
+ __ ddiv(left_reg, right_reg);
Label done;
// Check for x % 0, we have to deopt in this case because we can't return a
@@ -1171,6 +1155,7 @@ void LCodeGen::DoModI(LModI* instr) {
// If we care about -0, test if the dividend is <0 and the result is 0.
__ Branch(USE_DELAY_SLOT, &done, ge, left_reg, Operand(zero_reg));
__ mfhi(result_reg);
+
if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(eq, instr->environment(), result_reg, Operand(zero_reg));
}
@@ -1203,22 +1188,22 @@ void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
}
if (divisor == -1) { // Nice shortcut, not needed for correctness.
- __ Subu(result, zero_reg, dividend);
+ __ Dsubu(result, zero_reg, dividend);
return;
}
uint16_t shift = WhichPowerOf2Abs(divisor);
if (shift == 0) {
__ Move(result, dividend);
} else if (shift == 1) {
- __ srl(result, dividend, 31);
- __ Addu(result, dividend, Operand(result));
+ __ dsrl32(result, dividend, 31);
+ __ Daddu(result, dividend, Operand(result));
} else {
- __ sra(result, dividend, 31);
- __ srl(result, result, 32 - shift);
- __ Addu(result, dividend, Operand(result));
+ __ dsra32(result, dividend, 31);
+ __ dsrl32(result, result, 32 - shift);
+ __ Daddu(result, dividend, Operand(result));
}
- if (shift > 0) __ sra(result, result, shift);
- if (divisor < 0) __ Subu(result, zero_reg, result);
+ if (shift > 0) __ dsra(result, result, shift);
+ if (divisor < 0) __ Dsubu(result, zero_reg, result);
}
@@ -1243,8 +1228,8 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
if (divisor < 0) __ Subu(result, zero_reg, result);
if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
- __ Mul(scratch0(), result, Operand(divisor));
- __ Subu(scratch0(), scratch0(), dividend);
+ __ Dmul(scratch0(), result, Operand(divisor));
+ __ Dsubu(scratch0(), scratch0(), dividend);
DeoptimizeIf(ne, instr->environment(), scratch0(), Operand(zero_reg));
}
}
@@ -1259,7 +1244,7 @@ void LCodeGen::DoDivI(LDivI* instr) {
// On MIPS div is asynchronous - it will run in the background while we
// check for special cases.
- __ div(dividend, divisor);
+ __ ddiv(dividend, divisor);
// Check for x / 0.
if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
@@ -1301,7 +1286,7 @@ void LCodeGen::DoMultiplyAddD(LMultiplyAddD* instr) {
// This is computed in-place.
ASSERT(addend.is(ToDoubleRegister(instr->result())));
- __ madd_d(addend, addend, multiplier, multiplicand);
+ __ Madd_d(addend, addend, multiplier, multiplicand, double_scratch0());
}
@@ -1322,42 +1307,41 @@ void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
// can simply do an arithmetic right shift.
uint16_t shift = WhichPowerOf2Abs(divisor);
if (divisor > 1) {
- __ sra(result, dividend, shift);
+ __ dsra(result, dividend, shift);
return;
}
// If the divisor is negative, we have to negate and handle edge cases.
-
- // dividend can be the same register as result so save the value of it
+ // Dividend can be the same register as result so save the value of it
// for checking overflow.
__ Move(scratch, dividend);
- __ Subu(result, zero_reg, dividend);
+ __ Dsubu(result, zero_reg, dividend);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(eq, instr->environment(), result, Operand(zero_reg));
}
- // Dividing by -1 is basically negation, unless we overflow.
__ Xor(scratch, scratch, result);
+ // Dividing by -1 is basically negation, unless we overflow.
if (divisor == -1) {
if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
- DeoptimizeIf(ge, instr->environment(), scratch, Operand(zero_reg));
+ DeoptimizeIf(gt, instr->environment(), result, Operand(kMaxInt));
}
return;
}
// If the negation could not overflow, simply shifting is OK.
if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
- __ sra(result, result, shift);
+ __ dsra(result, result, shift);
return;
}
Label no_overflow, done;
__ Branch(&no_overflow, lt, scratch, Operand(zero_reg));
- __ li(result, Operand(kMinInt / divisor));
+ __ li(result, Operand(kMinInt / divisor), CONSTANT_SIZE);
__ Branch(&done);
__ bind(&no_overflow);
- __ sra(result, result, shift);
+ __ dsra(result, result, shift);
__ bind(&done);
}
@@ -1384,7 +1368,7 @@ void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) ||
(divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) {
__ TruncatingDiv(result, dividend, Abs(divisor));
- if (divisor < 0) __ Subu(result, zero_reg, result);
+ if (divisor < 0) __ Dsubu(result, zero_reg, result);
return;
}
@@ -1396,13 +1380,13 @@ void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
__ Branch(&needs_adjustment, divisor > 0 ? lt : gt,
dividend, Operand(zero_reg));
__ TruncatingDiv(result, dividend, Abs(divisor));
- if (divisor < 0) __ Subu(result, zero_reg, result);
+ if (divisor < 0) __ Dsubu(result, zero_reg, result);
__ jmp(&done);
__ bind(&needs_adjustment);
- __ Addu(temp, dividend, Operand(divisor > 0 ? 1 : -1));
+ __ Daddu(temp, dividend, Operand(divisor > 0 ? 1 : -1));
__ TruncatingDiv(result, temp, Abs(divisor));
- if (divisor < 0) __ Subu(result, zero_reg, result);
- __ Subu(result, result, Operand(1));
+ if (divisor < 0) __ Dsubu(result, zero_reg, result);
+ __ Dsubu(result, result, Operand(1));
__ bind(&done);
}
@@ -1416,7 +1400,7 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
// On MIPS div is asynchronous - it will run in the background while we
// check for special cases.
- __ div(dividend, divisor);
+ __ ddiv(dividend, divisor);
// Check for x / 0.
if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
@@ -1448,7 +1432,7 @@ void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
__ Branch(&done, eq, remainder, Operand(zero_reg), USE_DELAY_SLOT);
__ Xor(remainder, remainder, Operand(divisor));
__ Branch(&done, ge, remainder, Operand(zero_reg));
- __ Subu(result, result, Operand(1));
+ __ Dsubu(result, result, Operand(1));
__ bind(&done);
}
@@ -1477,9 +1461,9 @@ void LCodeGen::DoMulI(LMulI* instr) {
case -1:
if (overflow) {
__ SubuAndCheckForOverflow(result, zero_reg, left, scratch);
- DeoptimizeIf(lt, instr->environment(), scratch, Operand(zero_reg));
+ DeoptimizeIf(gt, instr->environment(), scratch, Operand(kMaxInt));
} else {
- __ Subu(result, zero_reg, left);
+ __ Dsubu(result, zero_reg, left);
}
break;
case 0:
@@ -1503,25 +1487,25 @@ void LCodeGen::DoMulI(LMulI* instr) {
if (IsPowerOf2(constant_abs)) {
int32_t shift = WhichPowerOf2(constant_abs);
- __ sll(result, left, shift);
+ __ dsll(result, left, shift);
// Correct the sign of the result if the constant is negative.
- if (constant < 0) __ Subu(result, zero_reg, result);
+ if (constant < 0) __ Dsubu(result, zero_reg, result);
} else if (IsPowerOf2(constant_abs - 1)) {
int32_t shift = WhichPowerOf2(constant_abs - 1);
- __ sll(scratch, left, shift);
- __ Addu(result, scratch, left);
+ __ dsll(scratch, left, shift);
+ __ Daddu(result, scratch, left);
// Correct the sign of the result if the constant is negative.
- if (constant < 0) __ Subu(result, zero_reg, result);
+ if (constant < 0) __ Dsubu(result, zero_reg, result);
} else if (IsPowerOf2(constant_abs + 1)) {
int32_t shift = WhichPowerOf2(constant_abs + 1);
- __ sll(scratch, left, shift);
- __ Subu(result, scratch, left);
+ __ dsll(scratch, left, shift);
+ __ Dsubu(result, scratch, left);
// Correct the sign of the result if the constant is negative.
- if (constant < 0) __ Subu(result, zero_reg, result);
+ if (constant < 0) __ Dsubu(result, zero_reg, result);
} else {
// Generate standard code.
__ li(at, constant);
- __ Mul(result, left, at);
+ __ Dmul(result, left, at);
}
}
@@ -1533,22 +1517,26 @@ void LCodeGen::DoMulI(LMulI* instr) {
// hi:lo = left * right.
if (instr->hydrogen()->representation().IsSmi()) {
__ SmiUntag(result, left);
- __ mult(result, right);
+ __ dmult(result, right);
__ mfhi(scratch);
__ mflo(result);
} else {
- __ mult(left, right);
+ __ dmult(left, right);
__ mfhi(scratch);
__ mflo(result);
}
- __ sra(at, result, 31);
+ __ dsra32(at, result, 31);
DeoptimizeIf(ne, instr->environment(), scratch, Operand(at));
+ if (!instr->hydrogen()->representation().IsSmi()) {
+ DeoptimizeIf(gt, instr->environment(), result, Operand(kMaxInt));
+ DeoptimizeIf(lt, instr->environment(), result, Operand(kMinInt));
+ }
} else {
if (instr->hydrogen()->representation().IsSmi()) {
__ SmiUntag(result, left);
- __ Mul(result, result, right);
+ __ Dmul(result, result, right);
} else {
- __ Mul(result, left, right);
+ __ Dmul(result, left, right);
}
}
@@ -1609,7 +1597,6 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
LOperand* right_op = instr->right();
Register left = ToRegister(instr->left());
Register result = ToRegister(instr->result());
- Register scratch = scratch0();
if (right_op->IsRegister()) {
// No need to mask the right operand on MIPS, it is built into the variable
@@ -1624,7 +1611,9 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
case Token::SHR:
__ srlv(result, left, ToRegister(right_op));
if (instr->can_deopt()) {
- DeoptimizeIf(lt, instr->environment(), result, Operand(zero_reg));
+ // TODO(yy): (-1) >>> 0. anything else?
+ DeoptimizeIf(lt, instr->environment(), result, Operand(zero_reg));
+ DeoptimizeIf(gt, instr->environment(), result, Operand(kMaxInt));
}
break;
case Token::SHL:
@@ -1666,15 +1655,8 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
break;
case Token::SHL:
if (shift_count != 0) {
- if (instr->hydrogen_value()->representation().IsSmi() &&
- instr->can_deopt()) {
- if (shift_count != 1) {
- __ sll(result, left, shift_count - 1);
- __ SmiTagCheckOverflow(result, result, scratch);
- } else {
- __ SmiTagCheckOverflow(result, left, scratch);
- }
- DeoptimizeIf(lt, instr->environment(), scratch, Operand(zero_reg));
+ if (instr->hydrogen_value()->representation().IsSmi()) {
+ __ dsll(result, left, shift_count);
} else {
__ sll(result, left, shift_count);
}
@@ -1699,10 +1681,10 @@ void LCodeGen::DoSubI(LSubI* instr) {
if (!can_overflow) {
if (right->IsStackSlot()) {
Register right_reg = EmitLoadRegister(right, at);
- __ Subu(ToRegister(result), ToRegister(left), Operand(right_reg));
+ __ Dsubu(ToRegister(result), ToRegister(left), Operand(right_reg));
} else {
ASSERT(right->IsRegister() || right->IsConstantOperand());
- __ Subu(ToRegister(result), ToRegister(left), ToOperand(right));
+ __ Dsubu(ToRegister(result), ToRegister(left), ToOperand(right));
}
} else { // can_overflow.
Register overflow = scratch0();
@@ -1723,6 +1705,12 @@ void LCodeGen::DoSubI(LSubI* instr) {
overflow); // Reg at also used as scratch.
}
DeoptimizeIf(lt, instr->environment(), overflow, Operand(zero_reg));
+ if (!instr->hydrogen()->representation().IsSmi()) {
+ DeoptimizeIf(gt, instr->environment(),
+ ToRegister(result), Operand(kMaxInt));
+ DeoptimizeIf(lt, instr->environment(),
+ ToRegister(result), Operand(kMinInt));
+ }
}
}
@@ -1781,15 +1769,15 @@ void LCodeGen::DoDateField(LDateField* instr) {
DeoptimizeIf(ne, instr->environment(), scratch, Operand(JS_DATE_TYPE));
if (index->value() == 0) {
- __ lw(result, FieldMemOperand(object, JSDate::kValueOffset));
+ __ ld(result, FieldMemOperand(object, JSDate::kValueOffset));
} else {
if (index->value() < JSDate::kFirstUncachedField) {
ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
__ li(scratch, Operand(stamp));
- __ lw(scratch, MemOperand(scratch));
- __ lw(scratch0(), FieldMemOperand(object, JSDate::kCacheStampOffset));
+ __ ld(scratch, MemOperand(scratch));
+ __ ld(scratch0(), FieldMemOperand(object, JSDate::kCacheStampOffset));
__ Branch(&runtime, ne, scratch, Operand(scratch0()));
- __ lw(result, FieldMemOperand(object, JSDate::kValueOffset +
+ __ ld(result, FieldMemOperand(object, JSDate::kValueOffset +
kPointerSize * index->value()));
__ jmp(&done);
}
@@ -1817,11 +1805,11 @@ MemOperand LCodeGen::BuildSeqStringOperand(Register string,
ASSERT(!scratch.is(string));
ASSERT(!scratch.is(ToRegister(index)));
if (encoding == String::ONE_BYTE_ENCODING) {
- __ Addu(scratch, string, ToRegister(index));
+ __ Daddu(scratch, string, ToRegister(index));
} else {
STATIC_ASSERT(kUC16Size == 2);
- __ sll(scratch, ToRegister(index), 1);
- __ Addu(scratch, string, scratch);
+ __ dsll(scratch, ToRegister(index), 1);
+ __ Daddu(scratch, string, scratch);
}
return FieldMemOperand(scratch, SeqString::kHeaderSize);
}
@@ -1834,14 +1822,14 @@ void LCodeGen::DoSeqStringGetChar(LSeqStringGetChar* instr) {
if (FLAG_debug_code) {
Register scratch = scratch0();
- __ lw(scratch, FieldMemOperand(string, HeapObject::kMapOffset));
+ __ ld(scratch, FieldMemOperand(string, HeapObject::kMapOffset));
__ lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
__ And(scratch, scratch,
Operand(kStringRepresentationMask | kStringEncodingMask));
static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
- __ Subu(at, scratch, Operand(encoding == String::ONE_BYTE_ENCODING
+ __ Dsubu(at, scratch, Operand(encoding == String::ONE_BYTE_ENCODING
? one_byte_seq_type : two_byte_seq_type));
__ Check(eq, kUnexpectedStringType, at, Operand(zero_reg));
}
@@ -1889,10 +1877,10 @@ void LCodeGen::DoAddI(LAddI* instr) {
if (!can_overflow) {
if (right->IsStackSlot()) {
Register right_reg = EmitLoadRegister(right, at);
- __ Addu(ToRegister(result), ToRegister(left), Operand(right_reg));
+ __ Daddu(ToRegister(result), ToRegister(left), Operand(right_reg));
} else {
ASSERT(right->IsRegister() || right->IsConstantOperand());
- __ Addu(ToRegister(result), ToRegister(left), ToOperand(right));
+ __ Daddu(ToRegister(result), ToRegister(left), ToOperand(right));
}
} else { // can_overflow.
Register overflow = scratch0();
@@ -1914,6 +1902,13 @@ void LCodeGen::DoAddI(LAddI* instr) {
overflow); // Reg at also used as scratch.
}
DeoptimizeIf(lt, instr->environment(), overflow, Operand(zero_reg));
+ // if not smi, it must int32.
+ if (!instr->hydrogen()->representation().IsSmi()) {
+ DeoptimizeIf(gt, instr->environment(),
+ ToRegister(result), Operand(kMaxInt));
+ DeoptimizeIf(lt, instr->environment(),
+ ToRegister(result), Operand(kMinInt));
+ }
}
}
@@ -2141,7 +2136,7 @@ void LCodeGen::DoBranch(LBranch* instr) {
EmitBranchF(instr, nue, dbl_scratch, kDoubleRegZero);
} else if (type.IsString()) {
ASSERT(!info()->IsStub());
- __ lw(at, FieldMemOperand(reg, String::kLengthOffset));
+ __ ld(at, FieldMemOperand(reg, String::kLengthOffset));
EmitBranch(instr, ne, at, Operand(zero_reg));
} else {
ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types();
@@ -2178,7 +2173,7 @@ void LCodeGen::DoBranch(LBranch* instr) {
const Register map = scratch0();
if (expected.NeedsMap()) {
- __ lw(map, FieldMemOperand(reg, HeapObject::kMapOffset));
+ __ ld(map, FieldMemOperand(reg, HeapObject::kMapOffset));
if (expected.CanBeUndetectable()) {
// Undetectable -> false.
__ lbu(at, FieldMemOperand(map, Map::kBitFieldOffset));
@@ -2199,7 +2194,7 @@ void LCodeGen::DoBranch(LBranch* instr) {
Label not_string;
__ lbu(at, FieldMemOperand(map, Map::kInstanceTypeOffset));
__ Branch(&not_string, ge , at, Operand(FIRST_NONSTRING_TYPE));
- __ lw(at, FieldMemOperand(reg, String::kLengthOffset));
+ __ ld(at, FieldMemOperand(reg, String::kLengthOffset));
__ Branch(instr->TrueLabel(chunk_), ne, at, Operand(zero_reg));
__ Branch(instr->FalseLabel(chunk_));
__ bind(&not_string);
@@ -2310,8 +2305,7 @@ void LCodeGen::DoCompareNumericAndBranch(LCompareNumericAndBranch* instr) {
EmitBranchF(instr, cond, left_reg, right_reg);
} else {
Register cmp_left;
- Operand cmp_right = Operand(0);
-
+ Operand cmp_right = Operand((int64_t)0);
if (right->IsConstantOperand()) {
int32_t value = ToInteger32(LConstantOperand::cast(right));
if (instr->hydrogen_value()->representation().IsSmi()) {
@@ -2324,8 +2318,8 @@ void LCodeGen::DoCompareNumericAndBranch(LCompareNumericAndBranch* instr) {
} else if (left->IsConstantOperand()) {
int32_t value = ToInteger32(LConstantOperand::cast(left));
if (instr->hydrogen_value()->representation().IsSmi()) {
- cmp_left = ToRegister(right);
- cmp_right = Operand(Smi::FromInt(value));
+ cmp_left = ToRegister(right);
+ cmp_right = Operand(Smi::FromInt(value));
} else {
cmp_left = ToRegister(right);
cmp_right = Operand(value);
@@ -2377,6 +2371,9 @@ void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) {
DoubleRegister value = ToDoubleRegister(instr->value());
EmitFalseBranchF(instr, ne, value, kDoubleRegZero);
__ FmoveHigh(scratch, value);
+ // Only use low 32-bits of value.
+ __ dsll32(scratch, scratch, 0);
+ __ dsrl32(scratch, scratch, 0);
__ li(at, 0x80000000);
} else {
Register value = ToRegister(instr->value());
@@ -2385,9 +2382,9 @@ void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) {
Heap::kHeapNumberMapRootIndex,
instr->FalseLabel(chunk()),
DO_SMI_CHECK);
- __ lw(scratch, FieldMemOperand(value, HeapNumber::kExponentOffset));
+ __ lwu(scratch, FieldMemOperand(value, HeapNumber::kExponentOffset));
EmitFalseBranch(instr, ne, scratch, Operand(0x80000000));
- __ lw(scratch, FieldMemOperand(value, HeapNumber::kMantissaOffset));
+ __ lwu(scratch, FieldMemOperand(value, HeapNumber::kMantissaOffset));
__ mov(at, zero_reg);
}
EmitBranch(instr, eq, scratch, Operand(at));
@@ -2405,7 +2402,7 @@ Condition LCodeGen::EmitIsObject(Register input,
__ Branch(is_object, eq, input, Operand(temp2));
// Load map.
- __ lw(temp1, FieldMemOperand(input, HeapObject::kMapOffset));
+ __ ld(temp1, FieldMemOperand(input, HeapObject::kMapOffset));
// Undetectable objects behave like undefined.
__ lbu(temp2, FieldMemOperand(temp1, Map::kBitFieldOffset));
__ And(temp2, temp2, Operand(1 << Map::kIsUndetectable));
@@ -2476,7 +2473,7 @@ void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) {
if (!instr->hydrogen()->value()->type().IsHeapObject()) {
__ JumpIfSmi(input, instr->FalseLabel(chunk_));
}
- __ lw(temp, FieldMemOperand(input, HeapObject::kMapOffset));
+ __ ld(temp, FieldMemOperand(input, HeapObject::kMapOffset));
__ lbu(temp, FieldMemOperand(temp, Map::kBitFieldOffset));
__ And(at, temp, Operand(1 << Map::kIsUndetectable));
EmitBranch(instr, ne, at, Operand(zero_reg));
@@ -2558,7 +2555,7 @@ void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) {
__ AssertString(input);
- __ lw(result, FieldMemOperand(input, String::kHashFieldOffset));
+ __ lwu(result, FieldMemOperand(input, String::kHashFieldOffset));
__ IndexFromHash(result, result);
}
@@ -2568,7 +2565,7 @@ void LCodeGen::DoHasCachedArrayIndexAndBranch(
Register input = ToRegister(instr->value());
Register scratch = scratch0();
- __ lw(scratch,
+ __ lwu(scratch,
FieldMemOperand(input, String::kHashFieldOffset));
__ And(at, scratch, Operand(String::kContainsCachedArrayIndexMask));
EmitBranch(instr, eq, at, Operand(zero_reg));
@@ -2607,14 +2604,14 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
// Faster code path to avoid two compares: subtract lower bound from the
// actual type and do a signed compare with the width of the type range.
__ GetObjectType(input, temp, temp2);
- __ Subu(temp2, temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
+ __ Dsubu(temp2, temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
__ Branch(is_false, gt, temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE -
FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
}
// Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range.
// Check if the constructor in the map is a function.
- __ lw(temp, FieldMemOperand(temp, Map::kConstructorOffset));
+ __ ld(temp, FieldMemOperand(temp, Map::kConstructorOffset));
// Objects with a non-function constructor have class 'Object'.
__ GetObjectType(temp, temp2, temp2);
@@ -2626,8 +2623,8 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
// temp now contains the constructor function. Grab the
// instance class name from there.
- __ lw(temp, FieldMemOperand(temp, JSFunction::kSharedFunctionInfoOffset));
- __ lw(temp, FieldMemOperand(temp,
+ __ ld(temp, FieldMemOperand(temp, JSFunction::kSharedFunctionInfoOffset));
+ __ ld(temp, FieldMemOperand(temp,
SharedFunctionInfo::kInstanceClassNameOffset));
// The class name we are testing against is internalized since it's a literal.
// The name in the constructor is internalized because of the way the context
@@ -2658,7 +2655,7 @@ void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) {
Register reg = ToRegister(instr->value());
Register temp = ToRegister(instr->temp());
- __ lw(temp, FieldMemOperand(reg, HeapObject::kMapOffset));
+ __ ld(temp, FieldMemOperand(reg, HeapObject::kMapOffset));
EmitBranch(instr, eq, temp, Operand(instr->map()));
}
@@ -2719,7 +2716,7 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
// instanceof stub.
Label cache_miss;
Register map = temp;
- __ lw(map, FieldMemOperand(object, HeapObject::kMapOffset));
+ __ ld(map, FieldMemOperand(object, HeapObject::kMapOffset));
Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
__ bind(deferred->map_check()); // Label for calculating code patching.
@@ -2728,12 +2725,12 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
// the cached map.
Handle<Cell> cell = factory()->NewCell(factory()->the_hole_value());
__ li(at, Operand(Handle<Object>(cell)));
- __ lw(at, FieldMemOperand(at, PropertyCell::kValueOffset));
+ __ ld(at, FieldMemOperand(at, PropertyCell::kValueOffset));
__ BranchShort(&cache_miss, ne, map, Operand(at));
// We use Factory::the_hole_value() on purpose instead of loading from the
// root array to force relocation to be able to later patch
// with true or false. The distance from map check has to be constant.
- __ li(result, Operand(factory()->the_hole_value()), CONSTANT_SIZE);
+ __ li(result, Operand(factory()->the_hole_value()));
__ Branch(&done);
// The inlined call site cache did not match. Check null and string before
@@ -2777,19 +2774,19 @@ void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
LoadContextFromDeferred(instr->context());
- // Get the temp register reserved by the instruction. This needs to be t0 as
+ // Get the temp register reserved by the instruction. This needs to be a4 as
// its slot of the pushing of safepoint registers is used to communicate the
// offset to the location of the map check.
Register temp = ToRegister(instr->temp());
- ASSERT(temp.is(t0));
+ ASSERT(temp.is(a4));
__ li(InstanceofStub::right(), instr->function());
- static const int kAdditionalDelta = 7;
+ static const int kAdditionalDelta = 13;
int delta = masm_->InstructionsGeneratedSince(map_check) + kAdditionalDelta;
Label before_push_delta;
__ bind(&before_push_delta);
{
Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
- __ li(temp, Operand(delta * kPointerSize), CONSTANT_SIZE);
+ __ li(temp, Operand(delta * kIntSize), CONSTANT_SIZE);
__ StoreToSafepointRegisterSlot(temp, temp);
}
CallCodeGeneric(stub.GetCode(),
@@ -2833,7 +2830,7 @@ void LCodeGen::DoReturn(LReturn* instr) {
// managed by the register allocator and tearing down the frame, it's
// safe to write to the context register.
__ push(v0);
- __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+ __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
__ CallRuntime(Runtime::kTraceExit, 1);
}
if (info()->saves_caller_doubles()) {
@@ -2849,14 +2846,14 @@ void LCodeGen::DoReturn(LReturn* instr) {
int parameter_count = ToInteger32(instr->constant_parameter_count());
int32_t sp_delta = (parameter_count + 1) * kPointerSize;
if (sp_delta != 0) {
- __ Addu(sp, sp, Operand(sp_delta));
+ __ Daddu(sp, sp, Operand(sp_delta));
}
} else {
Register reg = ToRegister(instr->parameter_count());
// The argument count parameter is a smi
__ SmiUntag(reg);
- __ sll(at, reg, kPointerSizeLog2);
- __ Addu(sp, sp, at);
+ __ dsll(at, reg, kPointerSizeLog2);
+ __ Daddu(sp, sp, at);
}
__ Jump(ra);
@@ -2870,7 +2867,7 @@ void LCodeGen::DoReturn(LReturn* instr) {
void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
Register result = ToRegister(instr->result());
__ li(at, Operand(Handle<Object>(instr->hydrogen()->cell().handle())));
- __ lw(result, FieldMemOperand(at, Cell::kValueOffset));
+ __ ld(result, FieldMemOperand(at, Cell::kValueOffset));
if (instr->hydrogen()->RequiresHoleCheck()) {
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
DeoptimizeIf(eq, instr->environment(), result, Operand(at));
@@ -2904,23 +2901,22 @@ void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) {
if (instr->hydrogen()->RequiresHoleCheck()) {
// We use a temp to check the payload.
Register payload = ToRegister(instr->temp());
- __ lw(payload, FieldMemOperand(cell, Cell::kValueOffset));
+ __ ld(payload, FieldMemOperand(cell, Cell::kValueOffset));
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
DeoptimizeIf(eq, instr->environment(), payload, Operand(at));
}
// Store the value.
- __ sw(value, FieldMemOperand(cell, Cell::kValueOffset));
+ __ sd(value, FieldMemOperand(cell, Cell::kValueOffset));
// Cells are always rescanned, so no write barrier here.
}
-
void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
Register context = ToRegister(instr->context());
Register result = ToRegister(instr->result());
- __ lw(result, ContextOperand(context, instr->slot_index()));
+ __ ld(result, ContextOperand(context, instr->slot_index()));
if (instr->hydrogen()->RequiresHoleCheck()) {
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
@@ -2945,7 +2941,7 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
Label skip_assignment;
if (instr->hydrogen()->RequiresHoleCheck()) {
- __ lw(scratch, target);
+ __ ld(scratch, target);
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
if (instr->hydrogen()->DeoptimizesOnHole()) {
@@ -2955,7 +2951,7 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
}
}
- __ sw(value, target);
+ __ sd(value, target);
if (instr->hydrogen()->NeedsWriteBarrier()) {
SmiCheck check_needed =
instr->hydrogen()->value()->type().IsHeapObject()
@@ -2978,7 +2974,6 @@ void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
HObjectAccess access = instr->hydrogen()->access();
int offset = access.offset();
Register object = ToRegister(instr->object());
-
if (access.IsExternalMemory()) {
Register result = ToRegister(instr->result());
MemOperand operand = MemOperand(object, offset);
@@ -2994,11 +2989,27 @@ void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
Register result = ToRegister(instr->result());
if (!access.IsInobject()) {
- __ lw(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
+ __ ld(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
object = result;
}
- MemOperand operand = FieldMemOperand(object, offset);
- __ Load(result, operand, access.representation());
+
+ Representation representation = access.representation();
+ if (representation.IsSmi() && SmiValuesAre32Bits() &&
+ instr->hydrogen()->representation().IsInteger32()) {
+ if (FLAG_debug_code) {
+ // Verify this is really an Smi.
+ Register scratch = scratch0();
+ __ Load(scratch, FieldMemOperand(object, offset), representation);
+ __ AssertSmi(scratch);
+ }
+
+ // Read int value directly from upper half of the smi.
+ STATIC_ASSERT(kSmiTag == 0);
+ STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32);
+ offset += kPointerSize / 2;
+ representation = Representation::Integer32();
+ }
+ __ Load(result, FieldMemOperand(object, offset), representation);
}
@@ -3031,7 +3042,7 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
__ Branch(&non_instance, ne, scratch, Operand(zero_reg));
// Get the prototype or initial map from the function.
- __ lw(result,
+ __ ld(result,
FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
// Check that the function has a prototype or an initial map.
@@ -3044,13 +3055,13 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
__ Branch(&done, ne, scratch, Operand(MAP_TYPE));
// Get the prototype from the initial map.
- __ lw(result, FieldMemOperand(result, Map::kPrototypeOffset));
+ __ ld(result, FieldMemOperand(result, Map::kPrototypeOffset));
__ Branch(&done);
// Non-instance prototype: Fetch prototype from constructor field
// in initial map.
__ bind(&non_instance);
- __ lw(result, FieldMemOperand(result, Map::kConstructorOffset));
+ __ ld(result, FieldMemOperand(result, Map::kConstructorOffset));
// All done.
__ bind(&done);
@@ -3073,37 +3084,37 @@ void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
if (instr->index()->IsConstantOperand()) {
int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
int index = (const_length - const_index) + 1;
- __ lw(result, MemOperand(arguments, index * kPointerSize));
+ __ ld(result, MemOperand(arguments, index * kPointerSize));
} else {
Register index = ToRegister(instr->index());
__ li(at, Operand(const_length + 1));
- __ Subu(result, at, index);
- __ sll(at, result, kPointerSizeLog2);
- __ Addu(at, arguments, at);
- __ lw(result, MemOperand(at));
+ __ Dsubu(result, at, index);
+ __ dsll(at, result, kPointerSizeLog2);
+ __ Daddu(at, arguments, at);
+ __ ld(result, MemOperand(at));
}
} else if (instr->index()->IsConstantOperand()) {
Register length = ToRegister(instr->length());
int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
int loc = const_index - 1;
if (loc != 0) {
- __ Subu(result, length, Operand(loc));
- __ sll(at, result, kPointerSizeLog2);
- __ Addu(at, arguments, at);
- __ lw(result, MemOperand(at));
+ __ Dsubu(result, length, Operand(loc));
+ __ dsll(at, result, kPointerSizeLog2);
+ __ Daddu(at, arguments, at);
+ __ ld(result, MemOperand(at));
} else {
- __ sll(at, length, kPointerSizeLog2);
- __ Addu(at, arguments, at);
- __ lw(result, MemOperand(at));
+ __ dsll(at, length, kPointerSizeLog2);
+ __ Daddu(at, arguments, at);
+ __ ld(result, MemOperand(at));
}
} else {
Register length = ToRegister(instr->length());
Register index = ToRegister(instr->index());
- __ Subu(result, length, index);
- __ Addu(result, result, 1);
- __ sll(at, result, kPointerSizeLog2);
- __ Addu(at, arguments, at);
- __ lw(result, MemOperand(at));
+ __ Dsubu(result, length, index);
+ __ Daddu(result, result, 1);
+ __ dsll(at, result, kPointerSizeLog2);
+ __ Daddu(at, arguments, at);
+ __ ld(result, MemOperand(at));
}
}
@@ -3124,7 +3135,8 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
}
int element_size_shift = ElementsKindToShiftSize(elements_kind);
int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
- ? (element_size_shift - kSmiTagSize) : element_size_shift;
+ ? (element_size_shift - (kSmiTagSize + kSmiShiftSize))
+ : element_size_shift;
int base_offset = instr->base_offset();
if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
@@ -3134,10 +3146,19 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
int base_offset = instr->base_offset();
FPURegister result = ToDoubleRegister(instr->result());
if (key_is_constant) {
- __ Addu(scratch0(), external_pointer, constant_key << element_size_shift);
+ __ Daddu(scratch0(), external_pointer,
+ constant_key << element_size_shift);
} else {
- __ sll(scratch0(), key, shift_size);
- __ Addu(scratch0(), scratch0(), external_pointer);
+ if (shift_size < 0) {
+ if (shift_size == -32) {
+ __ dsra32(scratch0(), key, 0);
+ } else {
+ __ dsra(scratch0(), key, -shift_size);
+ }
+ } else {
+ __ dsll(scratch0(), key, shift_size);
+ }
+ __ Daddu(scratch0(), scratch0(), external_pointer);
}
if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
elements_kind == FLOAT32_ELEMENTS) {
@@ -3218,26 +3239,34 @@ void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
}
base_offset += constant_key * kDoubleSize;
}
- __ Addu(scratch, elements, Operand(base_offset));
+ __ Daddu(scratch, elements, Operand(base_offset));
if (!key_is_constant) {
key = ToRegister(instr->key());
int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
- ? (element_size_shift - kSmiTagSize) : element_size_shift;
- __ sll(at, key, shift_size);
- __ Addu(scratch, scratch, at);
+ ? (element_size_shift - (kSmiTagSize + kSmiShiftSize))
+ : element_size_shift;
+ if (shift_size > 0) {
+ __ dsll(at, key, shift_size);
+ } else if (shift_size == -32) {
+ __ dsra32(at, key, 0);
+ } else {
+ __ dsra(at, key, -shift_size);
+ }
+ __ Daddu(scratch, scratch, at);
}
__ ldc1(result, MemOperand(scratch));
if (instr->hydrogen()->RequiresHoleCheck()) {
- __ lw(scratch, MemOperand(scratch, kHoleNanUpper32Offset));
+ __ lw(scratch, MemOperand(scratch, sizeof(kHoleNanLower32)));
DeoptimizeIf(eq, instr->environment(), scratch, Operand(kHoleNanUpper32));
}
}
void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
+ HLoadKeyed* hinstr = instr->hydrogen();
Register elements = ToRegister(instr->elements());
Register result = ToRegister(instr->result());
Register scratch = scratch0();
@@ -3255,17 +3284,34 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
// during bound check elimination with the index argument to the bounds
// check, which can be tagged, so that case must be handled here, too.
if (instr->hydrogen()->key()->representation().IsSmi()) {
- __ sll(scratch, key, kPointerSizeLog2 - kSmiTagSize);
- __ addu(scratch, elements, scratch);
+ __ SmiScale(scratch, key, kPointerSizeLog2);
+ __ daddu(scratch, elements, scratch);
} else {
- __ sll(scratch, key, kPointerSizeLog2);
- __ addu(scratch, elements, scratch);
+ __ dsll(scratch, key, kPointerSizeLog2);
+ __ daddu(scratch, elements, scratch);
}
}
- __ lw(result, MemOperand(store_base, offset));
+
+ Representation representation = hinstr->representation();
+ if (representation.IsInteger32() && SmiValuesAre32Bits() &&
+ hinstr->elements_kind() == FAST_SMI_ELEMENTS) {
+ ASSERT(!hinstr->RequiresHoleCheck());
+ if (FLAG_debug_code) {
+ Register temp = scratch1();
+ __ Load(temp, MemOperand(store_base, offset), Representation::Smi());
+ __ AssertSmi(temp);
+ }
+
+ // Read int value directly from upper half of the smi.
+ STATIC_ASSERT(kSmiTag == 0);
+ STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32);
+ offset += kPointerSize / 2;
+ }
+
+ __ Load(result, MemOperand(store_base, offset), representation);
// Check for the hole value.
- if (instr->hydrogen()->RequiresHoleCheck()) {
+ if (hinstr->RequiresHoleCheck()) {
if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) {
__ SmiTst(result, scratch);
DeoptimizeIf(ne, instr->environment(), scratch, Operand(zero_reg));
@@ -3301,25 +3347,31 @@ MemOperand LCodeGen::PrepareKeyedOperand(Register key,
if (base_offset == 0) {
if (shift_size >= 0) {
- __ sll(scratch0(), key, shift_size);
- __ Addu(scratch0(), base, scratch0());
+ __ dsll(scratch0(), key, shift_size);
+ __ Daddu(scratch0(), base, scratch0());
return MemOperand(scratch0());
} else {
- ASSERT_EQ(-1, shift_size);
- __ srl(scratch0(), key, 1);
- __ Addu(scratch0(), base, scratch0());
+ if (shift_size == -32) {
+ __ dsra32(scratch0(), key, 0);
+ } else {
+ __ dsra(scratch0(), key, -shift_size);
+ }
+ __ Daddu(scratch0(), base, scratch0());
return MemOperand(scratch0());
}
}
if (shift_size >= 0) {
- __ sll(scratch0(), key, shift_size);
- __ Addu(scratch0(), base, scratch0());
+ __ dsll(scratch0(), key, shift_size);
+ __ Daddu(scratch0(), base, scratch0());
return MemOperand(scratch0(), base_offset);
} else {
- ASSERT_EQ(-1, shift_size);
- __ sra(scratch0(), key, 1);
- __ Addu(scratch0(), base, scratch0());
+ if (shift_size == -32) {
+ __ dsra32(scratch0(), key, 0);
+ } else {
+ __ dsra(scratch0(), key, -shift_size);
+ }
+ __ Daddu(scratch0(), base, scratch0());
return MemOperand(scratch0(), base_offset);
}
}
@@ -3341,12 +3393,12 @@ void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) {
Register result = ToRegister(instr->result());
if (instr->hydrogen()->from_inlined()) {
- __ Subu(result, sp, 2 * kPointerSize);
+ __ Dsubu(result, sp, 2 * kPointerSize);
} else {
// Check if the calling frame is an arguments adaptor frame.
Label done, adapted;
- __ lw(scratch, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
- __ lw(result, MemOperand(scratch, StandardFrameConstants::kContextOffset));
+ __ ld(scratch, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+ __ ld(result, MemOperand(scratch, StandardFrameConstants::kContextOffset));
__ Xor(temp, result, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
// Result is the frame pointer for the frame if not adapted and for the real
@@ -3364,12 +3416,12 @@ void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
Label done;
// If no arguments adaptor frame the number of arguments is fixed.
- __ Addu(result, zero_reg, Operand(scope()->num_parameters()));
+ __ Daddu(result, zero_reg, Operand(scope()->num_parameters()));
__ Branch(&done, eq, fp, Operand(elem));
// Arguments adaptor frame present. Get argument length from there.
- __ lw(result, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
- __ lw(result,
+ __ ld(result, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+ __ ld(result,
MemOperand(result, ArgumentsAdaptorFrameConstants::kLengthOffset));
__ SmiUntag(result);
@@ -3390,19 +3442,23 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
Label global_object, result_in_receiver;
if (!instr->hydrogen()->known_function()) {
- // Do not transform the receiver to object for strict mode
- // functions.
- __ lw(scratch,
+ // Do not transform the receiver to object for strict mode functions.
+ __ ld(scratch,
FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset));
- __ lw(scratch,
- FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset));
// Do not transform the receiver to object for builtins.
int32_t strict_mode_function_mask =
- 1 << (SharedFunctionInfo::kStrictModeFunction + kSmiTagSize);
- int32_t native_mask = 1 << (SharedFunctionInfo::kNative + kSmiTagSize);
- __ And(scratch, scratch, Operand(strict_mode_function_mask | native_mask));
- __ Branch(&result_in_receiver, ne, scratch, Operand(zero_reg));
+ 1 << SharedFunctionInfo::kStrictModeBitWithinByte;
+ int32_t native_mask = 1 << SharedFunctionInfo::kNativeBitWithinByte;
+
+ __ lbu(at,
+ FieldMemOperand(scratch, SharedFunctionInfo::kStrictModeByteOffset));
+ __ And(at, at, Operand(strict_mode_function_mask));
+ __ Branch(&result_in_receiver, ne, at, Operand(zero_reg));
+ __ lbu(at,
+ FieldMemOperand(scratch, SharedFunctionInfo::kNativeByteOffset));
+ __ And(at, at, Operand(native_mask));
+ __ Branch(&result_in_receiver, ne, at, Operand(zero_reg));
}
// Normal function. Replace undefined or null with global receiver.
@@ -3418,13 +3474,13 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
__ GetObjectType(receiver, scratch, scratch);
DeoptimizeIf(lt, instr->environment(),
scratch, Operand(FIRST_SPEC_OBJECT_TYPE));
-
__ Branch(&result_in_receiver);
+
__ bind(&global_object);
- __ lw(result, FieldMemOperand(function, JSFunction::kContextOffset));
- __ lw(result,
+ __ ld(result, FieldMemOperand(function, JSFunction::kContextOffset));
+ __ ld(result,
ContextOperand(result, Context::GLOBAL_OBJECT_INDEX));
- __ lw(result,
+ __ ld(result,
FieldMemOperand(result, GlobalObject::kGlobalProxyOffset));
if (result.is(receiver)) {
@@ -3459,21 +3515,21 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
__ push(receiver);
__ Move(receiver, length);
// The arguments are at a one pointer size offset from elements.
- __ Addu(elements, elements, Operand(1 * kPointerSize));
+ __ Daddu(elements, elements, Operand(1 * kPointerSize));
// Loop through the arguments pushing them onto the execution
// stack.
Label invoke, loop;
// length is a small non-negative integer, due to the test above.
__ Branch(USE_DELAY_SLOT, &invoke, eq, length, Operand(zero_reg));
- __ sll(scratch, length, 2);
+ __ dsll(scratch, length, kPointerSizeLog2);
__ bind(&loop);
- __ Addu(scratch, elements, scratch);
- __ lw(scratch, MemOperand(scratch));
+ __ Daddu(scratch, elements, scratch);
+ __ ld(scratch, MemOperand(scratch));
__ push(scratch);
- __ Subu(length, length, Operand(1));
+ __ Dsubu(length, length, Operand(1));
__ Branch(USE_DELAY_SLOT, &loop, ne, length, Operand(zero_reg));
- __ sll(scratch, length, 2);
+ __ dsll(scratch, length, kPointerSizeLog2);
__ bind(&invoke);
ASSERT(instr->HasPointerMap());
@@ -3505,7 +3561,7 @@ void LCodeGen::DoDrop(LDrop* instr) {
void LCodeGen::DoThisFunction(LThisFunction* instr) {
Register result = ToRegister(instr->result());
- __ lw(result, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+ __ ld(result, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
}
@@ -3513,7 +3569,7 @@ void LCodeGen::DoContext(LContext* instr) {
// If there is a non-return use, the context must be moved to a register.
Register result = ToRegister(instr->result());
if (info()->IsOptimizing()) {
- __ lw(result, MemOperand(fp, StandardFrameConstants::kContextOffset));
+ __ ld(result, MemOperand(fp, StandardFrameConstants::kContextOffset));
} else {
// If there is no frame, the context must be in cp.
ASSERT(result.is(cp));
@@ -3549,7 +3605,7 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
}
// Change context.
- __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
+ __ ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
// Set r0 to arguments count if adaption is not needed. Assumes that r0
// is available to write to at this point.
@@ -3558,7 +3614,7 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
}
// Invoke function.
- __ lw(at, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
+ __ ld(at, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
__ Call(at);
// Set up deoptimization.
@@ -3580,14 +3636,14 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
Register scratch = scratch0();
// Deoptimize if not a heap number.
- __ lw(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
+ __ ld(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
__ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
DeoptimizeIf(ne, instr->environment(), scratch, Operand(at));
Label done;
Register exponent = scratch0();
scratch = no_reg;
- __ lw(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
+ __ lwu(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
// Check the sign of the argument. If the argument is positive, just
// return it.
__ Move(result, input);
@@ -3604,7 +3660,7 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
Register tmp1 = input.is(a1) ? a0 : a1;
Register tmp2 = input.is(a2) ? a0 : a2;
Register tmp3 = input.is(a3) ? a0 : a3;
- Register tmp4 = input.is(t0) ? a0 : t0;
+ Register tmp4 = input.is(a4) ? a0 : a4;
// exponent: floating point exponent value.
@@ -3623,14 +3679,14 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
__ mov(tmp1, v0);
// Restore input_reg after call to runtime.
__ LoadFromSafepointRegisterSlot(input, input);
- __ lw(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
+ __ lwu(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
__ bind(&allocated);
// exponent: floating point exponent value.
// tmp1: allocated heap number.
__ And(exponent, exponent, Operand(~HeapNumber::kSignMask));
__ sw(exponent, FieldMemOperand(tmp1, HeapNumber::kExponentOffset));
- __ lw(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset));
+ __ lwu(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset));
__ sw(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset));
__ StoreToSafepointRegisterSlot(tmp1, result);
@@ -3647,7 +3703,7 @@ void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) {
Label done;
__ Branch(USE_DELAY_SLOT, &done, ge, input, Operand(zero_reg));
__ mov(result, input);
- __ subu(result, zero_reg, input);
+ __ dsubu(result, zero_reg, input);
// Overflow if result is still negative, i.e. 0x80000000.
DeoptimizeIf(lt, instr->environment(), result, Operand(zero_reg));
__ bind(&done);
@@ -3709,7 +3765,7 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) {
// Test for -0.
Label done;
__ Branch(&done, ne, result, Operand(zero_reg));
- __ mfc1(scratch1, input.high());
+ __ mfhc1(scratch1, input); // Get exponent/sign bits.
__ And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
DeoptimizeIf(ne, instr->environment(), scratch1, Operand(zero_reg));
__ bind(&done);
@@ -3725,7 +3781,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) {
Label done, check_sign_on_zero;
// Extract exponent bits.
- __ mfc1(result, input.high());
+ __ mfhc1(result, input);
__ Ext(scratch,
result,
HeapNumber::kExponentShift,
@@ -3755,7 +3811,10 @@ void LCodeGen::DoMathRound(LMathRound* instr) {
// Check sign of the result: if the sign changed, the input
// value was in ]0.5, 0[ and the result should be -0.
- __ mfc1(result, double_scratch0().high());
+ __ mfhc1(result, double_scratch0());
+ // mfhc1 sign-extends, clear the upper bits.
+ __ dsll32(result, result, 0);
+ __ dsrl32(result, result, 0);
__ Xor(result, result, Operand(scratch));
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
// ARM uses 'mi' here, which is 'lt'
@@ -3785,7 +3844,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) {
// Test for -0.
__ Branch(&done, ne, result, Operand(zero_reg));
__ bind(&check_sign_on_zero);
- __ mfc1(scratch, input.high());
+ __ mfhc1(scratch, input); // Get exponent/sign bits.
__ And(scratch, scratch, Operand(HeapNumber::kSignMask));
DeoptimizeIf(ne, instr->environment(), scratch, Operand(zero_reg));
}
@@ -3841,9 +3900,9 @@ void LCodeGen::DoPower(LPower* instr) {
} else if (exponent_type.IsTagged()) {
Label no_deopt;
__ JumpIfSmi(a2, &no_deopt);
- __ lw(t3, FieldMemOperand(a2, HeapObject::kMapOffset));
+ __ ld(a7, FieldMemOperand(a2, HeapObject::kMapOffset));
__ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
- DeoptimizeIf(ne, instr->environment(), t3, Operand(at));
+ DeoptimizeIf(ne, instr->environment(), a7, Operand(at));
__ bind(&no_deopt);
MathPowStub stub(isolate(), MathPowStub::TAGGED);
__ CallStub(&stub);
@@ -3924,7 +3983,7 @@ void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) {
ASSERT(instr->target()->IsRegister());
Register target = ToRegister(instr->target());
generator.BeforeCall(__ CallSize(target));
- __ Addu(target, target, Operand(Code::kHeaderSize - kHeapObjectTag));
+ __ Daddu(target, target, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Call(target);
}
generator.AfterCall();
@@ -3940,10 +3999,10 @@ void LCodeGen::DoCallJSFunction(LCallJSFunction* instr) {
}
// Change context.
- __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
+ __ ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
// Load the code entry address
- __ lw(at, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
+ __ ld(at, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
__ Call(at);
RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
@@ -3996,8 +4055,8 @@ void LCodeGen::DoCallNewArray(LCallNewArray* instr) {
Label packed_case;
// We might need a change here,
// look at the first argument.
- __ lw(t1, MemOperand(sp, 0));
- __ Branch(&packed_case, eq, t1, Operand(zero_reg));
+ __ ld(a5, MemOperand(sp, 0));
+ __ Branch(&packed_case, eq, a5, Operand(zero_reg));
ElementsKind holey_kind = GetHoleyElementsKind(kind);
ArraySingleArgumentConstructorStub stub(isolate(),
@@ -4026,9 +4085,9 @@ void LCodeGen::DoCallRuntime(LCallRuntime* instr) {
void LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) {
Register function = ToRegister(instr->function());
Register code_object = ToRegister(instr->code_object());
- __ Addu(code_object, code_object,
+ __ Daddu(code_object, code_object,
Operand(Code::kHeaderSize - kHeapObjectTag));
- __ sw(code_object,
+ __ sd(code_object,
FieldMemOperand(function, JSFunction::kCodeEntryOffset));
}
@@ -4038,10 +4097,10 @@ void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) {
Register base = ToRegister(instr->base_object());
if (instr->offset()->IsConstantOperand()) {
LConstantOperand* offset = LConstantOperand::cast(instr->offset());
- __ Addu(result, base, Operand(ToInteger32(offset)));
+ __ Daddu(result, base, Operand(ToInteger32(offset)));
} else {
Register offset = ToRegister(instr->offset());
- __ Addu(result, base, offset);
+ __ Daddu(result, base, offset);
}
}
@@ -4050,10 +4109,10 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
Representation representation = instr->representation();
Register object = ToRegister(instr->object());
- Register scratch = scratch0();
+ Register scratch2 = scratch1();
+ Register scratch1 = scratch0();
HObjectAccess access = instr->hydrogen()->access();
int offset = access.offset();
-
if (access.IsExternalMemory()) {
Register value = ToRegister(instr->value());
MemOperand operand = MemOperand(object, offset);
@@ -4078,13 +4137,13 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
if (instr->hydrogen()->has_transition()) {
Handle<Map> transition = instr->hydrogen()->transition_map();
AddDeprecationDependency(transition);
- __ li(scratch, Operand(transition));
- __ sw(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
+ __ li(scratch1, Operand(transition));
+ __ sd(scratch1, FieldMemOperand(object, HeapObject::kMapOffset));
if (instr->hydrogen()->NeedsWriteBarrierForMap()) {
Register temp = ToRegister(instr->temp());
// Update the write barrier for the map field.
__ RecordWriteForMap(object,
- scratch,
+ scratch1,
temp,
GetRAState(),
kSaveFPRegs);
@@ -4092,39 +4151,38 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
}
// Do the store.
+ Register destination = object;
+ if (!access.IsInobject()) {
+ destination = scratch1;
+ __ ld(destination, FieldMemOperand(object, JSObject::kPropertiesOffset));
+ }
Register value = ToRegister(instr->value());
- if (access.IsInobject()) {
- MemOperand operand = FieldMemOperand(object, offset);
- __ Store(value, operand, representation);
- if (instr->hydrogen()->NeedsWriteBarrier()) {
- // Update the write barrier for the object for in-object properties.
- __ RecordWriteField(object,
- offset,
- value,
- scratch,
- GetRAState(),
- kSaveFPRegs,
- EMIT_REMEMBERED_SET,
- instr->hydrogen()->SmiCheckForWriteBarrier(),
- instr->hydrogen()->PointersToHereCheckForValue());
- }
- } else {
- __ lw(scratch, FieldMemOperand(object, JSObject::kPropertiesOffset));
- MemOperand operand = FieldMemOperand(scratch, offset);
- __ Store(value, operand, representation);
- if (instr->hydrogen()->NeedsWriteBarrier()) {
- // Update the write barrier for the properties array.
- // object is used as a scratch register.
- __ RecordWriteField(scratch,
- offset,
- value,
- object,
- GetRAState(),
- kSaveFPRegs,
- EMIT_REMEMBERED_SET,
- instr->hydrogen()->SmiCheckForWriteBarrier(),
- instr->hydrogen()->PointersToHereCheckForValue());
+ if (representation.IsSmi() && SmiValuesAre32Bits() &&
+ instr->hydrogen()->value()->representation().IsInteger32()) {
+ ASSERT(instr->hydrogen()->store_mode() == STORE_TO_INITIALIZED_ENTRY);
+ if (FLAG_debug_code) {
+ __ Load(scratch2, FieldMemOperand(destination, offset), representation);
+ __ AssertSmi(scratch2);
}
+
+ // Store int value directly to upper half of the smi.
+ offset += kPointerSize / 2;
+ representation = Representation::Integer32();
+ }
+
+ MemOperand operand = FieldMemOperand(destination, offset);
+ __ Store(value, operand, representation);
+ if (instr->hydrogen()->NeedsWriteBarrier()) {
+ // Update the write barrier for the object for in-object properties.
+ __ RecordWriteField(destination,
+ offset,
+ value,
+ scratch2,
+ GetRAState(),
+ kSaveFPRegs,
+ EMIT_REMEMBERED_SET,
+ instr->hydrogen()->SmiCheckForWriteBarrier(),
+ instr->hydrogen()->PointersToHereCheckForValue());
}
}
@@ -4143,7 +4201,7 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
Condition cc = instr->hydrogen()->allow_equality() ? hi : hs;
- Operand operand(0);
+ Operand operand((int64_t)0);
Register reg;
if (instr->index()->IsConstantOperand()) {
operand = ToOperand(instr->index());
@@ -4180,7 +4238,8 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
}
int element_size_shift = ElementsKindToShiftSize(elements_kind);
int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
- ? (element_size_shift - kSmiTagSize) : element_size_shift;
+ ? (element_size_shift - (kSmiTagSize + kSmiShiftSize))
+ : element_size_shift;
int base_offset = instr->base_offset();
if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
@@ -4191,14 +4250,22 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
FPURegister value(ToDoubleRegister(instr->value()));
if (key_is_constant) {
if (constant_key != 0) {
- __ Addu(address, external_pointer,
+ __ Daddu(address, external_pointer,
Operand(constant_key << element_size_shift));
} else {
address = external_pointer;
}
} else {
- __ sll(address, key, shift_size);
- __ Addu(address, external_pointer, address);
+ if (shift_size < 0) {
+ if (shift_size == -32) {
+ __ dsra32(address, key, 0);
+ } else {
+ __ dsra(address, key, -shift_size);
+ }
+ } else {
+ __ dsll(address, key, shift_size);
+ }
+ __ Daddu(address, external_pointer, address);
}
if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
@@ -4271,14 +4338,20 @@ void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
if (constant_key & 0xF0000000) {
Abort(kArrayIndexConstantValueTooBig);
}
- __ Addu(scratch, elements,
- Operand((constant_key << element_size_shift) + base_offset));
+ __ Daddu(scratch, elements,
+ Operand((constant_key << element_size_shift) + base_offset));
} else {
int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
- ? (element_size_shift - kSmiTagSize) : element_size_shift;
- __ Addu(scratch, elements, Operand(base_offset));
- __ sll(at, ToRegister(instr->key()), shift_size);
- __ Addu(scratch, scratch, at);
+ ? (element_size_shift - (kSmiTagSize + kSmiShiftSize))
+ : element_size_shift;
+ __ Daddu(scratch, elements, Operand(base_offset));
+ ASSERT((shift_size == 3) || (shift_size == -29));
+ if (shift_size == 3) {
+ __ dsll(at, ToRegister(instr->key()), 3);
+ } else if (shift_size == -29) {
+ __ dsra(at, ToRegister(instr->key()), 29);
+ }
+ __ Daddu(scratch, scratch, at);
}
if (instr->NeedsCanonicalization()) {
@@ -4322,21 +4395,39 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
// during bound check elimination with the index argument to the bounds
// check, which can be tagged, so that case must be handled here, too.
if (instr->hydrogen()->key()->representation().IsSmi()) {
- __ sll(scratch, key, kPointerSizeLog2 - kSmiTagSize);
- __ addu(scratch, elements, scratch);
+ __ SmiScale(scratch, key, kPointerSizeLog2);
+ __ daddu(store_base, elements, scratch);
} else {
- __ sll(scratch, key, kPointerSizeLog2);
- __ addu(scratch, elements, scratch);
+ __ dsll(scratch, key, kPointerSizeLog2);
+ __ daddu(store_base, elements, scratch);
}
}
- __ sw(value, MemOperand(store_base, offset));
+
+ Representation representation = instr->hydrogen()->value()->representation();
+ if (representation.IsInteger32() && SmiValuesAre32Bits()) {
+ ASSERT(instr->hydrogen()->store_mode() == STORE_TO_INITIALIZED_ENTRY);
+ ASSERT(instr->hydrogen()->elements_kind() == FAST_SMI_ELEMENTS);
+ if (FLAG_debug_code) {
+ Register temp = scratch1();
+ __ Load(temp, MemOperand(store_base, offset), Representation::Smi());
+ __ AssertSmi(temp);
+ }
+
+ // Store int value directly to upper half of the smi.
+ STATIC_ASSERT(kSmiTag == 0);
+ STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32);
+ offset += kPointerSize / 2;
+ representation = Representation::Integer32();
+ }
+
+ __ Store(value, MemOperand(store_base, offset), representation);
if (instr->hydrogen()->NeedsWriteBarrier()) {
SmiCheck check_needed =
instr->hydrogen()->value()->type().IsHeapObject()
? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
// Compute address of modified element and store it into key register.
- __ Addu(key, store_base, Operand(offset));
+ __ Daddu(key, store_base, Operand(offset));
__ RecordWrite(elements,
key,
value,
@@ -4384,13 +4475,13 @@ void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
ElementsKind to_kind = instr->to_kind();
Label not_applicable;
- __ lw(scratch, FieldMemOperand(object_reg, HeapObject::kMapOffset));
+ __ ld(scratch, FieldMemOperand(object_reg, HeapObject::kMapOffset));
__ Branch(&not_applicable, ne, scratch, Operand(from_map));
if (IsSimpleMapChangeTransition(from_kind, to_kind)) {
Register new_map_reg = ToRegister(instr->new_map_temp());
__ li(new_map_reg, Operand(to_map));
- __ sw(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset));
+ __ sd(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset));
// Write barrier.
__ RecordWriteForMap(object_reg,
new_map_reg,
@@ -4475,7 +4566,7 @@ void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) {
// DoStringCharCodeAt above.
if (instr->index()->IsConstantOperand()) {
int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
- __ Addu(scratch, zero_reg, Operand(Smi::FromInt(const_index)));
+ __ Daddu(scratch, zero_reg, Operand(Smi::FromInt(const_index)));
__ push(scratch);
} else {
Register index = ToRegister(instr->index());
@@ -4515,9 +4606,9 @@ void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) {
__ Branch(deferred->entry(), hi,
char_code, Operand(String::kMaxOneByteCharCode));
__ LoadRoot(result, Heap::kSingleCharacterStringCacheRootIndex);
- __ sll(scratch, char_code, kPointerSizeLog2);
- __ Addu(result, result, scratch);
- __ lw(result, FieldMemOperand(result, FixedArray::kHeaderSize));
+ __ dsll(scratch, char_code, kPointerSizeLog2);
+ __ Daddu(result, result, scratch);
+ __ ld(result, FieldMemOperand(result, FixedArray::kHeaderSize));
__ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
__ Branch(deferred->entry(), eq, result, Operand(scratch));
__ bind(deferred->exit());
@@ -4549,7 +4640,7 @@ void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
FPURegister single_scratch = double_scratch0().low();
if (input->IsStackSlot()) {
Register scratch = scratch0();
- __ lw(scratch, ToMemOperand(input));
+ __ ld(scratch, ToMemOperand(input));
__ mtc1(scratch, single_scratch);
} else {
__ mtc1(ToRegister(input), single_scratch);
@@ -4564,35 +4655,7 @@ void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
FPURegister dbl_scratch = double_scratch0();
__ mtc1(ToRegister(input), dbl_scratch);
- __ Cvt_d_uw(ToDoubleRegister(output), dbl_scratch, f22);
-}
-
-
-void LCodeGen::DoNumberTagI(LNumberTagI* instr) {
- class DeferredNumberTagI V8_FINAL : public LDeferredCode {
- public:
- DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr)
- : LDeferredCode(codegen), instr_(instr) { }
- virtual void Generate() V8_OVERRIDE {
- codegen()->DoDeferredNumberTagIU(instr_,
- instr_->value(),
- instr_->temp1(),
- instr_->temp2(),
- SIGNED_INT32);
- }
- virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
- private:
- LNumberTagI* instr_;
- };
-
- Register src = ToRegister(instr->value());
- Register dst = ToRegister(instr->result());
- Register overflow = scratch0();
-
- DeferredNumberTagI* deferred = new(zone()) DeferredNumberTagI(this, instr);
- __ SmiTagCheckOverflow(dst, src, overflow);
- __ BranchOnOverflow(deferred->entry(), overflow);
- __ bind(deferred->exit());
+ __ Cvt_d_uw(ToDoubleRegister(output), dbl_scratch, f22); // TODO(plind): f22?
}
@@ -4653,7 +4716,7 @@ void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr,
if (FLAG_inline_new) {
__ LoadRoot(tmp3, Heap::kHeapNumberMapRootIndex);
- __ AllocateHeapNumber(dst, tmp1, tmp2, tmp3, &slow, DONT_TAG_RESULT);
+ __ AllocateHeapNumber(dst, tmp1, tmp2, tmp3, &slow, TAG_RESULT);
__ Branch(&done);
}
@@ -4664,7 +4727,6 @@ void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr,
// result register is stored, as this register is in the pointer map, but
// contains an integer value.
__ mov(dst, zero_reg);
-
// Preserve the value of all registers.
PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
@@ -4673,20 +4735,17 @@ void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr,
// They only call Runtime::kAllocateHeapNumber.
// The corresponding HChange instructions are added in a phase that does
// not have easy access to the local context.
- __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+ __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
__ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
RecordSafepointWithRegisters(
instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
- __ Subu(v0, v0, kHeapObjectTag);
__ StoreToSafepointRegisterSlot(v0, dst);
}
-
// Done. Put the value in dbl_scratch into the value of the allocated heap
// number.
__ bind(&done);
- __ sdc1(dbl_scratch, MemOperand(dst, HeapNumber::kValueOffset));
- __ Addu(dst, dst, kHeapObjectTag);
+ __ sdc1(dbl_scratch, FieldMemOperand(dst, HeapNumber::kValueOffset));
}
@@ -4721,7 +4780,7 @@ void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
__ bind(deferred->exit());
__ sdc1(input_reg, MemOperand(reg, HeapNumber::kValueOffset));
// Now that we have finished with the object's real address tag it
- __ Addu(reg, reg, kHeapObjectTag);
+ __ Daddu(reg, reg, kHeapObjectTag);
}
@@ -4738,11 +4797,11 @@ void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) {
// They only call Runtime::kAllocateHeapNumber.
// The corresponding HChange instructions are added in a phase that does
// not have easy access to the local context.
- __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+ __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
__ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
RecordSafepointWithRegisters(
instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
- __ Subu(v0, v0, kHeapObjectTag);
+ __ Dsubu(v0, v0, kHeapObjectTag);
__ StoreToSafepointRegisterSlot(v0, reg);
}
@@ -4753,7 +4812,7 @@ void LCodeGen::DoSmiTag(LSmiTag* instr) {
Register output = ToRegister(instr->result());
if (hchange->CheckFlag(HValue::kCanOverflow) &&
hchange->value()->CheckFlag(HValue::kUint32)) {
- __ And(at, input, Operand(0xc0000000));
+ __ And(at, input, Operand(0x80000000));
DeoptimizeIf(ne, instr->environment(), at, Operand(zero_reg));
}
if (hchange->CheckFlag(HValue::kCanOverflow) &&
@@ -4794,7 +4853,7 @@ void LCodeGen::EmitNumberUntagD(Register input_reg,
// Smi check.
__ UntagAndJumpIfSmi(scratch, input_reg, &load_smi);
// Heap number map check.
- __ lw(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
+ __ ld(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
__ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
if (can_convert_undefined_to_nan) {
__ Branch(&convert, ne, scratch, Operand(at));
@@ -4804,9 +4863,9 @@ void LCodeGen::EmitNumberUntagD(Register input_reg,
// Load heap number.
__ ldc1(result_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset));
if (deoptimize_on_minus_zero) {
- __ mfc1(at, result_reg.low());
+ __ mfc1(at, result_reg);
__ Branch(&done, ne, at, Operand(zero_reg));
- __ mfc1(scratch, result_reg.high());
+ __ mfhc1(scratch, result_reg); // Get exponent/sign bits.
DeoptimizeIf(eq, env, scratch, Operand(HeapNumber::kSignMask));
}
__ Branch(&done);
@@ -4846,7 +4905,7 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
// The input is a tagged HeapObject.
// Heap number map check.
- __ lw(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset));
+ __ ld(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset));
__ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
// This 'at' value and scratch1 map value are used for tests in both clauses
// of the if.
@@ -4904,7 +4963,7 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
__ Branch(&done, ne, input_reg, Operand(zero_reg));
- __ mfc1(scratch1, double_scratch.high());
+ __ mfhc1(scratch1, double_scratch); // Get exponent/sign bits.
__ And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
DeoptimizeIf(ne, instr->environment(), scratch1, Operand(zero_reg));
}
@@ -4992,7 +5051,7 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
Label done;
__ Branch(&done, ne, result_reg, Operand(zero_reg));
- __ mfc1(scratch1, double_input.high());
+ __ mfhc1(scratch1, double_input); // Get exponent/sign bits.
__ And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
DeoptimizeIf(ne, instr->environment(), scratch1, Operand(zero_reg));
__ bind(&done);
@@ -5025,14 +5084,13 @@ void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
Label done;
__ Branch(&done, ne, result_reg, Operand(zero_reg));
- __ mfc1(scratch1, double_input.high());
+ __ mfhc1(scratch1, double_input); // Get exponent/sign bits.
__ And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
DeoptimizeIf(ne, instr->environment(), scratch1, Operand(zero_reg));
__ bind(&done);
}
}
- __ SmiTagCheckOverflow(result_reg, result_reg, scratch1);
- DeoptimizeIf(lt, instr->environment(), scratch1, Operand(zero_reg));
+ __ SmiTag(result_reg, result_reg);
}
@@ -5099,7 +5157,7 @@ void LCodeGen::DoCheckValue(LCheckValue* instr) {
Register reg = ToRegister(instr->value());
Handle<Cell> cell = isolate()->factory()->NewCell(object);
__ li(at, Operand(Handle<Object>(cell)));
- __ lw(at, FieldMemOperand(at, Cell::kValueOffset));
+ __ ld(at, FieldMemOperand(at, Cell::kValueOffset));
DeoptimizeIf(ne, instr->environment(), reg,
Operand(at));
} else {
@@ -5154,7 +5212,7 @@ void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
LOperand* input = instr->value();
ASSERT(input->IsRegister());
Register reg = ToRegister(input);
- __ lw(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset));
+ __ ld(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset));
DeferredCheckMaps* deferred = NULL;
if (instr->hydrogen()->HasMigrationTarget()) {
@@ -5206,7 +5264,7 @@ void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
__ UntagAndJumpIfSmi(scratch, input_reg, &is_smi);
// Check for heap number
- __ lw(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
+ __ ld(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
__ Branch(&heap_number, eq, scratch, Operand(factory()->heap_number_map()));
// Check for undefined. Undefined is converted to zero for clamping
@@ -5302,14 +5360,14 @@ void LCodeGen::DoAllocate(LAllocate* instr) {
int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
__ li(scratch, Operand(size - kHeapObjectTag));
} else {
- __ Subu(scratch, ToRegister(instr->size()), Operand(kHeapObjectTag));
+ __ Dsubu(scratch, ToRegister(instr->size()), Operand(kHeapObjectTag));
}
__ li(scratch2, Operand(isolate()->factory()->one_pointer_filler_map()));
Label loop;
__ bind(&loop);
- __ Subu(scratch, scratch, Operand(kPointerSize));
- __ Addu(at, result, Operand(scratch));
- __ sw(scratch2, MemOperand(at));
+ __ Dsubu(scratch, scratch, Operand(kPointerSize));
+ __ Daddu(at, result, Operand(scratch));
+ __ sd(scratch2, MemOperand(at));
__ Branch(&loop, ge, scratch, Operand(zero_reg));
}
}
@@ -5332,7 +5390,8 @@ void LCodeGen::DoDeferredAllocate(LAllocate* instr) {
} else {
int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
if (size >= 0 && size <= Smi::kMaxValue) {
- __ Push(Smi::FromInt(size));
+ __ li(v0, Operand(Smi::FromInt(size)));
+ __ Push(v0);
} else {
// We should never get here at runtime => abort
__ stop("invalid allocation size");
@@ -5352,7 +5411,8 @@ void LCodeGen::DoDeferredAllocate(LAllocate* instr) {
} else {
flags = AllocateTargetSpace::update(flags, NEW_SPACE);
}
- __ Push(Smi::FromInt(flags));
+ __ li(v0, Operand(Smi::FromInt(flags)));
+ __ Push(v0);
CallRuntimeFromDeferred(
Runtime::kAllocateInTargetSpace, 2, instr, instr->context());
@@ -5372,23 +5432,23 @@ void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
ASSERT(ToRegister(instr->context()).is(cp));
Label materialized;
// Registers will be used as follows:
- // t3 = literals array.
+ // a7 = literals array.
// a1 = regexp literal.
// a0 = regexp literal clone.
- // a2 and t0-t2 are used as temporaries.
+ // a2 and a4-a6 are used as temporaries.
int literal_offset =
FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index());
- __ li(t3, instr->hydrogen()->literals());
- __ lw(a1, FieldMemOperand(t3, literal_offset));
+ __ li(a7, instr->hydrogen()->literals());
+ __ ld(a1, FieldMemOperand(a7, literal_offset));
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
__ Branch(&materialized, ne, a1, Operand(at));
// Create regexp literal using runtime function
// Result will be in v0.
- __ li(t2, Operand(Smi::FromInt(instr->hydrogen()->literal_index())));
- __ li(t1, Operand(instr->hydrogen()->pattern()));
- __ li(t0, Operand(instr->hydrogen()->flags()));
- __ Push(t3, t2, t1, t0);
+ __ li(a6, Operand(Smi::FromInt(instr->hydrogen()->literal_index())));
+ __ li(a5, Operand(instr->hydrogen()->pattern()));
+ __ li(a4, Operand(instr->hydrogen()->flags()));
+ __ Push(a7, a6, a5, a4);
CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr);
__ mov(a1, v0);
@@ -5409,14 +5469,14 @@ void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
// Copy the content into the newly allocated memory.
// (Unroll copy loop once for better throughput).
for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) {
- __ lw(a3, FieldMemOperand(a1, i));
- __ lw(a2, FieldMemOperand(a1, i + kPointerSize));
- __ sw(a3, FieldMemOperand(v0, i));
- __ sw(a2, FieldMemOperand(v0, i + kPointerSize));
+ __ ld(a3, FieldMemOperand(a1, i));
+ __ ld(a2, FieldMemOperand(a1, i + kPointerSize));
+ __ sd(a3, FieldMemOperand(v0, i));
+ __ sd(a2, FieldMemOperand(v0, i + kPointerSize));
}
if ((size % (2 * kPointerSize)) != 0) {
- __ lw(a3, FieldMemOperand(a1, size - kPointerSize));
- __ sw(a3, FieldMemOperand(v0, size - kPointerSize));
+ __ ld(a3, FieldMemOperand(a1, size - kPointerSize));
+ __ sd(a3, FieldMemOperand(v0, size - kPointerSize));
}
}
@@ -5486,7 +5546,7 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
Factory* factory = isolate()->factory();
if (String::Equals(type_name, factory->number_string())) {
__ JumpIfSmi(input, true_label);
- __ lw(input, FieldMemOperand(input, HeapObject::kMapOffset));
+ __ ld(input, FieldMemOperand(input, HeapObject::kMapOffset));
__ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
*cmp1 = input;
*cmp2 = Operand(at);
@@ -5534,7 +5594,7 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
// slot.
__ JumpIfSmi(input, false_label);
// Check for undetectable objects => true.
- __ lw(input, FieldMemOperand(input, HeapObject::kMapOffset));
+ __ ld(input, FieldMemOperand(input, HeapObject::kMapOffset));
__ lbu(at, FieldMemOperand(input, Map::kBitFieldOffset));
__ And(at, at, 1 << Map::kIsUndetectable);
*cmp1 = at;
@@ -5593,18 +5653,18 @@ void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
void LCodeGen::EmitIsConstructCall(Register temp1, Register temp2) {
ASSERT(!temp1.is(temp2));
// Get the frame pointer for the calling frame.
- __ lw(temp1, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+ __ ld(temp1, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
// Skip the arguments adaptor frame if it exists.
Label check_frame_marker;
- __ lw(temp2, MemOperand(temp1, StandardFrameConstants::kContextOffset));
+ __ ld(temp2, MemOperand(temp1, StandardFrameConstants::kContextOffset));
__ Branch(&check_frame_marker, ne, temp2,
Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
- __ lw(temp1, MemOperand(temp1, StandardFrameConstants::kCallerFPOffset));
+ __ ld(temp1, MemOperand(temp1, StandardFrameConstants::kCallerFPOffset));
// Check the marker in the calling frame.
__ bind(&check_frame_marker);
- __ lw(temp1, MemOperand(temp1, StandardFrameConstants::kMarkerOffset));
+ __ ld(temp1, MemOperand(temp1, StandardFrameConstants::kMarkerOffset));
}
@@ -5739,7 +5799,7 @@ void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
DeoptimizeIf(eq, instr->environment(), object, Operand(at));
- Register null_value = t1;
+ Register null_value = a5;
__ LoadRoot(null_value, Heap::kNullValueRootIndex);
DeoptimizeIf(eq, instr->environment(), object, Operand(null_value));
@@ -5754,7 +5814,7 @@ void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
ASSERT(object.is(a0));
__ CheckEnumCache(null_value, &call_runtime);
- __ lw(result, FieldMemOperand(object, HeapObject::kMapOffset));
+ __ ld(result, FieldMemOperand(object, HeapObject::kMapOffset));
__ Branch(&use_cache);
// Get the set of properties to enumerate.
@@ -5762,7 +5822,7 @@ void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
__ push(object);
CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr);
- __ lw(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
+ __ ld(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
ASSERT(result.is(v0));
__ LoadRoot(at, Heap::kMetaMapRootIndex);
DeoptimizeIf(ne, instr->environment(), a1, Operand(at));
@@ -5781,9 +5841,9 @@ void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
__ bind(&load_cache);
__ LoadInstanceDescriptors(map, result);
- __ lw(result,
+ __ ld(result,
FieldMemOperand(result, DescriptorArray::kEnumCacheOffset));
- __ lw(result,
+ __ ld(result,
FieldMemOperand(result, FixedArray::SizeFor(instr->idx())));
DeoptimizeIf(eq, instr->environment(), result, Operand(zero_reg));
@@ -5794,7 +5854,7 @@ void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
Register object = ToRegister(instr->value());
Register map = ToRegister(instr->map());
- __ lw(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset));
+ __ ld(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset));
DeoptimizeIf(ne, instr->environment(), map, Operand(scratch0()));
}
@@ -5851,22 +5911,20 @@ void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) {
__ And(scratch, index, Operand(Smi::FromInt(1)));
__ Branch(deferred->entry(), ne, scratch, Operand(zero_reg));
- __ sra(index, index, 1);
+ __ dsra(index, index, 1);
__ Branch(USE_DELAY_SLOT, &out_of_object, lt, index, Operand(zero_reg));
- __ sll(scratch, index, kPointerSizeLog2 - kSmiTagSize); // In delay slot.
-
- STATIC_ASSERT(kPointerSizeLog2 > kSmiTagSize);
- __ Addu(scratch, object, scratch);
- __ lw(result, FieldMemOperand(scratch, JSObject::kHeaderSize));
+ __ SmiScale(scratch, index, kPointerSizeLog2); // In delay slot.
+ __ Daddu(scratch, object, scratch);
+ __ ld(result, FieldMemOperand(scratch, JSObject::kHeaderSize));
__ Branch(&done);
__ bind(&out_of_object);
- __ lw(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
+ __ ld(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
// Index is equal to negated out of object property index plus 1.
- __ Subu(scratch, result, scratch);
- __ lw(result, FieldMemOperand(scratch,
+ __ Dsubu(scratch, result, scratch);
+ __ ld(result, FieldMemOperand(scratch,
FixedArray::kHeaderSize - kPointerSize));
__ bind(deferred->exit());
__ bind(&done);
@@ -5875,7 +5933,7 @@ void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) {
void LCodeGen::DoStoreFrameContext(LStoreFrameContext* instr) {
Register context = ToRegister(instr->context());
- __ sw(context, MemOperand(fp, StandardFrameConstants::kContextOffset));
+ __ sd(context, MemOperand(fp, StandardFrameConstants::kContextOffset));
}
« no previous file with comments | « src/mips64/lithium-codegen-mips64.h ('k') | src/mips64/lithium-gap-resolver-mips64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698