__ Dror(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break;
case kMips64Tst:
- case kMips64Tst32:
// Pseudo-instruction used for cmp/branch. No opcode emitted here.
break;
case kMips64Cmp:
- case kMips64Cmp32:
// Pseudo-instruction used for cmp/branch. No opcode emitted here.
break;
case kMips64Mov:
// implemented differently than on the other arch's. The compare operations
// emit mips psuedo-instructions, which are handled here by branch
// instructions that do the actual comparison. Essential that the input
- // registers to compare psuedo-op are not modified before this branch op, as
+ // registers to compare pseudo-op are not modified before this branch op, as
// they are tested here.
- // TODO(plind): Add CHECK() to ensure that test/cmp and this branch were
- // not separated by other instructions.
if (instr->arch_opcode() == kMips64Tst) {
cc = FlagsConditionToConditionTst(branch->condition);
__ And(at, i.InputRegister(0), i.InputOperand(1));
__ Branch(tlabel, cc, at, Operand(zero_reg));
- } else if (instr->arch_opcode() == kMips64Tst32) {
- cc = FlagsConditionToConditionTst(branch->condition);
- // Zero-extend registers on MIPS64 only 64-bit operand
- // branch and compare op. is available.
- // This is a disadvantage to perform 32-bit operation on MIPS64.
- // Try to force globally in front-end Word64 representation to be preferred
- // for MIPS64 even for Word32.
- __ And(at, i.InputRegister(0), i.InputOperand(1));
- __ Dext(at, at, 0, 32);
- __ Branch(tlabel, cc, at, Operand(zero_reg));
} else if (instr->arch_opcode() == kMips64Dadd ||
instr->arch_opcode() == kMips64Dsub) {
cc = FlagsConditionToConditionOvf(branch->condition);
__ Branch(tlabel, cc, i.InputRegister(0), i.InputOperand(1));
if (!branch->fallthru) __ Branch(flabel); // no fallthru to flabel.
-
- } else if (instr->arch_opcode() == kMips64Cmp32) {
- cc = FlagsConditionToConditionCmp(branch->condition);
-
- switch (branch->condition) {
- case kEqual:
- case kNotEqual:
- case kSignedLessThan:
- case kSignedGreaterThanOrEqual:
- case kSignedLessThanOrEqual:
- case kSignedGreaterThan:
- // Sign-extend registers on MIPS64 only 64-bit operand
- // branch and compare op. is available.
- __ sll(i.InputRegister(0), i.InputRegister(0), 0);
- if (instr->InputAt(1)->IsRegister()) {
- __ sll(i.InputRegister(1), i.InputRegister(1), 0);
- }
- break;
- case kUnsignedLessThan:
- case kUnsignedGreaterThanOrEqual:
- case kUnsignedLessThanOrEqual:
- case kUnsignedGreaterThan:
- // Zero-extend registers on MIPS64 only 64-bit operand
- // branch and compare op. is available.
- __ Dext(i.InputRegister(0), i.InputRegister(0), 0, 32);
- if (instr->InputAt(1)->IsRegister()) {
- __ Dext(i.InputRegister(1), i.InputRegister(1), 0, 32);
- }
- break;
- default:
- UNSUPPORTED_COND(kMips64Cmp, branch->condition);
- break;
- }
- __ Branch(tlabel, cc, i.InputRegister(0), i.InputOperand(1));
-
- if (!branch->fallthru) __ Branch(flabel); // no fallthru to flabel.
} else if (instr->arch_opcode() == kMips64CmpD) {
// TODO(dusmil) optimize unordered checks to use less instructions
// even if we have to unfold BranchF macro.
__ And(at, i.InputRegister(0), i.InputOperand(1));
__ Branch(USE_DELAY_SLOT, &done, cc, at, Operand(zero_reg));
__ li(result, Operand(1)); // In delay slot.
- } else if (instr->arch_opcode() == kMips64Tst32) {
- cc = FlagsConditionToConditionTst(condition);
- // Zero-extend register on MIPS64 only 64-bit operand
- // branch and compare op. is available.
- __ And(at, i.InputRegister(0), i.InputOperand(1));
- __ Dext(at, at, 0, 32);
- __ Branch(USE_DELAY_SLOT, &done, cc, at, Operand(zero_reg));
- __ li(result, Operand(1)); // In delay slot.
} else if (instr->arch_opcode() == kMips64Dadd ||
instr->arch_opcode() == kMips64Dsub) {
cc = FlagsConditionToConditionOvf(condition);
cc = FlagsConditionToConditionCmp(condition);
__ Branch(USE_DELAY_SLOT, &done, cc, left, right);
__ li(result, Operand(1)); // In delay slot.
- } else if (instr->arch_opcode() == kMips64Cmp32) {
- Register left = i.InputRegister(0);
- Operand right = i.InputOperand(1);
- cc = FlagsConditionToConditionCmp(condition);
-
- switch (condition) {
- case kEqual:
- case kNotEqual:
- case kSignedLessThan:
- case kSignedGreaterThanOrEqual:
- case kSignedLessThanOrEqual:
- case kSignedGreaterThan:
- // Sign-extend registers on MIPS64 only 64-bit operand
- // branch and compare op. is available.
- __ sll(left, left, 0);
- if (instr->InputAt(1)->IsRegister()) {
- __ sll(i.InputRegister(1), i.InputRegister(1), 0);
- }
- break;
- case kUnsignedLessThan:
- case kUnsignedGreaterThanOrEqual:
- case kUnsignedLessThanOrEqual:
- case kUnsignedGreaterThan:
- // Zero-extend registers on MIPS64 only 64-bit operand
- // branch and compare op. is available.
- __ Dext(left, left, 0, 32);
- if (instr->InputAt(1)->IsRegister()) {
- __ Dext(i.InputRegister(1), i.InputRegister(1), 0, 32);
- }
- break;
- default:
- UNSUPPORTED_COND(kMips64Cmp32, condition);
- break;
- }
- __ Branch(USE_DELAY_SLOT, &done, cc, left, right);
- __ li(result, Operand(1)); // In delay slot.
} else if (instr->arch_opcode() == kMips64CmpD) {
FPURegister left = i.InputDoubleRegister(0);
FPURegister right = i.InputDoubleRegister(1);
V(Mips64Dror) \
V(Mips64Mov) \
V(Mips64Tst) \
- V(Mips64Tst32) \
V(Mips64Cmp) \
- V(Mips64Cmp32) \
V(Mips64CmpD) \
V(Mips64AddD) \
V(Mips64SubD) \
}
}
-
- bool CanBeImmediate(Node* node, InstructionCode opcode,
- FlagsContinuation* cont) {
- int64_t value;
- if (node->opcode() == IrOpcode::kInt32Constant)
- value = OpParameter<int32_t>(node);
- else if (node->opcode() == IrOpcode::kInt64Constant)
- value = OpParameter<int64_t>(node);
- else
- return false;
- switch (ArchOpcodeField::decode(opcode)) {
- case kMips64Cmp32:
- switch (cont->condition()) {
- case kUnsignedLessThan:
- case kUnsignedGreaterThanOrEqual:
- case kUnsignedLessThanOrEqual:
- case kUnsignedGreaterThan:
- // Immediate operands for unsigned 32-bit compare operations
- // should not be sign-extended.
- return is_uint15(value);
- default:
- return false;
- }
- default:
- return is_int16(value);
- }
- }
-
-
private:
bool ImmediateFitsAddrMode1Instruction(int32_t imm) const {
TRACE_UNIMPL();
Node* right = node->InputAt(1);
// Match immediates on left or right side of comparison.
- if (g.CanBeImmediate(right, opcode, cont)) {
+ if (g.CanBeImmediate(right, opcode)) {
VisitCompare(selector, opcode, g.UseRegister(left), g.UseImmediate(right),
cont);
- } else if (g.CanBeImmediate(left, opcode, cont)) {
+ } else if (g.CanBeImmediate(left, opcode)) {
if (!commutative) cont->Commute();
VisitCompare(selector, opcode, g.UseRegister(right), g.UseImmediate(left),
cont);
void VisitWord32Compare(InstructionSelector* selector, Node* node,
FlagsContinuation* cont) {
- VisitWordCompare(selector, node, kMips64Cmp32, cont, false);
+ VisitWordCompare(selector, node, kMips64Cmp, cont, false);
}
} // namespace
-void EmitWordCompareZero(InstructionSelector* selector, InstructionCode opcode,
- Node* value, FlagsContinuation* cont) {
+void EmitWordCompareZero(InstructionSelector* selector, Node* value,
+ FlagsContinuation* cont) {
Mips64OperandGenerator g(selector);
- opcode = cont->Encode(opcode);
+ InstructionCode opcode = cont->Encode(kMips64Cmp);
InstructionOperand const value_operand = g.UseRegister(value);
if (cont->IsBranch()) {
selector->Emit(opcode, g.NoOutput(), value_operand, g.TempImmediate(0),
// Shared routine for word comparisons against zero.
void VisitWordCompareZero(InstructionSelector* selector, Node* user,
Node* value, FlagsContinuation* cont) {
- // Initially set comparison against 0 to be 64-bit variant for branches that
- // cannot combine.
- InstructionCode opcode = kMips64Cmp;
while (selector->CanCover(user, value)) {
- if (user->opcode() == IrOpcode::kWord32Equal) {
- opcode = kMips64Cmp32;
- }
switch (value->opcode()) {
case IrOpcode::kWord32Equal: {
// Combine with comparisons against 0 by simply inverting the
user = value;
value = m.left().node();
cont->Negate();
- opcode = kMips64Cmp32;
continue;
}
cont->OverwriteAndNegateIfEqual(kEqual);
}
break;
case IrOpcode::kWord32And:
- return VisitWordCompare(selector, value, kMips64Tst32, cont, true);
case IrOpcode::kWord64And:
return VisitWordCompare(selector, value, kMips64Tst, cont, true);
default:
}
// Continuation could not be combined with a compare, emit compare against 0.
- EmitWordCompareZero(selector, opcode, value, cont);
+ EmitWordCompareZero(selector, value, cont);
}
*return_addr_reg = instr->RdValue();
break;
case SLL:
- *alu_out = (int32_t)rt << sa;
+ *alu_out = static_cast<int32_t>(rt) << sa;
break;
case DSLL:
*alu_out = rt << sa;
if (rs_reg == 0) {
// Regular logical right shift of a word by a fixed number of
// bits instruction. RS field is always equal to 0.
- *alu_out = (uint32_t)rt_u >> sa;
+ // Sign-extend the 32-bit result.
+ *alu_out = static_cast<int32_t>(static_cast<uint32_t>(rt_u) >> sa);
} else {
// Logical right-rotate of a word by a fixed number of bits. This
// is special case of SRL instruction, added in MIPS32 Release 2.
// RS field is equal to 00001.
- *alu_out = base::bits::RotateRight32((uint32_t)rt_u, sa);
+ *alu_out = static_cast<int32_t>(
+ base::bits::RotateRight32((uint32_t)rt_u, sa));
}
break;
case DSRL:
if (sa == 0) {
// Regular logical right-shift of a word by a variable number of
// bits instruction. SA field is always equal to 0.
- *alu_out = (uint32_t)rt_u >> rs;
+ *alu_out = static_cast<int32_t>((uint32_t)rt_u >> rs);
} else {
// Logical right-rotate of a word by a variable number of bits.
// This is special case od SRLV instruction, added in MIPS32
// Release 2. SA field is equal to 00001.
- *alu_out = base::bits::RotateRight32((uint32_t)rt_u, rs_u);
+ *alu_out = static_cast<int32_t>(
+ base::bits::RotateRight32((uint32_t)rt_u, rs_u));
}
break;
case DSRLV:
static uintptr_t Cast(void* r) { return reinterpret_cast<uintptr_t>(r); }
};
+#if V8_TARGET_ARCH_MIPS64
+// Additional template specialization required for mips64 to sign-extend
+// parameters defined by calling convention.
+template <>
+struct ParameterTraits<int32_t> {
+ static int64_t Cast(int32_t r) { return static_cast<int64_t>(r); }
+};
+
+template <>
+struct ParameterTraits<uint32_t> {
+ static int64_t Cast(uint32_t r) {
+ return static_cast<int64_t>(static_cast<int32_t>(r));
+ }
+};
+#endif
+
class CallHelper {
public:
explicit CallHelper(Isolate* isolate, MachineSignature* machine_sig)
return static_cast<uintptr_t>(simulator->Call(f, 4, p1, p2, p3, p4));
}
+
template <typename R, typename F>
R DoCall(F* f) {
return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f)));
{{&RawMachineAssembler::WordNotEqual, "WordNotEqual", kMips64Cmp,
kMachInt64},
1U},
- {{&RawMachineAssembler::Word32Equal, "Word32Equal", kMips64Cmp32,
- kMachInt32},
+ {{&RawMachineAssembler::Word32Equal, "Word32Equal", kMips64Cmp, kMachInt32},
1U},
- {{&RawMachineAssembler::Word32NotEqual, "Word32NotEqual", kMips64Cmp32,
+ {{&RawMachineAssembler::Word32NotEqual, "Word32NotEqual", kMips64Cmp,
kMachInt32},
1U},
- {{&RawMachineAssembler::Int32LessThan, "Int32LessThan", kMips64Cmp32,
+ {{&RawMachineAssembler::Int32LessThan, "Int32LessThan", kMips64Cmp,
kMachInt32},
1U},
{{&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual",
- kMips64Cmp32, kMachInt32},
+ kMips64Cmp, kMachInt32},
1U},
- {{&RawMachineAssembler::Int32GreaterThan, "Int32GreaterThan", kMips64Cmp32,
+ {{&RawMachineAssembler::Int32GreaterThan, "Int32GreaterThan", kMips64Cmp,
kMachInt32},
1U},
{{&RawMachineAssembler::Int32GreaterThanOrEqual, "Int32GreaterThanOrEqual",
- kMips64Cmp32, kMachInt32},
+ kMips64Cmp, kMachInt32},
1U},
- {{&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kMips64Cmp32,
+ {{&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kMips64Cmp,
kMachUint32},
1U},
{{&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual",
- kMips64Cmp32, kMachUint32},
+ kMips64Cmp, kMachUint32},
1U}};
m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0)));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
- EXPECT_EQ(kMips64Cmp32, s[0]->arch_opcode());
+ EXPECT_EQ(kMips64Cmp, s[0]->arch_opcode());
EXPECT_EQ(kMode_None, s[0]->addressing_mode());
ASSERT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(1U, s[0]->OutputCount());
m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0)));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
- EXPECT_EQ(kMips64Cmp32, s[0]->arch_opcode());
+ EXPECT_EQ(kMips64Cmp, s[0]->arch_opcode());
EXPECT_EQ(kMode_None, s[0]->addressing_mode());
ASSERT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(1U, s[0]->OutputCount());