Commit b10f21c6 authored by Ivica Bogosavljevic's avatar Ivica Bogosavljevic Committed by Commit Bot

MIPS[64]: Branch poisoning using conditional moves

Change-Id: I41c3945d72116dd501bf34bafd8d21c205aed17c
Reviewed-on: https://chromium-review.googlesource.com/973445Reviewed-by: 's avatarMichael Stanton <mvstanton@chromium.org>
Reviewed-by: 's avatarSreten Kovacevic <sreten.kovacevic@mips.com>
Commit-Queue: Ivica Bogosavljevic <ivica.bogosavljevic@mips.com>
Cr-Commit-Position: refs/heads/master@{#52248}
parent 39fcb540
...@@ -1166,7 +1166,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -1166,7 +1166,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ Ror(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); __ Ror(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break; break;
case kMipsTst: case kMipsTst:
// Pseudo-instruction used for tst/branch. No opcode emitted here. __ And(kScratchReg, i.InputRegister(0), i.InputOperand(1));
break; break;
case kMipsCmp: case kMipsCmp:
// Pseudo-instruction used for cmp/branch. No opcode emitted here. // Pseudo-instruction used for cmp/branch. No opcode emitted here.
...@@ -2886,8 +2886,7 @@ void AssembleBranchToLabels(CodeGenerator* gen, TurboAssembler* tasm, ...@@ -2886,8 +2886,7 @@ void AssembleBranchToLabels(CodeGenerator* gen, TurboAssembler* tasm,
MipsOperandConverter i(gen, instr); MipsOperandConverter i(gen, instr);
if (instr->arch_opcode() == kMipsTst) { if (instr->arch_opcode() == kMipsTst) {
cc = FlagsConditionToConditionTst(condition); cc = FlagsConditionToConditionTst(condition);
__ And(at, i.InputRegister(0), i.InputOperand(1)); __ Branch(tlabel, cc, kScratchReg, Operand(zero_reg));
__ Branch(tlabel, cc, at, Operand(zero_reg));
} else if (instr->arch_opcode() == kMipsAddOvf || } else if (instr->arch_opcode() == kMipsAddOvf ||
instr->arch_opcode() == kMipsSubOvf) { instr->arch_opcode() == kMipsSubOvf) {
// Overflow occurs if overflow register is negative // Overflow occurs if overflow register is negative
...@@ -2965,9 +2964,65 @@ void CodeGenerator::AssembleBranchPoisoning(FlagsCondition condition, ...@@ -2965,9 +2964,65 @@ void CodeGenerator::AssembleBranchPoisoning(FlagsCondition condition,
return; return;
} }
// TODO(mips): insert instructions here that place 0 into the MipsOperandConverter i(this, instr);
// kSpeculationPoisonRegister if the negation of the condition is condition = NegateFlagsCondition(condition);
// true.
switch (instr->arch_opcode()) {
case kMipsCmp: {
__ LoadZeroOnCondition(kSpeculationPoisonRegister, i.InputRegister(0),
i.InputOperand(1),
FlagsConditionToConditionCmp(condition));
}
return;
case kMipsTst: {
switch (condition) {
case kEqual:
__ LoadZeroIfConditionZero(kSpeculationPoisonRegister, kScratchReg);
break;
case kNotEqual:
__ LoadZeroIfConditionNotZero(kSpeculationPoisonRegister,
kScratchReg);
break;
default:
UNREACHABLE();
}
}
return;
case kMipsAddOvf:
case kMipsSubOvf: {
// Overflow occurs if overflow register is negative
__ Slt(kScratchReg2, kScratchReg, zero_reg);
switch (condition) {
case kOverflow:
__ LoadZeroIfConditionNotZero(kSpeculationPoisonRegister,
kScratchReg2);
break;
case kNotOverflow:
__ LoadZeroIfConditionZero(kSpeculationPoisonRegister, kScratchReg2);
break;
default:
UNSUPPORTED_COND(instr->arch_opcode(), condition);
}
}
return;
case kMipsMulOvf: {
// Overflow occurs if overflow register is not zero
switch (condition) {
case kOverflow:
__ LoadZeroIfConditionNotZero(kSpeculationPoisonRegister,
kScratchReg);
break;
case kNotOverflow:
__ LoadZeroIfConditionZero(kSpeculationPoisonRegister, kScratchReg);
break;
default:
UNSUPPORTED_COND(instr->arch_opcode(), condition);
}
}
return;
default:
break;
}
} }
void CodeGenerator::AssembleArchDeoptBranch(Instruction* instr, void CodeGenerator::AssembleArchDeoptBranch(Instruction* instr,
...@@ -3064,22 +3119,11 @@ void CodeGenerator::AssembleArchBoolean(Instruction* instr, ...@@ -3064,22 +3119,11 @@ void CodeGenerator::AssembleArchBoolean(Instruction* instr,
if (instr->arch_opcode() == kMipsTst) { if (instr->arch_opcode() == kMipsTst) {
cc = FlagsConditionToConditionTst(condition); cc = FlagsConditionToConditionTst(condition);
if (instr->InputAt(1)->IsImmediate() &&
base::bits::IsPowerOfTwo(i.InputOperand(1).immediate())) {
uint16_t pos =
base::bits::CountTrailingZeros32(i.InputOperand(1).immediate());
__ Ext(result, i.InputRegister(0), pos, 1);
if (cc == eq) {
__ xori(result, result, 1);
}
} else {
__ And(kScratchReg, i.InputRegister(0), i.InputOperand(1));
if (cc == eq) { if (cc == eq) {
__ Sltu(result, kScratchReg, 1); __ Sltu(result, kScratchReg, 1);
} else { } else {
__ Sltu(result, zero_reg, kScratchReg); __ Sltu(result, zero_reg, kScratchReg);
} }
}
return; return;
} else if (instr->arch_opcode() == kMipsAddOvf || } else if (instr->arch_opcode() == kMipsAddOvf ||
instr->arch_opcode() == kMipsSubOvf) { instr->arch_opcode() == kMipsSubOvf) {
......
...@@ -1315,6 +1315,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -1315,6 +1315,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ Dror(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); __ Dror(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break; break;
case kMips64Tst: case kMips64Tst:
__ And(kScratchReg, i.InputRegister(0), i.InputOperand(1));
// Pseudo-instruction used for cmp/branch. No opcode emitted here. // Pseudo-instruction used for cmp/branch. No opcode emitted here.
break; break;
case kMips64Cmp: case kMips64Cmp:
...@@ -3103,8 +3104,7 @@ void AssembleBranchToLabels(CodeGenerator* gen, TurboAssembler* tasm, ...@@ -3103,8 +3104,7 @@ void AssembleBranchToLabels(CodeGenerator* gen, TurboAssembler* tasm,
if (instr->arch_opcode() == kMips64Tst) { if (instr->arch_opcode() == kMips64Tst) {
cc = FlagsConditionToConditionTst(condition); cc = FlagsConditionToConditionTst(condition);
__ And(at, i.InputRegister(0), i.InputOperand(1)); __ Branch(tlabel, cc, kScratchReg, Operand(zero_reg));
__ Branch(tlabel, cc, at, Operand(zero_reg));
} else if (instr->arch_opcode() == kMips64Dadd || } else if (instr->arch_opcode() == kMips64Dadd ||
instr->arch_opcode() == kMips64Dsub) { instr->arch_opcode() == kMips64Dsub) {
cc = FlagsConditionToConditionOvf(condition); cc = FlagsConditionToConditionOvf(condition);
...@@ -3189,9 +3189,83 @@ void CodeGenerator::AssembleBranchPoisoning(FlagsCondition condition, ...@@ -3189,9 +3189,83 @@ void CodeGenerator::AssembleBranchPoisoning(FlagsCondition condition,
return; return;
} }
// TODO(mips64): insert instructions here that place 0 into the MipsOperandConverter i(this, instr);
// kSpeculationPoisonRegister if the negation of the condition is condition = NegateFlagsCondition(condition);
// true.
switch (instr->arch_opcode()) {
case kMips64Cmp: {
__ LoadZeroOnCondition(kSpeculationPoisonRegister, i.InputRegister(0),
i.InputOperand(1),
FlagsConditionToConditionCmp(condition));
}
return;
case kMips64Tst: {
switch (condition) {
case kEqual:
__ LoadZeroIfConditionZero(kSpeculationPoisonRegister, kScratchReg);
break;
case kNotEqual:
__ LoadZeroIfConditionNotZero(kSpeculationPoisonRegister,
kScratchReg);
break;
default:
UNREACHABLE();
}
}
return;
case kMips64Dadd:
case kMips64Dsub: {
// Check for overflow creates 1 or 0 for result.
__ dsrl32(kScratchReg, i.OutputRegister(), 31);
__ srl(at, i.OutputRegister(), 31);
__ xor_(at, kScratchReg, at);
switch (condition) {
case kOverflow:
__ LoadZeroIfConditionNotZero(kSpeculationPoisonRegister, at);
break;
case kNotOverflow:
__ LoadZeroIfConditionZero(kSpeculationPoisonRegister, at);
break;
default:
UNSUPPORTED_COND(instr->arch_opcode(), condition);
}
}
return;
case kMips64DaddOvf:
case kMips64DsubOvf: {
// Overflow occurs if overflow register is negative
__ Slt(kScratchReg2, kScratchReg, zero_reg);
switch (condition) {
case kOverflow:
__ LoadZeroIfConditionNotZero(kSpeculationPoisonRegister,
kScratchReg2);
break;
case kNotOverflow:
__ LoadZeroIfConditionZero(kSpeculationPoisonRegister, kScratchReg2);
break;
default:
UNSUPPORTED_COND(instr->arch_opcode(), condition);
}
}
return;
case kMips64MulOvf: {
// Overflow occurs if overflow register is not zero
switch (condition) {
case kOverflow:
__ LoadZeroIfConditionNotZero(kSpeculationPoisonRegister,
kScratchReg);
break;
case kNotOverflow:
__ LoadZeroIfConditionZero(kSpeculationPoisonRegister, kScratchReg);
break;
default:
UNSUPPORTED_COND(instr->arch_opcode(), condition);
}
}
return;
default:
break;
}
} }
void CodeGenerator::AssembleArchDeoptBranch(Instruction* instr, void CodeGenerator::AssembleArchDeoptBranch(Instruction* instr,
...@@ -3286,22 +3360,11 @@ void CodeGenerator::AssembleArchBoolean(Instruction* instr, ...@@ -3286,22 +3360,11 @@ void CodeGenerator::AssembleArchBoolean(Instruction* instr,
if (instr->arch_opcode() == kMips64Tst) { if (instr->arch_opcode() == kMips64Tst) {
cc = FlagsConditionToConditionTst(condition); cc = FlagsConditionToConditionTst(condition);
if (instr->InputAt(1)->IsImmediate() &&
base::bits::IsPowerOfTwo(i.InputOperand(1).immediate())) {
uint16_t pos =
base::bits::CountTrailingZeros64(i.InputOperand(1).immediate());
__ Dext(result, i.InputRegister(0), pos, 1);
if (cc == eq) {
__ xori(result, result, 1);
}
} else {
__ And(kScratchReg, i.InputRegister(0), i.InputOperand(1));
if (cc == eq) { if (cc == eq) {
__ Sltu(result, kScratchReg, 1); __ Sltu(result, kScratchReg, 1);
} else { } else {
__ Sltu(result, zero_reg, kScratchReg); __ Sltu(result, zero_reg, kScratchReg);
} }
}
return; return;
} else if (instr->arch_opcode() == kMips64Dadd || } else if (instr->arch_opcode() == kMips64Dadd ||
instr->arch_opcode() == kMips64Dsub) { instr->arch_opcode() == kMips64Dsub) {
......
...@@ -38,6 +38,14 @@ TurboAssembler::TurboAssembler(Isolate* isolate, void* buffer, int buffer_size, ...@@ -38,6 +38,14 @@ TurboAssembler::TurboAssembler(Isolate* isolate, void* buffer, int buffer_size,
} }
} }
static inline bool IsZero(const Operand& rt) {
if (rt.is_reg()) {
return rt.rm() == zero_reg;
} else {
return rt.immediate() == 0;
}
}
int TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode, int TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
Register exclusion1, Register exclusion1,
Register exclusion2, Register exclusion2,
...@@ -821,6 +829,44 @@ void TurboAssembler::Sltu(Register rd, Register rs, const Operand& rt) { ...@@ -821,6 +829,44 @@ void TurboAssembler::Sltu(Register rd, Register rs, const Operand& rt) {
} }
} }
void TurboAssembler::Sle(Register rd, Register rs, const Operand& rt) {
if (rt.is_reg()) {
slt(rd, rt.rm(), rs);
} else {
// li handles the relocation.
UseScratchRegisterScope temps(this);
Register scratch = temps.hasAvailable() ? temps.Acquire() : t8;
DCHECK(rs != scratch);
li(scratch, rt);
slt(rd, scratch, rs);
}
xori(rd, rd, 1);
}
void TurboAssembler::Sleu(Register rd, Register rs, const Operand& rt) {
if (rt.is_reg()) {
sltu(rd, rt.rm(), rs);
} else {
// li handles the relocation.
UseScratchRegisterScope temps(this);
Register scratch = temps.hasAvailable() ? temps.Acquire() : t8;
DCHECK(rs != scratch);
li(scratch, rt);
sltu(rd, scratch, rs);
}
xori(rd, rd, 1);
}
void TurboAssembler::Sge(Register rd, Register rs, const Operand& rt) {
Slt(rd, rs, rt);
xori(rd, rd, 1);
}
void TurboAssembler::Sgeu(Register rd, Register rs, const Operand& rt) {
Sltu(rd, rs, rt);
xori(rd, rd, 1);
}
void TurboAssembler::Sgt(Register rd, Register rs, const Operand& rt) { void TurboAssembler::Sgt(Register rd, Register rs, const Operand& rt) {
if (rt.is_reg()) { if (rt.is_reg()) {
slt(rd, rt.rm(), rs); slt(rd, rt.rm(), rs);
...@@ -2250,6 +2296,115 @@ void TurboAssembler::Move(FPURegister dst, uint64_t src) { ...@@ -2250,6 +2296,115 @@ void TurboAssembler::Move(FPURegister dst, uint64_t src) {
} }
} }
void TurboAssembler::LoadZeroOnCondition(Register rd, Register rs,
const Operand& rt, Condition cond) {
switch (cond) {
case cc_always:
mov(rd, zero_reg);
break;
case eq:
if (rs == zero_reg) {
if (rt.is_reg()) {
LoadZeroIfConditionZero(rd, rt.rm());
} else {
if (rt.immediate() == 0) {
mov(rd, zero_reg);
} else {
nop();
}
}
} else if (IsZero(rt)) {
LoadZeroIfConditionZero(rd, rs);
} else {
Subu(t9, rs, rt);
LoadZeroIfConditionZero(rd, t9);
}
break;
case ne:
if (rs == zero_reg) {
if (rt.is_reg()) {
LoadZeroIfConditionNotZero(rd, rt.rm());
} else {
if (rt.immediate() != 0) {
mov(rd, zero_reg);
} else {
nop();
}
}
} else if (IsZero(rt)) {
LoadZeroIfConditionNotZero(rd, rs);
} else {
Subu(t9, rs, rt);
LoadZeroIfConditionNotZero(rd, t9);
}
break;
// Signed comparison.
case greater:
Sgt(t9, rs, rt);
LoadZeroIfConditionNotZero(rd, t9);
break;
case greater_equal:
Sge(t9, rs, rt);
LoadZeroIfConditionNotZero(rd, t9);
// rs >= rt
break;
case less:
Slt(t9, rs, rt);
LoadZeroIfConditionNotZero(rd, t9);
// rs < rt
break;
case less_equal:
Sle(t9, rs, rt);
LoadZeroIfConditionNotZero(rd, t9);
// rs <= rt
break;
// Unsigned comparison.
case Ugreater:
Sgtu(t9, rs, rt);
LoadZeroIfConditionNotZero(rd, t9);
// rs > rt
break;
case Ugreater_equal:
Sgeu(t9, rs, rt);
LoadZeroIfConditionNotZero(rd, t9);
// rs >= rt
break;
case Uless:
Sltu(t9, rs, rt);
LoadZeroIfConditionNotZero(rd, t9);
// rs < rt
break;
case Uless_equal:
Sleu(t9, rs, rt);
LoadZeroIfConditionNotZero(rd, t9);
// rs <= rt
break;
default:
UNREACHABLE();
}
}
void TurboAssembler::LoadZeroIfConditionNotZero(Register dest,
Register condition) {
if (IsMipsArchVariant(kMips32r6)) {
seleqz(dest, dest, condition);
} else {
Movn(dest, zero_reg, condition);
}
}
void TurboAssembler::LoadZeroIfConditionZero(Register dest,
Register condition) {
if (IsMipsArchVariant(kMips32r6)) {
selnez(dest, dest, condition);
} else {
Movz(dest, zero_reg, condition);
}
}
void TurboAssembler::Movz(Register rd, Register rs, Register rt) { void TurboAssembler::Movz(Register rd, Register rs, Register rt) {
if (IsMipsArchVariant(kLoongson) || IsMipsArchVariant(kMips32r6)) { if (IsMipsArchVariant(kLoongson) || IsMipsArchVariant(kMips32r6)) {
Label done; Label done;
...@@ -2638,14 +2793,6 @@ void TurboAssembler::BranchShort(Label* L, BranchDelaySlot bdslot) { ...@@ -2638,14 +2793,6 @@ void TurboAssembler::BranchShort(Label* L, BranchDelaySlot bdslot) {
} }
static inline bool IsZero(const Operand& rt) {
if (rt.is_reg()) {
return rt.rm() == zero_reg;
} else {
return rt.immediate() == 0;
}
}
int32_t TurboAssembler::GetOffset(int32_t offset, Label* L, OffsetSize bits) { int32_t TurboAssembler::GetOffset(int32_t offset, Label* L, OffsetSize bits) {
if (L) { if (L) {
offset = branch_offset_helper(L, bits) >> 2; offset = branch_offset_helper(L, bits) >> 2;
......
...@@ -461,8 +461,12 @@ class TurboAssembler : public Assembler { ...@@ -461,8 +461,12 @@ class TurboAssembler : public Assembler {
DEFINE_INSTRUCTION(Slt); DEFINE_INSTRUCTION(Slt);
DEFINE_INSTRUCTION(Sltu); DEFINE_INSTRUCTION(Sltu);
DEFINE_INSTRUCTION(Sle);
DEFINE_INSTRUCTION(Sleu);
DEFINE_INSTRUCTION(Sgt); DEFINE_INSTRUCTION(Sgt);
DEFINE_INSTRUCTION(Sgtu); DEFINE_INSTRUCTION(Sgtu);
DEFINE_INSTRUCTION(Sge);
DEFINE_INSTRUCTION(Sgeu);
// MIPS32 R2 instruction macro. // MIPS32 R2 instruction macro.
DEFINE_INSTRUCTION(Ror); DEFINE_INSTRUCTION(Ror);
...@@ -563,6 +567,11 @@ class TurboAssembler : public Assembler { ...@@ -563,6 +567,11 @@ class TurboAssembler : public Assembler {
void Movt(Register rd, Register rs, uint16_t cc = 0); void Movt(Register rd, Register rs, uint16_t cc = 0);
void Movf(Register rd, Register rs, uint16_t cc = 0); void Movf(Register rd, Register rs, uint16_t cc = 0);
void LoadZeroIfConditionNotZero(Register dest, Register condition);
void LoadZeroIfConditionZero(Register dest, Register condition);
void LoadZeroOnCondition(Register rd, Register rs, const Operand& rt,
Condition cond);
void Clz(Register rd, Register rs); void Clz(Register rd, Register rs);
void Ctz(Register rd, Register rs); void Ctz(Register rd, Register rs);
void Popcnt(Register rd, Register rs); void Popcnt(Register rd, Register rs);
......
...@@ -38,6 +38,14 @@ TurboAssembler::TurboAssembler(Isolate* isolate, void* buffer, int buffer_size, ...@@ -38,6 +38,14 @@ TurboAssembler::TurboAssembler(Isolate* isolate, void* buffer, int buffer_size,
} }
} }
static inline bool IsZero(const Operand& rt) {
if (rt.is_reg()) {
return rt.rm() == zero_reg;
} else {
return rt.immediate() == 0;
}
}
int TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode, int TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
Register exclusion1, Register exclusion1,
Register exclusion2, Register exclusion2,
...@@ -959,6 +967,44 @@ void TurboAssembler::Sltu(Register rd, Register rs, const Operand& rt) { ...@@ -959,6 +967,44 @@ void TurboAssembler::Sltu(Register rd, Register rs, const Operand& rt) {
} }
} }
void TurboAssembler::Sle(Register rd, Register rs, const Operand& rt) {
if (rt.is_reg()) {
slt(rd, rt.rm(), rs);
} else {
// li handles the relocation.
UseScratchRegisterScope temps(this);
Register scratch = temps.hasAvailable() ? temps.Acquire() : t8;
DCHECK(rs != scratch);
li(scratch, rt);
slt(rd, scratch, rs);
}
xori(rd, rd, 1);
}
void TurboAssembler::Sleu(Register rd, Register rs, const Operand& rt) {
if (rt.is_reg()) {
sltu(rd, rt.rm(), rs);
} else {
// li handles the relocation.
UseScratchRegisterScope temps(this);
Register scratch = temps.hasAvailable() ? temps.Acquire() : t8;
DCHECK(rs != scratch);
li(scratch, rt);
sltu(rd, scratch, rs);
}
xori(rd, rd, 1);
}
void TurboAssembler::Sge(Register rd, Register rs, const Operand& rt) {
Slt(rd, rs, rt);
xori(rd, rd, 1);
}
void TurboAssembler::Sgeu(Register rd, Register rs, const Operand& rt) {
Sltu(rd, rs, rt);
xori(rd, rd, 1);
}
void TurboAssembler::Sgt(Register rd, Register rs, const Operand& rt) { void TurboAssembler::Sgt(Register rd, Register rs, const Operand& rt) {
if (rt.is_reg()) { if (rt.is_reg()) {
slt(rd, rt.rm(), rs); slt(rd, rt.rm(), rs);
...@@ -2792,6 +2838,115 @@ void TurboAssembler::Movn(Register rd, Register rs, Register rt) { ...@@ -2792,6 +2838,115 @@ void TurboAssembler::Movn(Register rd, Register rs, Register rt) {
} }
} }
void TurboAssembler::LoadZeroOnCondition(Register rd, Register rs,
const Operand& rt, Condition cond) {
switch (cond) {
case cc_always:
mov(rd, zero_reg);
break;
case eq:
if (rs == zero_reg) {
if (rt.is_reg()) {
LoadZeroIfConditionZero(rd, rt.rm());
} else {
if (rt.immediate() == 0) {
mov(rd, zero_reg);
} else {
nop();
}
}
} else if (IsZero(rt)) {
LoadZeroIfConditionZero(rd, rs);
} else {
Dsubu(t9, rs, rt);
LoadZeroIfConditionZero(rd, t9);
}
break;
case ne:
if (rs == zero_reg) {
if (rt.is_reg()) {
LoadZeroIfConditionNotZero(rd, rt.rm());
} else {
if (rt.immediate() != 0) {
mov(rd, zero_reg);
} else {
nop();
}
}
} else if (IsZero(rt)) {
LoadZeroIfConditionNotZero(rd, rs);
} else {
Dsubu(t9, rs, rt);
LoadZeroIfConditionNotZero(rd, t9);
}
break;
// Signed comparison.
case greater:
Sgt(t9, rs, rt);
LoadZeroIfConditionNotZero(rd, t9);
break;
case greater_equal:
Sge(t9, rs, rt);
LoadZeroIfConditionNotZero(rd, t9);
// rs >= rt
break;
case less:
Slt(t9, rs, rt);
LoadZeroIfConditionNotZero(rd, t9);
// rs < rt
break;
case less_equal:
Sle(t9, rs, rt);
LoadZeroIfConditionNotZero(rd, t9);
// rs <= rt
break;
// Unsigned comparison.
case Ugreater:
Sgtu(t9, rs, rt);
LoadZeroIfConditionNotZero(rd, t9);
// rs > rt
break;
case Ugreater_equal:
Sgeu(t9, rs, rt);
LoadZeroIfConditionNotZero(rd, t9);
// rs >= rt
break;
case Uless:
Sltu(t9, rs, rt);
LoadZeroIfConditionNotZero(rd, t9);
// rs < rt
break;
case Uless_equal:
Sleu(t9, rs, rt);
LoadZeroIfConditionNotZero(rd, t9);
// rs <= rt
break;
default:
UNREACHABLE();
}
}
void TurboAssembler::LoadZeroIfConditionNotZero(Register dest,
Register condition) {
if (kArchVariant == kMips64r6) {
seleqz(dest, dest, condition);
} else {
Movn(dest, zero_reg, condition);
}
}
void TurboAssembler::LoadZeroIfConditionZero(Register dest,
Register condition) {
if (kArchVariant == kMips64r6) {
selnez(dest, dest, condition);
} else {
Movz(dest, zero_reg, condition);
}
}
void TurboAssembler::Movt(Register rd, Register rs, uint16_t cc) { void TurboAssembler::Movt(Register rd, Register rs, uint16_t cc) {
movt(rd, rs, cc); movt(rd, rs, cc);
} }
...@@ -3149,14 +3304,6 @@ void TurboAssembler::BranchShort(Label* L, BranchDelaySlot bdslot) { ...@@ -3149,14 +3304,6 @@ void TurboAssembler::BranchShort(Label* L, BranchDelaySlot bdslot) {
} }
static inline bool IsZero(const Operand& rt) {
if (rt.is_reg()) {
return rt.rm() == zero_reg;
} else {
return rt.immediate() == 0;
}
}
int32_t TurboAssembler::GetOffset(int32_t offset, Label* L, OffsetSize bits) { int32_t TurboAssembler::GetOffset(int32_t offset, Label* L, OffsetSize bits) {
if (L) { if (L) {
offset = branch_offset_helper(L, bits) >> 2; offset = branch_offset_helper(L, bits) >> 2;
......
...@@ -495,8 +495,12 @@ class TurboAssembler : public Assembler { ...@@ -495,8 +495,12 @@ class TurboAssembler : public Assembler {
DEFINE_INSTRUCTION(Slt); DEFINE_INSTRUCTION(Slt);
DEFINE_INSTRUCTION(Sltu); DEFINE_INSTRUCTION(Sltu);
DEFINE_INSTRUCTION(Sle);
DEFINE_INSTRUCTION(Sleu);
DEFINE_INSTRUCTION(Sgt); DEFINE_INSTRUCTION(Sgt);
DEFINE_INSTRUCTION(Sgtu); DEFINE_INSTRUCTION(Sgtu);
DEFINE_INSTRUCTION(Sge);
DEFINE_INSTRUCTION(Sgeu);
// MIPS32 R2 instruction macro. // MIPS32 R2 instruction macro.
DEFINE_INSTRUCTION(Ror); DEFINE_INSTRUCTION(Ror);
...@@ -605,6 +609,11 @@ class TurboAssembler : public Assembler { ...@@ -605,6 +609,11 @@ class TurboAssembler : public Assembler {
void Movt(Register rd, Register rs, uint16_t cc = 0); void Movt(Register rd, Register rs, uint16_t cc = 0);
void Movf(Register rd, Register rs, uint16_t cc = 0); void Movf(Register rd, Register rs, uint16_t cc = 0);
void LoadZeroIfConditionNotZero(Register dest, Register condition);
void LoadZeroIfConditionZero(Register dest, Register condition);
void LoadZeroOnCondition(Register rd, Register rs, const Operand& rt,
Condition cond);
void Clz(Register rd, Register rs); void Clz(Register rd, Register rs);
void Ctz(Register rd, Register rs); void Ctz(Register rd, Register rs);
void Dctz(Register rd, Register rs); void Dctz(Register rd, Register rs);
......
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