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

Side by Side Diff: src/arm/assembler-arm.cc

Issue 153773002: A64: Synchronize with r16679. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 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 | « src/arm/assembler-arm.h ('k') | src/arm/assembler-arm-inl.h » ('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) 1994-2006 Sun Microsystems Inc. 1 // Copyright (c) 1994-2006 Sun Microsystems Inc.
2 // All Rights Reserved. 2 // All Rights Reserved.
3 // 3 //
4 // Redistribution and use in source and binary forms, with or without 4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions 5 // modification, are permitted provided that the following conditions
6 // are met: 6 // are met:
7 // 7 //
8 // - Redistributions of source code must retain the above copyright notice, 8 // - Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer. 9 // this list of conditions and the following disclaimer.
10 // 10 //
(...skipping 21 matching lines...) Expand all
32 32
33 // The original source code covered by the above license above has been 33 // The original source code covered by the above license above has been
34 // modified significantly by Google Inc. 34 // modified significantly by Google Inc.
35 // Copyright 2012 the V8 project authors. All rights reserved. 35 // Copyright 2012 the V8 project authors. All rights reserved.
36 36
37 #include "v8.h" 37 #include "v8.h"
38 38
39 #if V8_TARGET_ARCH_ARM 39 #if V8_TARGET_ARCH_ARM
40 40
41 #include "arm/assembler-arm-inl.h" 41 #include "arm/assembler-arm-inl.h"
42 #include "macro-assembler.h"
42 #include "serialize.h" 43 #include "serialize.h"
43 44
44 namespace v8 { 45 namespace v8 {
45 namespace internal { 46 namespace internal {
46 47
47 #ifdef DEBUG 48 #ifdef DEBUG
48 bool CpuFeatures::initialized_ = false; 49 bool CpuFeatures::initialized_ = false;
49 #endif 50 #endif
50 unsigned CpuFeatures::supported_ = 0; 51 unsigned CpuFeatures::supported_ = 0;
51 unsigned CpuFeatures::found_by_runtime_probing_only_ = 0; 52 unsigned CpuFeatures::found_by_runtime_probing_only_ = 0;
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 // Patch the code at the current address with a call to the target. 318 // Patch the code at the current address with a call to the target.
318 UNIMPLEMENTED(); 319 UNIMPLEMENTED();
319 } 320 }
320 321
321 322
322 // ----------------------------------------------------------------------------- 323 // -----------------------------------------------------------------------------
323 // Implementation of Operand and MemOperand 324 // Implementation of Operand and MemOperand
324 // See assembler-arm-inl.h for inlined constructors 325 // See assembler-arm-inl.h for inlined constructors
325 326
326 Operand::Operand(Handle<Object> handle) { 327 Operand::Operand(Handle<Object> handle) {
327 #ifdef DEBUG
328 Isolate* isolate = Isolate::Current();
329 #endif
330 AllowDeferredHandleDereference using_raw_address; 328 AllowDeferredHandleDereference using_raw_address;
331 rm_ = no_reg; 329 rm_ = no_reg;
332 // Verify all Objects referred by code are NOT in new space. 330 // Verify all Objects referred by code are NOT in new space.
333 Object* obj = *handle; 331 Object* obj = *handle;
334 ASSERT(!isolate->heap()->InNewSpace(obj));
335 if (obj->IsHeapObject()) { 332 if (obj->IsHeapObject()) {
333 ASSERT(!HeapObject::cast(obj)->GetHeap()->InNewSpace(obj));
336 imm32_ = reinterpret_cast<intptr_t>(handle.location()); 334 imm32_ = reinterpret_cast<intptr_t>(handle.location());
337 rmode_ = RelocInfo::EMBEDDED_OBJECT; 335 rmode_ = RelocInfo::EMBEDDED_OBJECT;
338 } else { 336 } else {
339 // no relocation needed 337 // no relocation needed
340 imm32_ = reinterpret_cast<intptr_t>(obj); 338 imm32_ = reinterpret_cast<intptr_t>(obj);
341 rmode_ = RelocInfo::NONE32; 339 rmode_ = RelocInfo::NONE32;
342 } 340 }
343 } 341 }
344 342
345 343
(...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after
771 // The linked labels form a link chain by making the branch offset 769 // The linked labels form a link chain by making the branch offset
772 // in the instruction steam to point to the previous branch 770 // in the instruction steam to point to the previous branch
773 // instruction using the same label. 771 // instruction using the same label.
774 // 772 //
775 // The link chain is terminated by a branch offset pointing to the 773 // The link chain is terminated by a branch offset pointing to the
776 // same position. 774 // same position.
777 775
778 776
779 int Assembler::target_at(int pos) { 777 int Assembler::target_at(int pos) {
780 Instr instr = instr_at(pos); 778 Instr instr = instr_at(pos);
781 if ((instr & ~kImm24Mask) == 0) { 779 if (is_uint24(instr)) {
782 // Emitted label constant, not part of a branch. 780 // Emitted link to a label, not part of a branch.
783 return instr - (Code::kHeaderSize - kHeapObjectTag); 781 return instr;
784 } 782 }
785 ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx imm24 783 ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx imm24
786 int imm26 = ((instr & kImm24Mask) << 8) >> 6; 784 int imm26 = ((instr & kImm24Mask) << 8) >> 6;
787 if ((Instruction::ConditionField(instr) == kSpecialCondition) && 785 if ((Instruction::ConditionField(instr) == kSpecialCondition) &&
788 ((instr & B24) != 0)) { 786 ((instr & B24) != 0)) {
789 // blx uses bit 24 to encode bit 2 of imm26 787 // blx uses bit 24 to encode bit 2 of imm26
790 imm26 += 2; 788 imm26 += 2;
791 } 789 }
792 return pos + kPcLoadDelta + imm26; 790 return pos + kPcLoadDelta + imm26;
793 } 791 }
794 792
795 793
796 void Assembler::target_at_put(int pos, int target_pos) { 794 void Assembler::target_at_put(int pos, int target_pos) {
797 Instr instr = instr_at(pos); 795 Instr instr = instr_at(pos);
798 if ((instr & ~kImm24Mask) == 0) { 796 if (is_uint24(instr)) {
799 ASSERT(target_pos == pos || target_pos >= 0); 797 ASSERT(target_pos == pos || target_pos >= 0);
800 // Emitted label constant, not part of a branch. 798 // Emitted link to a label, not part of a branch.
801 // Make label relative to Code* of generated Code object. 799 // Load the position of the label relative to the generated code object
802 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag)); 800 // pointer in a register.
801
802 // Here are the instructions we need to emit:
803 // For ARMv7: target24 => target16_1:target16_0
804 // movw dst, #target16_0
805 // movt dst, #target16_1
806 // For ARMv6: target24 => target8_2:target8_1:target8_0
807 // mov dst, #target8_0
808 // orr dst, dst, #target8_1 << 8
809 // orr dst, dst, #target8_2 << 16
810
811 // We extract the destination register from the emitted nop instruction.
812 Register dst = Register::from_code(
813 Instruction::RmValue(instr_at(pos + kInstrSize)));
814 ASSERT(IsNop(instr_at(pos + kInstrSize), dst.code()));
815 uint32_t target24 = target_pos + (Code::kHeaderSize - kHeapObjectTag);
816 ASSERT(is_uint24(target24));
817 if (is_uint8(target24)) {
818 // If the target fits in a byte then only patch with a mov
819 // instruction.
820 CodePatcher patcher(reinterpret_cast<byte*>(buffer_ + pos),
821 1,
822 CodePatcher::DONT_FLUSH);
823 patcher.masm()->mov(dst, Operand(target24));
824 } else {
825 uint16_t target16_0 = target24 & kImm16Mask;
826 uint16_t target16_1 = target24 >> 16;
827 if (CpuFeatures::IsSupported(ARMv7)) {
828 // Patch with movw/movt.
829 if (target16_1 == 0) {
830 CodePatcher patcher(reinterpret_cast<byte*>(buffer_ + pos),
831 1,
832 CodePatcher::DONT_FLUSH);
833 patcher.masm()->movw(dst, target16_0);
834 } else {
835 CodePatcher patcher(reinterpret_cast<byte*>(buffer_ + pos),
836 2,
837 CodePatcher::DONT_FLUSH);
838 patcher.masm()->movw(dst, target16_0);
839 patcher.masm()->movt(dst, target16_1);
840 }
841 } else {
842 // Patch with a sequence of mov/orr/orr instructions.
843 uint8_t target8_0 = target16_0 & kImm8Mask;
844 uint8_t target8_1 = target16_0 >> 8;
845 uint8_t target8_2 = target16_1 & kImm8Mask;
846 if (target8_2 == 0) {
847 CodePatcher patcher(reinterpret_cast<byte*>(buffer_ + pos),
848 2,
849 CodePatcher::DONT_FLUSH);
850 patcher.masm()->mov(dst, Operand(target8_0));
851 patcher.masm()->orr(dst, dst, Operand(target8_1 << 8));
852 } else {
853 CodePatcher patcher(reinterpret_cast<byte*>(buffer_ + pos),
854 3,
855 CodePatcher::DONT_FLUSH);
856 patcher.masm()->mov(dst, Operand(target8_0));
857 patcher.masm()->orr(dst, dst, Operand(target8_1 << 8));
858 patcher.masm()->orr(dst, dst, Operand(target8_2 << 16));
859 }
860 }
861 }
803 return; 862 return;
804 } 863 }
805 int imm26 = target_pos - (pos + kPcLoadDelta); 864 int imm26 = target_pos - (pos + kPcLoadDelta);
806 ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx imm24 865 ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx imm24
807 if (Instruction::ConditionField(instr) == kSpecialCondition) { 866 if (Instruction::ConditionField(instr) == kSpecialCondition) {
808 // blx uses bit 24 to encode bit 2 of imm26 867 // blx uses bit 24 to encode bit 2 of imm26
809 ASSERT((imm26 & 1) == 0); 868 ASSERT((imm26 & 1) == 0);
810 instr = (instr & ~(B24 | kImm24Mask)) | ((imm26 & 2) >> 1)*B24; 869 instr = (instr & ~(B24 | kImm24Mask)) | ((imm26 & 2) >> 1)*B24;
811 } else { 870 } else {
812 ASSERT((imm26 & 3) == 0); 871 ASSERT((imm26 & 3) == 0);
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after
1225 L->link_to(pc_offset()); 1284 L->link_to(pc_offset());
1226 } 1285 }
1227 1286
1228 // Block the emission of the constant pool, since the branch instruction must 1287 // Block the emission of the constant pool, since the branch instruction must
1229 // be emitted at the pc offset recorded by the label. 1288 // be emitted at the pc offset recorded by the label.
1230 BlockConstPoolFor(1); 1289 BlockConstPoolFor(1);
1231 return target_pos - (pc_offset() + kPcLoadDelta); 1290 return target_pos - (pc_offset() + kPcLoadDelta);
1232 } 1291 }
1233 1292
1234 1293
1235 void Assembler::label_at_put(Label* L, int at_offset) {
1236 int target_pos;
1237 ASSERT(!L->is_bound());
1238 if (L->is_linked()) {
1239 // Point to previous instruction that uses the link.
1240 target_pos = L->pos();
1241 } else {
1242 // First entry of the link chain points to itself.
1243 target_pos = at_offset;
1244 }
1245 L->link_to(at_offset);
1246 instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag));
1247 }
1248
1249
1250 // Branch instructions. 1294 // Branch instructions.
1251 void Assembler::b(int branch_offset, Condition cond) { 1295 void Assembler::b(int branch_offset, Condition cond) {
1252 ASSERT((branch_offset & 3) == 0); 1296 ASSERT((branch_offset & 3) == 0);
1253 int imm24 = branch_offset >> 2; 1297 int imm24 = branch_offset >> 2;
1254 ASSERT(is_int24(imm24)); 1298 ASSERT(is_int24(imm24));
1255 emit(cond | B27 | B25 | (imm24 & kImm24Mask)); 1299 emit(cond | B27 | B25 | (imm24 & kImm24Mask));
1256 1300
1257 if (cond == al) { 1301 if (cond == al) {
1258 // Dead code is a good location to emit the constant pool. 1302 // Dead code is a good location to emit the constant pool.
1259 CheckConstPool(false, false); 1303 CheckConstPool(false, false);
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
1382 positions_recorder()->WriteRecordedPositions(); 1426 positions_recorder()->WriteRecordedPositions();
1383 } 1427 }
1384 // Don't allow nop instructions in the form mov rn, rn to be generated using 1428 // Don't allow nop instructions in the form mov rn, rn to be generated using
1385 // the mov instruction. They must be generated using nop(int/NopMarkerTypes) 1429 // the mov instruction. They must be generated using nop(int/NopMarkerTypes)
1386 // or MarkCode(int/NopMarkerTypes) pseudo instructions. 1430 // or MarkCode(int/NopMarkerTypes) pseudo instructions.
1387 ASSERT(!(src.is_reg() && src.rm().is(dst) && s == LeaveCC && cond == al)); 1431 ASSERT(!(src.is_reg() && src.rm().is(dst) && s == LeaveCC && cond == al));
1388 addrmod1(cond | MOV | s, r0, dst, src); 1432 addrmod1(cond | MOV | s, r0, dst, src);
1389 } 1433 }
1390 1434
1391 1435
1436 void Assembler::mov_label_offset(Register dst, Label* label) {
1437 if (label->is_bound()) {
1438 mov(dst, Operand(label->pos() + (Code::kHeaderSize - kHeapObjectTag)));
1439 } else {
1440 // Emit the link to the label in the code stream followed by extra nop
1441 // instructions.
1442 // If the label is not linked, then start a new link chain by linking it to
1443 // itself, emitting pc_offset().
1444 int link = label->is_linked() ? label->pos() : pc_offset();
1445 label->link_to(pc_offset());
1446
1447 // When the label is bound, these instructions will be patched with a
1448 // sequence of movw/movt or mov/orr/orr instructions. They will load the
1449 // destination register with the position of the label from the beginning
1450 // of the code.
1451 //
1452 // The link will be extracted from the first instruction and the destination
1453 // register from the second.
1454 // For ARMv7:
1455 // link
1456 // mov dst, dst
1457 // For ARMv6:
1458 // link
1459 // mov dst, dst
1460 // mov dst, dst
1461 //
1462 // When the label gets bound: target_at extracts the link and target_at_put
1463 // patches the instructions.
1464 ASSERT(is_uint24(link));
1465 BlockConstPoolScope block_const_pool(this);
1466 emit(link);
1467 nop(dst.code());
1468 if (!CpuFeatures::IsSupported(ARMv7)) {
1469 nop(dst.code());
1470 }
1471 }
1472 }
1473
1474
1392 void Assembler::movw(Register reg, uint32_t immediate, Condition cond) { 1475 void Assembler::movw(Register reg, uint32_t immediate, Condition cond) {
1393 ASSERT(immediate < 0x10000); 1476 ASSERT(immediate < 0x10000);
1394 // May use movw if supported, but on unsupported platforms will try to use 1477 // May use movw if supported, but on unsupported platforms will try to use
1395 // equivalent rotated immed_8 value and other tricks before falling back to a 1478 // equivalent rotated immed_8 value and other tricks before falling back to a
1396 // constant pool load. 1479 // constant pool load.
1397 mov(reg, Operand(immediate), LeaveCC, cond); 1480 mov(reg, Operand(immediate), LeaveCC, cond);
1398 } 1481 }
1399 1482
1400 1483
1401 void Assembler::movt(Register reg, uint32_t immediate, Condition cond) { 1484 void Assembler::movt(Register reg, uint32_t immediate, Condition cond) {
(...skipping 1952 matching lines...) Expand 10 before | Expand all | Expand 10 after
3354 3437
3355 // Since a constant pool was just emitted, move the check offset forward by 3438 // Since a constant pool was just emitted, move the check offset forward by
3356 // the standard interval. 3439 // the standard interval.
3357 next_buffer_check_ = pc_offset() + kCheckPoolInterval; 3440 next_buffer_check_ = pc_offset() + kCheckPoolInterval;
3358 } 3441 }
3359 3442
3360 3443
3361 } } // namespace v8::internal 3444 } } // namespace v8::internal
3362 3445
3363 #endif // V8_TARGET_ARCH_ARM 3446 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/assembler-arm.h ('k') | src/arm/assembler-arm-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698