Index: runtime/vm/constants_mips.h |
=================================================================== |
--- runtime/vm/constants_mips.h (revision 42479) |
+++ runtime/vm/constants_mips.h (working copy) |
@@ -6,6 +6,8 @@ |
#define VM_CONSTANTS_MIPS_H_ |
#include "platform/assert.h" |
+#include "vm/allocation.h" |
+#include "vm/bitfield.h" |
namespace dart { |
@@ -45,6 +47,7 @@ |
R30 = 30, |
R31 = 31, |
kNumberOfCpuRegisters = 32, |
+ IMM = 32, // Positive value is easier to encode than kNoRegister in bitfield. |
kNoRegister = -1, |
// Register aliases. |
@@ -236,10 +239,15 @@ |
const int kDartVolatileFpuRegCount = 20; |
-// Values for the condition field. |
-// There is no condition field on MIPS, but Conditions are used and passed |
-// around by the intermediate language, so we need them here, too. |
-enum Condition { |
+// Values for the condition field in the status register. |
+// There is no dedicated status register on MIPS, but Condition values are used |
+// and passed around by the intermediate language, so we need them here, too. |
+// We delay code generation of a comparison that would result in a traditional |
+// condition code in the status register by keeping both register operands and |
+// the relational operator between them as the Condition. |
+enum RelationOperator { |
+ AL, // always |
+ NV, // never |
EQ, // equal |
NE, // not equal |
GT, // greater than |
@@ -246,10 +254,101 @@ |
GE, // greater equal |
LT, // less than |
LE, // less equal |
- VS, // overflow |
+ UGT, // unsigned greater than |
+ UGE, // unsigned greater equal |
+ ULT, // unsigned less than |
+ ULE, // unsigned less equal |
}; |
+class Condition : public ValueObject { |
zra
2014/12/19 17:49:47
Should this go in assembler_mips.h?
regis
2014/12/22 20:17:34
Done.
|
+ public: |
+ enum Bits { |
+ kLeftPos = 0, |
+ kLeftSize = 6, |
+ kRightPos = kLeftPos + kLeftSize, |
+ kRightSize = 6, |
+ kRelOpPos = kRightPos + kRightSize, |
+ kRelOpSize = 4, |
+ kImmPos = kRelOpPos + kRelOpSize, |
+ kImmSize = 16, |
+ }; |
+ |
+ class LeftBits : public BitField<Register, kLeftPos, kLeftSize> {}; |
+ class RightBits : public BitField<Register, kRightPos, kRightSize> {}; |
+ class RelOpBits : public BitField<RelationOperator, kRelOpPos, kRelOpSize> {}; |
+ class ImmBits : public BitField<uint16_t, kImmPos, kImmSize> {}; |
+ |
+ Register left() const { return LeftBits::decode(bits_); } |
+ Register right() const { return RightBits::decode(bits_); } |
+ RelationOperator rel_op() const { return RelOpBits::decode(bits_); } |
+ int16_t imm() const { return static_cast<int16_t>(ImmBits::decode(bits_)); } |
+ |
+ static bool IsValidImm(int32_t value) { |
+ // We want both value and value + 1 to fit in an int16_t. |
+ return (-0x08000 <= value) && (value < 0x7fff); |
+ } |
+ |
+ void set_rel_op(RelationOperator value) { |
+ ASSERT(IsValidRelOp(value)); |
+ bits_ = RelOpBits::update(value, bits_); |
+ } |
+ |
+ // Uninitialized condition. |
+ Condition() : ValueObject(), bits_(0) { } |
+ |
+ // Copy constructor. |
+ Condition(const Condition& other) : ValueObject(), bits_(other.bits_) { } |
+ |
+ // Copy assignment operator. |
+ Condition& operator=(const Condition& other) { |
+ bits_ = other.bits_; |
+ return *this; |
+ } |
+ |
+ Condition(Register left, |
+ Register right, |
+ RelationOperator rel_op, |
+ int16_t imm = 0) { |
+ // At most one constant, ZR or immediate. |
+ ASSERT(!(((left == ZR) || (left == IMM)) && |
+ ((right == ZR) || (right == IMM)))); |
+ // Non-zero immediate value is only allowed for IMM. |
+ ASSERT((imm != 0) == ((left == IMM) || (right == IMM))); |
+ set_left(left); |
+ set_right(right); |
+ set_rel_op(rel_op); |
+ set_imm(imm); |
+ } |
+ |
+ private: |
+ static bool IsValidRelOp(RelationOperator value) { |
+ return (AL <= value) && (value <= ULE); |
+ } |
+ |
+ static bool IsValidRegister(Register value) { |
+ return (ZR <= value) && (value <= IMM) && (value != AT); |
+ } |
+ |
+ void set_left(Register value) { |
+ ASSERT(IsValidRegister(value)); |
+ bits_ = LeftBits::update(value, bits_); |
+ } |
+ |
+ void set_right(Register value) { |
+ ASSERT(IsValidRegister(value)); |
+ bits_ = RightBits::update(value, bits_); |
+ } |
+ |
+ void set_imm(int16_t value) { |
+ ASSERT(IsValidImm(value)); |
+ bits_ = ImmBits::update(static_cast<uint16_t>(value), bits_); |
+ } |
+ |
+ uword bits_; |
+}; |
+ |
+ |
// Constants used for the decoding or encoding of the individual fields of |
// instructions. Based on the "Table 4.25 CPU Instruction Format Fields". |
enum InstructionFields { |
@@ -361,7 +460,7 @@ |
SYSCALL = 12, |
BREAK = 13, |
SYNC = 15, |
- MFHI =16, |
+ MFHI = 16, |
MTHI = 17, |
MFLO = 18, |
MTLO = 19, |