S390: Decouple Add/Sub/Neg to 32/64 Bit Op
1. Decouple kS390_Add/Sub/Neg to kS390_Add32/Sub32/Neg32/Add64/Sub64/Neg64 2. Nuke kS390_Add/SubWithOverflow32 3. Add Support for Load-On-Condition to optimize AssembleArchBoolean R=joransiu@ca.ibm.com, michael_dawson@ca.ibm.com, mbrandy@us.ibm.com, bjaideep@ca.ibm.com BUG= Review-Url: https://codereview.chromium.org/2220313002 Cr-Commit-Position: refs/heads/master@{#38443}
This commit is contained in:
parent
0d9ce3acff
commit
dc88458120
@ -235,26 +235,22 @@ Condition FlagsConditionToCondition(FlagsCondition condition, ArchOpcode op) {
|
|||||||
case kOverflow:
|
case kOverflow:
|
||||||
// Overflow checked for AddP/SubP only.
|
// Overflow checked for AddP/SubP only.
|
||||||
switch (op) {
|
switch (op) {
|
||||||
#if V8_TARGET_ARCH_S390X
|
case kS390_Add32:
|
||||||
case kS390_Add:
|
case kS390_Add64:
|
||||||
case kS390_Sub:
|
case kS390_Sub32:
|
||||||
#endif
|
case kS390_Sub64:
|
||||||
case kS390_AddWithOverflow32:
|
return overflow;
|
||||||
case kS390_SubWithOverflow32:
|
|
||||||
return lt;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case kNotOverflow:
|
case kNotOverflow:
|
||||||
switch (op) {
|
switch (op) {
|
||||||
#if V8_TARGET_ARCH_S390X
|
case kS390_Add32:
|
||||||
case kS390_Add:
|
case kS390_Add64:
|
||||||
case kS390_Sub:
|
case kS390_Sub32:
|
||||||
#endif
|
case kS390_Sub64:
|
||||||
case kS390_AddWithOverflow32:
|
return nooverflow;
|
||||||
case kS390_SubWithOverflow32:
|
|
||||||
return ge;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -290,56 +286,6 @@ Condition FlagsConditionToCondition(FlagsCondition condition, ArchOpcode op) {
|
|||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define ASSEMBLE_BINOP_INT(asm_instr_reg, asm_instr_imm) \
|
|
||||||
do { \
|
|
||||||
if (HasRegisterInput(instr, 1)) { \
|
|
||||||
__ asm_instr_reg(i.OutputRegister(), i.InputRegister(0), \
|
|
||||||
i.InputRegister(1)); \
|
|
||||||
} else { \
|
|
||||||
__ asm_instr_imm(i.OutputRegister(), i.InputRegister(0), \
|
|
||||||
i.InputInt32(1)); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define ASSEMBLE_ADD_WITH_OVERFLOW() \
|
|
||||||
do { \
|
|
||||||
if (HasRegisterInput(instr, 1)) { \
|
|
||||||
__ AddAndCheckForOverflow(i.OutputRegister(), i.InputRegister(0), \
|
|
||||||
i.InputRegister(1), kScratchReg, r0); \
|
|
||||||
} else { \
|
|
||||||
__ AddAndCheckForOverflow(i.OutputRegister(), i.InputRegister(0), \
|
|
||||||
i.InputInt32(1), kScratchReg, r0); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define ASSEMBLE_SUB_WITH_OVERFLOW() \
|
|
||||||
do { \
|
|
||||||
if (HasRegisterInput(instr, 1)) { \
|
|
||||||
__ SubAndCheckForOverflow(i.OutputRegister(), i.InputRegister(0), \
|
|
||||||
i.InputRegister(1), kScratchReg, r0); \
|
|
||||||
} else { \
|
|
||||||
__ AddAndCheckForOverflow(i.OutputRegister(), i.InputRegister(0), \
|
|
||||||
-i.InputInt32(1), kScratchReg, r0); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#if V8_TARGET_ARCH_S390X
|
|
||||||
#define ASSEMBLE_ADD_WITH_OVERFLOW32() \
|
|
||||||
do { \
|
|
||||||
ASSEMBLE_ADD_WITH_OVERFLOW(); \
|
|
||||||
__ LoadAndTestP_ExtendSrc(kScratchReg, kScratchReg); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define ASSEMBLE_SUB_WITH_OVERFLOW32() \
|
|
||||||
do { \
|
|
||||||
ASSEMBLE_SUB_WITH_OVERFLOW(); \
|
|
||||||
__ LoadAndTestP_ExtendSrc(kScratchReg, kScratchReg); \
|
|
||||||
} while (0)
|
|
||||||
#else
|
|
||||||
#define ASSEMBLE_ADD_WITH_OVERFLOW32 ASSEMBLE_ADD_WITH_OVERFLOW
|
|
||||||
#define ASSEMBLE_SUB_WITH_OVERFLOW32 ASSEMBLE_SUB_WITH_OVERFLOW
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define ASSEMBLE_COMPARE(cmp_instr, cmpl_instr) \
|
#define ASSEMBLE_COMPARE(cmp_instr, cmpl_instr) \
|
||||||
do { \
|
do { \
|
||||||
if (HasRegisterInput(instr, 1)) { \
|
if (HasRegisterInput(instr, 1)) { \
|
||||||
@ -1209,19 +1155,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case kS390_Add:
|
case kS390_Add32:
|
||||||
#if V8_TARGET_ARCH_S390X
|
ASSEMBLE_BINOP(Add32);
|
||||||
if (FlagsModeField::decode(instr->opcode()) != kFlags_none) {
|
__ LoadW(i.OutputRegister(), i.OutputRegister());
|
||||||
ASSEMBLE_ADD_WITH_OVERFLOW();
|
|
||||||
} else {
|
|
||||||
#endif
|
|
||||||
ASSEMBLE_BINOP(AddP);
|
|
||||||
#if V8_TARGET_ARCH_S390X
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
case kS390_AddWithOverflow32:
|
case kS390_Add64:
|
||||||
ASSEMBLE_ADD_WITH_OVERFLOW32();
|
ASSEMBLE_BINOP(AddP);
|
||||||
break;
|
break;
|
||||||
case kS390_AddFloat:
|
case kS390_AddFloat:
|
||||||
// Ensure we don't clobber right/InputReg(1)
|
// Ensure we don't clobber right/InputReg(1)
|
||||||
@ -1243,19 +1182,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
|||||||
__ adbr(i.OutputDoubleRegister(), i.InputDoubleRegister(1));
|
__ adbr(i.OutputDoubleRegister(), i.InputDoubleRegister(1));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case kS390_Sub:
|
case kS390_Sub32:
|
||||||
#if V8_TARGET_ARCH_S390X
|
ASSEMBLE_BINOP(Sub32);
|
||||||
if (FlagsModeField::decode(instr->opcode()) != kFlags_none) {
|
__ LoadW(i.OutputRegister(), i.OutputRegister());
|
||||||
ASSEMBLE_SUB_WITH_OVERFLOW();
|
|
||||||
} else {
|
|
||||||
#endif
|
|
||||||
ASSEMBLE_BINOP(SubP);
|
|
||||||
#if V8_TARGET_ARCH_S390X
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
case kS390_SubWithOverflow32:
|
case kS390_Sub64:
|
||||||
ASSEMBLE_SUB_WITH_OVERFLOW32();
|
ASSEMBLE_BINOP(SubP);
|
||||||
break;
|
break;
|
||||||
case kS390_SubFloat:
|
case kS390_SubFloat:
|
||||||
// OutputDoubleReg() = i.InputDoubleRegister(0) - i.InputDoubleRegister(1)
|
// OutputDoubleReg() = i.InputDoubleRegister(0) - i.InputDoubleRegister(1)
|
||||||
@ -1486,8 +1418,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
|||||||
__ Move(d1, d3);
|
__ Move(d1, d3);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case kS390_Neg:
|
case kS390_Neg32:
|
||||||
__ LoadComplementRR(i.OutputRegister(), i.InputRegister(0));
|
__ lcr(i.OutputRegister(), i.InputRegister(0));
|
||||||
|
__ LoadW(i.OutputRegister(), i.OutputRegister());
|
||||||
|
break;
|
||||||
|
case kS390_Neg64:
|
||||||
|
__ lcgr(i.OutputRegister(), i.InputRegister(0));
|
||||||
break;
|
break;
|
||||||
case kS390_MaxDouble:
|
case kS390_MaxDouble:
|
||||||
ASSEMBLE_FLOAT_MAX();
|
ASSEMBLE_FLOAT_MAX();
|
||||||
@ -2020,63 +1956,29 @@ void CodeGenerator::AssembleArchJump(RpoNumber target) {
|
|||||||
void CodeGenerator::AssembleArchBoolean(Instruction* instr,
|
void CodeGenerator::AssembleArchBoolean(Instruction* instr,
|
||||||
FlagsCondition condition) {
|
FlagsCondition condition) {
|
||||||
S390OperandConverter i(this, instr);
|
S390OperandConverter i(this, instr);
|
||||||
Label done;
|
|
||||||
ArchOpcode op = instr->arch_opcode();
|
ArchOpcode op = instr->arch_opcode();
|
||||||
bool check_unordered = (op == kS390_CmpDouble || kS390_CmpFloat);
|
bool check_unordered = (op == kS390_CmpDouble || op == kS390_CmpFloat);
|
||||||
|
|
||||||
// Overflow checked for add/sub only.
|
// Overflow checked for add/sub only.
|
||||||
DCHECK((condition != kOverflow && condition != kNotOverflow) ||
|
DCHECK((condition != kOverflow && condition != kNotOverflow) ||
|
||||||
(op == kS390_AddWithOverflow32 || op == kS390_SubWithOverflow32) ||
|
(op == kS390_Add32 || kS390_Add64 || op == kS390_Sub32 ||
|
||||||
(op == kS390_Add || op == kS390_Sub));
|
op == kS390_Sub64));
|
||||||
|
|
||||||
// Materialize a full 32-bit 1 or 0 value. The result register is always the
|
// Materialize a full 32-bit 1 or 0 value. The result register is always the
|
||||||
// last output of the instruction.
|
// last output of the instruction.
|
||||||
DCHECK_NE(0u, instr->OutputCount());
|
DCHECK_NE(0u, instr->OutputCount());
|
||||||
Register reg = i.OutputRegister(instr->OutputCount() - 1);
|
Register reg = i.OutputRegister(instr->OutputCount() - 1);
|
||||||
Condition cond = FlagsConditionToCondition(condition, op);
|
Condition cond = FlagsConditionToCondition(condition, op);
|
||||||
switch (cond) {
|
Label done;
|
||||||
case ne:
|
|
||||||
case ge:
|
|
||||||
case gt:
|
|
||||||
if (check_unordered) {
|
if (check_unordered) {
|
||||||
__ LoadImmP(reg, Operand(1));
|
__ LoadImmP(reg, (cond == eq || cond == le || cond == lt) ? Operand::Zero()
|
||||||
__ LoadImmP(kScratchReg, Operand::Zero());
|
: Operand(1));
|
||||||
__ bunordered(&done);
|
__ bunordered(&done);
|
||||||
Label cond_true;
|
|
||||||
__ b(cond, &cond_true, Label::kNear);
|
|
||||||
__ LoadRR(reg, kScratchReg);
|
|
||||||
__ bind(&cond_true);
|
|
||||||
} else {
|
|
||||||
Label cond_true, done_here;
|
|
||||||
__ LoadImmP(reg, Operand(1));
|
|
||||||
__ b(cond, &cond_true, Label::kNear);
|
|
||||||
__ LoadImmP(reg, Operand::Zero());
|
|
||||||
__ bind(&cond_true);
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case eq:
|
|
||||||
case lt:
|
|
||||||
case le:
|
|
||||||
if (check_unordered) {
|
|
||||||
__ LoadImmP(reg, Operand::Zero());
|
__ LoadImmP(reg, Operand::Zero());
|
||||||
__ LoadImmP(kScratchReg, Operand(1));
|
__ LoadImmP(kScratchReg, Operand(1));
|
||||||
__ bunordered(&done);
|
// locr is sufficient since reg's upper 32 is guarrantee to be 0
|
||||||
Label cond_false;
|
__ locr(cond, reg, kScratchReg);
|
||||||
__ b(NegateCondition(cond), &cond_false, Label::kNear);
|
|
||||||
__ LoadRR(reg, kScratchReg);
|
|
||||||
__ bind(&cond_false);
|
|
||||||
} else {
|
|
||||||
__ LoadImmP(reg, Operand::Zero());
|
|
||||||
Label cond_false;
|
|
||||||
__ b(NegateCondition(cond), &cond_false, Label::kNear);
|
|
||||||
__ LoadImmP(reg, Operand(1));
|
|
||||||
__ bind(&cond_false);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
UNREACHABLE();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
__ bind(&done);
|
__ bind(&done);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,13 +35,13 @@ namespace compiler {
|
|||||||
V(S390_RotLeftAndClear64) \
|
V(S390_RotLeftAndClear64) \
|
||||||
V(S390_RotLeftAndClearLeft64) \
|
V(S390_RotLeftAndClearLeft64) \
|
||||||
V(S390_RotLeftAndClearRight64) \
|
V(S390_RotLeftAndClearRight64) \
|
||||||
V(S390_Add) \
|
V(S390_Add32) \
|
||||||
V(S390_AddWithOverflow32) \
|
V(S390_Add64) \
|
||||||
V(S390_AddPair) \
|
V(S390_AddPair) \
|
||||||
V(S390_AddFloat) \
|
V(S390_AddFloat) \
|
||||||
V(S390_AddDouble) \
|
V(S390_AddDouble) \
|
||||||
V(S390_Sub) \
|
V(S390_Sub32) \
|
||||||
V(S390_SubWithOverflow32) \
|
V(S390_Sub64) \
|
||||||
V(S390_SubFloat) \
|
V(S390_SubFloat) \
|
||||||
V(S390_SubDouble) \
|
V(S390_SubDouble) \
|
||||||
V(S390_SubPair) \
|
V(S390_SubPair) \
|
||||||
@ -64,7 +64,8 @@ namespace compiler {
|
|||||||
V(S390_ModU32) \
|
V(S390_ModU32) \
|
||||||
V(S390_ModU64) \
|
V(S390_ModU64) \
|
||||||
V(S390_ModDouble) \
|
V(S390_ModDouble) \
|
||||||
V(S390_Neg) \
|
V(S390_Neg32) \
|
||||||
|
V(S390_Neg64) \
|
||||||
V(S390_NegDouble) \
|
V(S390_NegDouble) \
|
||||||
V(S390_SqrtFloat) \
|
V(S390_SqrtFloat) \
|
||||||
V(S390_FloorFloat) \
|
V(S390_FloorFloat) \
|
||||||
|
@ -36,13 +36,13 @@ int InstructionScheduler::GetTargetInstructionFlags(
|
|||||||
case kS390_RotLeftAndClear64:
|
case kS390_RotLeftAndClear64:
|
||||||
case kS390_RotLeftAndClearLeft64:
|
case kS390_RotLeftAndClearLeft64:
|
||||||
case kS390_RotLeftAndClearRight64:
|
case kS390_RotLeftAndClearRight64:
|
||||||
case kS390_Add:
|
case kS390_Add32:
|
||||||
case kS390_AddWithOverflow32:
|
case kS390_Add64:
|
||||||
case kS390_AddPair:
|
case kS390_AddPair:
|
||||||
case kS390_AddFloat:
|
case kS390_AddFloat:
|
||||||
case kS390_AddDouble:
|
case kS390_AddDouble:
|
||||||
case kS390_Sub:
|
case kS390_Sub32:
|
||||||
case kS390_SubWithOverflow32:
|
case kS390_Sub64:
|
||||||
case kS390_SubPair:
|
case kS390_SubPair:
|
||||||
case kS390_MulPair:
|
case kS390_MulPair:
|
||||||
case kS390_SubFloat:
|
case kS390_SubFloat:
|
||||||
@ -65,7 +65,8 @@ int InstructionScheduler::GetTargetInstructionFlags(
|
|||||||
case kS390_ModU32:
|
case kS390_ModU32:
|
||||||
case kS390_ModU64:
|
case kS390_ModU64:
|
||||||
case kS390_ModDouble:
|
case kS390_ModDouble:
|
||||||
case kS390_Neg:
|
case kS390_Neg32:
|
||||||
|
case kS390_Neg64:
|
||||||
case kS390_NegDouble:
|
case kS390_NegDouble:
|
||||||
case kS390_SqrtFloat:
|
case kS390_SqrtFloat:
|
||||||
case kS390_FloorFloat:
|
case kS390_FloorFloat:
|
||||||
|
@ -874,12 +874,12 @@ void InstructionSelector::VisitWord32ReverseBytes(Node* node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void InstructionSelector::VisitInt32Add(Node* node) {
|
void InstructionSelector::VisitInt32Add(Node* node) {
|
||||||
VisitBinop<Int32BinopMatcher>(this, node, kS390_Add, kInt16Imm);
|
VisitBinop<Int32BinopMatcher>(this, node, kS390_Add32, kInt16Imm);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if V8_TARGET_ARCH_S390X
|
#if V8_TARGET_ARCH_S390X
|
||||||
void InstructionSelector::VisitInt64Add(Node* node) {
|
void InstructionSelector::VisitInt64Add(Node* node) {
|
||||||
VisitBinop<Int64BinopMatcher>(this, node, kS390_Add, kInt16Imm);
|
VisitBinop<Int64BinopMatcher>(this, node, kS390_Add64, kInt16Imm);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -887,9 +887,10 @@ void InstructionSelector::VisitInt32Sub(Node* node) {
|
|||||||
S390OperandGenerator g(this);
|
S390OperandGenerator g(this);
|
||||||
Int32BinopMatcher m(node);
|
Int32BinopMatcher m(node);
|
||||||
if (m.left().Is(0)) {
|
if (m.left().Is(0)) {
|
||||||
Emit(kS390_Neg, g.DefineAsRegister(node), g.UseRegister(m.right().node()));
|
Emit(kS390_Neg32, g.DefineAsRegister(node),
|
||||||
|
g.UseRegister(m.right().node()));
|
||||||
} else {
|
} else {
|
||||||
VisitBinop<Int32BinopMatcher>(this, node, kS390_Sub, kInt16Imm_Negate);
|
VisitBinop<Int32BinopMatcher>(this, node, kS390_Sub32, kInt16Imm_Negate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -898,9 +899,10 @@ void InstructionSelector::VisitInt64Sub(Node* node) {
|
|||||||
S390OperandGenerator g(this);
|
S390OperandGenerator g(this);
|
||||||
Int64BinopMatcher m(node);
|
Int64BinopMatcher m(node);
|
||||||
if (m.left().Is(0)) {
|
if (m.left().Is(0)) {
|
||||||
Emit(kS390_Neg, g.DefineAsRegister(node), g.UseRegister(m.right().node()));
|
Emit(kS390_Neg64, g.DefineAsRegister(node),
|
||||||
|
g.UseRegister(m.right().node()));
|
||||||
} else {
|
} else {
|
||||||
VisitBinop<Int64BinopMatcher>(this, node, kS390_Sub, kInt16Imm_Negate);
|
VisitBinop<Int64BinopMatcher>(this, node, kS390_Sub64, kInt16Imm_Negate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1284,44 +1286,44 @@ void InstructionSelector::VisitFloat64Neg(Node* node) { UNREACHABLE(); }
|
|||||||
void InstructionSelector::VisitInt32AddWithOverflow(Node* node) {
|
void InstructionSelector::VisitInt32AddWithOverflow(Node* node) {
|
||||||
if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
|
if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
|
||||||
FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
|
FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
|
||||||
return VisitBinop<Int32BinopMatcher>(this, node, kS390_AddWithOverflow32,
|
return VisitBinop<Int32BinopMatcher>(this, node, kS390_Add32, kInt16Imm,
|
||||||
kInt16Imm, &cont);
|
&cont);
|
||||||
}
|
}
|
||||||
FlagsContinuation cont;
|
FlagsContinuation cont;
|
||||||
VisitBinop<Int32BinopMatcher>(this, node, kS390_AddWithOverflow32, kInt16Imm,
|
VisitBinop<Int32BinopMatcher>(this, node, kS390_Add32, kInt16Imm, &cont);
|
||||||
&cont);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstructionSelector::VisitInt32SubWithOverflow(Node* node) {
|
void InstructionSelector::VisitInt32SubWithOverflow(Node* node) {
|
||||||
if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
|
if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
|
||||||
FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
|
FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
|
||||||
return VisitBinop<Int32BinopMatcher>(this, node, kS390_SubWithOverflow32,
|
return VisitBinop<Int32BinopMatcher>(this, node, kS390_Sub32,
|
||||||
kInt16Imm_Negate, &cont);
|
kInt16Imm_Negate, &cont);
|
||||||
}
|
}
|
||||||
FlagsContinuation cont;
|
FlagsContinuation cont;
|
||||||
VisitBinop<Int32BinopMatcher>(this, node, kS390_SubWithOverflow32,
|
VisitBinop<Int32BinopMatcher>(this, node, kS390_Sub32, kInt16Imm_Negate,
|
||||||
kInt16Imm_Negate, &cont);
|
&cont);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if V8_TARGET_ARCH_S390X
|
#if V8_TARGET_ARCH_S390X
|
||||||
void InstructionSelector::VisitInt64AddWithOverflow(Node* node) {
|
void InstructionSelector::VisitInt64AddWithOverflow(Node* node) {
|
||||||
if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
|
if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
|
||||||
FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
|
FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
|
||||||
return VisitBinop<Int64BinopMatcher>(this, node, kS390_Add, kInt16Imm,
|
return VisitBinop<Int64BinopMatcher>(this, node, kS390_Add64, kInt16Imm,
|
||||||
&cont);
|
&cont);
|
||||||
}
|
}
|
||||||
FlagsContinuation cont;
|
FlagsContinuation cont;
|
||||||
VisitBinop<Int64BinopMatcher>(this, node, kS390_Add, kInt16Imm, &cont);
|
VisitBinop<Int64BinopMatcher>(this, node, kS390_Add64, kInt16Imm, &cont);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstructionSelector::VisitInt64SubWithOverflow(Node* node) {
|
void InstructionSelector::VisitInt64SubWithOverflow(Node* node) {
|
||||||
if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
|
if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
|
||||||
FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
|
FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
|
||||||
return VisitBinop<Int64BinopMatcher>(this, node, kS390_Sub,
|
return VisitBinop<Int64BinopMatcher>(this, node, kS390_Sub64,
|
||||||
kInt16Imm_Negate, &cont);
|
kInt16Imm_Negate, &cont);
|
||||||
}
|
}
|
||||||
FlagsContinuation cont;
|
FlagsContinuation cont;
|
||||||
VisitBinop<Int64BinopMatcher>(this, node, kS390_Sub, kInt16Imm_Negate, &cont);
|
VisitBinop<Int64BinopMatcher>(this, node, kS390_Sub64, kInt16Imm_Negate,
|
||||||
|
&cont);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1497,24 +1499,23 @@ void VisitWordCompareZero(InstructionSelector* selector, Node* user,
|
|||||||
case IrOpcode::kInt32AddWithOverflow:
|
case IrOpcode::kInt32AddWithOverflow:
|
||||||
cont->OverwriteAndNegateIfEqual(kOverflow);
|
cont->OverwriteAndNegateIfEqual(kOverflow);
|
||||||
return VisitBinop<Int32BinopMatcher>(
|
return VisitBinop<Int32BinopMatcher>(
|
||||||
selector, node, kS390_AddWithOverflow32, kInt16Imm, cont);
|
selector, node, kS390_Add32, kInt16Imm, cont);
|
||||||
case IrOpcode::kInt32SubWithOverflow:
|
case IrOpcode::kInt32SubWithOverflow:
|
||||||
cont->OverwriteAndNegateIfEqual(kOverflow);
|
cont->OverwriteAndNegateIfEqual(kOverflow);
|
||||||
return VisitBinop<Int32BinopMatcher>(selector, node,
|
return VisitBinop<Int32BinopMatcher>(
|
||||||
kS390_SubWithOverflow32,
|
selector, node, kS390_Sub32, kInt16Imm_Negate, cont);
|
||||||
kInt16Imm_Negate, cont);
|
|
||||||
case IrOpcode::kInt32MulWithOverflow:
|
case IrOpcode::kInt32MulWithOverflow:
|
||||||
cont->OverwriteAndNegateIfEqual(kNotEqual);
|
cont->OverwriteAndNegateIfEqual(kNotEqual);
|
||||||
return EmitInt32MulWithOverflow(selector, node, cont);
|
return EmitInt32MulWithOverflow(selector, node, cont);
|
||||||
#if V8_TARGET_ARCH_S390X
|
#if V8_TARGET_ARCH_S390X
|
||||||
case IrOpcode::kInt64AddWithOverflow:
|
case IrOpcode::kInt64AddWithOverflow:
|
||||||
cont->OverwriteAndNegateIfEqual(kOverflow);
|
cont->OverwriteAndNegateIfEqual(kOverflow);
|
||||||
return VisitBinop<Int64BinopMatcher>(selector, node, kS390_Add,
|
return VisitBinop<Int64BinopMatcher>(
|
||||||
kInt16Imm, cont);
|
selector, node, kS390_Add64, kInt16Imm, cont);
|
||||||
case IrOpcode::kInt64SubWithOverflow:
|
case IrOpcode::kInt64SubWithOverflow:
|
||||||
cont->OverwriteAndNegateIfEqual(kOverflow);
|
cont->OverwriteAndNegateIfEqual(kOverflow);
|
||||||
return VisitBinop<Int64BinopMatcher>(selector, node, kS390_Sub,
|
return VisitBinop<Int64BinopMatcher>(
|
||||||
kInt16Imm_Negate, cont);
|
selector, node, kS390_Sub64, kInt16Imm_Negate, cont);
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -1610,7 +1611,7 @@ void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) {
|
|||||||
InstructionOperand index_operand = value_operand;
|
InstructionOperand index_operand = value_operand;
|
||||||
if (sw.min_value) {
|
if (sw.min_value) {
|
||||||
index_operand = g.TempRegister();
|
index_operand = g.TempRegister();
|
||||||
Emit(kS390_Sub, index_operand, value_operand,
|
Emit(kS390_Sub32, index_operand, value_operand,
|
||||||
g.TempImmediate(sw.min_value));
|
g.TempImmediate(sw.min_value));
|
||||||
}
|
}
|
||||||
// Generate a table lookup.
|
// Generate a table lookup.
|
||||||
|
@ -1908,14 +1908,14 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Token::ADD: {
|
case Token::ADD: {
|
||||||
__ AddAndCheckForOverflow(scratch1, left, right, scratch2, r0);
|
__ AddP(scratch1, left, right);
|
||||||
__ BranchOnOverflow(&stub_call);
|
__ b(overflow, &stub_call);
|
||||||
__ LoadRR(right, scratch1);
|
__ LoadRR(right, scratch1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Token::SUB: {
|
case Token::SUB: {
|
||||||
__ SubAndCheckForOverflow(scratch1, left, right, scratch2, r0);
|
__ SubP(scratch1, left, right);
|
||||||
__ BranchOnOverflow(&stub_call);
|
__ b(overflow, &stub_call);
|
||||||
__ LoadRR(right, scratch1);
|
__ LoadRR(right, scratch1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -3204,10 +3204,10 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
|||||||
Register scratch1 = r3;
|
Register scratch1 = r3;
|
||||||
Register scratch2 = r4;
|
Register scratch2 = r4;
|
||||||
__ LoadSmiLiteral(scratch1, Smi::FromInt(count_value));
|
__ LoadSmiLiteral(scratch1, Smi::FromInt(count_value));
|
||||||
__ AddAndCheckForOverflow(r2, r2, scratch1, scratch2, r0);
|
__ AddP(scratch2, r2, scratch1);
|
||||||
__ BranchOnNoOverflow(&done);
|
__ LoadOnConditionP(nooverflow, r2, scratch2);
|
||||||
|
__ b(nooverflow, &done);
|
||||||
// Call stub. Undo operation first.
|
// Call stub. Undo operation first.
|
||||||
__ SubP(r2, r2, scratch1);
|
|
||||||
__ b(&stub_call);
|
__ b(&stub_call);
|
||||||
__ bind(&slow);
|
__ bind(&slow);
|
||||||
}
|
}
|
||||||
|
@ -971,6 +971,20 @@ void Assembler::rxy_form(Opcode op, Register r1, Register x2, Register b2,
|
|||||||
emit6bytes(code);
|
emit6bytes(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Assembler::rxy_form(Opcode op, Register r1, Condition m3, Register b2,
|
||||||
|
Disp d2) {
|
||||||
|
DCHECK(is_int20(d2));
|
||||||
|
DCHECK(is_uint16(op));
|
||||||
|
uint64_t code = (static_cast<uint64_t>(op & 0xFF00)) * B32 |
|
||||||
|
(static_cast<uint64_t>(r1.code())) * B36 |
|
||||||
|
(static_cast<uint64_t>(m3 & 0xF)) * B32 |
|
||||||
|
(static_cast<uint64_t>(b2.code())) * B28 |
|
||||||
|
(static_cast<uint64_t>(d2 & 0x0FFF)) * B16 |
|
||||||
|
(static_cast<uint64_t>(d2 & 0x0FF000)) >> 4 |
|
||||||
|
(static_cast<uint64_t>(op & 0x00FF));
|
||||||
|
emit6bytes(code);
|
||||||
|
}
|
||||||
|
|
||||||
void Assembler::rxy_form(Opcode op, DoubleRegister r1, Register x2, Register b2,
|
void Assembler::rxy_form(Opcode op, DoubleRegister r1, Register x2, Register b2,
|
||||||
Disp d2) {
|
Disp d2) {
|
||||||
DCHECK(is_int20(d2));
|
DCHECK(is_int20(d2));
|
||||||
@ -1418,7 +1432,6 @@ RIL1_FORM_EMIT(llihf, LLIHF)
|
|||||||
RIL1_FORM_EMIT(llilf, LLILF)
|
RIL1_FORM_EMIT(llilf, LLILF)
|
||||||
RRE_FORM_EMIT(lngr, LNGR)
|
RRE_FORM_EMIT(lngr, LNGR)
|
||||||
RR_FORM_EMIT(lnr, LNR)
|
RR_FORM_EMIT(lnr, LNR)
|
||||||
RSY1_FORM_EMIT(loc, LOC)
|
|
||||||
RRE_FORM_EMIT(lrvr, LRVR)
|
RRE_FORM_EMIT(lrvr, LRVR)
|
||||||
RRE_FORM_EMIT(lrvgr, LRVGR)
|
RRE_FORM_EMIT(lrvgr, LRVGR)
|
||||||
RXY_FORM_EMIT(lrv, LRV)
|
RXY_FORM_EMIT(lrv, LRV)
|
||||||
@ -1604,6 +1617,26 @@ void Assembler::llhr(Register r1, Register r2) { rre_form(LLHR, r1, r2); }
|
|||||||
// Load Logical halfword Register-Register (64)
|
// Load Logical halfword Register-Register (64)
|
||||||
void Assembler::llghr(Register r1, Register r2) { rre_form(LLGHR, r1, r2); }
|
void Assembler::llghr(Register r1, Register r2) { rre_form(LLGHR, r1, r2); }
|
||||||
|
|
||||||
|
// Load On Condition R-R (32)
|
||||||
|
void Assembler::locr(Condition m3, Register r1, Register r2) {
|
||||||
|
rrf2_form(LOCR << 16 | m3 * B12 | r1.code() * B4 | r2.code());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load On Condition R-R (64)
|
||||||
|
void Assembler::locgr(Condition m3, Register r1, Register r2) {
|
||||||
|
rrf2_form(LOCGR << 16 | m3 * B12 | r1.code() * B4 | r2.code());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load On Condition R-M (32)
|
||||||
|
void Assembler::loc(Condition m3, Register r1, const MemOperand& src) {
|
||||||
|
rxy_form(LOC, r1, m3, src.rb(), src.offset());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load On Condition R-M (64)
|
||||||
|
void Assembler::locg(Condition m3, Register r1, const MemOperand& src) {
|
||||||
|
rxy_form(LOCG, r1, m3, src.rb(), src.offset());
|
||||||
|
}
|
||||||
|
|
||||||
// -------------------
|
// -------------------
|
||||||
// Branch Instructions
|
// Branch Instructions
|
||||||
// -------------------
|
// -------------------
|
||||||
|
@ -875,6 +875,12 @@ class Assembler : public AssemblerBase {
|
|||||||
void lmy(Register r1, Register r2, const MemOperand& src);
|
void lmy(Register r1, Register r2, const MemOperand& src);
|
||||||
void lmg(Register r1, Register r2, const MemOperand& src);
|
void lmg(Register r1, Register r2, const MemOperand& src);
|
||||||
|
|
||||||
|
// Load On Condition Instructions
|
||||||
|
void locr(Condition m3, Register r1, Register r2);
|
||||||
|
void locgr(Condition m3, Register r1, Register r2);
|
||||||
|
void loc(Condition m3, Register r1, const MemOperand& src);
|
||||||
|
void locg(Condition m3, Register r1, const MemOperand& src);
|
||||||
|
|
||||||
// Store Instructions
|
// Store Instructions
|
||||||
void st(Register r, const MemOperand& src);
|
void st(Register r, const MemOperand& src);
|
||||||
void stc(Register r, const MemOperand& src);
|
void stc(Register r, const MemOperand& src);
|
||||||
@ -1416,6 +1422,8 @@ class Assembler : public AssemblerBase {
|
|||||||
|
|
||||||
inline void rxy_form(Opcode op, Register r1, Register x2, Register b2,
|
inline void rxy_form(Opcode op, Register r1, Register x2, Register b2,
|
||||||
Disp d2);
|
Disp d2);
|
||||||
|
inline void rxy_form(Opcode op, Register r1, Condition m3, Register b2,
|
||||||
|
Disp d2);
|
||||||
inline void rxy_form(Opcode op, DoubleRegister r1, Register x2, Register b2,
|
inline void rxy_form(Opcode op, DoubleRegister r1, Register x2, Register b2,
|
||||||
Disp d2);
|
Disp d2);
|
||||||
|
|
||||||
|
@ -820,6 +820,12 @@ bool Decoder::DecodeFourByte(Instruction* instr) {
|
|||||||
case LLGHR:
|
case LLGHR:
|
||||||
Format(instr, "llghr\t'r5,'r6");
|
Format(instr, "llghr\t'r5,'r6");
|
||||||
break;
|
break;
|
||||||
|
case LOCR:
|
||||||
|
Format(instr, "locr\t'm1,'r5,'r6");
|
||||||
|
break;
|
||||||
|
case LOCGR:
|
||||||
|
Format(instr, "locgr\t'm1,'r5,'r6");
|
||||||
|
break;
|
||||||
case LNGR:
|
case LNGR:
|
||||||
Format(instr, "lngr\t'r5,'r6");
|
Format(instr, "lngr\t'r5,'r6");
|
||||||
break;
|
break;
|
||||||
@ -1130,6 +1136,12 @@ bool Decoder::DecodeSixByte(Instruction* instr) {
|
|||||||
case RISBGN:
|
case RISBGN:
|
||||||
Format(instr, "risbgn\t'r1,'r2,'i9,'ia,'ib");
|
Format(instr, "risbgn\t'r1,'r2,'i9,'ia,'ib");
|
||||||
break;
|
break;
|
||||||
|
case LOCG:
|
||||||
|
Format(instr, "locg\t'm2,'r1,'d2('r3)");
|
||||||
|
break;
|
||||||
|
case LOC:
|
||||||
|
Format(instr, "loc\t'm2,'r1,'d2('r3)");
|
||||||
|
break;
|
||||||
case LMY:
|
case LMY:
|
||||||
Format(instr, "lmy\t'r1,'r2,'d2('r3)");
|
Format(instr, "lmy\t'r1,'r2,'d2('r3)");
|
||||||
break;
|
break;
|
||||||
|
@ -2188,89 +2188,6 @@ void MacroAssembler::StoreNumberToDoubleElements(
|
|||||||
FixedDoubleArray::kHeaderSize - elements_offset));
|
FixedDoubleArray::kHeaderSize - elements_offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroAssembler::AddAndCheckForOverflow(Register dst, Register left,
|
|
||||||
Register right,
|
|
||||||
Register overflow_dst,
|
|
||||||
Register scratch) {
|
|
||||||
DCHECK(!dst.is(overflow_dst));
|
|
||||||
DCHECK(!dst.is(scratch));
|
|
||||||
DCHECK(!overflow_dst.is(scratch));
|
|
||||||
DCHECK(!overflow_dst.is(left));
|
|
||||||
DCHECK(!overflow_dst.is(right));
|
|
||||||
|
|
||||||
// TODO(joransiu): Optimize paths for left == right.
|
|
||||||
bool left_is_right = left.is(right);
|
|
||||||
|
|
||||||
// C = A+B; C overflows if A/B have same sign and C has diff sign than A
|
|
||||||
if (dst.is(left)) {
|
|
||||||
LoadRR(scratch, left); // Preserve left.
|
|
||||||
AddP(dst, left, right); // Left is overwritten.
|
|
||||||
XorP(overflow_dst, scratch, dst); // Original left.
|
|
||||||
if (!left_is_right) XorP(scratch, dst, right);
|
|
||||||
} else if (dst.is(right)) {
|
|
||||||
LoadRR(scratch, right); // Preserve right.
|
|
||||||
AddP(dst, left, right); // Right is overwritten.
|
|
||||||
XorP(overflow_dst, dst, left);
|
|
||||||
if (!left_is_right) XorP(scratch, dst, scratch);
|
|
||||||
} else {
|
|
||||||
AddP(dst, left, right);
|
|
||||||
XorP(overflow_dst, dst, left);
|
|
||||||
if (!left_is_right) XorP(scratch, dst, right);
|
|
||||||
}
|
|
||||||
if (!left_is_right) AndP(overflow_dst, scratch, overflow_dst);
|
|
||||||
LoadAndTestRR(overflow_dst, overflow_dst);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacroAssembler::AddAndCheckForOverflow(Register dst, Register left,
|
|
||||||
intptr_t right,
|
|
||||||
Register overflow_dst,
|
|
||||||
Register scratch) {
|
|
||||||
DCHECK(!dst.is(overflow_dst));
|
|
||||||
DCHECK(!dst.is(scratch));
|
|
||||||
DCHECK(!overflow_dst.is(scratch));
|
|
||||||
DCHECK(!overflow_dst.is(left));
|
|
||||||
|
|
||||||
mov(r1, Operand(right));
|
|
||||||
AddAndCheckForOverflow(dst, left, r1, overflow_dst, scratch);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacroAssembler::SubAndCheckForOverflow(Register dst, Register left,
|
|
||||||
Register right,
|
|
||||||
Register overflow_dst,
|
|
||||||
Register scratch) {
|
|
||||||
DCHECK(!dst.is(overflow_dst));
|
|
||||||
DCHECK(!dst.is(scratch));
|
|
||||||
DCHECK(!overflow_dst.is(scratch));
|
|
||||||
DCHECK(!overflow_dst.is(left));
|
|
||||||
DCHECK(!overflow_dst.is(right));
|
|
||||||
|
|
||||||
// C = A-B; C overflows if A/B have diff signs and C has diff sign than A
|
|
||||||
if (dst.is(left)) {
|
|
||||||
LoadRR(scratch, left); // Preserve left.
|
|
||||||
SubP(dst, left, right); // Left is overwritten.
|
|
||||||
XorP(overflow_dst, dst, scratch);
|
|
||||||
XorP(scratch, right);
|
|
||||||
AndP(overflow_dst, scratch /*, SetRC*/);
|
|
||||||
LoadAndTestRR(overflow_dst, overflow_dst);
|
|
||||||
// Should be okay to remove rc
|
|
||||||
} else if (dst.is(right)) {
|
|
||||||
LoadRR(scratch, right); // Preserve right.
|
|
||||||
SubP(dst, left, right); // Right is overwritten.
|
|
||||||
XorP(overflow_dst, dst, left);
|
|
||||||
XorP(scratch, left);
|
|
||||||
AndP(overflow_dst, scratch /*, SetRC*/);
|
|
||||||
LoadAndTestRR(overflow_dst, overflow_dst);
|
|
||||||
// Should be okay to remove rc
|
|
||||||
} else {
|
|
||||||
SubP(dst, left, right);
|
|
||||||
XorP(overflow_dst, dst, left);
|
|
||||||
XorP(scratch, left, right);
|
|
||||||
AndP(overflow_dst, scratch /*, SetRC*/);
|
|
||||||
LoadAndTestRR(overflow_dst, overflow_dst);
|
|
||||||
// Should be okay to remove rc
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacroAssembler::CompareMap(Register obj, Register scratch, Handle<Map> map,
|
void MacroAssembler::CompareMap(Register obj, Register scratch, Handle<Map> map,
|
||||||
Label* early_success) {
|
Label* early_success) {
|
||||||
LoadP(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
|
LoadP(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
|
||||||
@ -4159,15 +4076,18 @@ void MacroAssembler::SubP_ExtendSrc(Register dst, Register src) {
|
|||||||
// Subtract 32-bit (Register = Register - Register)
|
// Subtract 32-bit (Register = Register - Register)
|
||||||
void MacroAssembler::Sub32(Register dst, Register src1, Register src2) {
|
void MacroAssembler::Sub32(Register dst, Register src1, Register src2) {
|
||||||
// Use non-clobbering version if possible
|
// Use non-clobbering version if possible
|
||||||
if (CpuFeatures::IsSupported(DISTINCT_OPS) && !dst.is(src1)) {
|
if (CpuFeatures::IsSupported(DISTINCT_OPS)) {
|
||||||
srk(dst, src1, src2);
|
srk(dst, src1, src2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!dst.is(src1) && !dst.is(src2)) lr(dst, src1);
|
if (!dst.is(src1) && !dst.is(src2)) lr(dst, src1);
|
||||||
// In scenario where we have dst = src - dst, we need to swap and negate
|
// In scenario where we have dst = src - dst, we need to swap and negate
|
||||||
if (!dst.is(src1) && dst.is(src2)) {
|
if (!dst.is(src1) && dst.is(src2)) {
|
||||||
sr(dst, src1); // dst = (dst - src)
|
Label done;
|
||||||
lcr(dst, dst); // dst = -dst
|
lcr(dst, dst); // dst = -dst
|
||||||
|
b(overflow, &done);
|
||||||
|
ar(dst, src1); // dst = dst + src
|
||||||
|
bind(&done);
|
||||||
} else {
|
} else {
|
||||||
sr(dst, src2);
|
sr(dst, src2);
|
||||||
}
|
}
|
||||||
@ -4176,15 +4096,18 @@ void MacroAssembler::Sub32(Register dst, Register src1, Register src2) {
|
|||||||
// Subtract Pointer Sized (Register = Register - Register)
|
// Subtract Pointer Sized (Register = Register - Register)
|
||||||
void MacroAssembler::SubP(Register dst, Register src1, Register src2) {
|
void MacroAssembler::SubP(Register dst, Register src1, Register src2) {
|
||||||
// Use non-clobbering version if possible
|
// Use non-clobbering version if possible
|
||||||
if (CpuFeatures::IsSupported(DISTINCT_OPS) && !dst.is(src1)) {
|
if (CpuFeatures::IsSupported(DISTINCT_OPS)) {
|
||||||
SubP_RRR(dst, src1, src2);
|
SubP_RRR(dst, src1, src2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!dst.is(src1) && !dst.is(src2)) LoadRR(dst, src1);
|
if (!dst.is(src1) && !dst.is(src2)) LoadRR(dst, src1);
|
||||||
// In scenario where we have dst = src - dst, we need to swap and negate
|
// In scenario where we have dst = src - dst, we need to swap and negate
|
||||||
if (!dst.is(src1) && dst.is(src2)) {
|
if (!dst.is(src1) && dst.is(src2)) {
|
||||||
SubP(dst, src1); // dst = (dst - src)
|
Label done;
|
||||||
LoadComplementRR(dst, dst); // dst = -dst
|
LoadComplementRR(dst, dst); // dst = -dst
|
||||||
|
b(overflow, &done);
|
||||||
|
AddP(dst, src1); // dst = dst + src
|
||||||
|
bind(&done);
|
||||||
} else {
|
} else {
|
||||||
SubP(dst, src2);
|
SubP(dst, src2);
|
||||||
}
|
}
|
||||||
@ -4202,8 +4125,8 @@ void MacroAssembler::SubP_ExtendSrc(Register dst, Register src1,
|
|||||||
// In scenario where we have dst = src - dst, we need to swap and negate
|
// In scenario where we have dst = src - dst, we need to swap and negate
|
||||||
if (!dst.is(src1) && dst.is(src2)) {
|
if (!dst.is(src1) && dst.is(src2)) {
|
||||||
lgfr(dst, dst); // Sign extend this operand first.
|
lgfr(dst, dst); // Sign extend this operand first.
|
||||||
SubP(dst, src1); // dst = (dst - src)
|
|
||||||
LoadComplementRR(dst, dst); // dst = -dst
|
LoadComplementRR(dst, dst); // dst = -dst
|
||||||
|
AddP(dst, src1); // dst = -dst + src
|
||||||
} else {
|
} else {
|
||||||
sgfr(dst, src2);
|
sgfr(dst, src2);
|
||||||
}
|
}
|
||||||
@ -5182,6 +5105,16 @@ void MacroAssembler::LoadAndTestP(Register dst, const MemOperand& mem) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load On Condition Pointer Sized (Reg <- Reg)
|
||||||
|
void MacroAssembler::LoadOnConditionP(Condition cond, Register dst,
|
||||||
|
Register src) {
|
||||||
|
#if V8_TARGET_ARCH_S390X
|
||||||
|
locgr(cond, dst, src);
|
||||||
|
#else
|
||||||
|
locr(cond, dst, src);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// Load Double Precision (64-bit) Floating Point number from memory
|
// Load Double Precision (64-bit) Floating Point number from memory
|
||||||
void MacroAssembler::LoadDouble(DoubleRegister dst, const MemOperand& mem) {
|
void MacroAssembler::LoadDouble(DoubleRegister dst, const MemOperand& mem) {
|
||||||
// for 32bit and 64bit we all use 64bit floating point regs
|
// for 32bit and 64bit we all use 64bit floating point regs
|
||||||
|
@ -353,6 +353,9 @@ class MacroAssembler : public Assembler {
|
|||||||
void LoadFloat32(DoubleRegister dst, const MemOperand& opnd);
|
void LoadFloat32(DoubleRegister dst, const MemOperand& opnd);
|
||||||
void LoadFloat32ConvertToDouble(DoubleRegister dst, const MemOperand& mem);
|
void LoadFloat32ConvertToDouble(DoubleRegister dst, const MemOperand& mem);
|
||||||
|
|
||||||
|
// Load On Condition
|
||||||
|
void LoadOnConditionP(Condition cond, Register dst, Register src);
|
||||||
|
|
||||||
// Store Floating Point
|
// Store Floating Point
|
||||||
void StoreDouble(DoubleRegister dst, const MemOperand& opnd);
|
void StoreDouble(DoubleRegister dst, const MemOperand& opnd);
|
||||||
void StoreFloat32(DoubleRegister dst, const MemOperand& opnd);
|
void StoreFloat32(DoubleRegister dst, const MemOperand& opnd);
|
||||||
@ -1226,44 +1229,6 @@ class MacroAssembler : public Assembler {
|
|||||||
Register heap_number_map, Register scratch1,
|
Register heap_number_map, Register scratch1,
|
||||||
Label* not_int32);
|
Label* not_int32);
|
||||||
|
|
||||||
// Overflow handling functions.
|
|
||||||
// Usage: call the appropriate arithmetic function and then call one of the
|
|
||||||
// flow control functions with the corresponding label.
|
|
||||||
|
|
||||||
// Compute dst = left + right, setting condition codes. dst may be same as
|
|
||||||
// either left or right (or a unique register). left and right must not be
|
|
||||||
// the same register.
|
|
||||||
void AddAndCheckForOverflow(Register dst, Register left, Register right,
|
|
||||||
Register overflow_dst, Register scratch = r0);
|
|
||||||
void AddAndCheckForOverflow(Register dst, Register left, intptr_t right,
|
|
||||||
Register overflow_dst, Register scratch = r0);
|
|
||||||
|
|
||||||
// Compute dst = left - right, setting condition codes. dst may be same as
|
|
||||||
// either left or right (or a unique register). left and right must not be
|
|
||||||
// the same register.
|
|
||||||
void SubAndCheckForOverflow(Register dst, Register left, Register right,
|
|
||||||
Register overflow_dst, Register scratch = r0);
|
|
||||||
|
|
||||||
void BranchOnOverflow(Label* label) { blt(label /*, cr0*/); }
|
|
||||||
|
|
||||||
void BranchOnNoOverflow(Label* label) { bge(label /*, cr0*/); }
|
|
||||||
|
|
||||||
void RetOnOverflow(void) {
|
|
||||||
Label label;
|
|
||||||
|
|
||||||
blt(&label /*, cr0*/);
|
|
||||||
Ret();
|
|
||||||
bind(&label);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RetOnNoOverflow(void) {
|
|
||||||
Label label;
|
|
||||||
|
|
||||||
bge(&label /*, cr0*/);
|
|
||||||
Ret();
|
|
||||||
bind(&label);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Runtime calls
|
// Runtime calls
|
||||||
|
|
||||||
|
@ -5978,6 +5978,12 @@ uintptr_t Simulator::PopAddress() {
|
|||||||
int r3 = AS(RRFInstruction)->R3Value(); \
|
int r3 = AS(RRFInstruction)->R3Value(); \
|
||||||
int length = 4;
|
int length = 4;
|
||||||
|
|
||||||
|
#define DECODE_RRF_C_INSTRUCTION(r1, r2, m3) \
|
||||||
|
int r1 = AS(RRFInstruction)->R1Value(); \
|
||||||
|
int r2 = AS(RRFInstruction)->R2Value(); \
|
||||||
|
Condition m3 = static_cast<Condition>(AS(RRFInstruction)->M3Value()); \
|
||||||
|
int length = 4;
|
||||||
|
|
||||||
#define DECODE_RR_INSTRUCTION(r1, r2) \
|
#define DECODE_RR_INSTRUCTION(r1, r2) \
|
||||||
int r1 = AS(RRInstruction)->R1Value(); \
|
int r1 = AS(RRInstruction)->R1Value(); \
|
||||||
int r2 = AS(RRInstruction)->R2Value(); \
|
int r2 = AS(RRInstruction)->R2Value(); \
|
||||||
@ -10467,9 +10473,12 @@ EVALUATE(POPCNT_Z) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
EVALUATE(LOCGR) {
|
EVALUATE(LOCGR) {
|
||||||
UNIMPLEMENTED();
|
DCHECK_OPCODE(LOCR);
|
||||||
USE(instr);
|
DECODE_RRF_C_INSTRUCTION(r1, r2, m3);
|
||||||
return 0;
|
if (TestConditionCode(m3)) {
|
||||||
|
set_register(r1, get_register(r2));
|
||||||
|
}
|
||||||
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
EVALUATE(NGRK) {
|
EVALUATE(NGRK) {
|
||||||
@ -10564,9 +10573,12 @@ EVALUATE(SLGRK) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
EVALUATE(LOCR) {
|
EVALUATE(LOCR) {
|
||||||
UNIMPLEMENTED();
|
DCHECK_OPCODE(LOCR);
|
||||||
USE(instr);
|
DECODE_RRF_C_INSTRUCTION(r1, r2, m3);
|
||||||
return 0;
|
if (TestConditionCode(m3)) {
|
||||||
|
set_low_register(r1, get_low_register<int32_t>(r2));
|
||||||
|
}
|
||||||
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
EVALUATE(NRK) {
|
EVALUATE(NRK) {
|
||||||
|
Loading…
Reference in New Issue
Block a user