| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef VM_ASSEMBLER_ARM_H_ | 5 #ifndef VM_ASSEMBLER_ARM_H_ |
| 6 #define VM_ASSEMBLER_ARM_H_ | 6 #define VM_ASSEMBLER_ARM_H_ |
| 7 | 7 |
| 8 #ifndef VM_ASSEMBLER_H_ | 8 #ifndef VM_ASSEMBLER_H_ |
| 9 #error Do not include assembler_arm.h directly; use assembler.h instead. | 9 #error Do not include assembler_arm.h directly; use assembler.h instead. |
| 10 #endif | 10 #endif |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 position_ = position + kWordSize; | 58 position_ = position + kWordSize; |
| 59 ASSERT(IsLinked()); | 59 ASSERT(IsLinked()); |
| 60 } | 60 } |
| 61 | 61 |
| 62 friend class Assembler; | 62 friend class Assembler; |
| 63 DISALLOW_COPY_AND_ASSIGN(Label); | 63 DISALLOW_COPY_AND_ASSIGN(Label); |
| 64 }; | 64 }; |
| 65 | 65 |
| 66 | 66 |
| 67 // Encodes Addressing Mode 1 - Data-processing operands. | 67 // Encodes Addressing Mode 1 - Data-processing operands. |
| 68 // TODO(regis): rename ShifterOperand to Operand. | 68 class Operand : public ValueObject { |
| 69 class ShifterOperand : public ValueObject { | |
| 70 public: | 69 public: |
| 71 // Data-processing operands - Uninitialized. | 70 // Data-processing operands - Uninitialized. |
| 72 ShifterOperand() : type_(-1), encoding_(-1) { } | 71 Operand() : type_(-1), encoding_(-1) { } |
| 73 | 72 |
| 74 // Data-processing operands - Copy constructor. | 73 // Data-processing operands - Copy constructor. |
| 75 ShifterOperand(const ShifterOperand& other) | 74 Operand(const Operand& other) |
| 76 : ValueObject(), type_(other.type_), encoding_(other.encoding_) { } | 75 : ValueObject(), type_(other.type_), encoding_(other.encoding_) { } |
| 77 | 76 |
| 78 // Data-processing operands - Assignment operator. | 77 // Data-processing operands - Assignment operator. |
| 79 ShifterOperand& operator=(const ShifterOperand& other) { | 78 Operand& operator=(const Operand& other) { |
| 80 type_ = other.type_; | 79 type_ = other.type_; |
| 81 encoding_ = other.encoding_; | 80 encoding_ = other.encoding_; |
| 82 return *this; | 81 return *this; |
| 83 } | 82 } |
| 84 | 83 |
| 85 // Data-processing operands - Immediate. | 84 // Data-processing operands - Immediate. |
| 86 explicit ShifterOperand(uint32_t immediate) { | 85 explicit Operand(uint32_t immediate) { |
| 87 ASSERT(immediate < (1 << kImmed8Bits)); | 86 ASSERT(immediate < (1 << kImmed8Bits)); |
| 88 type_ = 1; | 87 type_ = 1; |
| 89 encoding_ = immediate; | 88 encoding_ = immediate; |
| 90 } | 89 } |
| 91 | 90 |
| 92 // Data-processing operands - Rotated immediate. | 91 // Data-processing operands - Rotated immediate. |
| 93 ShifterOperand(uint32_t rotate, uint32_t immed8) { | 92 Operand(uint32_t rotate, uint32_t immed8) { |
| 94 ASSERT((rotate < (1 << kRotateBits)) && (immed8 < (1 << kImmed8Bits))); | 93 ASSERT((rotate < (1 << kRotateBits)) && (immed8 < (1 << kImmed8Bits))); |
| 95 type_ = 1; | 94 type_ = 1; |
| 96 encoding_ = (rotate << kRotateShift) | (immed8 << kImmed8Shift); | 95 encoding_ = (rotate << kRotateShift) | (immed8 << kImmed8Shift); |
| 97 } | 96 } |
| 98 | 97 |
| 99 // Data-processing operands - Register. | 98 // Data-processing operands - Register. |
| 100 explicit ShifterOperand(Register rm) { | 99 explicit Operand(Register rm) { |
| 101 type_ = 0; | 100 type_ = 0; |
| 102 encoding_ = static_cast<uint32_t>(rm); | 101 encoding_ = static_cast<uint32_t>(rm); |
| 103 } | 102 } |
| 104 | 103 |
| 105 // Data-processing operands - Logical shift/rotate by immediate. | 104 // Data-processing operands - Logical shift/rotate by immediate. |
| 106 ShifterOperand(Register rm, Shift shift, uint32_t shift_imm) { | 105 Operand(Register rm, Shift shift, uint32_t shift_imm) { |
| 107 ASSERT(shift_imm < (1 << kShiftImmBits)); | 106 ASSERT(shift_imm < (1 << kShiftImmBits)); |
| 108 type_ = 0; | 107 type_ = 0; |
| 109 encoding_ = shift_imm << kShiftImmShift | | 108 encoding_ = shift_imm << kShiftImmShift | |
| 110 static_cast<uint32_t>(shift) << kShiftShift | | 109 static_cast<uint32_t>(shift) << kShiftShift | |
| 111 static_cast<uint32_t>(rm); | 110 static_cast<uint32_t>(rm); |
| 112 } | 111 } |
| 113 | 112 |
| 114 // Data-processing operands - Logical shift/rotate by register. | 113 // Data-processing operands - Logical shift/rotate by register. |
| 115 ShifterOperand(Register rm, Shift shift, Register rs) { | 114 Operand(Register rm, Shift shift, Register rs) { |
| 116 type_ = 0; | 115 type_ = 0; |
| 117 encoding_ = static_cast<uint32_t>(rs) << kShiftRegisterShift | | 116 encoding_ = static_cast<uint32_t>(rs) << kShiftRegisterShift | |
| 118 static_cast<uint32_t>(shift) << kShiftShift | (1 << 4) | | 117 static_cast<uint32_t>(shift) << kShiftShift | (1 << 4) | |
| 119 static_cast<uint32_t>(rm); | 118 static_cast<uint32_t>(rm); |
| 120 } | 119 } |
| 121 | 120 |
| 122 static bool CanHold(uint32_t immediate, ShifterOperand* shifter_op) { | 121 static bool CanHold(uint32_t immediate, Operand* o) { |
| 123 // Avoid the more expensive test for frequent small immediate values. | 122 // Avoid the more expensive test for frequent small immediate values. |
| 124 if (immediate < (1 << kImmed8Bits)) { | 123 if (immediate < (1 << kImmed8Bits)) { |
| 125 shifter_op->type_ = 1; | 124 o->type_ = 1; |
| 126 shifter_op->encoding_ = (0 << kRotateShift) | (immediate << kImmed8Shift); | 125 o->encoding_ = (0 << kRotateShift) | (immediate << kImmed8Shift); |
| 127 return true; | 126 return true; |
| 128 } | 127 } |
| 129 // Note that immediate must be unsigned for the test to work correctly. | 128 // Note that immediate must be unsigned for the test to work correctly. |
| 130 for (int rot = 0; rot < 16; rot++) { | 129 for (int rot = 0; rot < 16; rot++) { |
| 131 uint32_t imm8 = (immediate << 2*rot) | (immediate >> (32 - 2*rot)); | 130 uint32_t imm8 = (immediate << 2*rot) | (immediate >> (32 - 2*rot)); |
| 132 if (imm8 < (1 << kImmed8Bits)) { | 131 if (imm8 < (1 << kImmed8Bits)) { |
| 133 shifter_op->type_ = 1; | 132 o->type_ = 1; |
| 134 shifter_op->encoding_ = (rot << kRotateShift) | (imm8 << kImmed8Shift); | 133 o->encoding_ = (rot << kRotateShift) | (imm8 << kImmed8Shift); |
| 135 return true; | 134 return true; |
| 136 } | 135 } |
| 137 } | 136 } |
| 138 return false; | 137 return false; |
| 139 } | 138 } |
| 140 | 139 |
| 141 private: | 140 private: |
| 142 bool is_valid() const { return (type_ == 0) || (type_ == 1); } | 141 bool is_valid() const { return (type_ == 0) || (type_ == 1); } |
| 143 | 142 |
| 144 uint32_t type() const { | 143 uint32_t type() const { |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 if (offset < 0) { | 225 if (offset < 0) { |
| 227 encoding_ = (am ^ (1 << kUShift)) | -offset; // Flip U to adjust sign. | 226 encoding_ = (am ^ (1 << kUShift)) | -offset; // Flip U to adjust sign. |
| 228 } else { | 227 } else { |
| 229 encoding_ = am | offset; | 228 encoding_ = am | offset; |
| 230 } | 229 } |
| 231 encoding_ |= static_cast<uint32_t>(rn) << kRnShift; | 230 encoding_ |= static_cast<uint32_t>(rn) << kRnShift; |
| 232 } | 231 } |
| 233 | 232 |
| 234 Address(Register rn, Register rm, | 233 Address(Register rn, Register rm, |
| 235 Shift shift = LSL, uint32_t shift_imm = 0, Mode am = Offset) { | 234 Shift shift = LSL, uint32_t shift_imm = 0, Mode am = Offset) { |
| 236 ShifterOperand so(rm, shift, shift_imm); | 235 Operand o(rm, shift, shift_imm); |
| 237 | 236 |
| 238 if ((shift == LSL) && (shift_imm == 0)) { | 237 if ((shift == LSL) && (shift_imm == 0)) { |
| 239 kind_ = IndexRegister; | 238 kind_ = IndexRegister; |
| 240 } else { | 239 } else { |
| 241 kind_ = ScaledIndexRegister; | 240 kind_ = ScaledIndexRegister; |
| 242 } | 241 } |
| 243 encoding_ = so.encoding() | am | (static_cast<uint32_t>(rn) << kRnShift); | 242 encoding_ = o.encoding() | am | (static_cast<uint32_t>(rn) << kRnShift); |
| 244 } | 243 } |
| 245 | 244 |
| 246 static OperandSize OperandSizeFor(intptr_t cid); | 245 static OperandSize OperandSizeFor(intptr_t cid); |
| 247 | 246 |
| 248 static bool CanHoldLoadOffset(OperandSize size, | 247 static bool CanHoldLoadOffset(OperandSize size, |
| 249 int32_t offset, | 248 int32_t offset, |
| 250 int32_t* offset_mask); | 249 int32_t* offset_mask); |
| 251 static bool CanHoldStoreOffset(OperandSize size, | 250 static bool CanHoldStoreOffset(OperandSize size, |
| 252 int32_t offset, | 251 int32_t offset, |
| 253 int32_t* offset_mask); | 252 int32_t* offset_mask); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 | 335 |
| 337 void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3); | 336 void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3); |
| 338 | 337 |
| 339 const Code::Comments& GetCodeComments() const; | 338 const Code::Comments& GetCodeComments() const; |
| 340 | 339 |
| 341 static const char* RegisterName(Register reg); | 340 static const char* RegisterName(Register reg); |
| 342 | 341 |
| 343 static const char* FpuRegisterName(FpuRegister reg); | 342 static const char* FpuRegisterName(FpuRegister reg); |
| 344 | 343 |
| 345 // Data-processing instructions. | 344 // Data-processing instructions. |
| 346 void and_(Register rd, Register rn, ShifterOperand so, Condition cond = AL); | 345 void and_(Register rd, Register rn, Operand o, Condition cond = AL); |
| 347 | 346 |
| 348 void eor(Register rd, Register rn, ShifterOperand so, Condition cond = AL); | 347 void eor(Register rd, Register rn, Operand o, Condition cond = AL); |
| 349 | 348 |
| 350 void sub(Register rd, Register rn, ShifterOperand so, Condition cond = AL); | 349 void sub(Register rd, Register rn, Operand o, Condition cond = AL); |
| 351 void subs(Register rd, Register rn, ShifterOperand so, Condition cond = AL); | 350 void subs(Register rd, Register rn, Operand o, Condition cond = AL); |
| 352 | 351 |
| 353 void rsb(Register rd, Register rn, ShifterOperand so, Condition cond = AL); | 352 void rsb(Register rd, Register rn, Operand o, Condition cond = AL); |
| 354 void rsbs(Register rd, Register rn, ShifterOperand so, Condition cond = AL); | 353 void rsbs(Register rd, Register rn, Operand o, Condition cond = AL); |
| 355 | 354 |
| 356 void add(Register rd, Register rn, ShifterOperand so, Condition cond = AL); | 355 void add(Register rd, Register rn, Operand o, Condition cond = AL); |
| 357 | 356 |
| 358 void adds(Register rd, Register rn, ShifterOperand so, Condition cond = AL); | 357 void adds(Register rd, Register rn, Operand o, Condition cond = AL); |
| 359 | 358 |
| 360 void adc(Register rd, Register rn, ShifterOperand so, Condition cond = AL); | 359 void adc(Register rd, Register rn, Operand o, Condition cond = AL); |
| 361 | 360 |
| 362 void adcs(Register rd, Register rn, ShifterOperand so, Condition cond = AL); | 361 void adcs(Register rd, Register rn, Operand o, Condition cond = AL); |
| 363 | 362 |
| 364 void sbc(Register rd, Register rn, ShifterOperand so, Condition cond = AL); | 363 void sbc(Register rd, Register rn, Operand o, Condition cond = AL); |
| 365 | 364 |
| 366 void sbcs(Register rd, Register rn, ShifterOperand so, Condition cond = AL); | 365 void sbcs(Register rd, Register rn, Operand o, Condition cond = AL); |
| 367 | 366 |
| 368 void rsc(Register rd, Register rn, ShifterOperand so, Condition cond = AL); | 367 void rsc(Register rd, Register rn, Operand o, Condition cond = AL); |
| 369 | 368 |
| 370 void tst(Register rn, ShifterOperand so, Condition cond = AL); | 369 void tst(Register rn, Operand o, Condition cond = AL); |
| 371 | 370 |
| 372 void teq(Register rn, ShifterOperand so, Condition cond = AL); | 371 void teq(Register rn, Operand o, Condition cond = AL); |
| 373 | 372 |
| 374 void cmp(Register rn, ShifterOperand so, Condition cond = AL); | 373 void cmp(Register rn, Operand o, Condition cond = AL); |
| 375 | 374 |
| 376 void cmn(Register rn, ShifterOperand so, Condition cond = AL); | 375 void cmn(Register rn, Operand o, Condition cond = AL); |
| 377 | 376 |
| 378 void orr(Register rd, Register rn, ShifterOperand so, Condition cond = AL); | 377 void orr(Register rd, Register rn, Operand o, Condition cond = AL); |
| 379 void orrs(Register rd, Register rn, ShifterOperand so, Condition cond = AL); | 378 void orrs(Register rd, Register rn, Operand o, Condition cond = AL); |
| 380 | 379 |
| 381 void mov(Register rd, ShifterOperand so, Condition cond = AL); | 380 void mov(Register rd, Operand o, Condition cond = AL); |
| 382 void movs(Register rd, ShifterOperand so, Condition cond = AL); | 381 void movs(Register rd, Operand o, Condition cond = AL); |
| 383 | 382 |
| 384 void bic(Register rd, Register rn, ShifterOperand so, Condition cond = AL); | 383 void bic(Register rd, Register rn, Operand o, Condition cond = AL); |
| 385 void bics(Register rd, Register rn, ShifterOperand so, Condition cond = AL); | 384 void bics(Register rd, Register rn, Operand o, Condition cond = AL); |
| 386 | 385 |
| 387 void mvn(Register rd, ShifterOperand so, Condition cond = AL); | 386 void mvn(Register rd, Operand o, Condition cond = AL); |
| 388 void mvns(Register rd, ShifterOperand so, Condition cond = AL); | 387 void mvns(Register rd, Operand o, Condition cond = AL); |
| 389 | 388 |
| 390 // Miscellaneous data-processing instructions. | 389 // Miscellaneous data-processing instructions. |
| 391 void clz(Register rd, Register rm, Condition cond = AL); | 390 void clz(Register rd, Register rm, Condition cond = AL); |
| 392 void movw(Register rd, uint16_t imm16, Condition cond = AL); | 391 void movw(Register rd, uint16_t imm16, Condition cond = AL); |
| 393 void movt(Register rd, uint16_t imm16, Condition cond = AL); | 392 void movt(Register rd, uint16_t imm16, Condition cond = AL); |
| 394 | 393 |
| 395 // Multiply instructions. | 394 // Multiply instructions. |
| 396 void mul(Register rd, Register rn, Register rm, Condition cond = AL); | 395 void mul(Register rd, Register rn, Register rm, Condition cond = AL); |
| 397 void muls(Register rd, Register rn, Register rm, Condition cond = AL); | 396 void muls(Register rd, Register rn, Register rm, Condition cond = AL); |
| 398 void mla(Register rd, Register rn, Register rm, Register ra, | 397 void mla(Register rd, Register rn, Register rm, Register ra, |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 813 }; | 812 }; |
| 814 | 813 |
| 815 GrowableArray<CodeComment*> comments_; | 814 GrowableArray<CodeComment*> comments_; |
| 816 | 815 |
| 817 void EmitType01(Condition cond, | 816 void EmitType01(Condition cond, |
| 818 int type, | 817 int type, |
| 819 Opcode opcode, | 818 Opcode opcode, |
| 820 int set_cc, | 819 int set_cc, |
| 821 Register rn, | 820 Register rn, |
| 822 Register rd, | 821 Register rd, |
| 823 ShifterOperand so); | 822 Operand o); |
| 824 | 823 |
| 825 void EmitType5(Condition cond, int32_t offset, bool link); | 824 void EmitType5(Condition cond, int32_t offset, bool link); |
| 826 | 825 |
| 827 void EmitMemOp(Condition cond, | 826 void EmitMemOp(Condition cond, |
| 828 bool load, | 827 bool load, |
| 829 bool byte, | 828 bool byte, |
| 830 Register rd, | 829 Register rd, |
| 831 Address ad); | 830 Address ad); |
| 832 | 831 |
| 833 void EmitMemOpAddressMode3(Condition cond, | 832 void EmitMemOpAddressMode3(Condition cond, |
| 834 int32_t mode, | 833 int32_t mode, |
| 835 Register rd, | 834 Register rd, |
| 836 Address ad); | 835 Address ad); |
| 837 | 836 |
| 838 void EmitMultiMemOp(Condition cond, | 837 void EmitMultiMemOp(Condition cond, |
| 839 BlockAddressMode am, | 838 BlockAddressMode am, |
| 840 bool load, | 839 bool load, |
| 841 Register base, | 840 Register base, |
| 842 RegList regs); | 841 RegList regs); |
| 843 | 842 |
| 844 void EmitShiftImmediate(Condition cond, | 843 void EmitShiftImmediate(Condition cond, |
| 845 Shift opcode, | 844 Shift opcode, |
| 846 Register rd, | 845 Register rd, |
| 847 Register rm, | 846 Register rm, |
| 848 ShifterOperand so); | 847 Operand o); |
| 849 | 848 |
| 850 void EmitShiftRegister(Condition cond, | 849 void EmitShiftRegister(Condition cond, |
| 851 Shift opcode, | 850 Shift opcode, |
| 852 Register rd, | 851 Register rd, |
| 853 Register rm, | 852 Register rm, |
| 854 ShifterOperand so); | 853 Operand o); |
| 855 | 854 |
| 856 void EmitMulOp(Condition cond, | 855 void EmitMulOp(Condition cond, |
| 857 int32_t opcode, | 856 int32_t opcode, |
| 858 Register rd, | 857 Register rd, |
| 859 Register rn, | 858 Register rn, |
| 860 Register rm, | 859 Register rm, |
| 861 Register rs); | 860 Register rs); |
| 862 | 861 |
| 863 void EmitDivOp(Condition cond, | 862 void EmitDivOp(Condition cond, |
| 864 int32_t opcode, | 863 int32_t opcode, |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 922 Register value, | 921 Register value, |
| 923 Label* no_update); | 922 Label* no_update); |
| 924 | 923 |
| 925 DISALLOW_ALLOCATION(); | 924 DISALLOW_ALLOCATION(); |
| 926 DISALLOW_COPY_AND_ASSIGN(Assembler); | 925 DISALLOW_COPY_AND_ASSIGN(Assembler); |
| 927 }; | 926 }; |
| 928 | 927 |
| 929 } // namespace dart | 928 } // namespace dart |
| 930 | 929 |
| 931 #endif // VM_ASSEMBLER_ARM_H_ | 930 #endif // VM_ASSEMBLER_ARM_H_ |
| OLD | NEW |