Commit 51c79bc4 authored by Ivica Bogosavljevic's avatar Ivica Bogosavljevic Committed by Commit Bot

MIPS[64]: Rewrite overflow instructions

Rewrite overflow instructions in order to allow branch
poisoning.

Change-Id: I5f97808c7eac08927243780a0ae0c48f6de0c45b
Reviewed-on: https://chromium-review.googlesource.com/964321
Commit-Queue: Ivica Bogosavljevic <ivica.bogosavljevic@mips.com>
Reviewed-by: 's avatarSreten Kovacevic <sreten.kovacevic@mips.com>
Cr-Commit-Position: refs/heads/master@{#51984}
parent 9625520f
...@@ -997,19 +997,22 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -997,19 +997,22 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ Addu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); __ Addu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break; break;
case kMipsAddOvf: case kMipsAddOvf:
// Pseudo-instruction used for overflow/branch. No opcode emitted here. __ AddOverflow(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1),
kScratchReg);
break; break;
case kMipsSub: case kMipsSub:
__ Subu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); __ Subu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break; break;
case kMipsSubOvf: case kMipsSubOvf:
// Pseudo-instruction used for overflow/branch. No opcode emitted here. __ SubOverflow(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1),
kScratchReg);
break; break;
case kMipsMul: case kMipsMul:
__ Mul(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); __ Mul(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break; break;
case kMipsMulOvf: case kMipsMulOvf:
// Pseudo-instruction used for overflow/branch. No opcode emitted here. __ MulOverflow(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1),
kScratchReg);
break; break;
case kMipsMulHigh: case kMipsMulHigh:
__ Mulh(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); __ Mulh(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
...@@ -2859,43 +2862,28 @@ void AssembleBranchToLabels(CodeGenerator* gen, TurboAssembler* tasm, ...@@ -2859,43 +2862,28 @@ void AssembleBranchToLabels(CodeGenerator* gen, TurboAssembler* tasm,
cc = FlagsConditionToConditionTst(condition); cc = FlagsConditionToConditionTst(condition);
__ And(at, i.InputRegister(0), i.InputOperand(1)); __ And(at, i.InputRegister(0), i.InputOperand(1));
__ Branch(tlabel, cc, at, Operand(zero_reg)); __ Branch(tlabel, cc, at, Operand(zero_reg));
} else if (instr->arch_opcode() == kMipsAddOvf) { } else if (instr->arch_opcode() == kMipsAddOvf ||
switch (condition) { instr->arch_opcode() == kMipsSubOvf) {
case kOverflow: // Overflow occurs if overflow register is negative
__ AddBranchOvf(i.OutputRegister(), i.InputRegister(0),
i.InputOperand(1), tlabel, flabel);
break;
case kNotOverflow:
__ AddBranchOvf(i.OutputRegister(), i.InputRegister(0),
i.InputOperand(1), flabel, tlabel);
break;
default:
UNSUPPORTED_COND(kMipsAddOvf, condition);
break;
}
} else if (instr->arch_opcode() == kMipsSubOvf) {
switch (condition) { switch (condition) {
case kOverflow: case kOverflow:
__ SubBranchOvf(i.OutputRegister(), i.InputRegister(0), __ Branch(tlabel, lt, kScratchReg, Operand(zero_reg));
i.InputOperand(1), tlabel, flabel);
break; break;
case kNotOverflow: case kNotOverflow:
__ SubBranchOvf(i.OutputRegister(), i.InputRegister(0), __ Branch(tlabel, ge, kScratchReg, Operand(zero_reg));
i.InputOperand(1), flabel, tlabel);
break; break;
default: default:
UNSUPPORTED_COND(kMipsAddOvf, condition); UNSUPPORTED_COND(instr->arch_opcode(), condition);
break; break;
} }
} else if (instr->arch_opcode() == kMipsMulOvf) { } else if (instr->arch_opcode() == kMipsMulOvf) {
// Overflow occurs if overflow register is not zero
switch (condition) { switch (condition) {
case kOverflow: case kOverflow:
__ MulBranchOvf(i.OutputRegister(), i.InputRegister(0), __ Branch(tlabel, ne, kScratchReg, Operand(zero_reg));
i.InputOperand(1), tlabel, flabel);
break; break;
case kNotOverflow: case kNotOverflow:
__ MulBranchOvf(i.OutputRegister(), i.InputRegister(0), __ Branch(tlabel, eq, kScratchReg, Operand(zero_reg));
i.InputOperand(1), flabel, tlabel);
break; break;
default: default:
UNSUPPORTED_COND(kMipsMulOvf, condition); UNSUPPORTED_COND(kMipsMulOvf, condition);
...@@ -3061,32 +3049,12 @@ void CodeGenerator::AssembleArchBoolean(Instruction* instr, ...@@ -3061,32 +3049,12 @@ void CodeGenerator::AssembleArchBoolean(Instruction* instr,
} }
return; return;
} else if (instr->arch_opcode() == kMipsAddOvf || } else if (instr->arch_opcode() == kMipsAddOvf ||
instr->arch_opcode() == kMipsSubOvf || instr->arch_opcode() == kMipsSubOvf) {
instr->arch_opcode() == kMipsMulOvf) { // Overflow occurs if overflow register is negative
Label flabel, tlabel; __ slt(result, kScratchReg, zero_reg);
switch (instr->arch_opcode()) { } else if (instr->arch_opcode() == kMipsMulOvf) {
case kMipsAddOvf: // Overflow occurs if overflow register is not zero
__ AddBranchNoOvf(i.OutputRegister(), i.InputRegister(0), __ Sgtu(result, kScratchReg, zero_reg);
i.InputOperand(1), &flabel);
break;
case kMipsSubOvf:
__ SubBranchNoOvf(i.OutputRegister(), i.InputRegister(0),
i.InputOperand(1), &flabel);
break;
case kMipsMulOvf:
__ MulBranchNoOvf(i.OutputRegister(), i.InputRegister(0),
i.InputOperand(1), &flabel);
break;
default:
UNREACHABLE();
break;
}
__ li(result, 1);
__ Branch(&tlabel);
__ bind(&flabel);
__ li(result, 0);
__ bind(&tlabel);
} else if (instr->arch_opcode() == kMipsCmp) { } else if (instr->arch_opcode() == kMipsCmp) {
cc = FlagsConditionToConditionCmp(condition); cc = FlagsConditionToConditionCmp(condition);
switch (cc) { switch (cc) {
......
...@@ -1024,7 +1024,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -1024,7 +1024,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ Daddu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); __ Daddu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break; break;
case kMips64DaddOvf: case kMips64DaddOvf:
// Pseudo-instruction used for overflow/branch. No opcode emitted here. __ DaddOverflow(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1),
kScratchReg);
break; break;
case kMips64Sub: case kMips64Sub:
__ Subu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); __ Subu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
...@@ -1033,13 +1034,15 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -1033,13 +1034,15 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ Dsubu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); __ Dsubu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break; break;
case kMips64DsubOvf: case kMips64DsubOvf:
// Pseudo-instruction used for overflow/branch. No opcode emitted here. __ DsubOverflow(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1),
kScratchReg);
break; break;
case kMips64Mul: case kMips64Mul:
__ Mul(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); __ Mul(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break; break;
case kMips64MulOvf: case kMips64MulOvf:
// Pseudo-instruction used for overflow/branch. No opcode emitted here. __ MulOverflow(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1),
kScratchReg);
break; break;
case kMips64MulHigh: case kMips64MulHigh:
__ Mulh(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); __ Mulh(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
...@@ -3078,46 +3081,31 @@ void AssembleBranchToLabels(CodeGenerator* gen, TurboAssembler* tasm, ...@@ -3078,46 +3081,31 @@ void AssembleBranchToLabels(CodeGenerator* gen, TurboAssembler* tasm,
__ dsra32(kScratchReg, i.OutputRegister(), 0); __ dsra32(kScratchReg, i.OutputRegister(), 0);
__ sra(at, i.OutputRegister(), 31); __ sra(at, i.OutputRegister(), 31);
__ Branch(tlabel, cc, at, Operand(kScratchReg)); __ Branch(tlabel, cc, at, Operand(kScratchReg));
} else if (instr->arch_opcode() == kMips64DaddOvf) { } else if (instr->arch_opcode() == kMips64DaddOvf ||
instr->arch_opcode() == kMips64DsubOvf) {
switch (condition) { switch (condition) {
// Overflow occurs if overflow register is negative
case kOverflow: case kOverflow:
__ DaddBranchOvf(i.OutputRegister(), i.InputRegister(0), __ Branch(tlabel, lt, kScratchReg, Operand(zero_reg));
i.InputOperand(1), tlabel, flabel);
break; break;
case kNotOverflow: case kNotOverflow:
__ DaddBranchOvf(i.OutputRegister(), i.InputRegister(0), __ Branch(tlabel, ge, kScratchReg, Operand(zero_reg));
i.InputOperand(1), flabel, tlabel);
break; break;
default: default:
UNSUPPORTED_COND(kMips64DaddOvf, condition); UNSUPPORTED_COND(instr->arch_opcode(), condition);
break; break;
} }
} else if (instr->arch_opcode() == kMips64DsubOvf) { } else if (instr->arch_opcode() == kMips64MulOvf) {
// Overflow occurs if overflow register is not zero
switch (condition) { switch (condition) {
case kOverflow: case kOverflow:
__ DsubBranchOvf(i.OutputRegister(), i.InputRegister(0), __ Branch(tlabel, ne, kScratchReg, Operand(zero_reg));
i.InputOperand(1), tlabel, flabel);
break; break;
case kNotOverflow: case kNotOverflow:
__ DsubBranchOvf(i.OutputRegister(), i.InputRegister(0), __ Branch(tlabel, eq, kScratchReg, Operand(zero_reg));
i.InputOperand(1), flabel, tlabel);
break; break;
default: default:
UNSUPPORTED_COND(kMips64DsubOvf, condition); UNSUPPORTED_COND(kMipsMulOvf, condition);
break;
}
} else if (instr->arch_opcode() == kMips64MulOvf) {
switch (condition) {
case kOverflow: {
__ MulBranchOvf(i.OutputRegister(), i.InputRegister(0),
i.InputOperand(1), tlabel, flabel, kScratchReg);
} break;
case kNotOverflow: {
__ MulBranchOvf(i.OutputRegister(), i.InputRegister(0),
i.InputOperand(1), flabel, tlabel, kScratchReg);
} break;
default:
UNSUPPORTED_COND(kMips64MulOvf, condition);
break; break;
} }
} else if (instr->arch_opcode() == kMips64Cmp) { } else if (instr->arch_opcode() == kMips64Cmp) {
...@@ -3289,32 +3277,12 @@ void CodeGenerator::AssembleArchBoolean(Instruction* instr, ...@@ -3289,32 +3277,12 @@ void CodeGenerator::AssembleArchBoolean(Instruction* instr,
__ xori(result, result, 1); __ xori(result, result, 1);
return; return;
} else if (instr->arch_opcode() == kMips64DaddOvf || } else if (instr->arch_opcode() == kMips64DaddOvf ||
instr->arch_opcode() == kMips64DsubOvf || instr->arch_opcode() == kMips64DsubOvf) {
instr->arch_opcode() == kMips64MulOvf) { // Overflow occurs if overflow register is negative
Label flabel, tlabel; __ slt(result, kScratchReg, zero_reg);
switch (instr->arch_opcode()) { } else if (instr->arch_opcode() == kMips64MulOvf) {
case kMips64DaddOvf: // Overflow occurs if overflow register is not zero
__ DaddBranchNoOvf(i.OutputRegister(), i.InputRegister(0), __ Sgtu(result, kScratchReg, zero_reg);
i.InputOperand(1), &flabel);
break;
case kMips64DsubOvf:
__ DsubBranchNoOvf(i.OutputRegister(), i.InputRegister(0),
i.InputOperand(1), &flabel);
break;
case kMips64MulOvf:
__ MulBranchNoOvf(i.OutputRegister(), i.InputRegister(0),
i.InputOperand(1), &flabel, kScratchReg);
break;
default:
UNREACHABLE();
break;
}
__ li(result, 1);
__ Branch(&tlabel);
__ bind(&flabel);
__ li(result, 0);
__ bind(&tlabel);
} else if (instr->arch_opcode() == kMips64Cmp) { } else if (instr->arch_opcode() == kMips64Cmp) {
cc = FlagsConditionToConditionCmp(condition); cc = FlagsConditionToConditionCmp(condition);
switch (cc) { switch (cc) {
......
This diff is collapsed.
...@@ -461,6 +461,8 @@ class TurboAssembler : public Assembler { ...@@ -461,6 +461,8 @@ class TurboAssembler : public Assembler {
DEFINE_INSTRUCTION(Slt); DEFINE_INSTRUCTION(Slt);
DEFINE_INSTRUCTION(Sltu); DEFINE_INSTRUCTION(Sltu);
DEFINE_INSTRUCTION(Sgt);
DEFINE_INSTRUCTION(Sgtu);
// MIPS32 R2 instruction macro. // MIPS32 R2 instruction macro.
DEFINE_INSTRUCTION(Ror); DEFINE_INSTRUCTION(Ror);
...@@ -742,63 +744,19 @@ class TurboAssembler : public Assembler { ...@@ -742,63 +744,19 @@ class TurboAssembler : public Assembler {
void Move(FPURegister dst, uint64_t src); void Move(FPURegister dst, uint64_t src);
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Overflow handling functions. // Overflow operations.
// Usage: first call the appropriate arithmetic function, then call one of the
// jump functions with the overflow_dst register as the second parameter. // AddOverflow sets overflow register to a negative value if
// overflow occured, otherwise it is zero or positive
inline void AddBranchOvf(Register dst, Register left, const Operand& right, void AddOverflow(Register dst, Register left, const Operand& right,
Label* overflow_label, Register scratch = at) { Register overflow);
AddBranchOvf(dst, left, right, overflow_label, nullptr, scratch); // SubOverflow sets overflow register to a negative value if
} // overflow occured, otherwise it is zero or positive
void SubOverflow(Register dst, Register left, const Operand& right,
inline void AddBranchNoOvf(Register dst, Register left, const Operand& right, Register overflow);
Label* no_overflow_label, Register scratch = at) { // MulOverflow sets overflow register to zero if no overflow occured
AddBranchOvf(dst, left, right, nullptr, no_overflow_label, scratch); void MulOverflow(Register dst, Register left, const Operand& right,
} Register overflow);
void AddBranchOvf(Register dst, Register left, const Operand& right,
Label* overflow_label, Label* no_overflow_label,
Register scratch = at);
void AddBranchOvf(Register dst, Register left, Register right,
Label* overflow_label, Label* no_overflow_label,
Register scratch = at);
inline void SubBranchOvf(Register dst, Register left, const Operand& right,
Label* overflow_label, Register scratch = at) {
SubBranchOvf(dst, left, right, overflow_label, nullptr, scratch);
}
inline void SubBranchNoOvf(Register dst, Register left, const Operand& right,
Label* no_overflow_label, Register scratch = at) {
SubBranchOvf(dst, left, right, nullptr, no_overflow_label, scratch);
}
void SubBranchOvf(Register dst, Register left, const Operand& right,
Label* overflow_label, Label* no_overflow_label,
Register scratch = at);
void SubBranchOvf(Register dst, Register left, Register right,
Label* overflow_label, Label* no_overflow_label,
Register scratch = at);
inline void MulBranchOvf(Register dst, Register left, const Operand& right,
Label* overflow_label, Register scratch = at) {
MulBranchOvf(dst, left, right, overflow_label, nullptr, scratch);
}
inline void MulBranchNoOvf(Register dst, Register left, const Operand& right,
Label* no_overflow_label, Register scratch = at) {
MulBranchOvf(dst, left, right, nullptr, no_overflow_label, scratch);
}
void MulBranchOvf(Register dst, Register left, const Operand& right,
Label* overflow_label, Label* no_overflow_label,
Register scratch = at);
void MulBranchOvf(Register dst, Register left, Register right,
Label* overflow_label, Label* no_overflow_label,
Register scratch = at);
// Number of instructions needed for calculation of switch table entry address // Number of instructions needed for calculation of switch table entry address
#ifdef _MIPS_ARCH_MIPS32R6 #ifdef _MIPS_ARCH_MIPS32R6
......
This diff is collapsed.
...@@ -495,6 +495,8 @@ class TurboAssembler : public Assembler { ...@@ -495,6 +495,8 @@ class TurboAssembler : public Assembler {
DEFINE_INSTRUCTION(Slt); DEFINE_INSTRUCTION(Slt);
DEFINE_INSTRUCTION(Sltu); DEFINE_INSTRUCTION(Sltu);
DEFINE_INSTRUCTION(Sgt);
DEFINE_INSTRUCTION(Sgtu);
// MIPS32 R2 instruction macro. // MIPS32 R2 instruction macro.
DEFINE_INSTRUCTION(Ror); DEFINE_INSTRUCTION(Ror);
...@@ -756,59 +758,17 @@ class TurboAssembler : public Assembler { ...@@ -756,59 +758,17 @@ class TurboAssembler : public Assembler {
void Move(FPURegister dst, uint32_t src); void Move(FPURegister dst, uint32_t src);
void Move(FPURegister dst, uint64_t src); void Move(FPURegister dst, uint64_t src);
inline void MulBranchOvf(Register dst, Register left, const Operand& right, // DaddOverflow sets overflow register to a negative value if
Label* overflow_label, Register scratch = at) { // overflow occured, otherwise it is zero or positive
MulBranchOvf(dst, left, right, overflow_label, nullptr, scratch); void DaddOverflow(Register dst, Register left, const Operand& right,
} Register overflow);
// DsubOverflow sets overflow register to a negative value if
inline void MulBranchNoOvf(Register dst, Register left, const Operand& right, // overflow occured, otherwise it is zero or positive
Label* no_overflow_label, Register scratch = at) { void DsubOverflow(Register dst, Register left, const Operand& right,
MulBranchOvf(dst, left, right, nullptr, no_overflow_label, scratch); Register overflow);
} // MulOverflow sets overflow register to zero if no overflow occured
void MulOverflow(Register dst, Register left, const Operand& right,
void MulBranchOvf(Register dst, Register left, const Operand& right, Register overflow);
Label* overflow_label, Label* no_overflow_label,
Register scratch = at);
void MulBranchOvf(Register dst, Register left, Register right,
Label* overflow_label, Label* no_overflow_label,
Register scratch = at);
inline void DaddBranchOvf(Register dst, Register left, const Operand& right,
Label* overflow_label, Register scratch = at) {
DaddBranchOvf(dst, left, right, overflow_label, nullptr, scratch);
}
inline void DaddBranchNoOvf(Register dst, Register left, const Operand& right,
Label* no_overflow_label, Register scratch = at) {
DaddBranchOvf(dst, left, right, nullptr, no_overflow_label, scratch);
}
void DaddBranchOvf(Register dst, Register left, const Operand& right,
Label* overflow_label, Label* no_overflow_label,
Register scratch = at);
void DaddBranchOvf(Register dst, Register left, Register right,
Label* overflow_label, Label* no_overflow_label,
Register scratch = at);
inline void DsubBranchOvf(Register dst, Register left, const Operand& right,
Label* overflow_label, Register scratch = at) {
DsubBranchOvf(dst, left, right, overflow_label, nullptr, scratch);
}
inline void DsubBranchNoOvf(Register dst, Register left, const Operand& right,
Label* no_overflow_label, Register scratch = at) {
DsubBranchOvf(dst, left, right, nullptr, no_overflow_label, scratch);
}
void DsubBranchOvf(Register dst, Register left, const Operand& right,
Label* overflow_label, Label* no_overflow_label,
Register scratch = at);
void DsubBranchOvf(Register dst, Register left, Register right,
Label* overflow_label, Label* no_overflow_label,
Register scratch = at);
// Number of instructions needed for calculation of switch table entry address // Number of instructions needed for calculation of switch table entry address
#ifdef _MIPS_ARCH_MIPS64R6 #ifdef _MIPS_ARCH_MIPS64R6
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment