Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1023)

Side by Side Diff: runtime/vm/assembler_mips.h

Issue 2481873005: clang-format runtime/vm (Closed)
Patch Set: Merge Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/assembler_ia32_test.cc ('k') | runtime/vm/assembler_mips.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 RUNTIME_VM_ASSEMBLER_MIPS_H_ 5 #ifndef RUNTIME_VM_ASSEMBLER_MIPS_H_
6 #define RUNTIME_VM_ASSEMBLER_MIPS_H_ 6 #define RUNTIME_VM_ASSEMBLER_MIPS_H_
7 7
8 #ifndef RUNTIME_VM_ASSEMBLER_H_ 8 #ifndef RUNTIME_VM_ASSEMBLER_H_
9 #error Do not include assembler_mips.h directly; use assembler.h instead. 9 #error Do not include assembler_mips.h directly; use assembler.h instead.
10 #endif 10 #endif
(...skipping 12 matching lines...) Expand all
23 // "MIPS® Architecture For Programmers Volume II-A: 23 // "MIPS® Architecture For Programmers Volume II-A:
24 // The MIPS32® Instruction Set" in short "VolII-A" 24 // The MIPS32® Instruction Set" in short "VolII-A"
25 namespace dart { 25 namespace dart {
26 26
27 // Forward declarations. 27 // Forward declarations.
28 class RuntimeEntry; 28 class RuntimeEntry;
29 class StubEntry; 29 class StubEntry;
30 30
31 class Immediate : public ValueObject { 31 class Immediate : public ValueObject {
32 public: 32 public:
33 explicit Immediate(int32_t value) : value_(value) { } 33 explicit Immediate(int32_t value) : value_(value) {}
34 34
35 Immediate(const Immediate& other) : ValueObject(), value_(other.value_) { } 35 Immediate(const Immediate& other) : ValueObject(), value_(other.value_) {}
36 Immediate& operator=(const Immediate& other) { 36 Immediate& operator=(const Immediate& other) {
37 value_ = other.value_; 37 value_ = other.value_;
38 return *this; 38 return *this;
39 } 39 }
40 40
41 private: 41 private:
42 int32_t value_; 42 int32_t value_;
43 43
44 int32_t value() const { return value_; } 44 int32_t value() const { return value_; }
45 45
46 friend class Assembler; 46 friend class Assembler;
47 }; 47 };
48 48
49 49
50 class Address : public ValueObject { 50 class Address : public ValueObject {
51 public: 51 public:
52 explicit Address(Register base, int32_t offset = 0) 52 explicit Address(Register base, int32_t offset = 0)
53 : ValueObject(), base_(base), offset_(offset) { } 53 : ValueObject(), base_(base), offset_(offset) {}
54 54
55 // This addressing mode does not exist. 55 // This addressing mode does not exist.
56 Address(Register base, Register offset); 56 Address(Register base, Register offset);
57 57
58 Address(const Address& other) 58 Address(const Address& other)
59 : ValueObject(), base_(other.base_), offset_(other.offset_) { } 59 : ValueObject(), base_(other.base_), offset_(other.offset_) {}
60 Address& operator=(const Address& other) { 60 Address& operator=(const Address& other) {
61 base_ = other.base_; 61 base_ = other.base_;
62 offset_ = other.offset_; 62 offset_ = other.offset_;
63 return *this; 63 return *this;
64 } 64 }
65 65
66 uint32_t encoding() const { 66 uint32_t encoding() const {
67 ASSERT(Utils::IsInt(kImmBits, offset_)); 67 ASSERT(Utils::IsInt(kImmBits, offset_));
68 uint16_t imm_value = static_cast<uint16_t>(offset_); 68 uint16_t imm_value = static_cast<uint16_t>(offset_);
69 return (base_ << kRsShift) | imm_value; 69 return (base_ << kRsShift) | imm_value;
70 } 70 }
71 71
72 static bool CanHoldOffset(int32_t offset) { 72 static bool CanHoldOffset(int32_t offset) {
73 return Utils::IsInt(kImmBits, offset); 73 return Utils::IsInt(kImmBits, offset);
74 } 74 }
75 75
76 Register base() const { return base_; } 76 Register base() const { return base_; }
77 int32_t offset() const { return offset_; } 77 int32_t offset() const { return offset_; }
78 78
79 private: 79 private:
80 Register base_; 80 Register base_;
81 int32_t offset_; 81 int32_t offset_;
82 }; 82 };
83 83
84 84
85 class FieldAddress : public Address { 85 class FieldAddress : public Address {
86 public: 86 public:
87 FieldAddress(Register base, int32_t disp) 87 FieldAddress(Register base, int32_t disp)
88 : Address(base, disp - kHeapObjectTag) { } 88 : Address(base, disp - kHeapObjectTag) {}
89 89
90 FieldAddress(const FieldAddress& other) : Address(other) { } 90 FieldAddress(const FieldAddress& other) : Address(other) {}
91 91
92 FieldAddress& operator=(const FieldAddress& other) { 92 FieldAddress& operator=(const FieldAddress& other) {
93 Address::operator=(other); 93 Address::operator=(other);
94 return *this; 94 return *this;
95 } 95 }
96 }; 96 };
97 97
98 98
99 class Label : public ValueObject { 99 class Label : public ValueObject {
100 public: 100 public:
101 Label() : position_(0) { } 101 Label() : position_(0) {}
102 102
103 ~Label() { 103 ~Label() {
104 // Assert if label is being destroyed with unresolved branches pending. 104 // Assert if label is being destroyed with unresolved branches pending.
105 ASSERT(!IsLinked()); 105 ASSERT(!IsLinked());
106 } 106 }
107 107
108 // Returns the position for bound and linked labels. Cannot be used 108 // Returns the position for bound and linked labels. Cannot be used
109 // for unused labels. 109 // for unused labels.
110 intptr_t Position() const { 110 intptr_t Position() const {
111 ASSERT(!IsUnused()); 111 ASSERT(!IsUnused());
112 return IsBound() ? -position_ - kWordSize : position_ - kWordSize; 112 return IsBound() ? -position_ - kWordSize : position_ - kWordSize;
113 } 113 }
114 114
115 bool IsBound() const { return position_ < 0; } 115 bool IsBound() const { return position_ < 0; }
116 bool IsUnused() const { return position_ == 0; } 116 bool IsUnused() const { return position_ == 0; }
117 bool IsLinked() const { return position_ > 0; } 117 bool IsLinked() const { return position_ > 0; }
118 118
119 private: 119 private:
120 intptr_t position_; 120 intptr_t position_;
121 121
122 void Reinitialize() { 122 void Reinitialize() { position_ = 0; }
123 position_ = 0;
124 }
125 123
126 void BindTo(intptr_t position) { 124 void BindTo(intptr_t position) {
127 ASSERT(!IsBound()); 125 ASSERT(!IsBound());
128 position_ = -position - kWordSize; 126 position_ = -position - kWordSize;
129 ASSERT(IsBound()); 127 ASSERT(IsBound());
130 } 128 }
131 129
132 void LinkTo(intptr_t position) { 130 void LinkTo(intptr_t position) {
133 ASSERT(!IsBound()); 131 ASSERT(!IsBound());
134 position_ = position + kWordSize; 132 position_ = position + kWordSize;
(...skipping 18 matching lines...) Expand all
153 kRightPos = kLeftPos + kLeftSize, 151 kRightPos = kLeftPos + kLeftSize,
154 kRightSize = 6, 152 kRightSize = 6,
155 kRelOpPos = kRightPos + kRightSize, 153 kRelOpPos = kRightPos + kRightSize,
156 kRelOpSize = 4, 154 kRelOpSize = 4,
157 kImmPos = kRelOpPos + kRelOpSize, 155 kImmPos = kRelOpPos + kRelOpSize,
158 kImmSize = 16, 156 kImmSize = 16,
159 }; 157 };
160 158
161 class LeftBits : public BitField<uword, Register, kLeftPos, kLeftSize> {}; 159 class LeftBits : public BitField<uword, Register, kLeftPos, kLeftSize> {};
162 class RightBits : public BitField<uword, Register, kRightPos, kRightSize> {}; 160 class RightBits : public BitField<uword, Register, kRightPos, kRightSize> {};
163 class RelOpBits : 161 class RelOpBits
164 public BitField<uword, RelationOperator, kRelOpPos, kRelOpSize> {}; 162 : public BitField<uword, RelationOperator, kRelOpPos, kRelOpSize> {};
165 class ImmBits : public BitField<uword, uint16_t, kImmPos, kImmSize> {}; 163 class ImmBits : public BitField<uword, uint16_t, kImmPos, kImmSize> {};
166 164
167 Register left() const { return LeftBits::decode(bits_); } 165 Register left() const { return LeftBits::decode(bits_); }
168 Register right() const { return RightBits::decode(bits_); } 166 Register right() const { return RightBits::decode(bits_); }
169 RelationOperator rel_op() const { return RelOpBits::decode(bits_); } 167 RelationOperator rel_op() const { return RelOpBits::decode(bits_); }
170 int16_t imm() const { return static_cast<int16_t>(ImmBits::decode(bits_)); } 168 int16_t imm() const { return static_cast<int16_t>(ImmBits::decode(bits_)); }
171 169
172 static bool IsValidImm(int32_t value) { 170 static bool IsValidImm(int32_t value) {
173 // We want both value and value + 1 to fit in an int16_t. 171 // We want both value and value + 1 to fit in an int16_t.
174 return (-0x08000 <= value) && (value < 0x7fff); 172 return (-0x08000 <= value) && (value < 0x7fff);
175 } 173 }
176 174
177 void set_rel_op(RelationOperator value) { 175 void set_rel_op(RelationOperator value) {
178 ASSERT(IsValidRelOp(value)); 176 ASSERT(IsValidRelOp(value));
179 bits_ = RelOpBits::update(value, bits_); 177 bits_ = RelOpBits::update(value, bits_);
180 } 178 }
181 179
182 // Uninitialized condition. 180 // Uninitialized condition.
183 Condition() : ValueObject(), bits_(0) { } 181 Condition() : ValueObject(), bits_(0) {}
184 182
185 // Copy constructor. 183 // Copy constructor.
186 Condition(const Condition& other) : ValueObject(), bits_(other.bits_) { } 184 Condition(const Condition& other) : ValueObject(), bits_(other.bits_) {}
187 185
188 // Copy assignment operator. 186 // Copy assignment operator.
189 Condition& operator=(const Condition& other) { 187 Condition& operator=(const Condition& other) {
190 bits_ = other.bits_; 188 bits_ = other.bits_;
191 return *this; 189 return *this;
192 } 190 }
193 191
194 Condition(Register left, 192 Condition(Register left,
195 Register right, 193 Register right,
196 RelationOperator rel_op, 194 RelationOperator rel_op,
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 class Assembler : public ValueObject { 235 class Assembler : public ValueObject {
238 public: 236 public:
239 explicit Assembler(bool use_far_branches = false) 237 explicit Assembler(bool use_far_branches = false)
240 : buffer_(), 238 : buffer_(),
241 prologue_offset_(-1), 239 prologue_offset_(-1),
242 has_single_entry_point_(true), 240 has_single_entry_point_(true),
243 use_far_branches_(use_far_branches), 241 use_far_branches_(use_far_branches),
244 delay_slot_available_(false), 242 delay_slot_available_(false),
245 in_delay_slot_(false), 243 in_delay_slot_(false),
246 comments_(), 244 comments_(),
247 constant_pool_allowed_(true) { 245 constant_pool_allowed_(true) {}
248 } 246 ~Assembler() {}
249 ~Assembler() { }
250 247
251 void PopRegister(Register r) { Pop(r); } 248 void PopRegister(Register r) { Pop(r); }
252 249
253 void Bind(Label* label); 250 void Bind(Label* label);
254 void Jump(Label* label) { b(label); } 251 void Jump(Label* label) { b(label); }
255 252
256 // Misc. functionality 253 // Misc. functionality
257 intptr_t CodeSize() const { return buffer_.Size(); } 254 intptr_t CodeSize() const { return buffer_.Size(); }
258 intptr_t prologue_offset() const { return prologue_offset_; } 255 intptr_t prologue_offset() const { return prologue_offset_; }
259 bool has_single_entry_point() const { return has_single_entry_point_; } 256 bool has_single_entry_point() const { return has_single_entry_point_; }
260 257
261 // Count the fixups that produce a pointer offset, without processing 258 // Count the fixups that produce a pointer offset, without processing
262 // the fixups. 259 // the fixups.
263 intptr_t CountPointerOffsets() const { 260 intptr_t CountPointerOffsets() const { return buffer_.CountPointerOffsets(); }
264 return buffer_.CountPointerOffsets();
265 }
266 261
267 const ZoneGrowableArray<intptr_t>& GetPointerOffsets() const { 262 const ZoneGrowableArray<intptr_t>& GetPointerOffsets() const {
268 return buffer_.pointer_offsets(); 263 return buffer_.pointer_offsets();
269 } 264 }
270 265
271 ObjectPoolWrapper& object_pool_wrapper() { return object_pool_wrapper_; } 266 ObjectPoolWrapper& object_pool_wrapper() { return object_pool_wrapper_; }
272 267
273 RawObjectPool* MakeObjectPool() { 268 RawObjectPool* MakeObjectPool() {
274 return object_pool_wrapper_.MakeObjectPool(); 269 return object_pool_wrapper_.MakeObjectPool();
275 } 270 }
276 271
277 void FinalizeInstructions(const MemoryRegion& region) { 272 void FinalizeInstructions(const MemoryRegion& region) {
278 buffer_.FinalizeInstructions(region); 273 buffer_.FinalizeInstructions(region);
279 } 274 }
280 275
281 bool use_far_branches() const { 276 bool use_far_branches() const {
282 return FLAG_use_far_branches || use_far_branches_; 277 return FLAG_use_far_branches || use_far_branches_;
283 } 278 }
284 279
285 void set_use_far_branches(bool b) { 280 void set_use_far_branches(bool b) { use_far_branches_ = b; }
286 use_far_branches_ = b;
287 }
288 281
289 void EnterFrame(); 282 void EnterFrame();
290 void LeaveFrameAndReturn(); 283 void LeaveFrameAndReturn();
291 284
292 // Set up a stub frame so that the stack traversal code can easily identify 285 // Set up a stub frame so that the stack traversal code can easily identify
293 // a stub frame. 286 // a stub frame.
294 void EnterStubFrame(intptr_t frame_size = 0); 287 void EnterStubFrame(intptr_t frame_size = 0);
295 void LeaveStubFrame(); 288 void LeaveStubFrame();
296 // A separate macro for when a Ret immediately follows, so that we can use 289 // A separate macro for when a Ret immediately follows, so that we can use
297 // the branch delay slot. 290 // the branch delay slot.
298 void LeaveStubFrameAndReturn(Register ra = RA); 291 void LeaveStubFrameAndReturn(Register ra = RA);
299 292
300 void MonomorphicCheckedEntry(); 293 void MonomorphicCheckedEntry();
301 294
302 void UpdateAllocationStats(intptr_t cid, 295 void UpdateAllocationStats(intptr_t cid,
303 Register temp_reg, 296 Register temp_reg,
304 Heap::Space space); 297 Heap::Space space);
305 298
306 void UpdateAllocationStatsWithSize(intptr_t cid, 299 void UpdateAllocationStatsWithSize(intptr_t cid,
307 Register size_reg, 300 Register size_reg,
308 Register temp_reg, 301 Register temp_reg,
309 Heap::Space space); 302 Heap::Space space);
310 303
311 304
312 void MaybeTraceAllocation(intptr_t cid, 305 void MaybeTraceAllocation(intptr_t cid, Register temp_reg, Label* trace);
313 Register temp_reg,
314 Label* trace);
315 306
316 // Inlined allocation of an instance of class 'cls', code has no runtime 307 // Inlined allocation of an instance of class 'cls', code has no runtime
317 // calls. Jump to 'failure' if the instance cannot be allocated here. 308 // calls. Jump to 'failure' if the instance cannot be allocated here.
318 // Allocated instance is returned in 'instance_reg'. 309 // Allocated instance is returned in 'instance_reg'.
319 // Only the tags field of the object is initialized. 310 // Only the tags field of the object is initialized.
320 void TryAllocate(const Class& cls, 311 void TryAllocate(const Class& cls,
321 Label* failure, 312 Label* failure,
322 Register instance_reg, 313 Register instance_reg,
323 Register temp_reg); 314 Register temp_reg);
324 315
(...skipping 25 matching lines...) Expand all
350 void SetPrologueOffset() { 341 void SetPrologueOffset() {
351 if (prologue_offset_ == -1) { 342 if (prologue_offset_ == -1) {
352 prologue_offset_ = CodeSize(); 343 prologue_offset_ = CodeSize();
353 } 344 }
354 } 345 }
355 346
356 // A utility to be able to assemble an instruction into the delay slot. 347 // A utility to be able to assemble an instruction into the delay slot.
357 Assembler* delay_slot() { 348 Assembler* delay_slot() {
358 ASSERT(delay_slot_available_); 349 ASSERT(delay_slot_available_);
359 ASSERT(buffer_.Load<int32_t>(buffer_.GetPosition() - sizeof(int32_t)) == 350 ASSERT(buffer_.Load<int32_t>(buffer_.GetPosition() - sizeof(int32_t)) ==
360 Instr::kNopInstruction); 351 Instr::kNopInstruction);
361 buffer_.Remit<int32_t>(); 352 buffer_.Remit<int32_t>();
362 delay_slot_available_ = false; 353 delay_slot_available_ = false;
363 in_delay_slot_ = true; 354 in_delay_slot_ = true;
364 return this; 355 return this;
365 } 356 }
366 357
367 // CPU instructions in alphabetical order. 358 // CPU instructions in alphabetical order.
368 void addd(DRegister dd, DRegister ds, DRegister dt) { 359 void addd(DRegister dd, DRegister ds, DRegister dt) {
369 // DRegisters start at the even FRegisters. 360 // DRegisters start at the even FRegisters.
370 FRegister fd = static_cast<FRegister>(dd * 2); 361 FRegister fd = static_cast<FRegister>(dd * 2);
(...skipping 16 matching lines...) Expand all
387 EmitRType(SPECIAL, rs, rt, rd, 0, AND); 378 EmitRType(SPECIAL, rs, rt, rd, 0, AND);
388 } 379 }
389 380
390 void andi(Register rt, Register rs, const Immediate& imm) { 381 void andi(Register rt, Register rs, const Immediate& imm) {
391 ASSERT(Utils::IsUint(kImmBits, imm.value())); 382 ASSERT(Utils::IsUint(kImmBits, imm.value()));
392 const uint16_t imm_value = static_cast<uint16_t>(imm.value()); 383 const uint16_t imm_value = static_cast<uint16_t>(imm.value());
393 EmitIType(ANDI, rs, rt, imm_value); 384 EmitIType(ANDI, rs, rt, imm_value);
394 } 385 }
395 386
396 // Unconditional branch. 387 // Unconditional branch.
397 void b(Label* l) { 388 void b(Label* l) { beq(R0, R0, l); }
398 beq(R0, R0, l);
399 }
400 389
401 void bal(Label *l) { 390 void bal(Label* l) {
402 ASSERT(!in_delay_slot_); 391 ASSERT(!in_delay_slot_);
403 EmitRegImmBranch(BGEZAL, R0, l); 392 EmitRegImmBranch(BGEZAL, R0, l);
404 EmitBranchDelayNop(); 393 EmitBranchDelayNop();
405 } 394 }
406 395
407 // Branch on floating point false. 396 // Branch on floating point false.
408 void bc1f(Label* l) { 397 void bc1f(Label* l) {
409 EmitFpuBranch(false, l); 398 EmitFpuBranch(false, l);
410 EmitBranchDelayNop(); 399 EmitBranchDelayNop();
411 } 400 }
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
501 // Branch if not equal, likely taken. 490 // Branch if not equal, likely taken.
502 // Delay slot executed only when branch taken. 491 // Delay slot executed only when branch taken.
503 void bnel(Register rs, Register rt, Label* l) { 492 void bnel(Register rs, Register rt, Label* l) {
504 ASSERT(!in_delay_slot_); // Jump within a delay slot is not supported. 493 ASSERT(!in_delay_slot_); // Jump within a delay slot is not supported.
505 EmitBranch(BNEL, rs, rt, l); 494 EmitBranch(BNEL, rs, rt, l);
506 EmitBranchDelayNop(); 495 EmitBranchDelayNop();
507 } 496 }
508 497
509 static int32_t BreakEncoding(int32_t code) { 498 static int32_t BreakEncoding(int32_t code) {
510 ASSERT(Utils::IsUint(20, code)); 499 ASSERT(Utils::IsUint(20, code));
511 return SPECIAL << kOpcodeShift | 500 return SPECIAL << kOpcodeShift | code << kBreakCodeShift |
512 code << kBreakCodeShift |
513 BREAK << kFunctionShift; 501 BREAK << kFunctionShift;
514 } 502 }
515 503
516 504
517 void break_(int32_t code) { 505 void break_(int32_t code) { Emit(BreakEncoding(code)); }
518 Emit(BreakEncoding(code));
519 }
520 506
521 static uword GetBreakInstructionFiller() { 507 static uword GetBreakInstructionFiller() { return BreakEncoding(0); }
522 return BreakEncoding(0);
523 }
524 508
525 // FPU compare, always false. 509 // FPU compare, always false.
526 void cfd(DRegister ds, DRegister dt) { 510 void cfd(DRegister ds, DRegister dt) {
527 FRegister fs = static_cast<FRegister>(ds * 2); 511 FRegister fs = static_cast<FRegister>(ds * 2);
528 FRegister ft = static_cast<FRegister>(dt * 2); 512 FRegister ft = static_cast<FRegister>(dt * 2);
529 EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_F); 513 EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_F);
530 } 514 }
531 515
532 // FPU compare, true if unordered, i.e. one is NaN. 516 // FPU compare, true if unordered, i.e. one is NaN.
533 void cund(DRegister ds, DRegister dt) { 517 void cund(DRegister ds, DRegister dt) {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
603 FRegister fd = static_cast<FRegister>(dd * 2); 587 FRegister fd = static_cast<FRegister>(dd * 2);
604 EmitFpuRType(COP1, FMT_W, F0, fs, fd, COP1_CVT_D); 588 EmitFpuRType(COP1, FMT_W, F0, fs, fd, COP1_CVT_D);
605 } 589 }
606 590
607 // Convert a 64-bit double in ds to a 32-bit float in fd. 591 // Convert a 64-bit double in ds to a 32-bit float in fd.
608 void cvtsd(FRegister fd, DRegister ds) { 592 void cvtsd(FRegister fd, DRegister ds) {
609 FRegister fs = static_cast<FRegister>(ds * 2); 593 FRegister fs = static_cast<FRegister>(ds * 2);
610 EmitFpuRType(COP1, FMT_D, F0, fs, fd, COP1_CVT_S); 594 EmitFpuRType(COP1, FMT_D, F0, fs, fd, COP1_CVT_S);
611 } 595 }
612 596
613 void div(Register rs, Register rt) { 597 void div(Register rs, Register rt) { EmitRType(SPECIAL, rs, rt, R0, 0, DIV); }
614 EmitRType(SPECIAL, rs, rt, R0, 0, DIV);
615 }
616 598
617 void divd(DRegister dd, DRegister ds, DRegister dt) { 599 void divd(DRegister dd, DRegister ds, DRegister dt) {
618 FRegister fd = static_cast<FRegister>(dd * 2); 600 FRegister fd = static_cast<FRegister>(dd * 2);
619 FRegister fs = static_cast<FRegister>(ds * 2); 601 FRegister fs = static_cast<FRegister>(ds * 2);
620 FRegister ft = static_cast<FRegister>(dt * 2); 602 FRegister ft = static_cast<FRegister>(dt * 2);
621 EmitFpuRType(COP1, FMT_D, ft, fs, fd, COP1_DIV); 603 EmitFpuRType(COP1, FMT_D, ft, fs, fd, COP1_DIV);
622 } 604 }
623 605
624 void divu(Register rs, Register rt) { 606 void divu(Register rs, Register rt) {
625 EmitRType(SPECIAL, rs, rt, R0, 0, DIVU); 607 EmitRType(SPECIAL, rs, rt, R0, 0, DIVU);
626 } 608 }
627 609
628 void jalr(Register rs, Register rd = RA) { 610 void jalr(Register rs, Register rd = RA) {
629 ASSERT(rs != rd); 611 ASSERT(rs != rd);
630 ASSERT(!in_delay_slot_); // Jump within a delay slot is not supported. 612 ASSERT(!in_delay_slot_); // Jump within a delay slot is not supported.
631 EmitRType(SPECIAL, rs, R0, rd, 0, JALR); 613 EmitRType(SPECIAL, rs, R0, rd, 0, JALR);
632 EmitBranchDelayNop(); 614 EmitBranchDelayNop();
633 } 615 }
634 616
635 void jr(Register rs) { 617 void jr(Register rs) {
636 ASSERT(!in_delay_slot_); // Jump within a delay slot is not supported. 618 ASSERT(!in_delay_slot_); // Jump within a delay slot is not supported.
637 EmitRType(SPECIAL, rs, R0, R0, 0, JR); 619 EmitRType(SPECIAL, rs, R0, R0, 0, JR);
638 EmitBranchDelayNop(); 620 EmitBranchDelayNop();
639 } 621 }
640 622
641 void lb(Register rt, const Address& addr) { 623 void lb(Register rt, const Address& addr) { EmitLoadStore(LB, rt, addr); }
642 EmitLoadStore(LB, rt, addr);
643 }
644 624
645 void lbu(Register rt, const Address& addr) { 625 void lbu(Register rt, const Address& addr) { EmitLoadStore(LBU, rt, addr); }
646 EmitLoadStore(LBU, rt, addr);
647 }
648 626
649 void ldc1(DRegister dt, const Address& addr) { 627 void ldc1(DRegister dt, const Address& addr) {
650 FRegister ft = static_cast<FRegister>(dt * 2); 628 FRegister ft = static_cast<FRegister>(dt * 2);
651 EmitFpuLoadStore(LDC1, ft, addr); 629 EmitFpuLoadStore(LDC1, ft, addr);
652 } 630 }
653 631
654 void lh(Register rt, const Address& addr) { 632 void lh(Register rt, const Address& addr) { EmitLoadStore(LH, rt, addr); }
655 EmitLoadStore(LH, rt, addr);
656 }
657 633
658 void lhu(Register rt, const Address& addr) { 634 void lhu(Register rt, const Address& addr) { EmitLoadStore(LHU, rt, addr); }
659 EmitLoadStore(LHU, rt, addr);
660 }
661 635
662 void ll(Register rt, const Address& addr) { 636 void ll(Register rt, const Address& addr) { EmitLoadStore(LL, rt, addr); }
663 EmitLoadStore(LL, rt, addr);
664 }
665 637
666 void lui(Register rt, const Immediate& imm) { 638 void lui(Register rt, const Immediate& imm) {
667 ASSERT(Utils::IsUint(kImmBits, imm.value())); 639 ASSERT(Utils::IsUint(kImmBits, imm.value()));
668 const uint16_t imm_value = static_cast<uint16_t>(imm.value()); 640 const uint16_t imm_value = static_cast<uint16_t>(imm.value());
669 EmitIType(LUI, R0, rt, imm_value); 641 EmitIType(LUI, R0, rt, imm_value);
670 } 642 }
671 643
672 void lw(Register rt, const Address& addr) { 644 void lw(Register rt, const Address& addr) { EmitLoadStore(LW, rt, addr); }
673 EmitLoadStore(LW, rt, addr);
674 }
675 645
676 void lwc1(FRegister ft, const Address& addr) { 646 void lwc1(FRegister ft, const Address& addr) {
677 EmitFpuLoadStore(LWC1, ft, addr); 647 EmitFpuLoadStore(LWC1, ft, addr);
678 } 648 }
679 649
680 void madd(Register rs, Register rt) { 650 void madd(Register rs, Register rt) {
681 EmitRType(SPECIAL2, rs, rt, R0, 0, MADD); 651 EmitRType(SPECIAL2, rs, rt, R0, 0, MADD);
682 } 652 }
683 653
684 void maddu(Register rs, Register rt) { 654 void maddu(Register rs, Register rt) {
685 EmitRType(SPECIAL2, rs, rt, R0, 0, MADDU); 655 EmitRType(SPECIAL2, rs, rt, R0, 0, MADDU);
686 } 656 }
687 657
688 void mfc1(Register rt, FRegister fs) { 658 void mfc1(Register rt, FRegister fs) {
689 Emit(COP1 << kOpcodeShift | 659 Emit(COP1 << kOpcodeShift | COP1_MF << kCop1SubShift | rt << kRtShift |
690 COP1_MF << kCop1SubShift |
691 rt << kRtShift |
692 fs << kFsShift); 660 fs << kFsShift);
693 } 661 }
694 662
695 void mfhi(Register rd) { 663 void mfhi(Register rd) { EmitRType(SPECIAL, R0, R0, rd, 0, MFHI); }
696 EmitRType(SPECIAL, R0, R0, rd, 0, MFHI);
697 }
698 664
699 void mflo(Register rd) { 665 void mflo(Register rd) { EmitRType(SPECIAL, R0, R0, rd, 0, MFLO); }
700 EmitRType(SPECIAL, R0, R0, rd, 0, MFLO);
701 }
702 666
703 void mov(Register rd, Register rs) { 667 void mov(Register rd, Register rs) { or_(rd, rs, ZR); }
704 or_(rd, rs, ZR);
705 }
706 668
707 void movd(DRegister dd, DRegister ds) { 669 void movd(DRegister dd, DRegister ds) {
708 FRegister fd = static_cast<FRegister>(dd * 2); 670 FRegister fd = static_cast<FRegister>(dd * 2);
709 FRegister fs = static_cast<FRegister>(ds * 2); 671 FRegister fs = static_cast<FRegister>(ds * 2);
710 EmitFpuRType(COP1, FMT_D, F0, fs, fd, COP1_MOV); 672 EmitFpuRType(COP1, FMT_D, F0, fs, fd, COP1_MOV);
711 } 673 }
712 674
713 // Move if floating point false. 675 // Move if floating point false.
714 void movf(Register rd, Register rs) { 676 void movf(Register rd, Register rs) {
715 EmitRType(SPECIAL, rs, R0, rd, 0, MOVCI); 677 EmitRType(SPECIAL, rs, R0, rd, 0, MOVCI);
(...skipping 11 matching lines...) Expand all
727 // rd <- (rt == 0) ? rs : rd; 689 // rd <- (rt == 0) ? rs : rd;
728 void movz(Register rd, Register rs, Register rt) { 690 void movz(Register rd, Register rs, Register rt) {
729 EmitRType(SPECIAL, rs, rt, rd, 0, MOVZ); 691 EmitRType(SPECIAL, rs, rt, rd, 0, MOVZ);
730 } 692 }
731 693
732 void movs(FRegister fd, FRegister fs) { 694 void movs(FRegister fd, FRegister fs) {
733 EmitFpuRType(COP1, FMT_S, F0, fs, fd, COP1_MOV); 695 EmitFpuRType(COP1, FMT_S, F0, fs, fd, COP1_MOV);
734 } 696 }
735 697
736 void mtc1(Register rt, FRegister fs) { 698 void mtc1(Register rt, FRegister fs) {
737 Emit(COP1 << kOpcodeShift | 699 Emit(COP1 << kOpcodeShift | COP1_MT << kCop1SubShift | rt << kRtShift |
738 COP1_MT << kCop1SubShift |
739 rt << kRtShift |
740 fs << kFsShift); 700 fs << kFsShift);
741 } 701 }
742 702
743 void mthi(Register rs) { 703 void mthi(Register rs) { EmitRType(SPECIAL, rs, R0, R0, 0, MTHI); }
744 EmitRType(SPECIAL, rs, R0, R0, 0, MTHI);
745 }
746 704
747 void mtlo(Register rs) { 705 void mtlo(Register rs) { EmitRType(SPECIAL, rs, R0, R0, 0, MTLO); }
748 EmitRType(SPECIAL, rs, R0, R0, 0, MTLO);
749 }
750 706
751 void muld(DRegister dd, DRegister ds, DRegister dt) { 707 void muld(DRegister dd, DRegister ds, DRegister dt) {
752 FRegister fd = static_cast<FRegister>(dd * 2); 708 FRegister fd = static_cast<FRegister>(dd * 2);
753 FRegister fs = static_cast<FRegister>(ds * 2); 709 FRegister fs = static_cast<FRegister>(ds * 2);
754 FRegister ft = static_cast<FRegister>(dt * 2); 710 FRegister ft = static_cast<FRegister>(dt * 2);
755 EmitFpuRType(COP1, FMT_D, ft, fs, fd, COP1_MUL); 711 EmitFpuRType(COP1, FMT_D, ft, fs, fd, COP1_MUL);
756 } 712 }
757 713
758 void mult(Register rs, Register rt) { 714 void mult(Register rs, Register rt) {
759 EmitRType(SPECIAL, rs, rt, R0, 0, MULT); 715 EmitRType(SPECIAL, rs, rt, R0, 0, MULT);
760 } 716 }
761 717
762 void multu(Register rs, Register rt) { 718 void multu(Register rs, Register rt) {
763 EmitRType(SPECIAL, rs, rt, R0, 0, MULTU); 719 EmitRType(SPECIAL, rs, rt, R0, 0, MULTU);
764 } 720 }
765 721
766 void negd(DRegister dd, DRegister ds) { 722 void negd(DRegister dd, DRegister ds) {
767 FRegister fd = static_cast<FRegister>(dd * 2); 723 FRegister fd = static_cast<FRegister>(dd * 2);
768 FRegister fs = static_cast<FRegister>(ds * 2); 724 FRegister fs = static_cast<FRegister>(ds * 2);
769 EmitFpuRType(COP1, FMT_D, F0, fs, fd, COP1_NEG); 725 EmitFpuRType(COP1, FMT_D, F0, fs, fd, COP1_NEG);
770 } 726 }
771 727
772 void nop() { 728 void nop() { Emit(Instr::kNopInstruction); }
773 Emit(Instr::kNopInstruction);
774 }
775 729
776 void nor(Register rd, Register rs, Register rt) { 730 void nor(Register rd, Register rs, Register rt) {
777 EmitRType(SPECIAL, rs, rt, rd, 0, NOR); 731 EmitRType(SPECIAL, rs, rt, rd, 0, NOR);
778 } 732 }
779 733
780 void or_(Register rd, Register rs, Register rt) { 734 void or_(Register rd, Register rs, Register rt) {
781 EmitRType(SPECIAL, rs, rt, rd, 0, OR); 735 EmitRType(SPECIAL, rs, rt, rd, 0, OR);
782 } 736 }
783 737
784 void ori(Register rt, Register rs, const Immediate& imm) { 738 void ori(Register rt, Register rs, const Immediate& imm) {
785 ASSERT(Utils::IsUint(kImmBits, imm.value())); 739 ASSERT(Utils::IsUint(kImmBits, imm.value()));
786 const uint16_t imm_value = static_cast<uint16_t>(imm.value()); 740 const uint16_t imm_value = static_cast<uint16_t>(imm.value());
787 EmitIType(ORI, rs, rt, imm_value); 741 EmitIType(ORI, rs, rt, imm_value);
788 } 742 }
789 743
790 void sb(Register rt, const Address& addr) { 744 void sb(Register rt, const Address& addr) { EmitLoadStore(SB, rt, addr); }
791 EmitLoadStore(SB, rt, addr);
792 }
793 745
794 // rt = 1 on success, 0 on failure. 746 // rt = 1 on success, 0 on failure.
795 void sc(Register rt, const Address& addr) { 747 void sc(Register rt, const Address& addr) { EmitLoadStore(SC, rt, addr); }
796 EmitLoadStore(SC, rt, addr);
797 }
798 748
799 void sdc1(DRegister dt, const Address& addr) { 749 void sdc1(DRegister dt, const Address& addr) {
800 FRegister ft = static_cast<FRegister>(dt * 2); 750 FRegister ft = static_cast<FRegister>(dt * 2);
801 EmitFpuLoadStore(SDC1, ft, addr); 751 EmitFpuLoadStore(SDC1, ft, addr);
802 } 752 }
803 753
804 void sh(Register rt, const Address& addr) { 754 void sh(Register rt, const Address& addr) { EmitLoadStore(SH, rt, addr); }
805 EmitLoadStore(SH, rt, addr);
806 }
807 755
808 void sll(Register rd, Register rt, int sa) { 756 void sll(Register rd, Register rt, int sa) {
809 EmitRType(SPECIAL, R0, rt, rd, sa, SLL); 757 EmitRType(SPECIAL, R0, rt, rd, sa, SLL);
810 } 758 }
811 759
812 void sllv(Register rd, Register rt, Register rs) { 760 void sllv(Register rd, Register rt, Register rs) {
813 EmitRType(SPECIAL, rs, rt, rd, 0, SLLV); 761 EmitRType(SPECIAL, rs, rt, rd, 0, SLLV);
814 } 762 }
815 763
816 void slt(Register rd, Register rs, Register rt) { 764 void slt(Register rd, Register rs, Register rt) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
862 FRegister fd = static_cast<FRegister>(dd * 2); 810 FRegister fd = static_cast<FRegister>(dd * 2);
863 FRegister fs = static_cast<FRegister>(ds * 2); 811 FRegister fs = static_cast<FRegister>(ds * 2);
864 FRegister ft = static_cast<FRegister>(dt * 2); 812 FRegister ft = static_cast<FRegister>(dt * 2);
865 EmitFpuRType(COP1, FMT_D, ft, fs, fd, COP1_SUB); 813 EmitFpuRType(COP1, FMT_D, ft, fs, fd, COP1_SUB);
866 } 814 }
867 815
868 void subu(Register rd, Register rs, Register rt) { 816 void subu(Register rd, Register rs, Register rt) {
869 EmitRType(SPECIAL, rs, rt, rd, 0, SUBU); 817 EmitRType(SPECIAL, rs, rt, rd, 0, SUBU);
870 } 818 }
871 819
872 void sw(Register rt, const Address& addr) { 820 void sw(Register rt, const Address& addr) { EmitLoadStore(SW, rt, addr); }
873 EmitLoadStore(SW, rt, addr);
874 }
875 821
876 void swc1(FRegister ft, const Address& addr) { 822 void swc1(FRegister ft, const Address& addr) {
877 EmitFpuLoadStore(SWC1, ft, addr); 823 EmitFpuLoadStore(SWC1, ft, addr);
878 } 824 }
879 825
880 void xori(Register rt, Register rs, const Immediate& imm) { 826 void xori(Register rt, Register rs, const Immediate& imm) {
881 ASSERT(Utils::IsUint(kImmBits, imm.value())); 827 ASSERT(Utils::IsUint(kImmBits, imm.value()));
882 const uint16_t imm_value = static_cast<uint16_t>(imm.value()); 828 const uint16_t imm_value = static_cast<uint16_t>(imm.value());
883 EmitIType(XORI, rs, rt, imm_value); 829 EmitIType(XORI, rs, rt, imm_value);
884 } 830 }
885 831
886 void xor_(Register rd, Register rs, Register rt) { 832 void xor_(Register rd, Register rs, Register rt) {
887 EmitRType(SPECIAL, rs, rt, rd, 0, XOR); 833 EmitRType(SPECIAL, rs, rt, rd, 0, XOR);
888 } 834 }
889 835
890 // Macros in alphabetical order. 836 // Macros in alphabetical order.
891 837
892 // Addition of rs and rt with the result placed in rd. 838 // Addition of rs and rt with the result placed in rd.
893 // After, ro < 0 if there was signed overflow, ro >= 0 otherwise. 839 // After, ro < 0 if there was signed overflow, ro >= 0 otherwise.
894 // rd and ro must not be TMP. 840 // rd and ro must not be TMP.
895 // ro must be different from all the other registers. 841 // ro must be different from all the other registers.
896 // If rd, rs, and rt are the same register, then a scratch register different 842 // If rd, rs, and rt are the same register, then a scratch register different
897 // from the other registers is needed. 843 // from the other registers is needed.
898 void AdduDetectOverflow(Register rd, Register rs, Register rt, Register ro, 844 void AdduDetectOverflow(Register rd,
845 Register rs,
846 Register rt,
847 Register ro,
899 Register scratch = kNoRegister); 848 Register scratch = kNoRegister);
900 849
901 // ro must be different from rd and rs. 850 // ro must be different from rd and rs.
902 // rd and ro must not be TMP. 851 // rd and ro must not be TMP.
903 // If rd and rs are the same, a scratch register different from the other 852 // If rd and rs are the same, a scratch register different from the other
904 // registers is needed. 853 // registers is needed.
905 void AddImmediateDetectOverflow(Register rd, Register rs, int32_t imm, 854 void AddImmediateDetectOverflow(Register rd,
906 Register ro, Register scratch = kNoRegister) { 855 Register rs,
856 int32_t imm,
857 Register ro,
858 Register scratch = kNoRegister) {
907 ASSERT(!in_delay_slot_); 859 ASSERT(!in_delay_slot_);
908 LoadImmediate(rd, imm); 860 LoadImmediate(rd, imm);
909 AdduDetectOverflow(rd, rs, rd, ro, scratch); 861 AdduDetectOverflow(rd, rs, rd, ro, scratch);
910 } 862 }
911 863
912 // Subtraction of rt from rs (rs - rt) with the result placed in rd. 864 // Subtraction of rt from rs (rs - rt) with the result placed in rd.
913 // After, ro < 0 if there was signed overflow, ro >= 0 otherwise. 865 // After, ro < 0 if there was signed overflow, ro >= 0 otherwise.
914 // None of rd, rs, rt, or ro may be TMP. 866 // None of rd, rs, rt, or ro may be TMP.
915 // ro must be different from the other registers. 867 // ro must be different from the other registers.
916 void SubuDetectOverflow(Register rd, Register rs, Register rt, Register ro); 868 void SubuDetectOverflow(Register rd, Register rs, Register rt, Register ro);
917 869
918 // ro must be different from rd and rs. 870 // ro must be different from rd and rs.
919 // None of rd, rs, rt, or ro may be TMP. 871 // None of rd, rs, rt, or ro may be TMP.
920 void SubImmediateDetectOverflow(Register rd, Register rs, int32_t imm, 872 void SubImmediateDetectOverflow(Register rd,
873 Register rs,
874 int32_t imm,
921 Register ro) { 875 Register ro) {
922 ASSERT(!in_delay_slot_); 876 ASSERT(!in_delay_slot_);
923 LoadImmediate(rd, imm); 877 LoadImmediate(rd, imm);
924 SubuDetectOverflow(rd, rs, rd, ro); 878 SubuDetectOverflow(rd, rs, rd, ro);
925 } 879 }
926 880
927 void Branch(const StubEntry& stub_entry, Register pp = PP); 881 void Branch(const StubEntry& stub_entry, Register pp = PP);
928 882
929 void BranchLink(const StubEntry& stub_entry, 883 void BranchLink(const StubEntry& stub_entry,
930 Patchability patchable = kNotPatchable); 884 Patchability patchable = kNotPatchable);
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
1080 return rd; 1034 return rd;
1081 } 1035 }
1082 1036
1083 // Branch to label if condition is true. 1037 // Branch to label if condition is true.
1084 void BranchOnCondition(Condition cond, Label* l) { 1038 void BranchOnCondition(Condition cond, Label* l) {
1085 ASSERT(!in_delay_slot_); 1039 ASSERT(!in_delay_slot_);
1086 Register left = cond.left(); 1040 Register left = cond.left();
1087 Register right = cond.right(); 1041 Register right = cond.right();
1088 RelationOperator rel_op = cond.rel_op(); 1042 RelationOperator rel_op = cond.rel_op();
1089 switch (rel_op) { 1043 switch (rel_op) {
1090 case NV: return; 1044 case NV:
1091 case AL: b(l); return; 1045 return;
1046 case AL:
1047 b(l);
1048 return;
1092 case EQ: // fall through. 1049 case EQ: // fall through.
1093 case NE: { 1050 case NE: {
1094 if (left == IMM) { 1051 if (left == IMM) {
1095 addiu(AT, ZR, Immediate(cond.imm())); 1052 addiu(AT, ZR, Immediate(cond.imm()));
1096 left = AT; 1053 left = AT;
1097 } else if (right == IMM) { 1054 } else if (right == IMM) {
1098 addiu(AT, ZR, Immediate(cond.imm())); 1055 addiu(AT, ZR, Immediate(cond.imm()));
1099 right = AT; 1056 right = AT;
1100 } 1057 }
1101 if (rel_op == EQ) { 1058 if (rel_op == EQ) {
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
1221 sltu(AT, right, left); 1178 sltu(AT, right, left);
1222 beq(AT, ZR, l); 1179 beq(AT, ZR, l);
1223 } 1180 }
1224 break; 1181 break;
1225 } 1182 }
1226 default: 1183 default:
1227 UNREACHABLE(); 1184 UNREACHABLE();
1228 } 1185 }
1229 } 1186 }
1230 1187
1231 void BranchEqual(Register rd, Register rn, Label* l) { 1188 void BranchEqual(Register rd, Register rn, Label* l) { beq(rd, rn, l); }
1232 beq(rd, rn, l);
1233 }
1234 1189
1235 void BranchEqual(Register rd, const Immediate& imm, Label* l) { 1190 void BranchEqual(Register rd, const Immediate& imm, Label* l) {
1236 ASSERT(!in_delay_slot_); 1191 ASSERT(!in_delay_slot_);
1237 if (imm.value() == 0) { 1192 if (imm.value() == 0) {
1238 beq(rd, ZR, l); 1193 beq(rd, ZR, l);
1239 } else { 1194 } else {
1240 ASSERT(rd != CMPRES2); 1195 ASSERT(rd != CMPRES2);
1241 LoadImmediate(CMPRES2, imm.value()); 1196 LoadImmediate(CMPRES2, imm.value());
1242 beq(rd, CMPRES2, l); 1197 beq(rd, CMPRES2, l);
1243 } 1198 }
1244 } 1199 }
1245 1200
1246 void BranchEqual(Register rd, const Object& object, Label* l) { 1201 void BranchEqual(Register rd, const Object& object, Label* l) {
1247 ASSERT(!in_delay_slot_); 1202 ASSERT(!in_delay_slot_);
1248 ASSERT(rd != CMPRES2); 1203 ASSERT(rd != CMPRES2);
1249 LoadObject(CMPRES2, object); 1204 LoadObject(CMPRES2, object);
1250 beq(rd, CMPRES2, l); 1205 beq(rd, CMPRES2, l);
1251 } 1206 }
1252 1207
1253 void BranchNotEqual(Register rd, Register rn, Label* l) { 1208 void BranchNotEqual(Register rd, Register rn, Label* l) { bne(rd, rn, l); }
1254 bne(rd, rn, l);
1255 }
1256 1209
1257 void BranchNotEqual(Register rd, const Immediate& imm, Label* l) { 1210 void BranchNotEqual(Register rd, const Immediate& imm, Label* l) {
1258 ASSERT(!in_delay_slot_); 1211 ASSERT(!in_delay_slot_);
1259 if (imm.value() == 0) { 1212 if (imm.value() == 0) {
1260 bne(rd, ZR, l); 1213 bne(rd, ZR, l);
1261 } else { 1214 } else {
1262 ASSERT(rd != CMPRES2); 1215 ASSERT(rd != CMPRES2);
1263 LoadImmediate(CMPRES2, imm.value()); 1216 LoadImmediate(CMPRES2, imm.value());
1264 bne(rd, CMPRES2, l); 1217 bne(rd, CMPRES2, l);
1265 } 1218 }
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1312 ASSERT(rd != CMPRES2); 1265 ASSERT(rd != CMPRES2);
1313 LoadImmediate(CMPRES2, imm.value()); 1266 LoadImmediate(CMPRES2, imm.value());
1314 BranchUnsignedGreater(rd, CMPRES2, l); 1267 BranchUnsignedGreater(rd, CMPRES2, l);
1315 } 1268 }
1316 } 1269 }
1317 } 1270 }
1318 1271
1319 void BranchSignedGreaterEqual(Register rd, Register rs, Label* l) { 1272 void BranchSignedGreaterEqual(Register rd, Register rs, Label* l) {
1320 ASSERT(!in_delay_slot_); 1273 ASSERT(!in_delay_slot_);
1321 slt(CMPRES2, rd, rs); // CMPRES2 = rd < rs ? 1 : 0. 1274 slt(CMPRES2, rd, rs); // CMPRES2 = rd < rs ? 1 : 0.
1322 beq(CMPRES2, ZR, l); // If CMPRES2 = 0, then rd >= rs. 1275 beq(CMPRES2, ZR, l); // If CMPRES2 = 0, then rd >= rs.
1323 } 1276 }
1324 1277
1325 void BranchSignedGreaterEqual(Register rd, const Immediate& imm, Label* l) { 1278 void BranchSignedGreaterEqual(Register rd, const Immediate& imm, Label* l) {
1326 ASSERT(!in_delay_slot_); 1279 ASSERT(!in_delay_slot_);
1327 if (imm.value() == 0) { 1280 if (imm.value() == 0) {
1328 bgez(rd, l); 1281 bgez(rd, l);
1329 } else { 1282 } else {
1330 if (Utils::IsInt(kImmBits, imm.value())) { 1283 if (Utils::IsInt(kImmBits, imm.value())) {
1331 slti(CMPRES2, rd, imm); 1284 slti(CMPRES2, rd, imm);
1332 beq(CMPRES2, ZR, l); 1285 beq(CMPRES2, ZR, l);
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
1449 addiu(SP, SP, Immediate(-kWordSize)); 1402 addiu(SP, SP, Immediate(-kWordSize));
1450 sw(rt, Address(SP)); 1403 sw(rt, Address(SP));
1451 } 1404 }
1452 1405
1453 void Pop(Register rt) { 1406 void Pop(Register rt) {
1454 ASSERT(!in_delay_slot_); 1407 ASSERT(!in_delay_slot_);
1455 lw(rt, Address(SP)); 1408 lw(rt, Address(SP));
1456 addiu(SP, SP, Immediate(kWordSize)); 1409 addiu(SP, SP, Immediate(kWordSize));
1457 } 1410 }
1458 1411
1459 void Ret() { 1412 void Ret() { jr(RA); }
1460 jr(RA);
1461 }
1462 1413
1463 void SmiTag(Register reg) { 1414 void SmiTag(Register reg) { sll(reg, reg, kSmiTagSize); }
1464 sll(reg, reg, kSmiTagSize);
1465 }
1466 1415
1467 void SmiTag(Register dst, Register src) { 1416 void SmiTag(Register dst, Register src) { sll(dst, src, kSmiTagSize); }
1468 sll(dst, src, kSmiTagSize);
1469 }
1470 1417
1471 void SmiUntag(Register reg) { 1418 void SmiUntag(Register reg) { sra(reg, reg, kSmiTagSize); }
1472 sra(reg, reg, kSmiTagSize);
1473 }
1474 1419
1475 void SmiUntag(Register dst, Register src) { 1420 void SmiUntag(Register dst, Register src) { sra(dst, src, kSmiTagSize); }
1476 sra(dst, src, kSmiTagSize);
1477 }
1478 1421
1479 void BranchIfNotSmi(Register reg, Label* label) { 1422 void BranchIfNotSmi(Register reg, Label* label) {
1480 andi(CMPRES1, reg, Immediate(kSmiTagMask)); 1423 andi(CMPRES1, reg, Immediate(kSmiTagMask));
1481 bne(CMPRES1, ZR, label); 1424 bne(CMPRES1, ZR, label);
1482 } 1425 }
1483 1426
1484 void LoadFromOffset(Register reg, Register base, int32_t offset) { 1427 void LoadFromOffset(Register reg, Register base, int32_t offset) {
1485 ASSERT(!in_delay_slot_); 1428 ASSERT(!in_delay_slot_);
1486 if (Utils::IsInt(kImmBits, offset)) { 1429 if (Utils::IsInt(kImmBits, offset)) {
1487 lw(reg, Address(base, offset)); 1430 lw(reg, Address(base, offset));
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1551 void PushObject(const Object& object); 1494 void PushObject(const Object& object);
1552 1495
1553 void LoadIsolate(Register result); 1496 void LoadIsolate(Register result);
1554 1497
1555 void LoadClassId(Register result, Register object); 1498 void LoadClassId(Register result, Register object);
1556 void LoadClassById(Register result, Register class_id); 1499 void LoadClassById(Register result, Register class_id);
1557 void LoadClass(Register result, Register object); 1500 void LoadClass(Register result, Register object);
1558 void LoadClassIdMayBeSmi(Register result, Register object); 1501 void LoadClassIdMayBeSmi(Register result, Register object);
1559 void LoadTaggedClassIdMayBeSmi(Register result, Register object); 1502 void LoadTaggedClassIdMayBeSmi(Register result, Register object);
1560 1503
1561 void StoreIntoObject(Register object, // Object we are storing into. 1504 void StoreIntoObject(Register object, // Object we are storing into.
1562 const Address& dest, // Where we are storing into. 1505 const Address& dest, // Where we are storing into.
1563 Register value, // Value we are storing. 1506 Register value, // Value we are storing.
1564 bool can_value_be_smi = true); 1507 bool can_value_be_smi = true);
1565 void StoreIntoObjectOffset(Register object, 1508 void StoreIntoObjectOffset(Register object,
1566 int32_t offset, 1509 int32_t offset,
1567 Register value, 1510 Register value,
1568 bool can_value_be_smi = true); 1511 bool can_value_be_smi = true);
1569 1512
1570 void StoreIntoObjectNoBarrier(Register object, 1513 void StoreIntoObjectNoBarrier(Register object,
1571 const Address& dest, 1514 const Address& dest,
1572 Register value); 1515 Register value);
1573 void StoreIntoObjectNoBarrierOffset(Register object, 1516 void StoreIntoObjectNoBarrierOffset(Register object,
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1627 1570
1628 static Address VMTagAddress() { 1571 static Address VMTagAddress() {
1629 return Address(THR, Thread::vm_tag_offset()); 1572 return Address(THR, Thread::vm_tag_offset());
1630 } 1573 }
1631 1574
1632 // On some other platforms, we draw a distinction between safe and unsafe 1575 // On some other platforms, we draw a distinction between safe and unsafe
1633 // smis. 1576 // smis.
1634 static bool IsSafe(const Object& object) { return true; } 1577 static bool IsSafe(const Object& object) { return true; }
1635 static bool IsSafeSmi(const Object& object) { return object.IsSmi(); } 1578 static bool IsSafeSmi(const Object& object) { return object.IsSmi(); }
1636 1579
1637 bool constant_pool_allowed() const { 1580 bool constant_pool_allowed() const { return constant_pool_allowed_; }
1638 return constant_pool_allowed_; 1581 void set_constant_pool_allowed(bool b) { constant_pool_allowed_ = b; }
1639 }
1640 void set_constant_pool_allowed(bool b) {
1641 constant_pool_allowed_ = b;
1642 }
1643 1582
1644 private: 1583 private:
1645 AssemblerBuffer buffer_; 1584 AssemblerBuffer buffer_;
1646 ObjectPoolWrapper object_pool_wrapper_; 1585 ObjectPoolWrapper object_pool_wrapper_;
1647 1586
1648 intptr_t prologue_offset_; 1587 intptr_t prologue_offset_;
1649 bool has_single_entry_point_; 1588 bool has_single_entry_point_;
1650 bool use_far_branches_; 1589 bool use_far_branches_;
1651 bool delay_slot_available_; 1590 bool delay_slot_available_;
1652 bool in_delay_slot_; 1591 bool in_delay_slot_;
1653 1592
1654 class CodeComment : public ZoneAllocated { 1593 class CodeComment : public ZoneAllocated {
1655 public: 1594 public:
1656 CodeComment(intptr_t pc_offset, const String& comment) 1595 CodeComment(intptr_t pc_offset, const String& comment)
1657 : pc_offset_(pc_offset), comment_(comment) { } 1596 : pc_offset_(pc_offset), comment_(comment) {}
1658 1597
1659 intptr_t pc_offset() const { return pc_offset_; } 1598 intptr_t pc_offset() const { return pc_offset_; }
1660 const String& comment() const { return comment_; } 1599 const String& comment() const { return comment_; }
1661 1600
1662 private: 1601 private:
1663 intptr_t pc_offset_; 1602 intptr_t pc_offset_;
1664 const String& comment_; 1603 const String& comment_;
1665 1604
1666 DISALLOW_COPY_AND_ASSIGN(CodeComment); 1605 DISALLOW_COPY_AND_ASSIGN(CodeComment);
1667 }; 1606 };
(...skipping 13 matching lines...) Expand all
1681 void Emit(int32_t value) { 1620 void Emit(int32_t value) {
1682 // Emitting an instruction clears the delay slot state. 1621 // Emitting an instruction clears the delay slot state.
1683 in_delay_slot_ = false; 1622 in_delay_slot_ = false;
1684 delay_slot_available_ = false; 1623 delay_slot_available_ = false;
1685 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 1624 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1686 buffer_.Emit<int32_t>(value); 1625 buffer_.Emit<int32_t>(value);
1687 } 1626 }
1688 1627
1689 // Encode CPU instructions according to the types specified in 1628 // Encode CPU instructions according to the types specified in
1690 // Figures 4-1, 4-2 and 4-3 in VolI-A. 1629 // Figures 4-1, 4-2 and 4-3 in VolI-A.
1691 void EmitIType(Opcode opcode, 1630 void EmitIType(Opcode opcode, Register rs, Register rt, uint16_t imm) {
1692 Register rs, 1631 Emit(opcode << kOpcodeShift | rs << kRsShift | rt << kRtShift | imm);
1693 Register rt,
1694 uint16_t imm) {
1695 Emit(opcode << kOpcodeShift |
1696 rs << kRsShift |
1697 rt << kRtShift |
1698 imm);
1699 } 1632 }
1700 1633
1701 void EmitLoadStore(Opcode opcode, Register rt, 1634 void EmitLoadStore(Opcode opcode, Register rt, const Address& addr) {
1702 const Address &addr) { 1635 Emit(opcode << kOpcodeShift | rt << kRtShift | addr.encoding());
1703 Emit(opcode << kOpcodeShift |
1704 rt << kRtShift |
1705 addr.encoding());
1706 } 1636 }
1707 1637
1708 void EmitFpuLoadStore(Opcode opcode, FRegister ft, 1638 void EmitFpuLoadStore(Opcode opcode, FRegister ft, const Address& addr) {
1709 const Address &addr) { 1639 Emit(opcode << kOpcodeShift | ft << kFtShift | addr.encoding());
1710 Emit(opcode << kOpcodeShift |
1711 ft << kFtShift |
1712 addr.encoding());
1713 } 1640 }
1714 1641
1715 void EmitRegImmType(Opcode opcode, 1642 void EmitRegImmType(Opcode opcode, Register rs, RtRegImm code, uint16_t imm) {
1716 Register rs, 1643 Emit(opcode << kOpcodeShift | rs << kRsShift | code << kRtShift | imm);
1717 RtRegImm code,
1718 uint16_t imm) {
1719 Emit(opcode << kOpcodeShift |
1720 rs << kRsShift |
1721 code << kRtShift |
1722 imm);
1723 } 1644 }
1724 1645
1725 void EmitJType(Opcode opcode, uint32_t destination) { 1646 void EmitJType(Opcode opcode, uint32_t destination) { UNIMPLEMENTED(); }
1726 UNIMPLEMENTED();
1727 }
1728 1647
1729 void EmitRType(Opcode opcode, 1648 void EmitRType(Opcode opcode,
1730 Register rs, 1649 Register rs,
1731 Register rt, 1650 Register rt,
1732 Register rd, 1651 Register rd,
1733 int sa, 1652 int sa,
1734 SpecialFunction func) { 1653 SpecialFunction func) {
1735 ASSERT(Utils::IsUint(5, sa)); 1654 ASSERT(Utils::IsUint(5, sa));
1736 Emit(opcode << kOpcodeShift | 1655 Emit(opcode << kOpcodeShift | rs << kRsShift | rt << kRtShift |
1737 rs << kRsShift | 1656 rd << kRdShift | sa << kSaShift | func << kFunctionShift);
1738 rt << kRtShift |
1739 rd << kRdShift |
1740 sa << kSaShift |
1741 func << kFunctionShift);
1742 } 1657 }
1743 1658
1744 void EmitFpuRType(Opcode opcode, 1659 void EmitFpuRType(Opcode opcode,
1745 Format fmt, 1660 Format fmt,
1746 FRegister ft, 1661 FRegister ft,
1747 FRegister fs, 1662 FRegister fs,
1748 FRegister fd, 1663 FRegister fd,
1749 Cop1Function func) { 1664 Cop1Function func) {
1750 Emit(opcode << kOpcodeShift | 1665 Emit(opcode << kOpcodeShift | fmt << kFmtShift | ft << kFtShift |
1751 fmt << kFmtShift | 1666 fs << kFsShift | fd << kFdShift | func << kCop1FnShift);
1752 ft << kFtShift |
1753 fs << kFsShift |
1754 fd << kFdShift |
1755 func << kCop1FnShift);
1756 } 1667 }
1757 1668
1758 int32_t EncodeBranchOffset(int32_t offset, int32_t instr); 1669 int32_t EncodeBranchOffset(int32_t offset, int32_t instr);
1759 1670
1760 void EmitFarJump(int32_t offset, bool link); 1671 void EmitFarJump(int32_t offset, bool link);
1761 void EmitFarBranch(Opcode b, Register rs, Register rt, int32_t offset); 1672 void EmitFarBranch(Opcode b, Register rs, Register rt, int32_t offset);
1762 void EmitFarRegImmBranch(RtRegImm b, Register rs, int32_t offset); 1673 void EmitFarRegImmBranch(RtRegImm b, Register rs, int32_t offset);
1763 void EmitFarFpuBranch(bool kind, int32_t offset); 1674 void EmitFarFpuBranch(bool kind, int32_t offset);
1764 void EmitBranch(Opcode b, Register rs, Register rt, Label* label); 1675 void EmitBranch(Opcode b, Register rs, Register rt, Label* label);
1765 void EmitRegImmBranch(RtRegImm b, Register rs, Label* label); 1676 void EmitRegImmBranch(RtRegImm b, Register rs, Label* label);
1766 void EmitFpuBranch(bool kind, Label *label); 1677 void EmitFpuBranch(bool kind, Label* label);
1767 1678
1768 void EmitBranchDelayNop() { 1679 void EmitBranchDelayNop() {
1769 Emit(Instr::kNopInstruction); // Branch delay NOP. 1680 Emit(Instr::kNopInstruction); // Branch delay NOP.
1770 delay_slot_available_ = true; 1681 delay_slot_available_ = true;
1771 } 1682 }
1772 1683
1773 void StoreIntoObjectFilter(Register object, Register value, Label* no_update); 1684 void StoreIntoObjectFilter(Register object, Register value, Label* no_update);
1774 1685
1775 // Shorter filtering sequence that assumes that value is not a smi. 1686 // Shorter filtering sequence that assumes that value is not a smi.
1776 void StoreIntoObjectFilterNoSmi(Register object, 1687 void StoreIntoObjectFilterNoSmi(Register object,
1777 Register value, 1688 Register value,
1778 Label* no_update); 1689 Label* no_update);
1779 1690
1780 DISALLOW_ALLOCATION(); 1691 DISALLOW_ALLOCATION();
1781 DISALLOW_COPY_AND_ASSIGN(Assembler); 1692 DISALLOW_COPY_AND_ASSIGN(Assembler);
1782 }; 1693 };
1783 1694
1784 } // namespace dart 1695 } // namespace dart
1785 1696
1786 #endif // RUNTIME_VM_ASSEMBLER_MIPS_H_ 1697 #endif // RUNTIME_VM_ASSEMBLER_MIPS_H_
OLDNEW
« no previous file with comments | « runtime/vm/assembler_ia32_test.cc ('k') | runtime/vm/assembler_mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698