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

Side by Side Diff: runtime/vm/assembler_arm.cc

Issue 1043943002: A few fixes for ARMv5TE. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 5 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 | « runtime/vm/assembler_arm.h ('k') | runtime/vm/assembler_arm_test.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 #include "vm/globals.h" // NOLINT 5 #include "vm/globals.h" // NOLINT
6 #if defined(TARGET_ARCH_ARM) 6 #if defined(TARGET_ARCH_ARM)
7 7
8 #include "vm/assembler.h" 8 #include "vm/assembler.h"
9 #include "vm/cpu.h" 9 #include "vm/cpu.h"
10 #include "vm/longjump.h" 10 #include "vm/longjump.h"
(...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 EmitMulOp(cond, B22 | B21, ra, rd, rn, rm); 428 EmitMulOp(cond, B22 | B21, ra, rd, rn, rm);
429 } else { 429 } else {
430 mul(IP, rn, rm, cond); 430 mul(IP, rn, rm, cond);
431 sub(rd, ra, Operand(IP), cond); 431 sub(rd, ra, Operand(IP), cond);
432 } 432 }
433 } 433 }
434 434
435 435
436 void Assembler::smull(Register rd_lo, Register rd_hi, 436 void Assembler::smull(Register rd_lo, Register rd_hi,
437 Register rn, Register rm, Condition cond) { 437 Register rn, Register rm, Condition cond) {
438 ASSERT(TargetCPUFeatures::arm_version() == ARMv7);
439 // Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs. 438 // Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
440 EmitMulOp(cond, B23 | B22, rd_lo, rd_hi, rn, rm); 439 EmitMulOp(cond, B23 | B22, rd_lo, rd_hi, rn, rm);
441 } 440 }
442 441
443 442
444 void Assembler::umull(Register rd_lo, Register rd_hi, 443 void Assembler::umull(Register rd_lo, Register rd_hi,
445 Register rn, Register rm, Condition cond) { 444 Register rn, Register rm, Condition cond) {
446 ASSERT(TargetCPUFeatures::arm_version() == ARMv7); 445 ASSERT(TargetCPUFeatures::arm_version() == ARMv7);
447 // Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs. 446 // Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
448 EmitMulOp(cond, B23, rd_lo, rd_hi, rn, rm); 447 EmitMulOp(cond, B23, rd_lo, rd_hi, rn, rm);
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
533 void Assembler::ldrsb(Register rd, Address ad, Condition cond) { 532 void Assembler::ldrsb(Register rd, Address ad, Condition cond) {
534 EmitMemOpAddressMode3(cond, L | B7 | B6 | B4, rd, ad); 533 EmitMemOpAddressMode3(cond, L | B7 | B6 | B4, rd, ad);
535 } 534 }
536 535
537 536
538 void Assembler::ldrsh(Register rd, Address ad, Condition cond) { 537 void Assembler::ldrsh(Register rd, Address ad, Condition cond) {
539 EmitMemOpAddressMode3(cond, L | B7 | B6 | H | B4, rd, ad); 538 EmitMemOpAddressMode3(cond, L | B7 | B6 | H | B4, rd, ad);
540 } 539 }
541 540
542 541
543 void Assembler::ldrd(Register rd, Address ad, Condition cond) { 542 void Assembler::ldrd(Register rd, Register rn, int32_t offset, Condition cond) {
544 ASSERT((rd % 2) == 0); 543 ASSERT((rd % 2) == 0);
545 EmitMemOpAddressMode3(cond, B7 | B6 | B4, rd, ad); 544 if (TargetCPUFeatures::arm_version() == ARMv5TE) {
545 const Register rd2 = static_cast<Register>(static_cast<int32_t>(rd) + 1);
546 ldr(rd, Address(rn, offset), cond);
547 ldr(rd2, Address(rn, offset + kWordSize), cond);
548 } else {
549 EmitMemOpAddressMode3(cond, B7 | B6 | B4, rd, Address(rn, offset));
550 }
546 } 551 }
547 552
548 553
549 void Assembler::strd(Register rd, Address ad, Condition cond) { 554 void Assembler::strd(Register rd, Register rn, int32_t offset, Condition cond) {
550 ASSERT((rd % 2) == 0); 555 ASSERT((rd % 2) == 0);
551 EmitMemOpAddressMode3(cond, B7 | B6 | B5 | B4, rd, ad); 556 if (TargetCPUFeatures::arm_version() == ARMv5TE) {
557 const Register rd2 = static_cast<Register>(static_cast<int32_t>(rd) + 1);
558 str(rd, Address(rn, offset), cond);
559 str(rd2, Address(rn, offset + kWordSize), cond);
560 } else {
561 EmitMemOpAddressMode3(cond, B7 | B6 | B5 | B4, rd, Address(rn, offset));
562 }
552 } 563 }
553 564
554 565
555 void Assembler::ldm(BlockAddressMode am, Register base, RegList regs, 566 void Assembler::ldm(BlockAddressMode am, Register base, RegList regs,
556 Condition cond) { 567 Condition cond) {
557 ASSERT(regs != 0); 568 ASSERT(regs != 0);
558 EmitMultiMemOp(cond, am, true, base, regs); 569 EmitMultiMemOp(cond, am, true, base, regs);
559 if (TargetCPUFeatures::arm_version() == ARMv5TE) {
560 // On ARMv5, touching a "banked" register after an ldm gives undefined
561 // behavior, so we just add a nop here to make that case easy to avoid.
562 nop();
563 }
564 } 570 }
565 571
566 572
567 void Assembler::stm(BlockAddressMode am, Register base, RegList regs, 573 void Assembler::stm(BlockAddressMode am, Register base, RegList regs,
568 Condition cond) { 574 Condition cond) {
569 ASSERT(regs != 0); 575 ASSERT(regs != 0);
570 EmitMultiMemOp(cond, am, false, base, regs); 576 EmitMultiMemOp(cond, am, false, base, regs);
571 if (TargetCPUFeatures::arm_version() == ARMv5TE) {
572 // On ARMv5, touching a "banked" register after an stm gives undefined
573 // behavior, so we just add a nop here to make that case easy to avoid.
574 nop();
575 }
576 } 577 }
577 578
578 579
579 void Assembler::ldrex(Register rt, Register rn, Condition cond) { 580 void Assembler::ldrex(Register rt, Register rn, Condition cond) {
580 ASSERT(TargetCPUFeatures::arm_version() != ARMv5TE); 581 ASSERT(TargetCPUFeatures::arm_version() != ARMv5TE);
581 ASSERT(rn != kNoRegister); 582 ASSERT(rn != kNoRegister);
582 ASSERT(rt != kNoRegister); 583 ASSERT(rt != kNoRegister);
583 ASSERT(cond != kNoCondition); 584 ASSERT(cond != kNoCondition);
584 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 585 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
585 B24 | 586 B24 |
(...skipping 1083 matching lines...) Expand 10 before | Expand all | Expand 10 after
1669 intptr_t offset, 1670 intptr_t offset,
1670 Register value_even, 1671 Register value_even,
1671 Register value_odd, 1672 Register value_odd,
1672 Condition cond) { 1673 Condition cond) {
1673 ASSERT(value_odd == value_even + 1); 1674 ASSERT(value_odd == value_even + 1);
1674 if (VerifiedMemory::enabled()) { 1675 if (VerifiedMemory::enabled()) {
1675 ASSERT(base != value_even); 1676 ASSERT(base != value_even);
1676 ASSERT(base != value_odd); 1677 ASSERT(base != value_odd);
1677 Operand shadow(GetVerifiedMemoryShadow()); 1678 Operand shadow(GetVerifiedMemoryShadow());
1678 add(base, base, shadow, cond); 1679 add(base, base, shadow, cond);
1679 strd(value_even, Address(base, offset), cond); 1680 strd(value_even, base, offset, cond);
1680 sub(base, base, shadow, cond); 1681 sub(base, base, shadow, cond);
1681 } 1682 }
1682 strd(value_even, Address(base, offset), cond); 1683 strd(value_even, base, offset, cond);
1683 } 1684 }
1684 1685
1685 1686
1686 Register UseRegister(Register reg, RegList* used) { 1687 Register UseRegister(Register reg, RegList* used) {
1687 ASSERT(reg != SP); 1688 ASSERT(reg != SP);
1688 ASSERT(reg != PC); 1689 ASSERT(reg != PC);
1689 ASSERT((*used & (1 << reg)) == 0); 1690 ASSERT((*used & (1 << reg)) == 0);
1690 *used |= (1 << reg); 1691 *used |= (1 << reg);
1691 return reg; 1692 return reg;
1692 } 1693 }
(...skipping 1094 matching lines...) Expand 10 before | Expand all | Expand 10 after
2787 case kHalfword: 2788 case kHalfword:
2788 ldrsh(reg, Address(base, offset), cond); 2789 ldrsh(reg, Address(base, offset), cond);
2789 break; 2790 break;
2790 case kUnsignedHalfword: 2791 case kUnsignedHalfword:
2791 ldrh(reg, Address(base, offset), cond); 2792 ldrh(reg, Address(base, offset), cond);
2792 break; 2793 break;
2793 case kWord: 2794 case kWord:
2794 ldr(reg, Address(base, offset), cond); 2795 ldr(reg, Address(base, offset), cond);
2795 break; 2796 break;
2796 case kWordPair: 2797 case kWordPair:
2797 ldrd(reg, Address(base, offset), cond); 2798 ldrd(reg, base, offset, cond);
2798 break; 2799 break;
2799 default: 2800 default:
2800 UNREACHABLE(); 2801 UNREACHABLE();
2801 } 2802 }
2802 } 2803 }
2803 2804
2804 2805
2805 void Assembler::StoreToOffset(OperandSize size, 2806 void Assembler::StoreToOffset(OperandSize size,
2806 Register reg, 2807 Register reg,
2807 Register base, 2808 Register base,
(...skipping 11 matching lines...) Expand all
2819 case kByte: 2820 case kByte:
2820 strb(reg, Address(base, offset), cond); 2821 strb(reg, Address(base, offset), cond);
2821 break; 2822 break;
2822 case kHalfword: 2823 case kHalfword:
2823 strh(reg, Address(base, offset), cond); 2824 strh(reg, Address(base, offset), cond);
2824 break; 2825 break;
2825 case kWord: 2826 case kWord:
2826 str(reg, Address(base, offset), cond); 2827 str(reg, Address(base, offset), cond);
2827 break; 2828 break;
2828 case kWordPair: 2829 case kWordPair:
2829 strd(reg, Address(base, offset), cond); 2830 strd(reg, base, offset, cond);
2830 break; 2831 break;
2831 default: 2832 default:
2832 UNREACHABLE(); 2833 UNREACHABLE();
2833 } 2834 }
2834 } 2835 }
2835 2836
2836 2837
2837 void Assembler::LoadSFromOffset(SRegister reg, 2838 void Assembler::LoadSFromOffset(SRegister reg,
2838 Register base, 2839 Register base,
2839 int32_t offset, 2840 int32_t offset,
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after
3125 vcvtdi(tmpl, stmpl); // left is in tmpl. 3126 vcvtdi(tmpl, stmpl); // left is in tmpl.
3126 vmovsr(stmpr, right); 3127 vmovsr(stmpr, right);
3127 vcvtdi(tmpr, stmpr); // right is in tmpr. 3128 vcvtdi(tmpr, stmpr); // right is in tmpr.
3128 vdivd(tmpr, tmpl, tmpr); 3129 vdivd(tmpr, tmpl, tmpr);
3129 vcvtid(stmpr, tmpr); 3130 vcvtid(stmpr, tmpr);
3130 vmovrs(result, stmpr); 3131 vmovrs(result, stmpr);
3131 } 3132 }
3132 } 3133 }
3133 3134
3134 3135
3135 // If we aren't on ARMv7, there is no smull, and we have to check for overflow
3136 // manually.
3137 void Assembler::CheckMultSignedOverflow(Register left,
3138 Register right,
3139 Register tmp,
3140 DRegister dtmp0, DRegister dtmp1,
3141 Label* overflow) {
3142 Label done, left_neg, left_pos_right_neg, left_neg_right_pos;
3143
3144 CompareImmediate(left, 0);
3145 b(&left_neg, LT);
3146 b(&done, EQ);
3147 CompareImmediate(right, 0);
3148 b(&left_pos_right_neg, LT);
3149 b(&done, EQ);
3150
3151 // Both positive.
3152 LoadImmediate(tmp, INT_MAX);
3153 IntegerDivide(tmp, tmp, left, dtmp0, dtmp1);
3154 cmp(tmp, Operand(right));
3155 b(overflow, LT);
3156 b(&done);
3157
3158 // left positive, right non-positive.
3159 Bind(&left_pos_right_neg);
3160 LoadImmediate(tmp, INT_MIN);
3161 IntegerDivide(tmp, tmp, left, dtmp0, dtmp1);
3162 cmp(tmp, Operand(right));
3163 b(overflow, GT);
3164 b(&done);
3165
3166 Bind(&left_neg);
3167 CompareImmediate(right, 0);
3168 b(&left_neg_right_pos, GT);
3169 b(&done, EQ);
3170
3171 // both negative.
3172 LoadImmediate(tmp, INT_MAX);
3173 IntegerDivide(tmp, tmp, left, dtmp0, dtmp1);
3174 cmp(tmp, Operand(right));
3175 b(overflow, GT);
3176 b(&done);
3177
3178 // left non-positive, right positive.
3179 Bind(&left_neg_right_pos);
3180 LoadImmediate(tmp, INT_MIN);
3181 IntegerDivide(tmp, tmp, right, dtmp0, dtmp1);
3182 cmp(tmp, Operand(left));
3183 b(overflow, GT);
3184
3185 Bind(&done);
3186 }
3187
3188
3189 static int NumRegsBelowFP(RegList regs) { 3136 static int NumRegsBelowFP(RegList regs) {
3190 int count = 0; 3137 int count = 0;
3191 for (int i = 0; i < FP; i++) { 3138 for (int i = 0; i < FP; i++) {
3192 if ((regs & (1 << i)) != 0) { 3139 if ((regs & (1 << i)) != 0) {
3193 count++; 3140 count++;
3194 } 3141 }
3195 } 3142 }
3196 return count; 3143 return count;
3197 } 3144 }
3198 3145
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
3316 AddImmediate(SP, -frame_size); 3263 AddImmediate(SP, -frame_size);
3317 } 3264 }
3318 3265
3319 3266
3320 // On entry to a function compiled for OSR, the caller's frame pointer, the 3267 // On entry to a function compiled for OSR, the caller's frame pointer, the
3321 // stack locals, and any copied parameters are already in place. The frame 3268 // stack locals, and any copied parameters are already in place. The frame
3322 // pointer is already set up. The PC marker is not correct for the 3269 // pointer is already set up. The PC marker is not correct for the
3323 // optimized function and there may be extra space for spill slots to 3270 // optimized function and there may be extra space for spill slots to
3324 // allocate. We must also set up the pool pointer for the function. 3271 // allocate. We must also set up the pool pointer for the function.
3325 void Assembler::EnterOsrFrame(intptr_t extra_size) { 3272 void Assembler::EnterOsrFrame(intptr_t extra_size) {
3326 const intptr_t offset = CodeSize(); 3273 // The offset for the PC marker is adjusted by the difference in PC offset
3274 // between stores and other instructions. In particular, on some ARMv5's the
3275 // PC offset for stores is 12 and the offset in other instructions is 8.
3276 const intptr_t offset = CodeSize() -
3277 (TargetCPUFeatures::store_pc_read_offset() - Instr::kPCReadOffset);
3327 3278
3328 Comment("EnterOsrFrame"); 3279 Comment("EnterOsrFrame");
3329 mov(IP, Operand(PC)); 3280 mov(IP, Operand(PC));
3330 3281
3331 AddImmediate(IP, -offset); 3282 AddImmediate(IP, -offset);
3332 str(IP, Address(FP, kPcMarkerSlotFromFp * kWordSize)); 3283 str(IP, Address(FP, kPcMarkerSlotFromFp * kWordSize));
3333 3284
3334 // Setup pool pointer for this dart function. 3285 // Setup pool pointer for this dart function.
3335 LoadPoolPointer(); 3286 LoadPoolPointer();
3336 3287
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after
3631 3582
3632 3583
3633 const char* Assembler::FpuRegisterName(FpuRegister reg) { 3584 const char* Assembler::FpuRegisterName(FpuRegister reg) {
3634 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters)); 3585 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters));
3635 return fpu_reg_names[reg]; 3586 return fpu_reg_names[reg];
3636 } 3587 }
3637 3588
3638 } // namespace dart 3589 } // namespace dart
3639 3590
3640 #endif // defined TARGET_ARCH_ARM 3591 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « runtime/vm/assembler_arm.h ('k') | runtime/vm/assembler_arm_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698