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 |
11 | 11 |
12 #include "platform/assert.h" | 12 #include "platform/assert.h" |
| 13 #include "platform/utils.h" |
13 #include "vm/constants_arm.h" | 14 #include "vm/constants_arm.h" |
14 | 15 |
15 namespace dart { | 16 namespace dart { |
16 | 17 |
17 class Operand : public ValueObject { | |
18 public: | |
19 Operand(const Operand& other) : ValueObject() { | |
20 UNIMPLEMENTED(); | |
21 } | |
22 | |
23 Operand& operator=(const Operand& other) { | |
24 UNIMPLEMENTED(); | |
25 return *this; | |
26 } | |
27 | |
28 protected: | |
29 Operand() { } // Needed by subclass Address. | |
30 }; | |
31 | |
32 | |
33 class Address : public Operand { | |
34 public: | |
35 Address(Register base, int32_t disp) { | |
36 UNIMPLEMENTED(); | |
37 } | |
38 | |
39 Address(const Address& other) : Operand(other) { } | |
40 | |
41 Address& operator=(const Address& other) { | |
42 Operand::operator=(other); | |
43 return *this; | |
44 } | |
45 }; | |
46 | |
47 | |
48 class FieldAddress : public Address { | |
49 public: | |
50 FieldAddress(Register base, int32_t disp) | |
51 : Address(base, disp - kHeapObjectTag) { } | |
52 | |
53 FieldAddress(const FieldAddress& other) : Address(other) { } | |
54 | |
55 FieldAddress& operator=(const FieldAddress& other) { | |
56 Address::operator=(other); | |
57 return *this; | |
58 } | |
59 }; | |
60 | |
61 | |
62 class Label : public ValueObject { | 18 class Label : public ValueObject { |
63 public: | 19 public: |
64 Label() : position_(0) { } | 20 Label() : position_(0) { } |
65 | 21 |
66 ~Label() { | 22 ~Label() { |
67 // Assert if label is being destroyed with unresolved branches pending. | 23 // Assert if label is being destroyed with unresolved branches pending. |
68 ASSERT(!IsLinked()); | 24 ASSERT(!IsLinked()); |
69 } | 25 } |
70 | 26 |
71 // Returns the position for bound and linked labels. Cannot be used | 27 // Returns the position for bound and linked labels. Cannot be used |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
106 class CPUFeatures : public AllStatic { | 62 class CPUFeatures : public AllStatic { |
107 public: | 63 public: |
108 static void InitOnce() { } | 64 static void InitOnce() { } |
109 static bool double_truncate_round_supported() { | 65 static bool double_truncate_round_supported() { |
110 UNIMPLEMENTED(); | 66 UNIMPLEMENTED(); |
111 return false; | 67 return false; |
112 } | 68 } |
113 }; | 69 }; |
114 | 70 |
115 | 71 |
| 72 // Encodes Addressing Mode 1 - Data-processing operands. |
| 73 class ShifterOperand : public ValueObject { |
| 74 public: |
| 75 // Data-processing operands - Uninitialized. |
| 76 ShifterOperand() : type_(-1) { } |
| 77 |
| 78 // Data-processing operands - Copy constructor. |
| 79 ShifterOperand(const ShifterOperand& other) |
| 80 : ValueObject(), type_(other.type_), encoding_(other.encoding_) { } |
| 81 |
| 82 // Data-processing operands - Assignment operator. |
| 83 ShifterOperand& operator=(const ShifterOperand& other) { |
| 84 type_ = other.type_; |
| 85 encoding_ = other.encoding_; |
| 86 return *this; |
| 87 } |
| 88 |
| 89 // Data-processing operands - Immediate. |
| 90 explicit ShifterOperand(uint32_t immediate) { |
| 91 ASSERT(immediate < (1 << kImmed8Bits)); |
| 92 type_ = 1; |
| 93 encoding_ = immediate; |
| 94 } |
| 95 |
| 96 // Data-processing operands - Rotated immediate. |
| 97 ShifterOperand(uint32_t rotate, uint32_t immed8) { |
| 98 ASSERT((rotate < (1 << kRotateBits)) && (immed8 < (1 << kImmed8Bits))); |
| 99 type_ = 1; |
| 100 encoding_ = (rotate << kRotateShift) | (immed8 << kImmed8Shift); |
| 101 } |
| 102 |
| 103 // Data-processing operands - Register. |
| 104 explicit ShifterOperand(Register rm) { |
| 105 type_ = 0; |
| 106 encoding_ = static_cast<uint32_t>(rm); |
| 107 } |
| 108 |
| 109 // Data-processing operands - Logical shift/rotate by immediate. |
| 110 ShifterOperand(Register rm, Shift shift, uint32_t shift_imm) { |
| 111 ASSERT(shift_imm < (1 << kShiftImmBits)); |
| 112 type_ = 0; |
| 113 encoding_ = shift_imm << kShiftImmShift | |
| 114 static_cast<uint32_t>(shift) << kShiftShift | |
| 115 static_cast<uint32_t>(rm); |
| 116 } |
| 117 |
| 118 // Data-processing operands - Logical shift/rotate by register. |
| 119 ShifterOperand(Register rm, Shift shift, Register rs) { |
| 120 type_ = 0; |
| 121 encoding_ = static_cast<uint32_t>(rs) << kShiftRegisterShift | |
| 122 static_cast<uint32_t>(shift) << kShiftShift | (1 << 4) | |
| 123 static_cast<uint32_t>(rm); |
| 124 } |
| 125 |
| 126 static bool CanHold(uint32_t immediate, ShifterOperand* shifter_op) { |
| 127 // Avoid the more expensive test for frequent small immediate values. |
| 128 if (immediate < (1 << kImmed8Bits)) { |
| 129 shifter_op->type_ = 1; |
| 130 shifter_op->encoding_ = (0 << kRotateShift) | (immediate << kImmed8Shift); |
| 131 return true; |
| 132 } |
| 133 // Note that immediate must be unsigned for the test to work correctly. |
| 134 for (int rot = 0; rot < 16; rot++) { |
| 135 uint32_t imm8 = (immediate << 2*rot) | (immediate >> (32 - 2*rot)); |
| 136 if (imm8 < (1 << kImmed8Bits)) { |
| 137 shifter_op->type_ = 1; |
| 138 shifter_op->encoding_ = (rot << kRotateShift) | (imm8 << kImmed8Shift); |
| 139 return true; |
| 140 } |
| 141 } |
| 142 return false; |
| 143 } |
| 144 |
| 145 private: |
| 146 bool is_valid() const { return (type_ == 0) || (type_ == 1); } |
| 147 |
| 148 uint32_t type() const { |
| 149 ASSERT(is_valid()); |
| 150 return type_; |
| 151 } |
| 152 |
| 153 uint32_t encoding() const { |
| 154 ASSERT(is_valid()); |
| 155 return encoding_; |
| 156 } |
| 157 |
| 158 uint32_t type_; // Encodes the type field (bits 27-25) in the instruction. |
| 159 uint32_t encoding_; |
| 160 |
| 161 friend class Assembler; |
| 162 }; |
| 163 |
| 164 |
| 165 enum LoadOperandType { |
| 166 kLoadSignedByte, |
| 167 kLoadUnsignedByte, |
| 168 kLoadSignedHalfword, |
| 169 kLoadUnsignedHalfword, |
| 170 kLoadWord, |
| 171 kLoadWordPair, |
| 172 kLoadSWord, |
| 173 kLoadDWord |
| 174 }; |
| 175 |
| 176 |
| 177 enum StoreOperandType { |
| 178 kStoreByte, |
| 179 kStoreHalfword, |
| 180 kStoreWord, |
| 181 kStoreWordPair, |
| 182 kStoreSWord, |
| 183 kStoreDWord |
| 184 }; |
| 185 |
| 186 |
| 187 // Load/store multiple addressing mode. |
| 188 enum BlockAddressMode { |
| 189 // bit encoding P U W |
| 190 DA = (0|0|0) << 21, // decrement after |
| 191 IA = (0|4|0) << 21, // increment after |
| 192 DB = (8|0|0) << 21, // decrement before |
| 193 IB = (8|4|0) << 21, // increment before |
| 194 DA_W = (0|0|1) << 21, // decrement after with writeback to base |
| 195 IA_W = (0|4|1) << 21, // increment after with writeback to base |
| 196 DB_W = (8|0|1) << 21, // decrement before with writeback to base |
| 197 IB_W = (8|4|1) << 21 // increment before with writeback to base |
| 198 }; |
| 199 |
| 200 |
| 201 class Address : public ValueObject { |
| 202 public: |
| 203 // Memory operand addressing mode |
| 204 enum Mode { |
| 205 // bit encoding P U W |
| 206 Offset = (8|4|0) << 21, // offset (w/o writeback to base) |
| 207 PreIndex = (8|4|1) << 21, // pre-indexed addressing with writeback |
| 208 PostIndex = (0|4|0) << 21, // post-indexed addressing with writeback |
| 209 NegOffset = (8|0|0) << 21, // negative offset (w/o writeback to base) |
| 210 NegPreIndex = (8|0|1) << 21, // negative pre-indexed with writeback |
| 211 NegPostIndex = (0|0|0) << 21 // negative post-indexed with writeback |
| 212 }; |
| 213 |
| 214 Address(const Address& other) : ValueObject(), encoding_(other.encoding_) { } |
| 215 |
| 216 Address& operator=(const Address& other) { |
| 217 encoding_ = other.encoding_; |
| 218 return *this; |
| 219 } |
| 220 |
| 221 explicit Address(Register rn, int32_t offset = 0, Mode am = Offset) { |
| 222 ASSERT(Utils::IsAbsoluteUint(12, offset)); |
| 223 if (offset < 0) { |
| 224 encoding_ = (am ^ (1 << kUShift)) | -offset; // Flip U to adjust sign. |
| 225 } else { |
| 226 encoding_ = am | offset; |
| 227 } |
| 228 encoding_ |= static_cast<uint32_t>(rn) << kRnShift; |
| 229 } |
| 230 |
| 231 static bool CanHoldLoadOffset(LoadOperandType type, int offset); |
| 232 static bool CanHoldStoreOffset(StoreOperandType type, int offset); |
| 233 |
| 234 private: |
| 235 uint32_t encoding() const { return encoding_; } |
| 236 |
| 237 // Encoding for addressing mode 3. |
| 238 uint32_t encoding3() const; |
| 239 |
| 240 // Encoding for vfp load/store addressing. |
| 241 uint32_t vencoding() const; |
| 242 |
| 243 uint32_t encoding_; |
| 244 |
| 245 friend class Assembler; |
| 246 }; |
| 247 |
| 248 |
| 249 class FieldAddress : public Address { |
| 250 public: |
| 251 FieldAddress(Register base, int32_t disp) |
| 252 : Address(base, disp - kHeapObjectTag) { } |
| 253 |
| 254 FieldAddress(const FieldAddress& other) : Address(other) { } |
| 255 |
| 256 FieldAddress& operator=(const FieldAddress& other) { |
| 257 Address::operator=(other); |
| 258 return *this; |
| 259 } |
| 260 }; |
| 261 |
| 262 |
116 class Assembler : public ValueObject { | 263 class Assembler : public ValueObject { |
117 public: | 264 public: |
118 Assembler() { UNIMPLEMENTED(); } | 265 Assembler() : buffer_(), prologue_offset_(-1), comments_() { } |
119 ~Assembler() { } | 266 ~Assembler() { } |
120 | 267 |
121 void PopRegister(Register r) { | 268 void PopRegister(Register r) { Pop(r); } |
122 UNIMPLEMENTED(); | 269 |
123 } | 270 void Bind(Label* label); |
124 | |
125 void Bind(Label* label) { | |
126 UNIMPLEMENTED(); | |
127 } | |
128 | 271 |
129 // Misc. functionality | 272 // Misc. functionality |
130 int CodeSize() const { | 273 int CodeSize() const { return buffer_.Size(); } |
131 UNIMPLEMENTED(); | 274 int prologue_offset() const { return prologue_offset_; } |
132 return 0; | |
133 } | |
134 int prologue_offset() const { | |
135 UNIMPLEMENTED(); | |
136 return 0; | |
137 } | |
138 const ZoneGrowableArray<int>& GetPointerOffsets() const { | 275 const ZoneGrowableArray<int>& GetPointerOffsets() const { |
139 UNIMPLEMENTED(); | 276 return buffer_.pointer_offsets(); |
140 return *pointer_offsets_; | 277 } |
141 } | 278 |
142 void FinalizeInstructions(const MemoryRegion& region) { | 279 void FinalizeInstructions(const MemoryRegion& region) { |
143 UNIMPLEMENTED(); | 280 buffer_.FinalizeInstructions(region); |
144 } | 281 } |
145 | 282 |
146 // Debugging and bringup support. | 283 // Debugging and bringup support. |
147 void Stop(const char* message) { UNIMPLEMENTED(); } | 284 void Stop(const char* message); |
148 void Unimplemented(const char* message); | 285 void Unimplemented(const char* message); |
149 void Untested(const char* message); | 286 void Untested(const char* message); |
150 void Unreachable(const char* message); | 287 void Unreachable(const char* message); |
151 | 288 |
152 static void InitializeMemoryWithBreakpoints(uword data, int length) { | 289 static void InitializeMemoryWithBreakpoints(uword data, int length) { |
153 UNIMPLEMENTED(); | 290 UNIMPLEMENTED(); |
154 } | 291 } |
155 | 292 |
156 void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3) { | 293 void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3); |
157 UNIMPLEMENTED(); | |
158 } | |
159 | 294 |
160 const Code::Comments& GetCodeComments() const { | 295 const Code::Comments& GetCodeComments() const; |
161 UNIMPLEMENTED(); | |
162 return Code::Comments::New(0); | |
163 } | |
164 | 296 |
165 static const char* RegisterName(Register reg) { | 297 static const char* RegisterName(Register reg) { |
166 UNIMPLEMENTED(); | 298 UNIMPLEMENTED(); |
167 return NULL; | 299 return NULL; |
168 } | 300 } |
169 | 301 |
170 static const char* FpuRegisterName(FpuRegister reg) { | 302 static const char* FpuRegisterName(FpuRegister reg) { |
171 UNIMPLEMENTED(); | 303 UNIMPLEMENTED(); |
172 return NULL; | 304 return NULL; |
173 } | 305 } |
174 | 306 |
| 307 // Data-processing instructions. |
| 308 void and_(Register rd, Register rn, ShifterOperand so, Condition cond = AL); |
| 309 |
| 310 void eor(Register rd, Register rn, ShifterOperand so, Condition cond = AL); |
| 311 |
| 312 void sub(Register rd, Register rn, ShifterOperand so, Condition cond = AL); |
| 313 void subs(Register rd, Register rn, ShifterOperand so, Condition cond = AL); |
| 314 |
| 315 void rsb(Register rd, Register rn, ShifterOperand so, Condition cond = AL); |
| 316 void rsbs(Register rd, Register rn, ShifterOperand so, Condition cond = AL); |
| 317 |
| 318 void add(Register rd, Register rn, ShifterOperand so, Condition cond = AL); |
| 319 |
| 320 void adds(Register rd, Register rn, ShifterOperand so, Condition cond = AL); |
| 321 |
| 322 void adc(Register rd, Register rn, ShifterOperand so, Condition cond = AL); |
| 323 |
| 324 void sbc(Register rd, Register rn, ShifterOperand so, Condition cond = AL); |
| 325 |
| 326 void rsc(Register rd, Register rn, ShifterOperand so, Condition cond = AL); |
| 327 |
| 328 void tst(Register rn, ShifterOperand so, Condition cond = AL); |
| 329 |
| 330 void teq(Register rn, ShifterOperand so, Condition cond = AL); |
| 331 |
| 332 void cmp(Register rn, ShifterOperand so, Condition cond = AL); |
| 333 |
| 334 void cmn(Register rn, ShifterOperand so, Condition cond = AL); |
| 335 |
| 336 void orr(Register rd, Register rn, ShifterOperand so, Condition cond = AL); |
| 337 void orrs(Register rd, Register rn, ShifterOperand so, Condition cond = AL); |
| 338 |
| 339 void mov(Register rd, ShifterOperand so, Condition cond = AL); |
| 340 void movs(Register rd, ShifterOperand so, Condition cond = AL); |
| 341 |
| 342 void bic(Register rd, Register rn, ShifterOperand so, Condition cond = AL); |
| 343 |
| 344 void mvn(Register rd, ShifterOperand so, Condition cond = AL); |
| 345 void mvns(Register rd, ShifterOperand so, Condition cond = AL); |
| 346 |
| 347 // Miscellaneous data-processing instructions. |
| 348 void clz(Register rd, Register rm, Condition cond = AL); |
| 349 void movw(Register rd, uint16_t imm16, Condition cond = AL); |
| 350 void movt(Register rd, uint16_t imm16, Condition cond = AL); |
| 351 |
| 352 // Multiply instructions. |
| 353 void mul(Register rd, Register rn, Register rm, Condition cond = AL); |
| 354 void mla(Register rd, Register rn, Register rm, Register ra, |
| 355 Condition cond = AL); |
| 356 void mls(Register rd, Register rn, Register rm, Register ra, |
| 357 Condition cond = AL); |
| 358 void umull(Register rd_lo, Register rd_hi, Register rn, Register rm, |
| 359 Condition cond = AL); |
| 360 |
| 361 // Load/store instructions. |
| 362 void ldr(Register rd, Address ad, Condition cond = AL); |
| 363 void str(Register rd, Address ad, Condition cond = AL); |
| 364 |
| 365 void ldrb(Register rd, Address ad, Condition cond = AL); |
| 366 void strb(Register rd, Address ad, Condition cond = AL); |
| 367 |
| 368 void ldrh(Register rd, Address ad, Condition cond = AL); |
| 369 void strh(Register rd, Address ad, Condition cond = AL); |
| 370 |
| 371 void ldrsb(Register rd, Address ad, Condition cond = AL); |
| 372 void ldrsh(Register rd, Address ad, Condition cond = AL); |
| 373 |
| 374 void ldrd(Register rd, Address ad, Condition cond = AL); |
| 375 void strd(Register rd, Address ad, Condition cond = AL); |
| 376 |
| 377 void ldm(BlockAddressMode am, Register base, |
| 378 RegList regs, Condition cond = AL); |
| 379 void stm(BlockAddressMode am, Register base, |
| 380 RegList regs, Condition cond = AL); |
| 381 |
| 382 void ldrex(Register rd, Register rn, Condition cond = AL); |
| 383 void strex(Register rd, Register rt, Register rn, Condition cond = AL); |
| 384 |
| 385 // Miscellaneous instructions. |
| 386 void clrex(); |
| 387 void nop(Condition cond = AL); |
| 388 |
| 389 // Note that gdb sets breakpoints using the undefined instruction 0xe7f001f0. |
| 390 void bkpt(uint16_t imm16); |
| 391 void svc(uint32_t imm24); |
| 392 |
| 393 // Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles). |
| 394 void vmovsr(SRegister sn, Register rt, Condition cond = AL); |
| 395 void vmovrs(Register rt, SRegister sn, Condition cond = AL); |
| 396 void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL); |
| 397 void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL); |
| 398 void vmovdrr(DRegister dm, Register rt, Register rt2, Condition cond = AL); |
| 399 void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL); |
| 400 void vmovs(SRegister sd, SRegister sm, Condition cond = AL); |
| 401 void vmovd(DRegister dd, DRegister dm, Condition cond = AL); |
| 402 |
| 403 // Returns false if the immediate cannot be encoded. |
| 404 bool vmovs(SRegister sd, float s_imm, Condition cond = AL); |
| 405 bool vmovd(DRegister dd, double d_imm, Condition cond = AL); |
| 406 |
| 407 void vldrs(SRegister sd, Address ad, Condition cond = AL); |
| 408 void vstrs(SRegister sd, Address ad, Condition cond = AL); |
| 409 void vldrd(DRegister dd, Address ad, Condition cond = AL); |
| 410 void vstrd(DRegister dd, Address ad, Condition cond = AL); |
| 411 |
| 412 void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL); |
| 413 void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL); |
| 414 void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL); |
| 415 void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL); |
| 416 void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL); |
| 417 void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL); |
| 418 void vmlas(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL); |
| 419 void vmlad(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL); |
| 420 void vmlss(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL); |
| 421 void vmlsd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL); |
| 422 void vdivs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL); |
| 423 void vdivd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL); |
| 424 |
| 425 void vabss(SRegister sd, SRegister sm, Condition cond = AL); |
| 426 void vabsd(DRegister dd, DRegister dm, Condition cond = AL); |
| 427 void vnegs(SRegister sd, SRegister sm, Condition cond = AL); |
| 428 void vnegd(DRegister dd, DRegister dm, Condition cond = AL); |
| 429 void vsqrts(SRegister sd, SRegister sm, Condition cond = AL); |
| 430 void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL); |
| 431 |
| 432 void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL); |
| 433 void vcvtds(DRegister dd, SRegister sm, Condition cond = AL); |
| 434 void vcvtis(SRegister sd, SRegister sm, Condition cond = AL); |
| 435 void vcvtid(SRegister sd, DRegister dm, Condition cond = AL); |
| 436 void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL); |
| 437 void vcvtdi(DRegister dd, SRegister sm, Condition cond = AL); |
| 438 void vcvtus(SRegister sd, SRegister sm, Condition cond = AL); |
| 439 void vcvtud(SRegister sd, DRegister dm, Condition cond = AL); |
| 440 void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL); |
| 441 void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL); |
| 442 |
| 443 void vcmps(SRegister sd, SRegister sm, Condition cond = AL); |
| 444 void vcmpd(DRegister dd, DRegister dm, Condition cond = AL); |
| 445 void vcmpsz(SRegister sd, Condition cond = AL); |
| 446 void vcmpdz(DRegister dd, Condition cond = AL); |
| 447 void vmstat(Condition cond = AL); // VMRS APSR_nzcv, FPSCR |
| 448 |
| 449 // Branch instructions. |
| 450 void b(Label* label, Condition cond = AL); |
| 451 void bl(Label* label, Condition cond = AL); |
| 452 void blx(Register rm, Condition cond = AL); |
| 453 |
| 454 // Macros. |
| 455 // Branch to an entry address that can be patched at runtime. |
| 456 void Branch(const ExternalLabel* label); |
| 457 void BranchLink(const ExternalLabel* label); |
| 458 |
| 459 // Branch to entry after setting LR and storing LR at ad. |
| 460 void BranchLinkStore(const ExternalLabel* label, Address ad); |
| 461 |
| 462 // Branch to [base + offset] after setting LR. |
| 463 void BranchLinkOffset(Register base, int offset); |
| 464 |
| 465 // Add signed constant value to rd. May clobber IP. |
| 466 void AddConstant(Register rd, int32_t value, Condition cond = AL); |
| 467 void AddConstant(Register rd, Register rn, int32_t value, |
| 468 Condition cond = AL); |
| 469 void AddConstantSetFlags(Register rd, Register rn, int32_t value, |
| 470 Condition cond = AL); |
| 471 void AddConstantWithCarry(Register rd, Register rn, int32_t value, |
| 472 Condition cond = AL); |
| 473 |
| 474 // Load and Store. May clobber IP. |
| 475 void LoadImmediate(Register rd, int32_t value, Condition cond = AL); |
| 476 void LoadSImmediate(SRegister sd, float value, Condition cond = AL); |
| 477 void LoadDImmediate(DRegister dd, double value, |
| 478 Register scratch, Condition cond = AL); |
| 479 void MarkExceptionHandler(Label* label); |
| 480 void LoadObject(Register rd, const Object& object); |
| 481 void LoadFromOffset(LoadOperandType type, |
| 482 Register reg, |
| 483 Register base, |
| 484 int32_t offset, |
| 485 Condition cond = AL); |
| 486 void StoreToOffset(StoreOperandType type, |
| 487 Register reg, |
| 488 Register base, |
| 489 int32_t offset, |
| 490 Condition cond = AL); |
| 491 void LoadSFromOffset(SRegister reg, |
| 492 Register base, |
| 493 int32_t offset, |
| 494 Condition cond = AL); |
| 495 void StoreSToOffset(SRegister reg, |
| 496 Register base, |
| 497 int32_t offset, |
| 498 Condition cond = AL); |
| 499 void LoadDFromOffset(DRegister reg, |
| 500 Register base, |
| 501 int32_t offset, |
| 502 Condition cond = AL); |
| 503 void StoreDToOffset(DRegister reg, |
| 504 Register base, |
| 505 int32_t offset, |
| 506 Condition cond = AL); |
| 507 |
| 508 void Push(Register rd, Condition cond = AL); |
| 509 void Pop(Register rd, Condition cond = AL); |
| 510 |
| 511 void PushList(RegList regs, Condition cond = AL); |
| 512 void PopList(RegList regs, Condition cond = AL); |
| 513 |
| 514 void Mov(Register rd, Register rm, Condition cond = AL); |
| 515 |
| 516 // Convenience shift instructions. Use mov instruction with shifter operand |
| 517 // for variants setting the status flags or using a register shift count. |
| 518 void Lsl(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL); |
| 519 void Lsr(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL); |
| 520 void Asr(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL); |
| 521 void Ror(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL); |
| 522 void Rrx(Register rd, Register rm, Condition cond = AL); |
| 523 |
| 524 // Emit data (e.g encoded instruction or immediate) in instruction stream. |
| 525 void Emit(int32_t value); |
| 526 |
175 private: | 527 private: |
| 528 AssemblerBuffer buffer_; |
176 ZoneGrowableArray<int>* pointer_offsets_; | 529 ZoneGrowableArray<int>* pointer_offsets_; |
| 530 int prologue_offset_; |
| 531 |
| 532 class CodeComment : public ZoneAllocated { |
| 533 public: |
| 534 CodeComment(intptr_t pc_offset, const String& comment) |
| 535 : pc_offset_(pc_offset), comment_(comment) { } |
| 536 |
| 537 intptr_t pc_offset() const { return pc_offset_; } |
| 538 const String& comment() const { return comment_; } |
| 539 |
| 540 private: |
| 541 intptr_t pc_offset_; |
| 542 const String& comment_; |
| 543 |
| 544 DISALLOW_COPY_AND_ASSIGN(CodeComment); |
| 545 }; |
| 546 |
| 547 GrowableArray<CodeComment*> comments_; |
| 548 |
| 549 void EmitType01(Condition cond, |
| 550 int type, |
| 551 Opcode opcode, |
| 552 int set_cc, |
| 553 Register rn, |
| 554 Register rd, |
| 555 ShifterOperand so); |
| 556 |
| 557 void EmitType5(Condition cond, int offset, bool link); |
| 558 |
| 559 void EmitMemOp(Condition cond, |
| 560 bool load, |
| 561 bool byte, |
| 562 Register rd, |
| 563 Address ad); |
| 564 |
| 565 void EmitMemOpAddressMode3(Condition cond, |
| 566 int32_t mode, |
| 567 Register rd, |
| 568 Address ad); |
| 569 |
| 570 void EmitMultiMemOp(Condition cond, |
| 571 BlockAddressMode am, |
| 572 bool load, |
| 573 Register base, |
| 574 RegList regs); |
| 575 |
| 576 void EmitShiftImmediate(Condition cond, |
| 577 Shift opcode, |
| 578 Register rd, |
| 579 Register rm, |
| 580 ShifterOperand so); |
| 581 |
| 582 void EmitShiftRegister(Condition cond, |
| 583 Shift opcode, |
| 584 Register rd, |
| 585 Register rm, |
| 586 ShifterOperand so); |
| 587 |
| 588 void EmitMulOp(Condition cond, |
| 589 int32_t opcode, |
| 590 Register rd, |
| 591 Register rn, |
| 592 Register rm, |
| 593 Register rs); |
| 594 |
| 595 void EmitVFPsss(Condition cond, |
| 596 int32_t opcode, |
| 597 SRegister sd, |
| 598 SRegister sn, |
| 599 SRegister sm); |
| 600 |
| 601 void EmitVFPddd(Condition cond, |
| 602 int32_t opcode, |
| 603 DRegister dd, |
| 604 DRegister dn, |
| 605 DRegister dm); |
| 606 |
| 607 void EmitVFPsd(Condition cond, |
| 608 int32_t opcode, |
| 609 SRegister sd, |
| 610 DRegister dm); |
| 611 |
| 612 void EmitVFPds(Condition cond, |
| 613 int32_t opcode, |
| 614 DRegister dd, |
| 615 SRegister sm); |
| 616 |
| 617 void EmitBranch(Condition cond, Label* label, bool link); |
| 618 static int32_t EncodeBranchOffset(int offset, int32_t inst); |
| 619 static int DecodeBranchOffset(int32_t inst); |
| 620 int32_t EncodeTstOffset(int offset, int32_t inst); |
| 621 int DecodeTstOffset(int32_t inst); |
| 622 |
| 623 // Returns whether or not the given register is used for passing parameters. |
| 624 static int RegisterCompare(const Register* reg1, const Register* reg2) { |
| 625 return *reg1 - *reg2; |
| 626 } |
| 627 |
177 DISALLOW_ALLOCATION(); | 628 DISALLOW_ALLOCATION(); |
178 DISALLOW_COPY_AND_ASSIGN(Assembler); | 629 DISALLOW_COPY_AND_ASSIGN(Assembler); |
179 }; | 630 }; |
180 | 631 |
181 } // namespace dart | 632 } // namespace dart |
182 | 633 |
183 #endif // VM_ASSEMBLER_ARM_H_ | 634 #endif // VM_ASSEMBLER_ARM_H_ |
OLD | NEW |