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(
__ Addu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break;
case kMipsAddOvf:
// Pseudo-instruction used for overflow/branch. No opcode emitted here.
__ AddOverflow(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1),
kScratchReg);
break;
case kMipsSub:
__ Subu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break;
case kMipsSubOvf:
// Pseudo-instruction used for overflow/branch. No opcode emitted here.
__ SubOverflow(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1),
kScratchReg);
break;
case kMipsMul:
__ Mul(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break;
case kMipsMulOvf:
// Pseudo-instruction used for overflow/branch. No opcode emitted here.
__ MulOverflow(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1),
kScratchReg);
break;
case kMipsMulHigh:
__ Mulh(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
......@@ -2859,43 +2862,28 @@ void AssembleBranchToLabels(CodeGenerator* gen, TurboAssembler* tasm,
cc = FlagsConditionToConditionTst(condition);
__ And(at, i.InputRegister(0), i.InputOperand(1));
__ Branch(tlabel, cc, at, Operand(zero_reg));
} else if (instr->arch_opcode() == kMipsAddOvf) {
switch (condition) {
case kOverflow:
__ 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) {
} else if (instr->arch_opcode() == kMipsAddOvf ||
instr->arch_opcode() == kMipsSubOvf) {
// Overflow occurs if overflow register is negative
switch (condition) {
case kOverflow:
__ SubBranchOvf(i.OutputRegister(), i.InputRegister(0),
i.InputOperand(1), tlabel, flabel);
__ Branch(tlabel, lt, kScratchReg, Operand(zero_reg));
break;
case kNotOverflow:
__ SubBranchOvf(i.OutputRegister(), i.InputRegister(0),
i.InputOperand(1), flabel, tlabel);
__ Branch(tlabel, ge, kScratchReg, Operand(zero_reg));
break;
default:
UNSUPPORTED_COND(kMipsAddOvf, condition);
UNSUPPORTED_COND(instr->arch_opcode(), condition);
break;
}
} else if (instr->arch_opcode() == kMipsMulOvf) {
// Overflow occurs if overflow register is not zero
switch (condition) {
case kOverflow:
__ MulBranchOvf(i.OutputRegister(), i.InputRegister(0),
i.InputOperand(1), tlabel, flabel);
__ Branch(tlabel, ne, kScratchReg, Operand(zero_reg));
break;
case kNotOverflow:
__ MulBranchOvf(i.OutputRegister(), i.InputRegister(0),
i.InputOperand(1), flabel, tlabel);
__ Branch(tlabel, eq, kScratchReg, Operand(zero_reg));
break;
default:
UNSUPPORTED_COND(kMipsMulOvf, condition);
......@@ -3061,32 +3049,12 @@ void CodeGenerator::AssembleArchBoolean(Instruction* instr,
}
return;
} else if (instr->arch_opcode() == kMipsAddOvf ||
instr->arch_opcode() == kMipsSubOvf ||
instr->arch_opcode() == kMipsMulOvf) {
Label flabel, tlabel;
switch (instr->arch_opcode()) {
case kMipsAddOvf:
__ AddBranchNoOvf(i.OutputRegister(), i.InputRegister(0),
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);
instr->arch_opcode() == kMipsSubOvf) {
// Overflow occurs if overflow register is negative
__ slt(result, kScratchReg, zero_reg);
} else if (instr->arch_opcode() == kMipsMulOvf) {
// Overflow occurs if overflow register is not zero
__ Sgtu(result, kScratchReg, zero_reg);
} else if (instr->arch_opcode() == kMipsCmp) {
cc = FlagsConditionToConditionCmp(condition);
switch (cc) {
......
......@@ -1024,7 +1024,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ Daddu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break;
case kMips64DaddOvf:
// Pseudo-instruction used for overflow/branch. No opcode emitted here.
__ DaddOverflow(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1),
kScratchReg);
break;
case kMips64Sub:
__ Subu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
......@@ -1033,13 +1034,15 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ Dsubu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break;
case kMips64DsubOvf:
// Pseudo-instruction used for overflow/branch. No opcode emitted here.
__ DsubOverflow(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1),
kScratchReg);
break;
case kMips64Mul:
__ Mul(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break;
case kMips64MulOvf:
// Pseudo-instruction used for overflow/branch. No opcode emitted here.
__ MulOverflow(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1),
kScratchReg);
break;
case kMips64MulHigh:
__ Mulh(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
......@@ -3078,46 +3081,31 @@ void AssembleBranchToLabels(CodeGenerator* gen, TurboAssembler* tasm,
__ dsra32(kScratchReg, i.OutputRegister(), 0);
__ sra(at, i.OutputRegister(), 31);
__ Branch(tlabel, cc, at, Operand(kScratchReg));
} else if (instr->arch_opcode() == kMips64DaddOvf) {
} else if (instr->arch_opcode() == kMips64DaddOvf ||
instr->arch_opcode() == kMips64DsubOvf) {
switch (condition) {
// Overflow occurs if overflow register is negative
case kOverflow:
__ DaddBranchOvf(i.OutputRegister(), i.InputRegister(0),
i.InputOperand(1), tlabel, flabel);
__ Branch(tlabel, lt, kScratchReg, Operand(zero_reg));
break;
case kNotOverflow:
__ DaddBranchOvf(i.OutputRegister(), i.InputRegister(0),
i.InputOperand(1), flabel, tlabel);
__ Branch(tlabel, ge, kScratchReg, Operand(zero_reg));
break;
default:
UNSUPPORTED_COND(kMips64DaddOvf, condition);
UNSUPPORTED_COND(instr->arch_opcode(), condition);
break;
}
} else if (instr->arch_opcode() == kMips64DsubOvf) {
} else if (instr->arch_opcode() == kMips64MulOvf) {
// Overflow occurs if overflow register is not zero
switch (condition) {
case kOverflow:
__ DsubBranchOvf(i.OutputRegister(), i.InputRegister(0),
i.InputOperand(1), tlabel, flabel);
__ Branch(tlabel, ne, kScratchReg, Operand(zero_reg));
break;
case kNotOverflow:
__ DsubBranchOvf(i.OutputRegister(), i.InputRegister(0),
i.InputOperand(1), flabel, tlabel);
__ Branch(tlabel, eq, kScratchReg, Operand(zero_reg));
break;
default:
UNSUPPORTED_COND(kMips64DsubOvf, 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);
UNSUPPORTED_COND(kMipsMulOvf, condition);
break;
}
} else if (instr->arch_opcode() == kMips64Cmp) {
......@@ -3289,32 +3277,12 @@ void CodeGenerator::AssembleArchBoolean(Instruction* instr,
__ xori(result, result, 1);
return;
} else if (instr->arch_opcode() == kMips64DaddOvf ||
instr->arch_opcode() == kMips64DsubOvf ||
instr->arch_opcode() == kMips64MulOvf) {
Label flabel, tlabel;
switch (instr->arch_opcode()) {
case kMips64DaddOvf:
__ DaddBranchNoOvf(i.OutputRegister(), i.InputRegister(0),
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);
instr->arch_opcode() == kMips64DsubOvf) {
// Overflow occurs if overflow register is negative
__ slt(result, kScratchReg, zero_reg);
} else if (instr->arch_opcode() == kMips64MulOvf) {
// Overflow occurs if overflow register is not zero
__ Sgtu(result, kScratchReg, zero_reg);
} else if (instr->arch_opcode() == kMips64Cmp) {
cc = FlagsConditionToConditionCmp(condition);
switch (cc) {
......
This diff is collapsed.
......@@ -461,6 +461,8 @@ class TurboAssembler : public Assembler {
DEFINE_INSTRUCTION(Slt);
DEFINE_INSTRUCTION(Sltu);
DEFINE_INSTRUCTION(Sgt);
DEFINE_INSTRUCTION(Sgtu);
// MIPS32 R2 instruction macro.
DEFINE_INSTRUCTION(Ror);
......@@ -742,63 +744,19 @@ class TurboAssembler : public Assembler {
void Move(FPURegister dst, uint64_t src);
// -------------------------------------------------------------------------
// Overflow handling functions.
// Usage: first call the appropriate arithmetic function, then call one of the
// jump functions with the overflow_dst register as the second parameter.
inline void AddBranchOvf(Register dst, Register left, const Operand& right,
Label* overflow_label, Register scratch = at) {
AddBranchOvf(dst, left, right, overflow_label, nullptr, scratch);
}
inline void AddBranchNoOvf(Register dst, Register left, const Operand& right,
Label* no_overflow_label, Register scratch = at) {
AddBranchOvf(dst, left, right, nullptr, no_overflow_label, scratch);
}
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);
// Overflow operations.
// AddOverflow sets overflow register to a negative value if
// overflow occured, otherwise it is zero or positive
void AddOverflow(Register dst, Register left, const Operand& right,
Register overflow);
// 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,
Register overflow);
// MulOverflow sets overflow register to zero if no overflow occured
void MulOverflow(Register dst, Register left, const Operand& right,
Register overflow);
// Number of instructions needed for calculation of switch table entry address
#ifdef _MIPS_ARCH_MIPS32R6
......
This diff is collapsed.
......@@ -495,6 +495,8 @@ class TurboAssembler : public Assembler {
DEFINE_INSTRUCTION(Slt);
DEFINE_INSTRUCTION(Sltu);
DEFINE_INSTRUCTION(Sgt);
DEFINE_INSTRUCTION(Sgtu);
// MIPS32 R2 instruction macro.
DEFINE_INSTRUCTION(Ror);
......@@ -756,59 +758,17 @@ class TurboAssembler : public Assembler {
void Move(FPURegister dst, uint32_t src);
void Move(FPURegister dst, uint64_t src);
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);
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);
// DaddOverflow sets overflow register to a negative value if
// overflow occured, otherwise it is zero or positive
void DaddOverflow(Register dst, Register left, const Operand& right,
Register overflow);
// DsubOverflow sets overflow register to a negative value if
// overflow occured, otherwise it is zero or positive
void DsubOverflow(Register dst, Register left, const Operand& right,
Register overflow);
// MulOverflow sets overflow register to zero if no overflow occured
void MulOverflow(Register dst, Register left, const Operand& right,
Register overflow);
// Number of instructions needed for calculation of switch table entry address
#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