diff options
Diffstat (limited to 'compiler/utils/mips')
-rw-r--r-- | compiler/utils/mips/assembler_mips.cc | 274 | ||||
-rw-r--r-- | compiler/utils/mips/assembler_mips.h | 170 | ||||
-rw-r--r-- | compiler/utils/mips/assembler_mips_test.cc | 321 |
3 files changed, 587 insertions, 178 deletions
diff --git a/compiler/utils/mips/assembler_mips.cc b/compiler/utils/mips/assembler_mips.cc index 733ad2cc38..afca8adcbb 100644 --- a/compiler/utils/mips/assembler_mips.cc +++ b/compiler/utils/mips/assembler_mips.cc @@ -503,6 +503,18 @@ void MipsAssembler::Bgtz(Register rt, uint16_t imm16) { EmitI(0x7, rt, static_cast<Register>(0), imm16); } +void MipsAssembler::Bc1f(int cc, uint16_t imm16) { + CHECK(!IsR6()); + CHECK(IsUint<3>(cc)) << cc; + EmitI(0x11, static_cast<Register>(0x8), static_cast<Register>(cc << 2), imm16); +} + +void MipsAssembler::Bc1t(int cc, uint16_t imm16) { + CHECK(!IsR6()); + CHECK(IsUint<3>(cc)) << cc; + EmitI(0x11, static_cast<Register>(0x8), static_cast<Register>((cc << 2) | 1), imm16); +} + void MipsAssembler::J(uint32_t addr26) { EmitI26(0x2, addr26); } @@ -637,7 +649,17 @@ void MipsAssembler::Bnezc(Register rs, uint32_t imm21) { EmitI21(0x3E, rs, imm21); } -void MipsAssembler::EmitBcond(BranchCondition cond, Register rs, Register rt, uint16_t imm16) { +void MipsAssembler::Bc1eqz(FRegister ft, uint16_t imm16) { + CHECK(IsR6()); + EmitFI(0x11, 0x9, ft, imm16); +} + +void MipsAssembler::Bc1nez(FRegister ft, uint16_t imm16) { + CHECK(IsR6()); + EmitFI(0x11, 0xD, ft, imm16); +} + +void MipsAssembler::EmitBcondR2(BranchCondition cond, Register rs, Register rt, uint16_t imm16) { switch (cond) { case kCondLTZ: CHECK_EQ(rt, ZERO); @@ -669,6 +691,14 @@ void MipsAssembler::EmitBcond(BranchCondition cond, Register rs, Register rt, ui CHECK_EQ(rt, ZERO); Bnez(rs, imm16); break; + case kCondF: + CHECK_EQ(rt, ZERO); + Bc1f(static_cast<int>(rs), imm16); + break; + case kCondT: + CHECK_EQ(rt, ZERO); + Bc1t(static_cast<int>(rs), imm16); + break; case kCondLT: case kCondGE: case kCondLE: @@ -683,7 +713,7 @@ void MipsAssembler::EmitBcond(BranchCondition cond, Register rs, Register rt, ui } } -void MipsAssembler::EmitBcondc(BranchCondition cond, Register rs, Register rt, uint32_t imm16_21) { +void MipsAssembler::EmitBcondR6(BranchCondition cond, Register rs, Register rt, uint32_t imm16_21) { switch (cond) { case kCondLT: Bltc(rs, rt, imm16_21); @@ -733,6 +763,14 @@ void MipsAssembler::EmitBcondc(BranchCondition cond, Register rs, Register rt, u case kCondGEU: Bgeuc(rs, rt, imm16_21); break; + case kCondF: + CHECK_EQ(rt, ZERO); + Bc1eqz(static_cast<FRegister>(rs), imm16_21); + break; + case kCondT: + CHECK_EQ(rt, ZERO); + Bc1nez(static_cast<FRegister>(rs), imm16_21); + break; case kUncond: LOG(FATAL) << "Unexpected branch condition " << cond; UNREACHABLE(); @@ -787,6 +825,202 @@ void MipsAssembler::NegD(FRegister fd, FRegister fs) { EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x7); } +void MipsAssembler::CunS(int cc, FRegister fs, FRegister ft) { + CHECK(!IsR6()); + CHECK(IsUint<3>(cc)) << cc; + EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x31); +} + +void MipsAssembler::CeqS(int cc, FRegister fs, FRegister ft) { + CHECK(!IsR6()); + CHECK(IsUint<3>(cc)) << cc; + EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x32); +} + +void MipsAssembler::CueqS(int cc, FRegister fs, FRegister ft) { + CHECK(!IsR6()); + CHECK(IsUint<3>(cc)) << cc; + EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x33); +} + +void MipsAssembler::ColtS(int cc, FRegister fs, FRegister ft) { + CHECK(!IsR6()); + CHECK(IsUint<3>(cc)) << cc; + EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x34); +} + +void MipsAssembler::CultS(int cc, FRegister fs, FRegister ft) { + CHECK(!IsR6()); + CHECK(IsUint<3>(cc)) << cc; + EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x35); +} + +void MipsAssembler::ColeS(int cc, FRegister fs, FRegister ft) { + CHECK(!IsR6()); + CHECK(IsUint<3>(cc)) << cc; + EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x36); +} + +void MipsAssembler::CuleS(int cc, FRegister fs, FRegister ft) { + CHECK(!IsR6()); + CHECK(IsUint<3>(cc)) << cc; + EmitFR(0x11, 0x10, ft, fs, static_cast<FRegister>(cc << 2), 0x37); +} + +void MipsAssembler::CunD(int cc, FRegister fs, FRegister ft) { + CHECK(!IsR6()); + CHECK(IsUint<3>(cc)) << cc; + EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x31); +} + +void MipsAssembler::CeqD(int cc, FRegister fs, FRegister ft) { + CHECK(!IsR6()); + CHECK(IsUint<3>(cc)) << cc; + EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x32); +} + +void MipsAssembler::CueqD(int cc, FRegister fs, FRegister ft) { + CHECK(!IsR6()); + CHECK(IsUint<3>(cc)) << cc; + EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x33); +} + +void MipsAssembler::ColtD(int cc, FRegister fs, FRegister ft) { + CHECK(!IsR6()); + CHECK(IsUint<3>(cc)) << cc; + EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x34); +} + +void MipsAssembler::CultD(int cc, FRegister fs, FRegister ft) { + CHECK(!IsR6()); + CHECK(IsUint<3>(cc)) << cc; + EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x35); +} + +void MipsAssembler::ColeD(int cc, FRegister fs, FRegister ft) { + CHECK(!IsR6()); + CHECK(IsUint<3>(cc)) << cc; + EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x36); +} + +void MipsAssembler::CuleD(int cc, FRegister fs, FRegister ft) { + CHECK(!IsR6()); + CHECK(IsUint<3>(cc)) << cc; + EmitFR(0x11, 0x11, ft, fs, static_cast<FRegister>(cc << 2), 0x37); +} + +void MipsAssembler::CmpUnS(FRegister fd, FRegister fs, FRegister ft) { + CHECK(IsR6()); + EmitFR(0x11, 0x14, ft, fs, fd, 0x01); +} + +void MipsAssembler::CmpEqS(FRegister fd, FRegister fs, FRegister ft) { + CHECK(IsR6()); + EmitFR(0x11, 0x14, ft, fs, fd, 0x02); +} + +void MipsAssembler::CmpUeqS(FRegister fd, FRegister fs, FRegister ft) { + CHECK(IsR6()); + EmitFR(0x11, 0x14, ft, fs, fd, 0x03); +} + +void MipsAssembler::CmpLtS(FRegister fd, FRegister fs, FRegister ft) { + CHECK(IsR6()); + EmitFR(0x11, 0x14, ft, fs, fd, 0x04); +} + +void MipsAssembler::CmpUltS(FRegister fd, FRegister fs, FRegister ft) { + CHECK(IsR6()); + EmitFR(0x11, 0x14, ft, fs, fd, 0x05); +} + +void MipsAssembler::CmpLeS(FRegister fd, FRegister fs, FRegister ft) { + CHECK(IsR6()); + EmitFR(0x11, 0x14, ft, fs, fd, 0x06); +} + +void MipsAssembler::CmpUleS(FRegister fd, FRegister fs, FRegister ft) { + CHECK(IsR6()); + EmitFR(0x11, 0x14, ft, fs, fd, 0x07); +} + +void MipsAssembler::CmpOrS(FRegister fd, FRegister fs, FRegister ft) { + CHECK(IsR6()); + EmitFR(0x11, 0x14, ft, fs, fd, 0x11); +} + +void MipsAssembler::CmpUneS(FRegister fd, FRegister fs, FRegister ft) { + CHECK(IsR6()); + EmitFR(0x11, 0x14, ft, fs, fd, 0x12); +} + +void MipsAssembler::CmpNeS(FRegister fd, FRegister fs, FRegister ft) { + CHECK(IsR6()); + EmitFR(0x11, 0x14, ft, fs, fd, 0x13); +} + +void MipsAssembler::CmpUnD(FRegister fd, FRegister fs, FRegister ft) { + CHECK(IsR6()); + EmitFR(0x11, 0x15, ft, fs, fd, 0x01); +} + +void MipsAssembler::CmpEqD(FRegister fd, FRegister fs, FRegister ft) { + CHECK(IsR6()); + EmitFR(0x11, 0x15, ft, fs, fd, 0x02); +} + +void MipsAssembler::CmpUeqD(FRegister fd, FRegister fs, FRegister ft) { + CHECK(IsR6()); + EmitFR(0x11, 0x15, ft, fs, fd, 0x03); +} + +void MipsAssembler::CmpLtD(FRegister fd, FRegister fs, FRegister ft) { + CHECK(IsR6()); + EmitFR(0x11, 0x15, ft, fs, fd, 0x04); +} + +void MipsAssembler::CmpUltD(FRegister fd, FRegister fs, FRegister ft) { + CHECK(IsR6()); + EmitFR(0x11, 0x15, ft, fs, fd, 0x05); +} + +void MipsAssembler::CmpLeD(FRegister fd, FRegister fs, FRegister ft) { + CHECK(IsR6()); + EmitFR(0x11, 0x15, ft, fs, fd, 0x06); +} + +void MipsAssembler::CmpUleD(FRegister fd, FRegister fs, FRegister ft) { + CHECK(IsR6()); + EmitFR(0x11, 0x15, ft, fs, fd, 0x07); +} + +void MipsAssembler::CmpOrD(FRegister fd, FRegister fs, FRegister ft) { + CHECK(IsR6()); + EmitFR(0x11, 0x15, ft, fs, fd, 0x11); +} + +void MipsAssembler::CmpUneD(FRegister fd, FRegister fs, FRegister ft) { + CHECK(IsR6()); + EmitFR(0x11, 0x15, ft, fs, fd, 0x12); +} + +void MipsAssembler::CmpNeD(FRegister fd, FRegister fs, FRegister ft) { + CHECK(IsR6()); + EmitFR(0x11, 0x15, ft, fs, fd, 0x13); +} + +void MipsAssembler::Movf(Register rd, Register rs, int cc) { + CHECK(!IsR6()); + CHECK(IsUint<3>(cc)) << cc; + EmitR(0, rs, static_cast<Register>(cc << 2), rd, 0, 0x01); +} + +void MipsAssembler::Movt(Register rd, Register rs, int cc) { + CHECK(!IsR6()); + CHECK(IsUint<3>(cc)) << cc; + EmitR(0, rs, static_cast<Register>((cc << 2) | 1), rd, 0, 0x01); +} + void MipsAssembler::Cvtsw(FRegister fd, FRegister fs) { EmitFR(0x11, 0x14, static_cast<FRegister>(0), fs, fd, 0x20); } @@ -1058,6 +1292,10 @@ MipsAssembler::Branch::Branch(bool is_r6, CHECK_NE(lhs_reg, ZERO); CHECK_EQ(rhs_reg, ZERO); break; + case kCondF: + case kCondT: + CHECK_EQ(rhs_reg, ZERO); + break; case kUncond: UNREACHABLE(); } @@ -1112,6 +1350,10 @@ MipsAssembler::BranchCondition MipsAssembler::Branch::OppositeCondition( return kCondGEU; case kCondGEU: return kCondLTU; + case kCondF: + return kCondT; + case kCondT: + return kCondF; case kUncond: LOG(FATAL) << "Unexpected branch condition " << cond; } @@ -1514,7 +1756,7 @@ void MipsAssembler::EmitBranch(MipsAssembler::Branch* branch) { break; case Branch::kCondBranch: CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); - EmitBcond(condition, lhs, rhs, offset); + EmitBcondR2(condition, lhs, rhs, offset); Nop(); // TODO: improve by filling the delay slot. break; case Branch::kCall: @@ -1561,7 +1803,7 @@ void MipsAssembler::EmitBranch(MipsAssembler::Branch* branch) { // Note: the opposite condition branch encodes 8 as the distance, which is equal to the // number of instructions skipped: // (PUSH(IncreaseFrameSize(ADDIU) + SW) + NAL + LUI + ORI + ADDU + LW + JR). - EmitBcond(Branch::OppositeCondition(condition), lhs, rhs, 8); + EmitBcondR2(Branch::OppositeCondition(condition), lhs, rhs, 8); Push(RA); Nal(); CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); @@ -1589,8 +1831,8 @@ void MipsAssembler::EmitBranch(MipsAssembler::Branch* branch) { break; case Branch::kR6CondBranch: CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); - EmitBcondc(condition, lhs, rhs, offset); - Nop(); // TODO: improve by filling the forbidden slot. + EmitBcondR6(condition, lhs, rhs, offset); + Nop(); // TODO: improve by filling the forbidden/delay slot. break; case Branch::kR6Call: CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); @@ -1606,7 +1848,7 @@ void MipsAssembler::EmitBranch(MipsAssembler::Branch* branch) { Jic(AT, Low16Bits(offset)); break; case Branch::kR6LongCondBranch: - EmitBcondc(Branch::OppositeCondition(condition), lhs, rhs, 2); + EmitBcondR6(Branch::OppositeCondition(condition), lhs, rhs, 2); offset += (offset & 0x8000) << 1; // Account for sign extension in jic. CHECK_EQ(overwrite_location_, branch->GetOffsetLocation()); Auipc(AT, High16Bits(offset)); @@ -1708,6 +1950,24 @@ void MipsAssembler::Bgeu(Register rs, Register rt, MipsLabel* label) { } } +void MipsAssembler::Bc1f(int cc, MipsLabel* label) { + CHECK(IsUint<3>(cc)) << cc; + Bcond(label, kCondF, static_cast<Register>(cc), ZERO); +} + +void MipsAssembler::Bc1t(int cc, MipsLabel* label) { + CHECK(IsUint<3>(cc)) << cc; + Bcond(label, kCondT, static_cast<Register>(cc), ZERO); +} + +void MipsAssembler::Bc1eqz(FRegister ft, MipsLabel* label) { + Bcond(label, kCondF, static_cast<Register>(ft), ZERO); +} + +void MipsAssembler::Bc1nez(FRegister ft, MipsLabel* label) { + Bcond(label, kCondT, static_cast<Register>(ft), ZERO); +} + void MipsAssembler::LoadFromOffset(LoadOperandType type, Register reg, Register base, int32_t offset) { // IsInt<16> must be passed a signed value. diff --git a/compiler/utils/mips/assembler_mips.h b/compiler/utils/mips/assembler_mips.h index 62366f6a8b..f569aa858c 100644 --- a/compiler/utils/mips/assembler_mips.h +++ b/compiler/utils/mips/assembler_mips.h @@ -72,8 +72,8 @@ class MipsExceptionSlowPath { : scratch_(scratch), stack_adjust_(stack_adjust) {} MipsExceptionSlowPath(MipsExceptionSlowPath&& src) - : scratch_(std::move(src.scratch_)), - stack_adjust_(std::move(src.stack_adjust_)), + : scratch_(src.scratch_), + stack_adjust_(src.stack_adjust_), exception_entry_(std::move(src.exception_entry_)) {} private: @@ -185,6 +185,8 @@ class MipsAssembler FINAL : public Assembler { void Bgez(Register rt, uint16_t imm16); void Blez(Register rt, uint16_t imm16); void Bgtz(Register rt, uint16_t imm16); + void Bc1f(int cc, uint16_t imm16); // R2 + void Bc1t(int cc, uint16_t imm16); // R2 void J(uint32_t addr26); void Jal(uint32_t addr26); void Jalr(Register rd, Register rs); @@ -208,6 +210,8 @@ class MipsAssembler FINAL : public Assembler { void Bnec(Register rs, Register rt, uint16_t imm16); // R6 void Beqzc(Register rs, uint32_t imm21); // R6 void Bnezc(Register rs, uint32_t imm21); // R6 + void Bc1eqz(FRegister ft, uint16_t imm16); // R6 + void Bc1nez(FRegister ft, uint16_t imm16); // R6 void AddS(FRegister fd, FRegister fs, FRegister ft); void SubS(FRegister fd, FRegister fs, FRegister ft); @@ -222,6 +226,43 @@ class MipsAssembler FINAL : public Assembler { void NegS(FRegister fd, FRegister fs); void NegD(FRegister fd, FRegister fs); + void CunS(int cc, FRegister fs, FRegister ft); // R2 + void CeqS(int cc, FRegister fs, FRegister ft); // R2 + void CueqS(int cc, FRegister fs, FRegister ft); // R2 + void ColtS(int cc, FRegister fs, FRegister ft); // R2 + void CultS(int cc, FRegister fs, FRegister ft); // R2 + void ColeS(int cc, FRegister fs, FRegister ft); // R2 + void CuleS(int cc, FRegister fs, FRegister ft); // R2 + void CunD(int cc, FRegister fs, FRegister ft); // R2 + void CeqD(int cc, FRegister fs, FRegister ft); // R2 + void CueqD(int cc, FRegister fs, FRegister ft); // R2 + void ColtD(int cc, FRegister fs, FRegister ft); // R2 + void CultD(int cc, FRegister fs, FRegister ft); // R2 + void ColeD(int cc, FRegister fs, FRegister ft); // R2 + void CuleD(int cc, FRegister fs, FRegister ft); // R2 + void CmpUnS(FRegister fd, FRegister fs, FRegister ft); // R6 + void CmpEqS(FRegister fd, FRegister fs, FRegister ft); // R6 + void CmpUeqS(FRegister fd, FRegister fs, FRegister ft); // R6 + void CmpLtS(FRegister fd, FRegister fs, FRegister ft); // R6 + void CmpUltS(FRegister fd, FRegister fs, FRegister ft); // R6 + void CmpLeS(FRegister fd, FRegister fs, FRegister ft); // R6 + void CmpUleS(FRegister fd, FRegister fs, FRegister ft); // R6 + void CmpOrS(FRegister fd, FRegister fs, FRegister ft); // R6 + void CmpUneS(FRegister fd, FRegister fs, FRegister ft); // R6 + void CmpNeS(FRegister fd, FRegister fs, FRegister ft); // R6 + void CmpUnD(FRegister fd, FRegister fs, FRegister ft); // R6 + void CmpEqD(FRegister fd, FRegister fs, FRegister ft); // R6 + void CmpUeqD(FRegister fd, FRegister fs, FRegister ft); // R6 + void CmpLtD(FRegister fd, FRegister fs, FRegister ft); // R6 + void CmpUltD(FRegister fd, FRegister fs, FRegister ft); // R6 + void CmpLeD(FRegister fd, FRegister fs, FRegister ft); // R6 + void CmpUleD(FRegister fd, FRegister fs, FRegister ft); // R6 + void CmpOrD(FRegister fd, FRegister fs, FRegister ft); // R6 + void CmpUneD(FRegister fd, FRegister fs, FRegister ft); // R6 + void CmpNeD(FRegister fd, FRegister fs, FRegister ft); // R6 + void Movf(Register rd, Register rs, int cc); // R2 + void Movt(Register rd, Register rs, int cc); // R2 + void Cvtsw(FRegister fd, FRegister fs); void Cvtdw(FRegister fd, FRegister fs); void Cvtsd(FRegister fd, FRegister fs); @@ -267,6 +308,10 @@ class MipsAssembler FINAL : public Assembler { void Bge(Register rs, Register rt, MipsLabel* label); void Bltu(Register rs, Register rt, MipsLabel* label); void Bgeu(Register rs, Register rt, MipsLabel* label); + void Bc1f(int cc, MipsLabel* label); // R2 + void Bc1t(int cc, MipsLabel* label); // R2 + void Bc1eqz(FRegister ft, MipsLabel* label); // R6 + void Bc1nez(FRegister ft, MipsLabel* label); // R6 void EmitLoad(ManagedRegister m_dst, Register src_register, int32_t src_offset, size_t size); void LoadFromOffset(LoadOperandType type, Register reg, Register base, int32_t offset); @@ -296,7 +341,8 @@ class MipsAssembler FINAL : public Assembler { // // Emit code that will create an activation on the stack. - void BuildFrame(size_t frame_size, ManagedRegister method_reg, + void BuildFrame(size_t frame_size, + ManagedRegister method_reg, const std::vector<ManagedRegister>& callee_save_regs, const ManagedRegisterEntrySpills& entry_spills) OVERRIDE; @@ -314,58 +360,85 @@ class MipsAssembler FINAL : public Assembler { void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister mscratch) OVERRIDE; - void StoreImmediateToThread32(ThreadOffset<4> dest, uint32_t imm, ManagedRegister mscratch) - OVERRIDE; + void StoreImmediateToThread32(ThreadOffset<kMipsWordSize> dest, + uint32_t imm, + ManagedRegister mscratch) OVERRIDE; - void StoreStackOffsetToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs, + void StoreStackOffsetToThread32(ThreadOffset<kMipsWordSize> thr_offs, + FrameOffset fr_offs, ManagedRegister mscratch) OVERRIDE; - void StoreStackPointerToThread32(ThreadOffset<4> thr_offs) OVERRIDE; + void StoreStackPointerToThread32(ThreadOffset<kMipsWordSize> thr_offs) OVERRIDE; - void StoreSpanning(FrameOffset dest, ManagedRegister msrc, FrameOffset in_off, + void StoreSpanning(FrameOffset dest, + ManagedRegister msrc, + FrameOffset in_off, ManagedRegister mscratch) OVERRIDE; // Load routines. void Load(ManagedRegister mdest, FrameOffset src, size_t size) OVERRIDE; - void LoadFromThread32(ManagedRegister mdest, ThreadOffset<4> src, size_t size) OVERRIDE; + void LoadFromThread32(ManagedRegister mdest, + ThreadOffset<kMipsWordSize> src, + size_t size) OVERRIDE; void LoadRef(ManagedRegister dest, FrameOffset src) OVERRIDE; - void LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs, + void LoadRef(ManagedRegister mdest, + ManagedRegister base, + MemberOffset offs, bool unpoison_reference) OVERRIDE; void LoadRawPtr(ManagedRegister mdest, ManagedRegister base, Offset offs) OVERRIDE; - void LoadRawPtrFromThread32(ManagedRegister mdest, ThreadOffset<4> offs) OVERRIDE; + void LoadRawPtrFromThread32(ManagedRegister mdest, ThreadOffset<kMipsWordSize> offs) OVERRIDE; // Copying routines. void Move(ManagedRegister mdest, ManagedRegister msrc, size_t size) OVERRIDE; - void CopyRawPtrFromThread32(FrameOffset fr_offs, ThreadOffset<4> thr_offs, + void CopyRawPtrFromThread32(FrameOffset fr_offs, + ThreadOffset<kMipsWordSize> thr_offs, ManagedRegister mscratch) OVERRIDE; - void CopyRawPtrToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs, + void CopyRawPtrToThread32(ThreadOffset<kMipsWordSize> thr_offs, + FrameOffset fr_offs, ManagedRegister mscratch) OVERRIDE; void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister mscratch) OVERRIDE; void Copy(FrameOffset dest, FrameOffset src, ManagedRegister mscratch, size_t size) OVERRIDE; - void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, ManagedRegister mscratch, + void Copy(FrameOffset dest, + ManagedRegister src_base, + Offset src_offset, + ManagedRegister mscratch, size_t size) OVERRIDE; - void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src, - ManagedRegister mscratch, size_t size) OVERRIDE; + void Copy(ManagedRegister dest_base, + Offset dest_offset, + FrameOffset src, + ManagedRegister mscratch, + size_t size) OVERRIDE; - void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset, ManagedRegister mscratch, + void Copy(FrameOffset dest, + FrameOffset src_base, + Offset src_offset, + ManagedRegister mscratch, size_t size) OVERRIDE; - void Copy(ManagedRegister dest, Offset dest_offset, ManagedRegister src, Offset src_offset, - ManagedRegister mscratch, size_t size) OVERRIDE; + void Copy(ManagedRegister dest, + Offset dest_offset, + ManagedRegister src, + Offset src_offset, + ManagedRegister mscratch, + size_t size) OVERRIDE; - void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset, - ManagedRegister mscratch, size_t size) OVERRIDE; + void Copy(FrameOffset dest, + Offset dest_offset, + FrameOffset src, + Offset src_offset, + ManagedRegister mscratch, + size_t size) OVERRIDE; void MemoryBarrier(ManagedRegister) OVERRIDE; @@ -383,13 +456,17 @@ class MipsAssembler FINAL : public Assembler { // value is null and null_allowed. in_reg holds a possibly stale reference // that can be used to avoid loading the handle scope entry to see if the value is // null. - void CreateHandleScopeEntry(ManagedRegister out_reg, FrameOffset handlescope_offset, - ManagedRegister in_reg, bool null_allowed) OVERRIDE; + void CreateHandleScopeEntry(ManagedRegister out_reg, + FrameOffset handlescope_offset, + ManagedRegister in_reg, + bool null_allowed) OVERRIDE; // Set up out_off to hold a Object** into the handle scope, or to be null if the // value is null and null_allowed. - void CreateHandleScopeEntry(FrameOffset out_off, FrameOffset handlescope_offset, - ManagedRegister mscratch, bool null_allowed) OVERRIDE; + void CreateHandleScopeEntry(FrameOffset out_off, + FrameOffset handlescope_offset, + ManagedRegister mscratch, + bool null_allowed) OVERRIDE; // src holds a handle scope entry (Object**) load this into dst. void LoadReferenceFromHandleScope(ManagedRegister dst, ManagedRegister src) OVERRIDE; @@ -402,7 +479,7 @@ class MipsAssembler FINAL : public Assembler { // Call to address held at [base+offset]. void Call(ManagedRegister base, Offset offset, ManagedRegister mscratch) OVERRIDE; void Call(FrameOffset base, Offset offset, ManagedRegister mscratch) OVERRIDE; - void CallFromThread32(ThreadOffset<4> offset, ManagedRegister mscratch) OVERRIDE; + void CallFromThread32(ThreadOffset<kMipsWordSize> offset, ManagedRegister mscratch) OVERRIDE; // Generate code to check if Thread::Current()->exception_ is non-null // and branch to a ExceptionSlowPath if it is. @@ -437,6 +514,8 @@ class MipsAssembler FINAL : public Assembler { kCondNEZ, kCondLTU, kCondGEU, + kCondF, // Floating-point predicate false. + kCondT, // Floating-point predicate true. kUncond, }; friend std::ostream& operator<<(std::ostream& os, const BranchCondition& rhs); @@ -543,7 +622,22 @@ class MipsAssembler FINAL : public Assembler { // // Composite branches (made of several instructions) with longer reach have 32-bit // offsets encoded as 2 16-bit "halves" in two instructions (high half goes first). - // The composite branches cover the range of PC + +/-2GB. + // The composite branches cover the range of PC + +/-2GB on MIPS32 CPUs. However, + // the range is not end-to-end on MIPS64 (unless addresses are forced to zero- or + // sign-extend from 32 to 64 bits by the appropriate CPU configuration). + // Consider the following implementation of a long unconditional branch, for + // example: + // + // auipc at, offset_31_16 // at = pc + sign_extend(offset_31_16) << 16 + // jic at, offset_15_0 // pc = at + sign_extend(offset_15_0) + // + // Both of the above instructions take 16-bit signed offsets as immediate operands. + // When bit 15 of offset_15_0 is 1, it effectively causes subtraction of 0x10000 + // due to sign extension. This must be compensated for by incrementing offset_31_16 + // by 1. offset_31_16 can only be incremented by 1 if it's not 0x7FFF. If it is + // 0x7FFF, adding 1 will overflow the positive offset into the negative range. + // Therefore, the long branch range is something like from PC - 0x80000000 to + // PC + 0x7FFF7FFF, IOW, shorter by 32KB on one side. // // The returned values are therefore: 18, 21, 23, 28 and 32. There's also a special // case with the addiu instruction and a 16 bit offset. @@ -580,17 +674,17 @@ class MipsAssembler FINAL : public Assembler { // Helper for the above. void InitShortOrLong(OffsetBits ofs_size, Type short_type, Type long_type); - uint32_t old_location_; // Offset into assembler buffer in bytes. - uint32_t location_; // Offset into assembler buffer in bytes. - uint32_t target_; // Offset into assembler buffer in bytes. + uint32_t old_location_; // Offset into assembler buffer in bytes. + uint32_t location_; // Offset into assembler buffer in bytes. + uint32_t target_; // Offset into assembler buffer in bytes. - uint32_t lhs_reg_ : 5; // Left-hand side register in conditional branches or - // indirect call register. - uint32_t rhs_reg_ : 5; // Right-hand side register in conditional branches. - BranchCondition condition_ : 5; // Condition for conditional branches. + uint32_t lhs_reg_; // Left-hand side register in conditional branches or + // indirect call register. + uint32_t rhs_reg_; // Right-hand side register in conditional branches. + BranchCondition condition_; // Condition for conditional branches. - Type type_ : 5; // Current type of the branch. - Type old_type_ : 5; // Initial type of the branch. + Type type_; // Current type of the branch. + Type old_type_; // Initial type of the branch. }; friend std::ostream& operator<<(std::ostream& os, const Branch::Type& rhs); friend std::ostream& operator<<(std::ostream& os, const Branch::OffsetBits& rhs); @@ -601,8 +695,8 @@ class MipsAssembler FINAL : public Assembler { void EmitI26(int opcode, uint32_t imm26); void EmitFR(int opcode, int fmt, FRegister ft, FRegister fs, FRegister fd, int funct); void EmitFI(int opcode, int fmt, FRegister rt, uint16_t imm); - void EmitBcond(BranchCondition cond, Register rs, Register rt, uint16_t imm16); - void EmitBcondc(BranchCondition cond, Register rs, Register rt, uint32_t imm16_21); // R6 + void EmitBcondR2(BranchCondition cond, Register rs, Register rt, uint16_t imm16); + void EmitBcondR6(BranchCondition cond, Register rs, Register rt, uint32_t imm16_21); void Buncond(MipsLabel* label); void Bcond(MipsLabel* label, BranchCondition condition, Register lhs, Register rhs = ZERO); diff --git a/compiler/utils/mips/assembler_mips_test.cc b/compiler/utils/mips/assembler_mips_test.cc index 063d8bd825..6f8b3e8c57 100644 --- a/compiler/utils/mips/assembler_mips_test.cc +++ b/compiler/utils/mips/assembler_mips_test.cc @@ -21,6 +21,8 @@ #include "base/stl_util.h" #include "utils/assembler_test.h" +#define __ GetAssembler()-> + namespace art { struct MIPSCpuRegisterCompare { @@ -184,6 +186,63 @@ class AssemblerMIPSTest : public AssemblerTest<mips::MipsAssembler, return result; } + void BranchCondOneRegHelper(void (mips::MipsAssembler::*f)(mips::Register, + mips::MipsLabel*), + std::string instr_name) { + mips::MipsLabel label; + (Base::GetAssembler()->*f)(mips::A0, &label); + constexpr size_t kAdduCount1 = 63; + for (size_t i = 0; i != kAdduCount1; ++i) { + __ Addu(mips::ZERO, mips::ZERO, mips::ZERO); + } + __ Bind(&label); + constexpr size_t kAdduCount2 = 64; + for (size_t i = 0; i != kAdduCount2; ++i) { + __ Addu(mips::ZERO, mips::ZERO, mips::ZERO); + } + (Base::GetAssembler()->*f)(mips::A1, &label); + + std::string expected = + ".set noreorder\n" + + instr_name + " $a0, 1f\n" + "nop\n" + + RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") + + "1:\n" + + RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") + + instr_name + " $a1, 1b\n" + "nop\n"; + DriverStr(expected, instr_name); + } + + void BranchCondTwoRegsHelper(void (mips::MipsAssembler::*f)(mips::Register, + mips::Register, + mips::MipsLabel*), + std::string instr_name) { + mips::MipsLabel label; + (Base::GetAssembler()->*f)(mips::A0, mips::A1, &label); + constexpr size_t kAdduCount1 = 63; + for (size_t i = 0; i != kAdduCount1; ++i) { + __ Addu(mips::ZERO, mips::ZERO, mips::ZERO); + } + __ Bind(&label); + constexpr size_t kAdduCount2 = 64; + for (size_t i = 0; i != kAdduCount2; ++i) { + __ Addu(mips::ZERO, mips::ZERO, mips::ZERO); + } + (Base::GetAssembler()->*f)(mips::A2, mips::A3, &label); + + std::string expected = + ".set noreorder\n" + + instr_name + " $a0, $a1, 1f\n" + "nop\n" + + RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") + + "1:\n" + + RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") + + instr_name + " $a2, $a3, 1b\n" + "nop\n"; + DriverStr(expected, instr_name); + } + private: std::vector<mips::Register*> registers_; std::map<mips::Register, std::string, MIPSCpuRegisterCompare> secondary_register_names_; @@ -196,8 +255,6 @@ TEST_F(AssemblerMIPSTest, Toolchain) { EXPECT_TRUE(CheckTools()); } -#define __ GetAssembler()-> - TEST_F(AssemblerMIPSTest, Addu) { DriverStr(RepeatRRR(&mips::MipsAssembler::Addu, "addu ${reg1}, ${reg2}, ${reg3}"), "Addu"); } @@ -418,6 +475,84 @@ TEST_F(AssemblerMIPSTest, NegD) { DriverStr(RepeatFF(&mips::MipsAssembler::NegD, "neg.d ${reg1}, ${reg2}"), "NegD"); } +TEST_F(AssemblerMIPSTest, CunS) { + DriverStr(RepeatIbFF(&mips::MipsAssembler::CunS, 3, "c.un.s $fcc{imm}, ${reg1}, ${reg2}"), + "CunS"); +} + +TEST_F(AssemblerMIPSTest, CeqS) { + DriverStr(RepeatIbFF(&mips::MipsAssembler::CeqS, 3, "c.eq.s $fcc{imm}, ${reg1}, ${reg2}"), + "CeqS"); +} + +TEST_F(AssemblerMIPSTest, CueqS) { + DriverStr(RepeatIbFF(&mips::MipsAssembler::CueqS, 3, "c.ueq.s $fcc{imm}, ${reg1}, ${reg2}"), + "CueqS"); +} + +TEST_F(AssemblerMIPSTest, ColtS) { + DriverStr(RepeatIbFF(&mips::MipsAssembler::ColtS, 3, "c.olt.s $fcc{imm}, ${reg1}, ${reg2}"), + "ColtS"); +} + +TEST_F(AssemblerMIPSTest, CultS) { + DriverStr(RepeatIbFF(&mips::MipsAssembler::CultS, 3, "c.ult.s $fcc{imm}, ${reg1}, ${reg2}"), + "CultS"); +} + +TEST_F(AssemblerMIPSTest, ColeS) { + DriverStr(RepeatIbFF(&mips::MipsAssembler::ColeS, 3, "c.ole.s $fcc{imm}, ${reg1}, ${reg2}"), + "ColeS"); +} + +TEST_F(AssemblerMIPSTest, CuleS) { + DriverStr(RepeatIbFF(&mips::MipsAssembler::CuleS, 3, "c.ule.s $fcc{imm}, ${reg1}, ${reg2}"), + "CuleS"); +} + +TEST_F(AssemblerMIPSTest, CunD) { + DriverStr(RepeatIbFF(&mips::MipsAssembler::CunD, 3, "c.un.d $fcc{imm}, ${reg1}, ${reg2}"), + "CunD"); +} + +TEST_F(AssemblerMIPSTest, CeqD) { + DriverStr(RepeatIbFF(&mips::MipsAssembler::CeqD, 3, "c.eq.d $fcc{imm}, ${reg1}, ${reg2}"), + "CeqD"); +} + +TEST_F(AssemblerMIPSTest, CueqD) { + DriverStr(RepeatIbFF(&mips::MipsAssembler::CueqD, 3, "c.ueq.d $fcc{imm}, ${reg1}, ${reg2}"), + "CueqD"); +} + +TEST_F(AssemblerMIPSTest, ColtD) { + DriverStr(RepeatIbFF(&mips::MipsAssembler::ColtD, 3, "c.olt.d $fcc{imm}, ${reg1}, ${reg2}"), + "ColtD"); +} + +TEST_F(AssemblerMIPSTest, CultD) { + DriverStr(RepeatIbFF(&mips::MipsAssembler::CultD, 3, "c.ult.d $fcc{imm}, ${reg1}, ${reg2}"), + "CultD"); +} + +TEST_F(AssemblerMIPSTest, ColeD) { + DriverStr(RepeatIbFF(&mips::MipsAssembler::ColeD, 3, "c.ole.d $fcc{imm}, ${reg1}, ${reg2}"), + "ColeD"); +} + +TEST_F(AssemblerMIPSTest, CuleD) { + DriverStr(RepeatIbFF(&mips::MipsAssembler::CuleD, 3, "c.ule.d $fcc{imm}, ${reg1}, ${reg2}"), + "CuleD"); +} + +TEST_F(AssemblerMIPSTest, Movf) { + DriverStr(RepeatRRIb(&mips::MipsAssembler::Movf, 3, "movf ${reg1}, ${reg2}, $fcc{imm}"), "Movf"); +} + +TEST_F(AssemblerMIPSTest, Movt) { + DriverStr(RepeatRRIb(&mips::MipsAssembler::Movt, 3, "movt ${reg1}, ${reg2}, $fcc{imm}"), "Movt"); +} + TEST_F(AssemblerMIPSTest, CvtSW) { DriverStr(RepeatFF(&mips::MipsAssembler::Cvtsw, "cvt.s.w ${reg1}, ${reg2}"), "CvtSW"); } @@ -1000,55 +1135,11 @@ TEST_F(AssemblerMIPSTest, B) { } TEST_F(AssemblerMIPSTest, Beq) { - mips::MipsLabel label; - __ Beq(mips::A0, mips::A1, &label); - constexpr size_t kAdduCount1 = 63; - for (size_t i = 0; i != kAdduCount1; ++i) { - __ Addu(mips::ZERO, mips::ZERO, mips::ZERO); - } - __ Bind(&label); - constexpr size_t kAdduCount2 = 64; - for (size_t i = 0; i != kAdduCount2; ++i) { - __ Addu(mips::ZERO, mips::ZERO, mips::ZERO); - } - __ Beq(mips::A2, mips::A3, &label); - - std::string expected = - ".set noreorder\n" - "beq $a0, $a1, 1f\n" - "nop\n" + - RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") + - "1:\n" + - RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") + - "beq $a2, $a3, 1b\n" - "nop\n"; - DriverStr(expected, "Beq"); + BranchCondTwoRegsHelper(&mips::MipsAssembler::Beq, "Beq"); } TEST_F(AssemblerMIPSTest, Bne) { - mips::MipsLabel label; - __ Bne(mips::A0, mips::A1, &label); - constexpr size_t kAdduCount1 = 63; - for (size_t i = 0; i != kAdduCount1; ++i) { - __ Addu(mips::ZERO, mips::ZERO, mips::ZERO); - } - __ Bind(&label); - constexpr size_t kAdduCount2 = 64; - for (size_t i = 0; i != kAdduCount2; ++i) { - __ Addu(mips::ZERO, mips::ZERO, mips::ZERO); - } - __ Bne(mips::A2, mips::A3, &label); - - std::string expected = - ".set noreorder\n" - "bne $a0, $a1, 1f\n" - "nop\n" + - RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") + - "1:\n" + - RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") + - "bne $a2, $a3, 1b\n" - "nop\n"; - DriverStr(expected, "Bne"); + BranchCondTwoRegsHelper(&mips::MipsAssembler::Bne, "Bne"); } TEST_F(AssemblerMIPSTest, Beqz) { @@ -1104,60 +1195,24 @@ TEST_F(AssemblerMIPSTest, Bnez) { } TEST_F(AssemblerMIPSTest, Bltz) { - mips::MipsLabel label; - __ Bltz(mips::A0, &label); - constexpr size_t kAdduCount1 = 63; - for (size_t i = 0; i != kAdduCount1; ++i) { - __ Addu(mips::ZERO, mips::ZERO, mips::ZERO); - } - __ Bind(&label); - constexpr size_t kAdduCount2 = 64; - for (size_t i = 0; i != kAdduCount2; ++i) { - __ Addu(mips::ZERO, mips::ZERO, mips::ZERO); - } - __ Bltz(mips::A1, &label); - - std::string expected = - ".set noreorder\n" - "bltz $a0, 1f\n" - "nop\n" + - RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") + - "1:\n" + - RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") + - "bltz $a1, 1b\n" - "nop\n"; - DriverStr(expected, "Bltz"); + BranchCondOneRegHelper(&mips::MipsAssembler::Bltz, "Bltz"); } TEST_F(AssemblerMIPSTest, Bgez) { - mips::MipsLabel label; - __ Bgez(mips::A0, &label); - constexpr size_t kAdduCount1 = 63; - for (size_t i = 0; i != kAdduCount1; ++i) { - __ Addu(mips::ZERO, mips::ZERO, mips::ZERO); - } - __ Bind(&label); - constexpr size_t kAdduCount2 = 64; - for (size_t i = 0; i != kAdduCount2; ++i) { - __ Addu(mips::ZERO, mips::ZERO, mips::ZERO); - } - __ Bgez(mips::A1, &label); - - std::string expected = - ".set noreorder\n" - "bgez $a0, 1f\n" - "nop\n" + - RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") + - "1:\n" + - RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") + - "bgez $a1, 1b\n" - "nop\n"; - DriverStr(expected, "Bgez"); + BranchCondOneRegHelper(&mips::MipsAssembler::Bgez, "Bgez"); } TEST_F(AssemblerMIPSTest, Blez) { + BranchCondOneRegHelper(&mips::MipsAssembler::Blez, "Blez"); +} + +TEST_F(AssemblerMIPSTest, Bgtz) { + BranchCondOneRegHelper(&mips::MipsAssembler::Bgtz, "Bgtz"); +} + +TEST_F(AssemblerMIPSTest, Blt) { mips::MipsLabel label; - __ Blez(mips::A0, &label); + __ Blt(mips::A0, mips::A1, &label); constexpr size_t kAdduCount1 = 63; for (size_t i = 0; i != kAdduCount1; ++i) { __ Addu(mips::ZERO, mips::ZERO, mips::ZERO); @@ -1167,23 +1222,25 @@ TEST_F(AssemblerMIPSTest, Blez) { for (size_t i = 0; i != kAdduCount2; ++i) { __ Addu(mips::ZERO, mips::ZERO, mips::ZERO); } - __ Blez(mips::A1, &label); + __ Blt(mips::A2, mips::A3, &label); std::string expected = ".set noreorder\n" - "blez $a0, 1f\n" + "slt $at, $a0, $a1\n" + "bne $zero, $at, 1f\n" "nop\n" + RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") + "1:\n" + RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") + - "blez $a1, 1b\n" + "slt $at, $a2, $a3\n" + "bne $zero, $at, 1b\n" "nop\n"; - DriverStr(expected, "Blez"); + DriverStr(expected, "Blt"); } -TEST_F(AssemblerMIPSTest, Bgtz) { +TEST_F(AssemblerMIPSTest, Bge) { mips::MipsLabel label; - __ Bgtz(mips::A0, &label); + __ Bge(mips::A0, mips::A1, &label); constexpr size_t kAdduCount1 = 63; for (size_t i = 0; i != kAdduCount1; ++i) { __ Addu(mips::ZERO, mips::ZERO, mips::ZERO); @@ -1193,23 +1250,25 @@ TEST_F(AssemblerMIPSTest, Bgtz) { for (size_t i = 0; i != kAdduCount2; ++i) { __ Addu(mips::ZERO, mips::ZERO, mips::ZERO); } - __ Bgtz(mips::A1, &label); + __ Bge(mips::A2, mips::A3, &label); std::string expected = ".set noreorder\n" - "bgtz $a0, 1f\n" + "slt $at, $a0, $a1\n" + "beq $zero, $at, 1f\n" "nop\n" + RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") + "1:\n" + RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") + - "bgtz $a1, 1b\n" + "slt $at, $a2, $a3\n" + "beq $zero, $at, 1b\n" "nop\n"; - DriverStr(expected, "Bgtz"); + DriverStr(expected, "Bge"); } -TEST_F(AssemblerMIPSTest, Blt) { +TEST_F(AssemblerMIPSTest, Bltu) { mips::MipsLabel label; - __ Blt(mips::A0, mips::A1, &label); + __ Bltu(mips::A0, mips::A1, &label); constexpr size_t kAdduCount1 = 63; for (size_t i = 0; i != kAdduCount1; ++i) { __ Addu(mips::ZERO, mips::ZERO, mips::ZERO); @@ -1219,25 +1278,25 @@ TEST_F(AssemblerMIPSTest, Blt) { for (size_t i = 0; i != kAdduCount2; ++i) { __ Addu(mips::ZERO, mips::ZERO, mips::ZERO); } - __ Blt(mips::A2, mips::A3, &label); + __ Bltu(mips::A2, mips::A3, &label); std::string expected = ".set noreorder\n" - "slt $at, $a0, $a1\n" + "sltu $at, $a0, $a1\n" "bne $zero, $at, 1f\n" "nop\n" + RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") + "1:\n" + RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") + - "slt $at, $a2, $a3\n" + "sltu $at, $a2, $a3\n" "bne $zero, $at, 1b\n" "nop\n"; - DriverStr(expected, "Blt"); + DriverStr(expected, "Bltu"); } -TEST_F(AssemblerMIPSTest, Bge) { +TEST_F(AssemblerMIPSTest, Bgeu) { mips::MipsLabel label; - __ Bge(mips::A0, mips::A1, &label); + __ Bgeu(mips::A0, mips::A1, &label); constexpr size_t kAdduCount1 = 63; for (size_t i = 0; i != kAdduCount1; ++i) { __ Addu(mips::ZERO, mips::ZERO, mips::ZERO); @@ -1247,25 +1306,25 @@ TEST_F(AssemblerMIPSTest, Bge) { for (size_t i = 0; i != kAdduCount2; ++i) { __ Addu(mips::ZERO, mips::ZERO, mips::ZERO); } - __ Bge(mips::A2, mips::A3, &label); + __ Bgeu(mips::A2, mips::A3, &label); std::string expected = ".set noreorder\n" - "slt $at, $a0, $a1\n" + "sltu $at, $a0, $a1\n" "beq $zero, $at, 1f\n" "nop\n" + RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") + "1:\n" + RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") + - "slt $at, $a2, $a3\n" + "sltu $at, $a2, $a3\n" "beq $zero, $at, 1b\n" "nop\n"; - DriverStr(expected, "Bge"); + DriverStr(expected, "Bgeu"); } -TEST_F(AssemblerMIPSTest, Bltu) { +TEST_F(AssemblerMIPSTest, Bc1f) { mips::MipsLabel label; - __ Bltu(mips::A0, mips::A1, &label); + __ Bc1f(0, &label); constexpr size_t kAdduCount1 = 63; for (size_t i = 0; i != kAdduCount1; ++i) { __ Addu(mips::ZERO, mips::ZERO, mips::ZERO); @@ -1275,25 +1334,23 @@ TEST_F(AssemblerMIPSTest, Bltu) { for (size_t i = 0; i != kAdduCount2; ++i) { __ Addu(mips::ZERO, mips::ZERO, mips::ZERO); } - __ Bltu(mips::A2, mips::A3, &label); + __ Bc1f(7, &label); std::string expected = ".set noreorder\n" - "sltu $at, $a0, $a1\n" - "bne $zero, $at, 1f\n" + "bc1f $fcc0, 1f\n" "nop\n" + RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") + "1:\n" + RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") + - "sltu $at, $a2, $a3\n" - "bne $zero, $at, 1b\n" + "bc1f $fcc7, 1b\n" "nop\n"; - DriverStr(expected, "Bltu"); + DriverStr(expected, "Bc1f"); } -TEST_F(AssemblerMIPSTest, Bgeu) { +TEST_F(AssemblerMIPSTest, Bc1t) { mips::MipsLabel label; - __ Bgeu(mips::A0, mips::A1, &label); + __ Bc1t(0, &label); constexpr size_t kAdduCount1 = 63; for (size_t i = 0; i != kAdduCount1; ++i) { __ Addu(mips::ZERO, mips::ZERO, mips::ZERO); @@ -1303,20 +1360,18 @@ TEST_F(AssemblerMIPSTest, Bgeu) { for (size_t i = 0; i != kAdduCount2; ++i) { __ Addu(mips::ZERO, mips::ZERO, mips::ZERO); } - __ Bgeu(mips::A2, mips::A3, &label); + __ Bc1t(7, &label); std::string expected = ".set noreorder\n" - "sltu $at, $a0, $a1\n" - "beq $zero, $at, 1f\n" + "bc1t $fcc0, 1f\n" "nop\n" + RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") + "1:\n" + RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") + - "sltu $at, $a2, $a3\n" - "beq $zero, $at, 1b\n" + "bc1t $fcc7, 1b\n" "nop\n"; - DriverStr(expected, "Bgeu"); + DriverStr(expected, "Bc1t"); } #undef __ |