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

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') | runtime/vm/assembler_arm64.cc » ('J')
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 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 if (Utils::IsUint(12, imm)) { 210 if (Utils::IsUint(12, imm)) {
211 encoding_ = imm << kImm12Shift; 211 encoding_ = imm << kImm12Shift;
212 } else { 212 } else {
213 // imm only has bits in [12, 24) set. 213 // imm only has bits in [12, 24) set.
214 ASSERT(((imm & 0xfff) == 0) && (Utils::IsUint(12, imm >> 12))); 214 ASSERT(((imm & 0xfff) == 0) && (Utils::IsUint(12, imm >> 12)));
215 encoding_ = B22 | ((imm >> 12) << kImm12Shift); 215 encoding_ = B22 | ((imm >> 12) << kImm12Shift);
216 } 216 }
217 type_ = Immediate; 217 type_ = Immediate;
218 } 218 }
219 219
220 // TODO(zra): Add bitfield immediate operand 220 // Call Assembler::IsImmLogical to find values for these arguments.
regis 2014/04/09 20:49:49 I do not understand this comment.
zra 2014/04/09 22:14:28 Tried to clarify.
221 // Operand(int32_t n, int32_t imms, int32_t immr); 221 Operand(uint8_t n, int8_t imm_s, int8_t imm_r) {
222 ASSERT((n == 1) || (n == 0));
223 ASSERT(Utils::IsUint(6, imm_s) && Utils::IsUint(6, imm_r));
224 type_ = BitfieldImm;
225 encoding_ =
226 (static_cast<int32_t>(n) << kNShift) |
227 (static_cast<int32_t>(imm_s) << kImmSShift) |
228 (static_cast<int32_t>(imm_r) << kImmRShift);
229 }
222 230
223 enum OperandType { 231 enum OperandType {
224 Shifted, 232 Shifted,
225 Extended, 233 Extended,
226 Immediate, 234 Immediate,
227 BitfieldImm, 235 BitfieldImm,
228 Unknown, 236 Unknown,
229 }; 237 };
230 238
231 private: 239 private:
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 327
320 // On some other platforms, we draw a distinction between safe and unsafe 328 // On some other platforms, we draw a distinction between safe and unsafe
321 // smis. 329 // smis.
322 static bool IsSafe(const Object& object) { return true; } 330 static bool IsSafe(const Object& object) { return true; }
323 static bool IsSafeSmi(const Object& object) { return object.IsSmi(); } 331 static bool IsSafeSmi(const Object& object) { return object.IsSmi(); }
324 332
325 // Addition and subtraction. 333 // Addition and subtraction.
326 void add(Register rd, Register rn, Operand o) { 334 void add(Register rd, Register rn, Operand o) {
327 AddSubHelper(kDoubleWord, false, false, rd, rn, o); 335 AddSubHelper(kDoubleWord, false, false, rd, rn, o);
328 } 336 }
337 void adds(Register rd, Register rn, Operand o) {
338 AddSubHelper(kDoubleWord, true, false, rd, rn, o);
339 }
329 void addw(Register rd, Register rn, Operand o) { 340 void addw(Register rd, Register rn, Operand o) {
330 AddSubHelper(kWord, false, false, rd, rn, o); 341 AddSubHelper(kWord, false, false, rd, rn, o);
331 } 342 }
332 void sub(Register rd, Register rn, Operand o) { 343 void sub(Register rd, Register rn, Operand o) {
333 AddSubHelper(kDoubleWord, false, true, rd, rn, o); 344 AddSubHelper(kDoubleWord, false, true, rd, rn, o);
334 } 345 }
346 void subs(Register rd, Register rn, Operand o) {
347 AddSubHelper(kDoubleWord, true, true, rd, rn, o);
348 }
349
350 // Logical immediate operations.
351 // TODO(zra): Add macros that check IsImmLogical, and fall back on a longer
352 // sequence on failure.
353 void andi(Register rd, Register rn, uint64_t imm) {
354 uint8_t n = 0, imm_s = 0, imm_r = 0;
355 const bool immok = IsImmLogical(imm, kXRegSizeInBits, &n, &imm_s, &imm_r);
regis 2014/04/09 20:49:49 You could also use a pattern similar to ShifterOpe
zra 2014/04/09 22:14:28 Done.
356 ASSERT(immok);
357 EmitLogicalImmOp(ANDI, rd, rn, Operand(n, imm_s, imm_r), kDoubleWord);
358 }
359 void orri(Register rd, Register rn, uint64_t imm) {
360 uint8_t n = 0, imm_s = 0, imm_r = 0;
361 const bool immok = IsImmLogical(imm, kXRegSizeInBits, &n, &imm_s, &imm_r);
362 ASSERT(immok);
363 EmitLogicalImmOp(ORRI, rd, rn, Operand(n, imm_s, imm_r), kDoubleWord);
364 }
365 void eori(Register rd, Register rn, uint64_t imm) {
366 uint8_t n = 0, imm_s = 0, imm_r = 0;
367 const bool immok = IsImmLogical(imm, kXRegSizeInBits, &n, &imm_s, &imm_r);
368 ASSERT(immok);
369 EmitLogicalImmOp(EORI, rd, rn, Operand(n, imm_s, imm_r), kDoubleWord);
370 }
371 void andis(Register rd, Register rn, uint64_t imm) {
372 uint8_t n = 0, imm_s = 0, imm_r = 0;
373 const bool immok = IsImmLogical(imm, kXRegSizeInBits, &n, &imm_s, &imm_r);
374 ASSERT(immok);
375 EmitLogicalImmOp(ANDIS, rd, rn, Operand(n, imm_s, imm_r), kDoubleWord);
376 }
377
378 // Logical (shifted) register operations.
379 void and_(Register rd, Register rn, Operand o) {
380 EmitLogicalShiftOp(AND, rd, rn, o, kDoubleWord);
381 }
382 void bic(Register rd, Register rn, Operand o) {
383 EmitLogicalShiftOp(BIC, rd, rn, o, kDoubleWord);
384 }
385 void orr(Register rd, Register rn, Operand o) {
386 EmitLogicalShiftOp(ORR, rd, rn, o, kDoubleWord);
387 }
388 void orn(Register rd, Register rn, Operand o) {
389 EmitLogicalShiftOp(ORN, rd, rn, o, kDoubleWord);
390 }
391 void eor(Register rd, Register rn, Operand o) {
392 EmitLogicalShiftOp(EOR, rd, rn, o, kDoubleWord);
393 }
394 void eon(Register rd, Register rn, Operand o) {
395 EmitLogicalShiftOp(EON, rd, rn, o, kDoubleWord);
396 }
397 void ands(Register rd, Register rn, Operand o) {
398 EmitLogicalShiftOp(ANDS, rd, rn, o, kDoubleWord);
399 }
400 void bics(Register rd, Register rn, Operand o) {
401 EmitLogicalShiftOp(BICS, rd, rn, o, kDoubleWord);
402 }
403
404 // Comparison.
405 // rn cmp o.
406 void cmp(Register rn, Operand o) {
407 subs(ZR, rn, o);
408 }
409 // rn cmp -o.
410 void cmn(Register rn, Operand o) {
411 adds(ZR, rn, o);
412 }
335 413
336 // Move wide immediate. 414 // Move wide immediate.
337 void movk(Register rd, int32_t imm, int32_t hw_idx) { 415 void movk(Register rd, int32_t imm, int32_t hw_idx) {
338 ASSERT(rd != SP); 416 ASSERT(rd != SP);
339 const Register crd = ConcreteRegister(rd); 417 const Register crd = ConcreteRegister(rd);
340 EmitMoveWideOp(MOVK, crd, imm, hw_idx, kDoubleWord); 418 EmitMoveWideOp(MOVK, crd, imm, hw_idx, kDoubleWord);
341 } 419 }
342 void movn(Register rd, int32_t imm, int32_t hw_idx) { 420 void movn(Register rd, int32_t imm, int32_t hw_idx) {
343 ASSERT(rd != SP); 421 ASSERT(rd != SP);
344 const Register crd = ConcreteRegister(rd); 422 const Register crd = ConcreteRegister(rd);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 464
387 private: 465 private:
388 intptr_t pc_offset_; 466 intptr_t pc_offset_;
389 const String& comment_; 467 const String& comment_;
390 468
391 DISALLOW_COPY_AND_ASSIGN(CodeComment); 469 DISALLOW_COPY_AND_ASSIGN(CodeComment);
392 }; 470 };
393 471
394 GrowableArray<CodeComment*> comments_; 472 GrowableArray<CodeComment*> comments_;
395 473
474 bool IsImmLogical(uint64_t value, uint8_t width,
475 uint8_t* n, uint8_t* imm_s, uint8_t* imm_r);
476
396 void AddSubHelper(OperandSize os, bool set_flags, bool subtract, 477 void AddSubHelper(OperandSize os, bool set_flags, bool subtract,
397 Register rd, Register rn, Operand o) { 478 Register rd, Register rn, Operand o) {
398 ASSERT((rd != R31) && (rn != R31)); 479 ASSERT((rd != R31) && (rn != R31));
399 const Register crd = ConcreteRegister(rd); 480 const Register crd = ConcreteRegister(rd);
400 const Register crn = ConcreteRegister(rn); 481 const Register crn = ConcreteRegister(rn);
401 if (o.type() == Operand::Immediate) { 482 if (o.type() == Operand::Immediate) {
402 ASSERT((rd != ZR) && (rn != ZR)); 483 ASSERT((rd != ZR) && (rn != ZR));
403 EmitAddSubImmOp(subtract ? SUBI : ADDI, crd, crn, o, os, set_flags); 484 EmitAddSubImmOp(subtract ? SUBI : ADDI, crd, crn, o, os, set_flags);
404 } else if (o.type() == Operand::Shifted) { 485 } else if (o.type() == Operand::Shifted) {
405 ASSERT((rd != SP) && (rn != SP)); 486 ASSERT((rd != SP) && (rn != SP));
406 EmitAddSubShiftExtOp(subtract ? SUB : ADD, crd, crn, o, os, set_flags); 487 EmitAddSubShiftExtOp(subtract ? SUB : ADD, crd, crn, o, os, set_flags);
407 } else { 488 } else {
408 ASSERT(o.type() == Operand::Extended); 489 ASSERT(o.type() == Operand::Extended);
409 ASSERT((rd != SP) && (rn != ZR)); 490 ASSERT((rd != SP) && (rn != ZR));
410 EmitAddSubShiftExtOp(subtract ? SUB : ADD, crd, crn, o, os, set_flags); 491 EmitAddSubShiftExtOp(subtract ? SUB : ADD, crd, crn, o, os, set_flags);
411 } 492 }
412 } 493 }
413 494
414 void EmitAddSubImmOp(AddSubImmOp op, Register rd, Register rn, 495 void EmitAddSubImmOp(AddSubImmOp op, Register rd, Register rn,
415 Operand o, OperandSize os, bool set_flags) { 496 Operand o, OperandSize sz, bool set_flags) {
416 ASSERT((os == kDoubleWord) || (os == kWord)); 497 ASSERT((sz == kDoubleWord) || (sz == kWord));
417 const int32_t size = (os == kDoubleWord) ? B31 : 0; 498 const int32_t size = (sz == kDoubleWord) ? B31 : 0;
418 const int32_t s = set_flags ? B29 : 0; 499 const int32_t s = set_flags ? B29 : 0;
419 const int32_t encoding = 500 const int32_t encoding =
420 op | size | s | 501 op | size | s |
421 (static_cast<int32_t>(rd) << kRdShift) | 502 (static_cast<int32_t>(rd) << kRdShift) |
422 (static_cast<int32_t>(rn) << kRnShift) | 503 (static_cast<int32_t>(rn) << kRnShift) |
423 o.encoding(); 504 o.encoding();
424 Emit(encoding); 505 Emit(encoding);
425 } 506 }
426 507
508 void EmitLogicalImmOp(LogicalImmOp op, Register rd, Register rn,
509 Operand o, OperandSize sz) {
510 ASSERT((sz == kDoubleWord) || (sz == kWord));
511 ASSERT((rd != R31) && (rn != R31));
512 ASSERT(rn != SP);
513 ASSERT((op == ANDIS) || (rd != ZR)); // op != ANDIS => rd != ZR.
514 ASSERT((op != ANDIS) || (rd != SP)); // op == ANDIS => rd != SP.
515 ASSERT(o.type() == Operand::BitfieldImm);
516 const int32_t size = (sz == kDoubleWord) ? B31 : 0;
517 const Register crd = ConcreteRegister(rd);
518 const Register crn = ConcreteRegister(rn);
519 const int32_t encoding =
520 op | size |
521 (static_cast<int32_t>(crd) << kRdShift) |
522 (static_cast<int32_t>(crn) << kRnShift) |
523 o.encoding();
524 Emit(encoding);
525 }
526
527 void EmitLogicalShiftOp(LogicalShiftOp op,
528 Register rd, Register rn, Operand o, OperandSize sz) {
529 ASSERT((sz == kDoubleWord) || (sz == kWord));
530 ASSERT((rd != R31) && (rn != R31));
531 ASSERT((rd != SP) && (rn != SP));
532 ASSERT(o.type() == Operand::Shifted);
533 const int32_t size = (sz == kDoubleWord) ? B31 : 0;
534 const Register crd = ConcreteRegister(rd);
535 const Register crn = ConcreteRegister(rn);
536 const int32_t encoding =
537 op | size |
538 (static_cast<int32_t>(crd) << kRdShift) |
539 (static_cast<int32_t>(crn) << kRnShift) |
540 o.encoding();
541 Emit(encoding);
542 }
543
427 void EmitAddSubShiftExtOp(AddSubShiftExtOp op, 544 void EmitAddSubShiftExtOp(AddSubShiftExtOp op,
428 Register rd, Register rn, Operand o, 545 Register rd, Register rn, Operand o,
429 OperandSize sz, bool set_flags) { 546 OperandSize sz, bool set_flags) {
430 ASSERT((sz == kDoubleWord) || (sz == kWord)); 547 ASSERT((sz == kDoubleWord) || (sz == kWord));
431 const int32_t size = (sz == kDoubleWord) ? B31 : 0; 548 const int32_t size = (sz == kDoubleWord) ? B31 : 0;
432 const int32_t s = set_flags ? B29 : 0; 549 const int32_t s = set_flags ? B29 : 0;
433 const int32_t encoding = 550 const int32_t encoding =
434 op | size | s | 551 op | size | s |
435 (static_cast<int32_t>(rd) << kRdShift) | 552 (static_cast<int32_t>(rd) << kRdShift) |
436 (static_cast<int32_t>(rn) << kRnShift) | 553 (static_cast<int32_t>(rn) << kRnShift) |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 Emit(encoding); 585 Emit(encoding);
469 } 586 }
470 587
471 DISALLOW_ALLOCATION(); 588 DISALLOW_ALLOCATION();
472 DISALLOW_COPY_AND_ASSIGN(Assembler); 589 DISALLOW_COPY_AND_ASSIGN(Assembler);
473 }; 590 };
474 591
475 } // namespace dart 592 } // namespace dart
476 593
477 #endif // VM_ASSEMBLER_ARM64_H_ 594 #endif // VM_ASSEMBLER_ARM64_H_
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/assembler_arm64.cc » ('j') | runtime/vm/assembler_arm64.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698