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

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

Issue 231373003: Adds logical operations to arm64. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 8 months 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | runtime/vm/assembler_arm64.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) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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_ARM64_H_ 5 #ifndef VM_ASSEMBLER_ARM64_H_
6 #define VM_ASSEMBLER_ARM64_H_ 6 #define VM_ASSEMBLER_ARM64_H_
7 7
8 #ifndef VM_ASSEMBLER_H_ 8 #ifndef VM_ASSEMBLER_H_
9 #error Do not include assembler_arm64.h directly; use assembler.h instead. 9 #error Do not include assembler_arm64.h directly; use assembler.h instead.
10 #endif 10 #endif
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
169 169
170 class Operand : public ValueObject { 170 class Operand : public ValueObject {
171 public: 171 public:
172 // Data-processing operand - Uninitialized. 172 // Data-processing operand - Uninitialized.
173 Operand() : encoding_(-1), type_(Unknown) { } 173 Operand() : encoding_(-1), type_(Unknown) { }
174 174
175 // Data-processing operands - Copy constructor. 175 // Data-processing operands - Copy constructor.
176 Operand(const Operand& other) 176 Operand(const Operand& other)
177 : ValueObject(), encoding_(other.encoding_), type_(other.type_) { } 177 : ValueObject(), encoding_(other.encoding_), type_(other.type_) { }
178 178
179 Operand& operator=(const Operand& other) {
180 type_ = other.type_;
181 encoding_ = other.encoding_;
182 return *this;
183 }
184
179 explicit Operand(Register rm) { 185 explicit Operand(Register rm) {
180 ASSERT((rm != R31) && (rm != SP)); 186 ASSERT((rm != R31) && (rm != SP));
181 const Register crm = ConcreteRegister(rm); 187 const Register crm = ConcreteRegister(rm);
182 encoding_ = (static_cast<int32_t>(crm) << kRmShift); 188 encoding_ = (static_cast<int32_t>(crm) << kRmShift);
183 type_ = Shifted; 189 type_ = Shifted;
184 } 190 }
185 191
186 Operand(Register rm, Shift shift, int32_t imm) { 192 Operand(Register rm, Shift shift, int32_t imm) {
187 ASSERT(Utils::IsUint(6, imm)); 193 ASSERT(Utils::IsUint(6, imm));
188 ASSERT((rm != R31) && (rm != SP)); 194 ASSERT((rm != R31) && (rm != SP));
(...skipping 21 matching lines...) Expand all
210 if (Utils::IsUint(12, imm)) { 216 if (Utils::IsUint(12, imm)) {
211 encoding_ = imm << kImm12Shift; 217 encoding_ = imm << kImm12Shift;
212 } else { 218 } else {
213 // imm only has bits in [12, 24) set. 219 // imm only has bits in [12, 24) set.
214 ASSERT(((imm & 0xfff) == 0) && (Utils::IsUint(12, imm >> 12))); 220 ASSERT(((imm & 0xfff) == 0) && (Utils::IsUint(12, imm >> 12)));
215 encoding_ = B22 | ((imm >> 12) << kImm12Shift); 221 encoding_ = B22 | ((imm >> 12) << kImm12Shift);
216 } 222 }
217 type_ = Immediate; 223 type_ = Immediate;
218 } 224 }
219 225
220 // TODO(zra): Add bitfield immediate operand 226 // Encodes the value of an immediate for a logical operation.
221 // Operand(int32_t n, int32_t imms, int32_t immr); 227 // Since these values are difficult to craft by hand, instead pass the
228 // logical mask to the function Assembler::IsImmLogical to get n, imm_s, and
229 // imm_r.
230 Operand(uint8_t n, int8_t imm_s, int8_t imm_r) {
231 ASSERT((n == 1) || (n == 0));
232 ASSERT(Utils::IsUint(6, imm_s) && Utils::IsUint(6, imm_r));
233 type_ = BitfieldImm;
234 encoding_ =
235 (static_cast<int32_t>(n) << kNShift) |
236 (static_cast<int32_t>(imm_s) << kImmSShift) |
237 (static_cast<int32_t>(imm_r) << kImmRShift);
238 }
222 239
223 enum OperandType { 240 enum OperandType {
224 Shifted, 241 Shifted,
225 Extended, 242 Extended,
226 Immediate, 243 Immediate,
227 BitfieldImm, 244 BitfieldImm,
228 Unknown, 245 Unknown,
229 }; 246 };
230 247
231 private: 248 private:
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 336
320 // On some other platforms, we draw a distinction between safe and unsafe 337 // On some other platforms, we draw a distinction between safe and unsafe
321 // smis. 338 // smis.
322 static bool IsSafe(const Object& object) { return true; } 339 static bool IsSafe(const Object& object) { return true; }
323 static bool IsSafeSmi(const Object& object) { return object.IsSmi(); } 340 static bool IsSafeSmi(const Object& object) { return object.IsSmi(); }
324 341
325 // Addition and subtraction. 342 // Addition and subtraction.
326 void add(Register rd, Register rn, Operand o) { 343 void add(Register rd, Register rn, Operand o) {
327 AddSubHelper(kDoubleWord, false, false, rd, rn, o); 344 AddSubHelper(kDoubleWord, false, false, rd, rn, o);
328 } 345 }
346 void adds(Register rd, Register rn, Operand o) {
347 AddSubHelper(kDoubleWord, true, false, rd, rn, o);
348 }
329 void addw(Register rd, Register rn, Operand o) { 349 void addw(Register rd, Register rn, Operand o) {
330 AddSubHelper(kWord, false, false, rd, rn, o); 350 AddSubHelper(kWord, false, false, rd, rn, o);
331 } 351 }
332 void sub(Register rd, Register rn, Operand o) { 352 void sub(Register rd, Register rn, Operand o) {
333 AddSubHelper(kDoubleWord, false, true, rd, rn, o); 353 AddSubHelper(kDoubleWord, false, true, rd, rn, o);
334 } 354 }
355 void subs(Register rd, Register rn, Operand o) {
356 AddSubHelper(kDoubleWord, true, true, rd, rn, o);
357 }
358
359 // Logical immediate operations.
360 // TODO(zra): Add macros that check IsImmLogical, and fall back on a longer
361 // sequence on failure.
362 void andi(Register rd, Register rn, uint64_t imm) {
363 Operand imm_op;
364 const bool immok = IsImmLogical(imm, kXRegSizeInBits, &imm_op);
365 ASSERT(immok);
366 EmitLogicalImmOp(ANDI, rd, rn, imm_op, kDoubleWord);
367 }
368 void orri(Register rd, Register rn, uint64_t imm) {
369 Operand imm_op;
370 const bool immok = IsImmLogical(imm, kXRegSizeInBits, &imm_op);
371 ASSERT(immok);
372 EmitLogicalImmOp(ORRI, rd, rn, imm_op, kDoubleWord);
373 }
374 void eori(Register rd, Register rn, uint64_t imm) {
375 Operand imm_op;
376 const bool immok = IsImmLogical(imm, kXRegSizeInBits, &imm_op);
377 ASSERT(immok);
378 EmitLogicalImmOp(EORI, rd, rn, imm_op, kDoubleWord);
379 }
380 void andis(Register rd, Register rn, uint64_t imm) {
381 Operand imm_op;
382 const bool immok = IsImmLogical(imm, kXRegSizeInBits, &imm_op);
383 ASSERT(immok);
384 EmitLogicalImmOp(ANDIS, rd, rn, imm_op, kDoubleWord);
385 }
386
387 // Logical (shifted) register operations.
388 void and_(Register rd, Register rn, Operand o) {
389 EmitLogicalShiftOp(AND, rd, rn, o, kDoubleWord);
390 }
391 void bic(Register rd, Register rn, Operand o) {
392 EmitLogicalShiftOp(BIC, rd, rn, o, kDoubleWord);
393 }
394 void orr(Register rd, Register rn, Operand o) {
395 EmitLogicalShiftOp(ORR, rd, rn, o, kDoubleWord);
396 }
397 void orn(Register rd, Register rn, Operand o) {
398 EmitLogicalShiftOp(ORN, rd, rn, o, kDoubleWord);
399 }
400 void eor(Register rd, Register rn, Operand o) {
401 EmitLogicalShiftOp(EOR, rd, rn, o, kDoubleWord);
402 }
403 void eon(Register rd, Register rn, Operand o) {
404 EmitLogicalShiftOp(EON, rd, rn, o, kDoubleWord);
405 }
406 void ands(Register rd, Register rn, Operand o) {
407 EmitLogicalShiftOp(ANDS, rd, rn, o, kDoubleWord);
408 }
409 void bics(Register rd, Register rn, Operand o) {
410 EmitLogicalShiftOp(BICS, rd, rn, o, kDoubleWord);
411 }
412
413 // Comparison.
414 // rn cmp o.
415 void cmp(Register rn, Operand o) {
416 subs(ZR, rn, o);
417 }
418 // rn cmp -o.
419 void cmn(Register rn, Operand o) {
420 adds(ZR, rn, o);
421 }
335 422
336 // Move wide immediate. 423 // Move wide immediate.
337 void movk(Register rd, int32_t imm, int32_t hw_idx) { 424 void movk(Register rd, int32_t imm, int32_t hw_idx) {
338 ASSERT(rd != SP); 425 ASSERT(rd != SP);
339 const Register crd = ConcreteRegister(rd); 426 const Register crd = ConcreteRegister(rd);
340 EmitMoveWideOp(MOVK, crd, imm, hw_idx, kDoubleWord); 427 EmitMoveWideOp(MOVK, crd, imm, hw_idx, kDoubleWord);
341 } 428 }
342 void movn(Register rd, int32_t imm, int32_t hw_idx) { 429 void movn(Register rd, int32_t imm, int32_t hw_idx) {
343 ASSERT(rd != SP); 430 ASSERT(rd != SP);
344 const Register crd = ConcreteRegister(rd); 431 const Register crd = ConcreteRegister(rd);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 473
387 private: 474 private:
388 intptr_t pc_offset_; 475 intptr_t pc_offset_;
389 const String& comment_; 476 const String& comment_;
390 477
391 DISALLOW_COPY_AND_ASSIGN(CodeComment); 478 DISALLOW_COPY_AND_ASSIGN(CodeComment);
392 }; 479 };
393 480
394 GrowableArray<CodeComment*> comments_; 481 GrowableArray<CodeComment*> comments_;
395 482
483 bool IsImmLogical(uint64_t value, uint8_t width, Operand* imm_op);
484
396 void AddSubHelper(OperandSize os, bool set_flags, bool subtract, 485 void AddSubHelper(OperandSize os, bool set_flags, bool subtract,
397 Register rd, Register rn, Operand o) { 486 Register rd, Register rn, Operand o) {
398 ASSERT((rd != R31) && (rn != R31)); 487 ASSERT((rd != R31) && (rn != R31));
399 const Register crd = ConcreteRegister(rd); 488 const Register crd = ConcreteRegister(rd);
400 const Register crn = ConcreteRegister(rn); 489 const Register crn = ConcreteRegister(rn);
401 if (o.type() == Operand::Immediate) { 490 if (o.type() == Operand::Immediate) {
402 ASSERT((rd != ZR) && (rn != ZR)); 491 ASSERT((rd != ZR) && (rn != ZR));
403 EmitAddSubImmOp(subtract ? SUBI : ADDI, crd, crn, o, os, set_flags); 492 EmitAddSubImmOp(subtract ? SUBI : ADDI, crd, crn, o, os, set_flags);
404 } else if (o.type() == Operand::Shifted) { 493 } else if (o.type() == Operand::Shifted) {
405 ASSERT((rd != SP) && (rn != SP)); 494 ASSERT((rd != SP) && (rn != SP));
406 EmitAddSubShiftExtOp(subtract ? SUB : ADD, crd, crn, o, os, set_flags); 495 EmitAddSubShiftExtOp(subtract ? SUB : ADD, crd, crn, o, os, set_flags);
407 } else { 496 } else {
408 ASSERT(o.type() == Operand::Extended); 497 ASSERT(o.type() == Operand::Extended);
409 ASSERT((rd != SP) && (rn != ZR)); 498 ASSERT((rd != SP) && (rn != ZR));
410 EmitAddSubShiftExtOp(subtract ? SUB : ADD, crd, crn, o, os, set_flags); 499 EmitAddSubShiftExtOp(subtract ? SUB : ADD, crd, crn, o, os, set_flags);
411 } 500 }
412 } 501 }
413 502
414 void EmitAddSubImmOp(AddSubImmOp op, Register rd, Register rn, 503 void EmitAddSubImmOp(AddSubImmOp op, Register rd, Register rn,
415 Operand o, OperandSize os, bool set_flags) { 504 Operand o, OperandSize sz, bool set_flags) {
416 ASSERT((os == kDoubleWord) || (os == kWord)); 505 ASSERT((sz == kDoubleWord) || (sz == kWord));
417 const int32_t size = (os == kDoubleWord) ? B31 : 0; 506 const int32_t size = (sz == kDoubleWord) ? B31 : 0;
418 const int32_t s = set_flags ? B29 : 0; 507 const int32_t s = set_flags ? B29 : 0;
419 const int32_t encoding = 508 const int32_t encoding =
420 op | size | s | 509 op | size | s |
421 (static_cast<int32_t>(rd) << kRdShift) | 510 (static_cast<int32_t>(rd) << kRdShift) |
422 (static_cast<int32_t>(rn) << kRnShift) | 511 (static_cast<int32_t>(rn) << kRnShift) |
423 o.encoding(); 512 o.encoding();
424 Emit(encoding); 513 Emit(encoding);
425 } 514 }
426 515
516 void EmitLogicalImmOp(LogicalImmOp op, Register rd, Register rn,
517 Operand o, OperandSize sz) {
518 ASSERT((sz == kDoubleWord) || (sz == kWord));
519 ASSERT((rd != R31) && (rn != R31));
520 ASSERT(rn != SP);
521 ASSERT((op == ANDIS) || (rd != ZR)); // op != ANDIS => rd != ZR.
522 ASSERT((op != ANDIS) || (rd != SP)); // op == ANDIS => rd != SP.
523 ASSERT(o.type() == Operand::BitfieldImm);
524 const int32_t size = (sz == kDoubleWord) ? B31 : 0;
525 const Register crd = ConcreteRegister(rd);
526 const Register crn = ConcreteRegister(rn);
527 const int32_t encoding =
528 op | size |
529 (static_cast<int32_t>(crd) << kRdShift) |
530 (static_cast<int32_t>(crn) << kRnShift) |
531 o.encoding();
532 Emit(encoding);
533 }
534
535 void EmitLogicalShiftOp(LogicalShiftOp op,
536 Register rd, Register rn, Operand o, OperandSize sz) {
537 ASSERT((sz == kDoubleWord) || (sz == kWord));
538 ASSERT((rd != R31) && (rn != R31));
539 ASSERT((rd != SP) && (rn != SP));
540 ASSERT(o.type() == Operand::Shifted);
541 const int32_t size = (sz == kDoubleWord) ? B31 : 0;
542 const Register crd = ConcreteRegister(rd);
543 const Register crn = ConcreteRegister(rn);
544 const int32_t encoding =
545 op | size |
546 (static_cast<int32_t>(crd) << kRdShift) |
547 (static_cast<int32_t>(crn) << kRnShift) |
548 o.encoding();
549 Emit(encoding);
550 }
551
427 void EmitAddSubShiftExtOp(AddSubShiftExtOp op, 552 void EmitAddSubShiftExtOp(AddSubShiftExtOp op,
428 Register rd, Register rn, Operand o, 553 Register rd, Register rn, Operand o,
429 OperandSize sz, bool set_flags) { 554 OperandSize sz, bool set_flags) {
430 ASSERT((sz == kDoubleWord) || (sz == kWord)); 555 ASSERT((sz == kDoubleWord) || (sz == kWord));
431 const int32_t size = (sz == kDoubleWord) ? B31 : 0; 556 const int32_t size = (sz == kDoubleWord) ? B31 : 0;
432 const int32_t s = set_flags ? B29 : 0; 557 const int32_t s = set_flags ? B29 : 0;
433 const int32_t encoding = 558 const int32_t encoding =
434 op | size | s | 559 op | size | s |
435 (static_cast<int32_t>(rd) << kRdShift) | 560 (static_cast<int32_t>(rd) << kRdShift) |
436 (static_cast<int32_t>(rn) << kRnShift) | 561 (static_cast<int32_t>(rn) << kRnShift) |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 Emit(encoding); 593 Emit(encoding);
469 } 594 }
470 595
471 DISALLOW_ALLOCATION(); 596 DISALLOW_ALLOCATION();
472 DISALLOW_COPY_AND_ASSIGN(Assembler); 597 DISALLOW_COPY_AND_ASSIGN(Assembler);
473 }; 598 };
474 599
475 } // namespace dart 600 } // namespace dart
476 601
477 #endif // VM_ASSEMBLER_ARM64_H_ 602 #endif // VM_ASSEMBLER_ARM64_H_
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/assembler_arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698