summaryrefslogtreecommitdiff
path: root/compiler/utils
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/utils')
-rw-r--r--compiler/utils/arm/assembler_arm.h3
-rw-r--r--compiler/utils/arm/assembler_arm32.cc44
-rw-r--r--compiler/utils/arm/assembler_arm32.h8
-rw-r--r--compiler/utils/arm/assembler_arm32_test.cc12
-rw-r--r--compiler/utils/arm/assembler_thumb2.cc77
-rw-r--r--compiler/utils/arm/assembler_thumb2.h14
-rw-r--r--compiler/utils/arm/assembler_thumb2_test.cc24
-rw-r--r--compiler/utils/mips/assembler_mips.cc160
-rw-r--r--compiler/utils/mips/assembler_mips.h54
9 files changed, 384 insertions, 12 deletions
diff --git a/compiler/utils/arm/assembler_arm.h b/compiler/utils/arm/assembler_arm.h
index f96376d9fe..a894565425 100644
--- a/compiler/utils/arm/assembler_arm.h
+++ b/compiler/utils/arm/assembler_arm.h
@@ -545,6 +545,9 @@ class ArmAssembler : public Assembler {
virtual void movw(Register rd, uint16_t imm16, Condition cond = AL) = 0;
virtual void movt(Register rd, uint16_t imm16, Condition cond = AL) = 0;
virtual void rbit(Register rd, Register rm, Condition cond = AL) = 0;
+ virtual void rev(Register rd, Register rm, Condition cond = AL) = 0;
+ virtual void rev16(Register rd, Register rm, Condition cond = AL) = 0;
+ virtual void revsh(Register rd, Register rm, Condition cond = AL) = 0;
// Multiply instructions.
virtual void mul(Register rd, Register rn, Register rm, Condition cond = AL) = 0;
diff --git a/compiler/utils/arm/assembler_arm32.cc b/compiler/utils/arm/assembler_arm32.cc
index ebca25bbf9..0a227b21cd 100644
--- a/compiler/utils/arm/assembler_arm32.cc
+++ b/compiler/utils/arm/assembler_arm32.cc
@@ -750,6 +750,35 @@ void Arm32Assembler::movt(Register rd, uint16_t imm16, Condition cond) {
}
+void Arm32Assembler::EmitMiscellaneous(Condition cond, uint8_t op1,
+ uint8_t op2, uint32_t a_part,
+ uint32_t rest) {
+ int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
+ B26 | B25 | B23 |
+ (op1 << 20) |
+ (a_part << 16) |
+ (op2 << 5) |
+ B4 |
+ rest;
+ Emit(encoding);
+}
+
+
+void Arm32Assembler::EmitReverseBytes(Register rd, Register rm, Condition cond,
+ uint8_t op1, uint8_t op2) {
+ CHECK_NE(rd, kNoRegister);
+ CHECK_NE(rm, kNoRegister);
+ CHECK_NE(cond, kNoCondition);
+ CHECK_NE(rd, PC);
+ CHECK_NE(rm, PC);
+
+ int32_t encoding = (static_cast<int32_t>(rd) << kRdShift) |
+ (0b1111 << 8) |
+ static_cast<int32_t>(rm);
+ EmitMiscellaneous(cond, op1, op2, 0b1111, encoding);
+}
+
+
void Arm32Assembler::rbit(Register rd, Register rm, Condition cond) {
CHECK_NE(rd, kNoRegister);
CHECK_NE(rm, kNoRegister);
@@ -764,6 +793,21 @@ void Arm32Assembler::rbit(Register rd, Register rm, Condition cond) {
}
+void Arm32Assembler::rev(Register rd, Register rm, Condition cond) {
+ EmitReverseBytes(rd, rm, cond, 0b011, 0b001);
+}
+
+
+void Arm32Assembler::rev16(Register rd, Register rm, Condition cond) {
+ EmitReverseBytes(rd, rm, cond, 0b011, 0b101);
+}
+
+
+void Arm32Assembler::revsh(Register rd, Register rm, Condition cond) {
+ EmitReverseBytes(rd, rm, cond, 0b111, 0b101);
+}
+
+
void Arm32Assembler::EmitMulOp(Condition cond, int32_t opcode,
Register rd, Register rn,
Register rm, Register rs) {
diff --git a/compiler/utils/arm/assembler_arm32.h b/compiler/utils/arm/assembler_arm32.h
index bf332feb62..e3e05caf92 100644
--- a/compiler/utils/arm/assembler_arm32.h
+++ b/compiler/utils/arm/assembler_arm32.h
@@ -91,6 +91,9 @@ class Arm32Assembler FINAL : public ArmAssembler {
void movw(Register rd, uint16_t imm16, Condition cond = AL) OVERRIDE;
void movt(Register rd, uint16_t imm16, Condition cond = AL) OVERRIDE;
void rbit(Register rd, Register rm, Condition cond = AL) OVERRIDE;
+ void rev(Register rd, Register rm, Condition cond = AL) OVERRIDE;
+ void rev16(Register rd, Register rm, Condition cond = AL) OVERRIDE;
+ void revsh(Register rd, Register rm, Condition cond = AL) OVERRIDE;
// Multiply instructions.
void mul(Register rd, Register rn, Register rm, Condition cond = AL) OVERRIDE;
@@ -388,6 +391,11 @@ class Arm32Assembler FINAL : public ArmAssembler {
void EmitVPushPop(uint32_t reg, int nregs, bool push, bool dbl, Condition cond);
+ void EmitMiscellaneous(Condition cond, uint8_t op1, uint8_t op2,
+ uint32_t a_part, uint32_t rest);
+ void EmitReverseBytes(Register rd, Register rm, Condition cond,
+ uint8_t op1, uint8_t op2);
+
void EmitBranch(Condition cond, Label* label, bool link);
static int32_t EncodeBranchOffset(int offset, int32_t inst);
static int DecodeBranchOffset(int32_t inst);
diff --git a/compiler/utils/arm/assembler_arm32_test.cc b/compiler/utils/arm/assembler_arm32_test.cc
index 43805966a9..e570e22fca 100644
--- a/compiler/utils/arm/assembler_arm32_test.cc
+++ b/compiler/utils/arm/assembler_arm32_test.cc
@@ -887,4 +887,16 @@ TEST_F(AssemblerArm32Test, rbit) {
T3Helper(&arm::Arm32Assembler::rbit, true, "rbit{cond} {reg1}, {reg2}", "rbit");
}
+TEST_F(AssemblerArm32Test, rev) {
+ T3Helper(&arm::Arm32Assembler::rev, true, "rev{cond} {reg1}, {reg2}", "rev");
+}
+
+TEST_F(AssemblerArm32Test, rev16) {
+ T3Helper(&arm::Arm32Assembler::rev16, true, "rev16{cond} {reg1}, {reg2}", "rev16");
+}
+
+TEST_F(AssemblerArm32Test, revsh) {
+ T3Helper(&arm::Arm32Assembler::revsh, true, "revsh{cond} {reg1}, {reg2}", "revsh");
+}
+
} // namespace art
diff --git a/compiler/utils/arm/assembler_thumb2.cc b/compiler/utils/arm/assembler_thumb2.cc
index 52023a67ee..15298b390b 100644
--- a/compiler/utils/arm/assembler_thumb2.cc
+++ b/compiler/utils/arm/assembler_thumb2.cc
@@ -2569,20 +2569,36 @@ void Thumb2Assembler::EmitBranch(Condition cond, Label* label, bool link, bool x
}
+void Thumb2Assembler::Emit32Miscellaneous(uint8_t op1,
+ uint8_t op2,
+ uint32_t rest_encoding) {
+ int32_t encoding = B31 | B30 | B29 | B28 | B27 | B25 | B23 |
+ op1 << 20 |
+ 0xf << 12 |
+ B7 |
+ op2 << 4 |
+ rest_encoding;
+ Emit32(encoding);
+}
+
+
+void Thumb2Assembler::Emit16Miscellaneous(uint32_t rest_encoding) {
+ int16_t encoding = B15 | B13 | B12 |
+ rest_encoding;
+ Emit16(encoding);
+}
+
void Thumb2Assembler::clz(Register rd, Register rm, Condition cond) {
CHECK_NE(rd, kNoRegister);
CHECK_NE(rm, kNoRegister);
CheckCondition(cond);
CHECK_NE(rd, PC);
CHECK_NE(rm, PC);
- int32_t encoding = B31 | B30 | B29 | B28 | B27 |
- B25 | B23 | B21 | B20 |
+ int32_t encoding =
static_cast<uint32_t>(rm) << 16 |
- 0xf << 12 |
static_cast<uint32_t>(rd) << 8 |
- B7 |
static_cast<uint32_t>(rm);
- Emit32(encoding);
+ Emit32Miscellaneous(0b11, 0b00, encoding);
}
@@ -2630,14 +2646,55 @@ void Thumb2Assembler::rbit(Register rd, Register rm, Condition cond) {
CHECK_NE(rm, PC);
CHECK_NE(rd, SP);
CHECK_NE(rm, SP);
- int32_t encoding = B31 | B30 | B29 | B28 | B27 |
- B25 | B23 | B20 |
+ int32_t encoding =
static_cast<uint32_t>(rm) << 16 |
- 0xf << 12 |
static_cast<uint32_t>(rd) << 8 |
- B7 | B5 |
static_cast<uint32_t>(rm);
- Emit32(encoding);
+
+ Emit32Miscellaneous(0b01, 0b10, encoding);
+}
+
+
+void Thumb2Assembler::EmitReverseBytes(Register rd, Register rm,
+ uint32_t op) {
+ CHECK_NE(rd, kNoRegister);
+ CHECK_NE(rm, kNoRegister);
+ CHECK_NE(rd, PC);
+ CHECK_NE(rm, PC);
+ CHECK_NE(rd, SP);
+ CHECK_NE(rm, SP);
+
+ if (!IsHighRegister(rd) && !IsHighRegister(rm) && !force_32bit_) {
+ uint16_t t1_op = B11 | B9 | (op << 6);
+ int16_t encoding = t1_op |
+ static_cast<uint16_t>(rm) << 3 |
+ static_cast<uint16_t>(rd);
+ Emit16Miscellaneous(encoding);
+ } else {
+ int32_t encoding =
+ static_cast<uint32_t>(rm) << 16 |
+ static_cast<uint32_t>(rd) << 8 |
+ static_cast<uint32_t>(rm);
+ Emit32Miscellaneous(0b01, op, encoding);
+ }
+}
+
+
+void Thumb2Assembler::rev(Register rd, Register rm, Condition cond) {
+ CheckCondition(cond);
+ EmitReverseBytes(rd, rm, 0b00);
+}
+
+
+void Thumb2Assembler::rev16(Register rd, Register rm, Condition cond) {
+ CheckCondition(cond);
+ EmitReverseBytes(rd, rm, 0b01);
+}
+
+
+void Thumb2Assembler::revsh(Register rd, Register rm, Condition cond) {
+ CheckCondition(cond);
+ EmitReverseBytes(rd, rm, 0b11);
}
diff --git a/compiler/utils/arm/assembler_thumb2.h b/compiler/utils/arm/assembler_thumb2.h
index bf07b2dbf8..6b61acafac 100644
--- a/compiler/utils/arm/assembler_thumb2.h
+++ b/compiler/utils/arm/assembler_thumb2.h
@@ -117,6 +117,9 @@ class Thumb2Assembler FINAL : public ArmAssembler {
void movw(Register rd, uint16_t imm16, Condition cond = AL) OVERRIDE;
void movt(Register rd, uint16_t imm16, Condition cond = AL) OVERRIDE;
void rbit(Register rd, Register rm, Condition cond = AL) OVERRIDE;
+ void rev(Register rd, Register rm, Condition cond = AL) OVERRIDE;
+ void rev16(Register rd, Register rm, Condition cond = AL) OVERRIDE;
+ void revsh(Register rd, Register rm, Condition cond = AL) OVERRIDE;
// Multiply instructions.
void mul(Register rd, Register rn, Register rm, Condition cond = AL) OVERRIDE;
@@ -644,6 +647,17 @@ class Thumb2Assembler FINAL : public ArmAssembler {
Register rd,
const ShifterOperand& so);
+ // Emit a single 32 bit miscellaneous instruction.
+ void Emit32Miscellaneous(uint8_t op1,
+ uint8_t op2,
+ uint32_t rest_encoding);
+
+ // Emit reverse byte instructions: rev, rev16, revsh.
+ void EmitReverseBytes(Register rd, Register rm, uint32_t op);
+
+ // Emit a single 16 bit miscellaneous instruction.
+ void Emit16Miscellaneous(uint32_t rest_encoding);
+
// Must the instruction be 32 bits or can it possibly be encoded
// in 16 bits?
bool Is32BitDataProcessing(Condition cond,
diff --git a/compiler/utils/arm/assembler_thumb2_test.cc b/compiler/utils/arm/assembler_thumb2_test.cc
index 7b32b0fd26..650b08900b 100644
--- a/compiler/utils/arm/assembler_thumb2_test.cc
+++ b/compiler/utils/arm/assembler_thumb2_test.cc
@@ -1331,4 +1331,28 @@ TEST_F(AssemblerThumb2Test, rbit) {
DriverStr(expected, "rbit");
}
+TEST_F(AssemblerThumb2Test, rev) {
+ __ rev(arm::R1, arm::R0);
+
+ const char* expected = "rev r1, r0\n";
+
+ DriverStr(expected, "rev");
+}
+
+TEST_F(AssemblerThumb2Test, rev16) {
+ __ rev16(arm::R1, arm::R0);
+
+ const char* expected = "rev16 r1, r0\n";
+
+ DriverStr(expected, "rev16");
+}
+
+TEST_F(AssemblerThumb2Test, revsh) {
+ __ revsh(arm::R1, arm::R0);
+
+ const char* expected = "revsh r1, r0\n";
+
+ DriverStr(expected, "revsh");
+}
+
} // namespace art
diff --git a/compiler/utils/mips/assembler_mips.cc b/compiler/utils/mips/assembler_mips.cc
index 6fd65ee9a4..7c41813457 100644
--- a/compiler/utils/mips/assembler_mips.cc
+++ b/compiler/utils/mips/assembler_mips.cc
@@ -537,12 +537,20 @@ void MipsAssembler::Bgtz(Register rt, uint16_t imm16) {
EmitI(0x7, rt, static_cast<Register>(0), imm16);
}
+void MipsAssembler::Bc1f(uint16_t imm16) {
+ Bc1f(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(uint16_t imm16) {
+ Bc1t(0, imm16);
+}
+
void MipsAssembler::Bc1t(int cc, uint16_t imm16) {
CHECK(!IsR6());
CHECK(IsUint<3>(cc)) << cc;
@@ -843,6 +851,22 @@ void MipsAssembler::DivD(FRegister fd, FRegister fs, FRegister ft) {
EmitFR(0x11, 0x11, ft, fs, fd, 0x3);
}
+void MipsAssembler::SqrtS(FRegister fd, FRegister fs) {
+ EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x4);
+}
+
+void MipsAssembler::SqrtD(FRegister fd, FRegister fs) {
+ EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x4);
+}
+
+void MipsAssembler::AbsS(FRegister fd, FRegister fs) {
+ EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x5);
+}
+
+void MipsAssembler::AbsD(FRegister fd, FRegister fs) {
+ EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x5);
+}
+
void MipsAssembler::MovS(FRegister fd, FRegister fs) {
EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x6);
}
@@ -859,84 +883,140 @@ void MipsAssembler::NegD(FRegister fd, FRegister fs) {
EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x7);
}
+void MipsAssembler::CunS(FRegister fs, FRegister ft) {
+ CunS(0, fs, ft);
+}
+
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(FRegister fs, FRegister ft) {
+ CeqS(0, fs, ft);
+}
+
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(FRegister fs, FRegister ft) {
+ CueqS(0, fs, ft);
+}
+
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(FRegister fs, FRegister ft) {
+ ColtS(0, fs, ft);
+}
+
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(FRegister fs, FRegister ft) {
+ CultS(0, fs, ft);
+}
+
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(FRegister fs, FRegister ft) {
+ ColeS(0, fs, ft);
+}
+
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(FRegister fs, FRegister ft) {
+ CuleS(0, fs, ft);
+}
+
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(FRegister fs, FRegister ft) {
+ CunD(0, fs, ft);
+}
+
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(FRegister fs, FRegister ft) {
+ CeqD(0, fs, ft);
+}
+
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(FRegister fs, FRegister ft) {
+ CueqD(0, fs, ft);
+}
+
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(FRegister fs, FRegister ft) {
+ ColtD(0, fs, ft);
+}
+
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(FRegister fs, FRegister ft) {
+ CultD(0, fs, ft);
+}
+
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(FRegister fs, FRegister ft) {
+ ColeD(0, fs, ft);
+}
+
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(FRegister fs, FRegister ft) {
+ CuleD(0, fs, ft);
+}
+
void MipsAssembler::CuleD(int cc, FRegister fs, FRegister ft) {
CHECK(!IsR6());
CHECK(IsUint<3>(cc)) << cc;
@@ -1055,6 +1135,70 @@ void MipsAssembler::Movt(Register rd, Register rs, int cc) {
EmitR(0, rs, static_cast<Register>((cc << 2) | 1), rd, 0, 0x01);
}
+void MipsAssembler::MovfS(FRegister fd, FRegister fs, int cc) {
+ CHECK(!IsR6());
+ CHECK(IsUint<3>(cc)) << cc;
+ EmitFR(0x11, 0x10, static_cast<FRegister>(cc << 2), fs, fd, 0x11);
+}
+
+void MipsAssembler::MovfD(FRegister fd, FRegister fs, int cc) {
+ CHECK(!IsR6());
+ CHECK(IsUint<3>(cc)) << cc;
+ EmitFR(0x11, 0x11, static_cast<FRegister>(cc << 2), fs, fd, 0x11);
+}
+
+void MipsAssembler::MovtS(FRegister fd, FRegister fs, int cc) {
+ CHECK(!IsR6());
+ CHECK(IsUint<3>(cc)) << cc;
+ EmitFR(0x11, 0x10, static_cast<FRegister>((cc << 2) | 1), fs, fd, 0x11);
+}
+
+void MipsAssembler::MovtD(FRegister fd, FRegister fs, int cc) {
+ CHECK(!IsR6());
+ CHECK(IsUint<3>(cc)) << cc;
+ EmitFR(0x11, 0x11, static_cast<FRegister>((cc << 2) | 1), fs, fd, 0x11);
+}
+
+void MipsAssembler::SelS(FRegister fd, FRegister fs, FRegister ft) {
+ CHECK(IsR6());
+ EmitFR(0x11, 0x10, ft, fs, fd, 0x10);
+}
+
+void MipsAssembler::SelD(FRegister fd, FRegister fs, FRegister ft) {
+ CHECK(IsR6());
+ EmitFR(0x11, 0x11, ft, fs, fd, 0x10);
+}
+
+void MipsAssembler::ClassS(FRegister fd, FRegister fs) {
+ CHECK(IsR6());
+ EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x1b);
+}
+
+void MipsAssembler::ClassD(FRegister fd, FRegister fs) {
+ CHECK(IsR6());
+ EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0x1b);
+}
+
+void MipsAssembler::MinS(FRegister fd, FRegister fs, FRegister ft) {
+ CHECK(IsR6());
+ EmitFR(0x11, 0x10, ft, fs, fd, 0x1c);
+}
+
+void MipsAssembler::MinD(FRegister fd, FRegister fs, FRegister ft) {
+ CHECK(IsR6());
+ EmitFR(0x11, 0x11, ft, fs, fd, 0x1c);
+}
+
+void MipsAssembler::MaxS(FRegister fd, FRegister fs, FRegister ft) {
+ CHECK(IsR6());
+ EmitFR(0x11, 0x10, ft, fs, fd, 0x1e);
+}
+
+void MipsAssembler::MaxD(FRegister fd, FRegister fs, FRegister ft) {
+ CHECK(IsR6());
+ EmitFR(0x11, 0x11, ft, fs, fd, 0x1e);
+}
+
void MipsAssembler::TruncLS(FRegister fd, FRegister fs) {
EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x09);
}
@@ -1095,6 +1239,14 @@ void MipsAssembler::Cvtdl(FRegister fd, FRegister fs) {
EmitFR(0x11, 0x15, static_cast<FRegister>(0), fs, fd, 0x21);
}
+void MipsAssembler::FloorWS(FRegister fd, FRegister fs) {
+ EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0xf);
+}
+
+void MipsAssembler::FloorWD(FRegister fd, FRegister fs) {
+ EmitFR(0x11, 0x11, static_cast<FRegister>(0), fs, fd, 0xf);
+}
+
void MipsAssembler::Mfc1(Register rt, FRegister fs) {
EmitFR(0x11, 0x00, static_cast<FRegister>(rt), fs, static_cast<FRegister>(0), 0x0);
}
@@ -2062,11 +2214,19 @@ void MipsAssembler::Bgeu(Register rs, Register rt, MipsLabel* label) {
}
}
+void MipsAssembler::Bc1f(MipsLabel* label) {
+ Bc1f(0, label);
+}
+
void MipsAssembler::Bc1f(int cc, MipsLabel* label) {
CHECK(IsUint<3>(cc)) << cc;
Bcond(label, kCondF, static_cast<Register>(cc), ZERO);
}
+void MipsAssembler::Bc1t(MipsLabel* label) {
+ Bc1t(0, label);
+}
+
void MipsAssembler::Bc1t(int cc, MipsLabel* label) {
CHECK(IsUint<3>(cc)) << cc;
Bcond(label, kCondT, static_cast<Register>(cc), ZERO);
diff --git a/compiler/utils/mips/assembler_mips.h b/compiler/utils/mips/assembler_mips.h
index 2262af49b3..a7179fd1dc 100644
--- a/compiler/utils/mips/assembler_mips.h
+++ b/compiler/utils/mips/assembler_mips.h
@@ -51,6 +51,20 @@ enum StoreOperandType {
kStoreDoubleword
};
+// Used to test the values returned by ClassS/ClassD.
+enum FPClassMaskType {
+ kSignalingNaN = 0x001,
+ kQuietNaN = 0x002,
+ kNegativeInfinity = 0x004,
+ kNegativeNormal = 0x008,
+ kNegativeSubnormal = 0x010,
+ kNegativeZero = 0x020,
+ kPositiveInfinity = 0x040,
+ kPositiveNormal = 0x080,
+ kPositiveSubnormal = 0x100,
+ kPositiveZero = 0x200,
+};
+
class MipsLabel : public Label {
public:
MipsLabel() : prev_branch_id_plus_one_(0) {}
@@ -191,7 +205,9 @@ 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(uint16_t imm16); // R2
void Bc1f(int cc, uint16_t imm16); // R2
+ void Bc1t(uint16_t imm16); // R2
void Bc1t(int cc, uint16_t imm16); // R2
void J(uint32_t addr26);
void Jal(uint32_t addr26);
@@ -227,24 +243,42 @@ class MipsAssembler FINAL : public Assembler {
void SubD(FRegister fd, FRegister fs, FRegister ft);
void MulD(FRegister fd, FRegister fs, FRegister ft);
void DivD(FRegister fd, FRegister fs, FRegister ft);
+ void SqrtS(FRegister fd, FRegister fs);
+ void SqrtD(FRegister fd, FRegister fs);
+ void AbsS(FRegister fd, FRegister fs);
+ void AbsD(FRegister fd, FRegister fs);
void MovS(FRegister fd, FRegister fs);
void MovD(FRegister fd, FRegister fs);
void NegS(FRegister fd, FRegister fs);
void NegD(FRegister fd, FRegister fs);
+ void CunS(FRegister fs, FRegister ft); // R2
void CunS(int cc, FRegister fs, FRegister ft); // R2
+ void CeqS(FRegister fs, FRegister ft); // R2
void CeqS(int cc, FRegister fs, FRegister ft); // R2
+ void CueqS(FRegister fs, FRegister ft); // R2
void CueqS(int cc, FRegister fs, FRegister ft); // R2
+ void ColtS(FRegister fs, FRegister ft); // R2
void ColtS(int cc, FRegister fs, FRegister ft); // R2
+ void CultS(FRegister fs, FRegister ft); // R2
void CultS(int cc, FRegister fs, FRegister ft); // R2
+ void ColeS(FRegister fs, FRegister ft); // R2
void ColeS(int cc, FRegister fs, FRegister ft); // R2
+ void CuleS(FRegister fs, FRegister ft); // R2
void CuleS(int cc, FRegister fs, FRegister ft); // R2
+ void CunD(FRegister fs, FRegister ft); // R2
void CunD(int cc, FRegister fs, FRegister ft); // R2
+ void CeqD(FRegister fs, FRegister ft); // R2
void CeqD(int cc, FRegister fs, FRegister ft); // R2
+ void CueqD(FRegister fs, FRegister ft); // R2
void CueqD(int cc, FRegister fs, FRegister ft); // R2
+ void ColtD(FRegister fs, FRegister ft); // R2
void ColtD(int cc, FRegister fs, FRegister ft); // R2
+ void CultD(FRegister fs, FRegister ft); // R2
void CultD(int cc, FRegister fs, FRegister ft); // R2
+ void ColeD(FRegister fs, FRegister ft); // R2
void ColeD(int cc, FRegister fs, FRegister ft); // R2
+ void CuleD(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
@@ -266,8 +300,20 @@ class MipsAssembler FINAL : public Assembler {
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 Movf(Register rd, Register rs, int cc = 0); // R2
+ void Movt(Register rd, Register rs, int cc = 0); // R2
+ void MovfS(FRegister fd, FRegister fs, int cc = 0); // R2
+ void MovfD(FRegister fd, FRegister fs, int cc = 0); // R2
+ void MovtS(FRegister fd, FRegister fs, int cc = 0); // R2
+ void MovtD(FRegister fd, FRegister fs, int cc = 0); // R2
+ void SelS(FRegister fd, FRegister fs, FRegister ft); // R6
+ void SelD(FRegister fd, FRegister fs, FRegister ft); // R6
+ void ClassS(FRegister fd, FRegister fs); // R6
+ void ClassD(FRegister fd, FRegister fs); // R6
+ void MinS(FRegister fd, FRegister fs, FRegister ft); // R6
+ void MinD(FRegister fd, FRegister fs, FRegister ft); // R6
+ void MaxS(FRegister fd, FRegister fs, FRegister ft); // R6
+ void MaxD(FRegister fd, FRegister fs, FRegister ft); // R6
void TruncLS(FRegister fd, FRegister fs); // R2+, FR=1
void TruncLD(FRegister fd, FRegister fs); // R2+, FR=1
@@ -279,6 +325,8 @@ class MipsAssembler FINAL : public Assembler {
void Cvtds(FRegister fd, FRegister fs);
void Cvtsl(FRegister fd, FRegister fs); // R2+, FR=1
void Cvtdl(FRegister fd, FRegister fs); // R2+, FR=1
+ void FloorWS(FRegister fd, FRegister fs);
+ void FloorWD(FRegister fd, FRegister fs);
void Mfc1(Register rt, FRegister fs);
void Mtc1(Register rt, FRegister fs);
@@ -322,7 +370,9 @@ 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(MipsLabel* label); // R2
void Bc1f(int cc, MipsLabel* label); // R2
+ void Bc1t(MipsLabel* label); // R2
void Bc1t(int cc, MipsLabel* label); // R2
void Bc1eqz(FRegister ft, MipsLabel* label); // R6
void Bc1nez(FRegister ft, MipsLabel* label); // R6