Chromium Code Reviews| Index: runtime/vm/assembler_arm64.h |
| =================================================================== |
| --- runtime/vm/assembler_arm64.h (revision 34831) |
| +++ runtime/vm/assembler_arm64.h (working copy) |
| @@ -217,8 +217,16 @@ |
| type_ = Immediate; |
| } |
| - // TODO(zra): Add bitfield immediate operand |
| - // Operand(int32_t n, int32_t imms, int32_t immr); |
| + // Call Assembler::IsImmLogical to find values for these arguments. |
|
regis
2014/04/09 20:49:49
I do not understand this comment.
zra
2014/04/09 22:14:28
Tried to clarify.
|
| + Operand(uint8_t n, int8_t imm_s, int8_t imm_r) { |
| + ASSERT((n == 1) || (n == 0)); |
| + ASSERT(Utils::IsUint(6, imm_s) && Utils::IsUint(6, imm_r)); |
| + type_ = BitfieldImm; |
| + encoding_ = |
| + (static_cast<int32_t>(n) << kNShift) | |
| + (static_cast<int32_t>(imm_s) << kImmSShift) | |
| + (static_cast<int32_t>(imm_r) << kImmRShift); |
| + } |
| enum OperandType { |
| Shifted, |
| @@ -326,13 +334,83 @@ |
| void add(Register rd, Register rn, Operand o) { |
| AddSubHelper(kDoubleWord, false, false, rd, rn, o); |
| } |
| + void adds(Register rd, Register rn, Operand o) { |
| + AddSubHelper(kDoubleWord, true, false, rd, rn, o); |
| + } |
| void addw(Register rd, Register rn, Operand o) { |
| AddSubHelper(kWord, false, false, rd, rn, o); |
| } |
| void sub(Register rd, Register rn, Operand o) { |
| AddSubHelper(kDoubleWord, false, true, rd, rn, o); |
| } |
| + void subs(Register rd, Register rn, Operand o) { |
| + AddSubHelper(kDoubleWord, true, true, rd, rn, o); |
| + } |
| + // Logical immediate operations. |
| + // TODO(zra): Add macros that check IsImmLogical, and fall back on a longer |
| + // sequence on failure. |
| + void andi(Register rd, Register rn, uint64_t imm) { |
| + uint8_t n = 0, imm_s = 0, imm_r = 0; |
| + const bool immok = IsImmLogical(imm, kXRegSizeInBits, &n, &imm_s, &imm_r); |
|
regis
2014/04/09 20:49:49
You could also use a pattern similar to ShifterOpe
zra
2014/04/09 22:14:28
Done.
|
| + ASSERT(immok); |
| + EmitLogicalImmOp(ANDI, rd, rn, Operand(n, imm_s, imm_r), kDoubleWord); |
| + } |
| + void orri(Register rd, Register rn, uint64_t imm) { |
| + uint8_t n = 0, imm_s = 0, imm_r = 0; |
| + const bool immok = IsImmLogical(imm, kXRegSizeInBits, &n, &imm_s, &imm_r); |
| + ASSERT(immok); |
| + EmitLogicalImmOp(ORRI, rd, rn, Operand(n, imm_s, imm_r), kDoubleWord); |
| + } |
| + void eori(Register rd, Register rn, uint64_t imm) { |
| + uint8_t n = 0, imm_s = 0, imm_r = 0; |
| + const bool immok = IsImmLogical(imm, kXRegSizeInBits, &n, &imm_s, &imm_r); |
| + ASSERT(immok); |
| + EmitLogicalImmOp(EORI, rd, rn, Operand(n, imm_s, imm_r), kDoubleWord); |
| + } |
| + void andis(Register rd, Register rn, uint64_t imm) { |
| + uint8_t n = 0, imm_s = 0, imm_r = 0; |
| + const bool immok = IsImmLogical(imm, kXRegSizeInBits, &n, &imm_s, &imm_r); |
| + ASSERT(immok); |
| + EmitLogicalImmOp(ANDIS, rd, rn, Operand(n, imm_s, imm_r), kDoubleWord); |
| + } |
| + |
| + // Logical (shifted) register operations. |
| + void and_(Register rd, Register rn, Operand o) { |
| + EmitLogicalShiftOp(AND, rd, rn, o, kDoubleWord); |
| + } |
| + void bic(Register rd, Register rn, Operand o) { |
| + EmitLogicalShiftOp(BIC, rd, rn, o, kDoubleWord); |
| + } |
| + void orr(Register rd, Register rn, Operand o) { |
| + EmitLogicalShiftOp(ORR, rd, rn, o, kDoubleWord); |
| + } |
| + void orn(Register rd, Register rn, Operand o) { |
| + EmitLogicalShiftOp(ORN, rd, rn, o, kDoubleWord); |
| + } |
| + void eor(Register rd, Register rn, Operand o) { |
| + EmitLogicalShiftOp(EOR, rd, rn, o, kDoubleWord); |
| + } |
| + void eon(Register rd, Register rn, Operand o) { |
| + EmitLogicalShiftOp(EON, rd, rn, o, kDoubleWord); |
| + } |
| + void ands(Register rd, Register rn, Operand o) { |
| + EmitLogicalShiftOp(ANDS, rd, rn, o, kDoubleWord); |
| + } |
| + void bics(Register rd, Register rn, Operand o) { |
| + EmitLogicalShiftOp(BICS, rd, rn, o, kDoubleWord); |
| + } |
| + |
| + // Comparison. |
| + // rn cmp o. |
| + void cmp(Register rn, Operand o) { |
| + subs(ZR, rn, o); |
| + } |
| + // rn cmp -o. |
| + void cmn(Register rn, Operand o) { |
| + adds(ZR, rn, o); |
| + } |
| + |
| // Move wide immediate. |
| void movk(Register rd, int32_t imm, int32_t hw_idx) { |
| ASSERT(rd != SP); |
| @@ -393,6 +471,9 @@ |
| GrowableArray<CodeComment*> comments_; |
| + bool IsImmLogical(uint64_t value, uint8_t width, |
| + uint8_t* n, uint8_t* imm_s, uint8_t* imm_r); |
| + |
| void AddSubHelper(OperandSize os, bool set_flags, bool subtract, |
| Register rd, Register rn, Operand o) { |
| ASSERT((rd != R31) && (rn != R31)); |
| @@ -412,9 +493,9 @@ |
| } |
| void EmitAddSubImmOp(AddSubImmOp op, Register rd, Register rn, |
| - Operand o, OperandSize os, bool set_flags) { |
| - ASSERT((os == kDoubleWord) || (os == kWord)); |
| - const int32_t size = (os == kDoubleWord) ? B31 : 0; |
| + Operand o, OperandSize sz, bool set_flags) { |
| + ASSERT((sz == kDoubleWord) || (sz == kWord)); |
| + const int32_t size = (sz == kDoubleWord) ? B31 : 0; |
| const int32_t s = set_flags ? B29 : 0; |
| const int32_t encoding = |
| op | size | s | |
| @@ -424,6 +505,42 @@ |
| Emit(encoding); |
| } |
| + void EmitLogicalImmOp(LogicalImmOp op, Register rd, Register rn, |
| + Operand o, OperandSize sz) { |
| + ASSERT((sz == kDoubleWord) || (sz == kWord)); |
| + ASSERT((rd != R31) && (rn != R31)); |
| + ASSERT(rn != SP); |
| + ASSERT((op == ANDIS) || (rd != ZR)); // op != ANDIS => rd != ZR. |
| + ASSERT((op != ANDIS) || (rd != SP)); // op == ANDIS => rd != SP. |
| + ASSERT(o.type() == Operand::BitfieldImm); |
| + const int32_t size = (sz == kDoubleWord) ? B31 : 0; |
| + const Register crd = ConcreteRegister(rd); |
| + const Register crn = ConcreteRegister(rn); |
| + const int32_t encoding = |
| + op | size | |
| + (static_cast<int32_t>(crd) << kRdShift) | |
| + (static_cast<int32_t>(crn) << kRnShift) | |
| + o.encoding(); |
| + Emit(encoding); |
| + } |
| + |
| + void EmitLogicalShiftOp(LogicalShiftOp op, |
| + Register rd, Register rn, Operand o, OperandSize sz) { |
| + ASSERT((sz == kDoubleWord) || (sz == kWord)); |
| + ASSERT((rd != R31) && (rn != R31)); |
| + ASSERT((rd != SP) && (rn != SP)); |
| + ASSERT(o.type() == Operand::Shifted); |
| + const int32_t size = (sz == kDoubleWord) ? B31 : 0; |
| + const Register crd = ConcreteRegister(rd); |
| + const Register crn = ConcreteRegister(rn); |
| + const int32_t encoding = |
| + op | size | |
| + (static_cast<int32_t>(crd) << kRdShift) | |
| + (static_cast<int32_t>(crn) << kRnShift) | |
| + o.encoding(); |
| + Emit(encoding); |
| + } |
| + |
| void EmitAddSubShiftExtOp(AddSubShiftExtOp op, |
| Register rd, Register rn, Operand o, |
| OperandSize sz, bool set_flags) { |