OLD | NEW |
---|---|
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 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
418 | 418 |
419 // Return true if this is a register operand. | 419 // Return true if this is a register operand. |
420 INLINE(bool is_reg() const); | 420 INLINE(bool is_reg() const); |
421 | 421 |
422 // Return true if this operand fits in one instruction so that no | 422 // Return true if this operand fits in one instruction so that no |
423 // 2-instruction solution with a load into the ip register is necessary. If | 423 // 2-instruction solution with a load into the ip register is necessary. If |
424 // the instruction this operand is used for is a MOV or MVN instruction the | 424 // the instruction this operand is used for is a MOV or MVN instruction the |
425 // actual instruction to use is required for this calculation. For other | 425 // actual instruction to use is required for this calculation. For other |
426 // instructions instr is ignored. | 426 // instructions instr is ignored. |
427 bool is_single_instruction(const Assembler* assembler, Instr instr = 0) const; | 427 bool is_single_instruction(const Assembler* assembler, Instr instr = 0) const; |
428 bool must_use_constant_pool(const Assembler* assembler) const; | 428 bool must_output_reloc_info(const Assembler* assembler) const; |
429 | 429 |
430 inline int32_t immediate() const { | 430 inline int32_t immediate() const { |
431 ASSERT(!rm_.is_valid()); | 431 ASSERT(!rm_.is_valid()); |
432 return imm32_; | 432 return imm32_; |
433 } | 433 } |
434 | 434 |
435 Register rm() const { return rm_; } | 435 Register rm() const { return rm_; } |
436 Register rs() const { return rs_; } | 436 Register rs() const { return rs_; } |
437 ShiftOp shift_op() const { return shift_op_; } | 437 ShiftOp shift_op() const { return shift_op_; } |
438 | 438 |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
686 void label_at_put(Label* L, int at_offset); | 686 void label_at_put(Label* L, int at_offset); |
687 | 687 |
688 // Return the address in the constant pool of the code target address used by | 688 // Return the address in the constant pool of the code target address used by |
689 // the branch/call instruction at pc. | 689 // the branch/call instruction at pc. |
690 INLINE(static Address target_address_address_at(Address pc)); | 690 INLINE(static Address target_address_address_at(Address pc)); |
691 | 691 |
692 // Read/Modify the code target address in the branch/call instruction at pc. | 692 // Read/Modify the code target address in the branch/call instruction at pc. |
693 INLINE(static Address target_address_at(Address pc)); | 693 INLINE(static Address target_address_at(Address pc)); |
694 INLINE(static void set_target_address_at(Address pc, Address target)); | 694 INLINE(static void set_target_address_at(Address pc, Address target)); |
695 | 695 |
696 INLINE(static Address target_address_from_return_address(Address pc)); | |
Michael Starzinger
2012/10/10 14:19:29
Can we have a one-liner comment of what this metho
danno
2012/10/17 10:04:44
Done.
| |
697 INLINE(static Address return_address_from_call_start(Address pc)); | |
698 | |
696 // This sets the branch destination (which is in the constant pool on ARM). | 699 // This sets the branch destination (which is in the constant pool on ARM). |
697 // This is for calls and branches within generated code. | 700 // This is for calls and branches within generated code. |
698 inline static void deserialization_set_special_target_at( | 701 inline static void deserialization_set_special_target_at( |
699 Address constant_pool_entry, Address target); | 702 Address constant_pool_entry, Address target); |
700 | 703 |
701 // This sets the branch destination (which is in the constant pool on ARM). | 704 // This sets the branch destination (which is in the constant pool on ARM). |
702 // This is for calls and branches to runtime code. | 705 // This is for calls and branches to runtime code. |
703 inline static void set_external_target_at(Address constant_pool_entry, | 706 inline static void set_external_target_at(Address constant_pool_entry, |
704 Address target); | 707 Address target); |
705 | 708 |
706 // Here we are patching the address in the constant pool, not the actual call | 709 // Here we are patching the address in the constant pool, not the actual call |
707 // instruction. The address in the constant pool is the same size as a | 710 // instruction. The address in the constant pool is the same size as a |
708 // pointer. | 711 // pointer. |
709 static const int kSpecialTargetSize = kPointerSize; | 712 static const int kSpecialTargetSize = kPointerSize; |
710 | 713 |
711 // Size of an instruction. | 714 // Size of an instruction. |
712 static const int kInstrSize = sizeof(Instr); | 715 static const int kInstrSize = sizeof(Instr); |
713 | 716 |
714 // Distance between the instruction referring to the address of the call | |
715 // target and the return address. | |
716 #ifdef USE_BLX | |
717 // Call sequence is: | |
718 // ldr ip, [pc, #...] @ call address | |
719 // blx ip | |
720 // @ return address | |
721 static const int kCallTargetAddressOffset = 2 * kInstrSize; | |
722 #else | |
723 // Call sequence is: | |
724 // mov lr, pc | |
725 // ldr pc, [pc, #...] @ call address | |
726 // @ return address | |
727 static const int kCallTargetAddressOffset = kInstrSize; | |
728 #endif | |
729 | |
730 // Distance between start of patched return sequence and the emitted address | 717 // Distance between start of patched return sequence and the emitted address |
731 // to jump to. | 718 // to jump to. |
732 #ifdef USE_BLX | 719 #ifdef USE_BLX |
733 // Patched return sequence is: | 720 // Patched return sequence is: |
734 // ldr ip, [pc, #0] @ emited address and start | 721 // ldr ip, [pc, #0] @ emited address and start |
735 // blx ip | 722 // blx ip |
736 static const int kPatchReturnSequenceAddressOffset = 0 * kInstrSize; | 723 static const int kPatchReturnSequenceAddressOffset = 0 * kInstrSize; |
737 #else | 724 #else |
738 // Patched return sequence is: | 725 // Patched return sequence is: |
739 // mov lr, pc @ start of sequence | 726 // mov lr, pc @ start of sequence |
740 // ldr pc, [pc, #-4] @ emited address | 727 // ldr pc, [pc, #-4] @ emited address |
741 static const int kPatchReturnSequenceAddressOffset = kInstrSize; | 728 static const int kPatchReturnSequenceAddressOffset = kInstrSize; |
742 #endif | 729 #endif |
743 | 730 |
744 // Distance between start of patched debug break slot and the emitted address | 731 // Distance between start of patched debug break slot and the emitted address |
745 // to jump to. | 732 // to jump to. |
746 #ifdef USE_BLX | 733 #ifdef USE_BLX |
747 // Patched debug break slot code is: | 734 // Patched debug break slot code is: |
748 // ldr ip, [pc, #0] @ emited address and start | 735 // ldr ip, [pc, #0] @ emited address and start |
749 // blx ip | 736 // blx ip |
750 static const int kPatchDebugBreakSlotAddressOffset = 0 * kInstrSize; | 737 static const int kPatchDebugBreakSlotAddressOffset = 0 * kInstrSize; |
751 #else | 738 #else |
752 // Patched debug break slot code is: | 739 // Patched debug break slot code is: |
753 // mov lr, pc @ start of sequence | 740 // mov lr, pc @ start of sequence |
754 // ldr pc, [pc, #-4] @ emited address | 741 // ldr pc, [pc, #-4] @ emited address |
755 static const int kPatchDebugBreakSlotAddressOffset = kInstrSize; | 742 static const int kPatchDebugBreakSlotAddressOffset = kInstrSize; |
756 #endif | 743 #endif |
757 | 744 |
745 static const int kPatchDebugBreakSlotReturnOffset = 2 * kInstrSize; | |
746 | |
758 // Difference between address of current opcode and value read from pc | 747 // Difference between address of current opcode and value read from pc |
759 // register. | 748 // register. |
760 static const int kPcLoadDelta = 8; | 749 static const int kPcLoadDelta = 8; |
761 | 750 |
762 static const int kJSReturnSequenceInstructions = 4; | 751 static const int kJSReturnSequenceInstructions = 4; |
763 static const int kDebugBreakSlotInstructions = 3; | 752 static const int kDebugBreakSlotInstructions = 3; |
764 static const int kDebugBreakSlotLength = | 753 static const int kDebugBreakSlotLength = |
765 kDebugBreakSlotInstructions * kInstrSize; | 754 kDebugBreakSlotInstructions * kInstrSize; |
766 | 755 |
767 // --------------------------------------------------------------------------- | 756 // --------------------------------------------------------------------------- |
(...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1175 | 1164 |
1176 void pop() { | 1165 void pop() { |
1177 add(sp, sp, Operand(kPointerSize)); | 1166 add(sp, sp, Operand(kPointerSize)); |
1178 } | 1167 } |
1179 | 1168 |
1180 // Jump unconditionally to given label. | 1169 // Jump unconditionally to given label. |
1181 void jmp(Label* L) { b(L, al); } | 1170 void jmp(Label* L) { b(L, al); } |
1182 | 1171 |
1183 bool predictable_code_size() const { return predictable_code_size_; } | 1172 bool predictable_code_size() const { return predictable_code_size_; } |
1184 | 1173 |
1174 static bool allow_immediate_constant_pool_loads( | |
1175 const Assembler* assembler) { | |
1176 return CpuFeatures::IsSupported(ARMv7) && | |
1177 (assembler == NULL || !assembler->predictable_code_size()); | |
1178 } | |
1179 | |
1185 // Check the code size generated from label to here. | 1180 // Check the code size generated from label to here. |
1186 int SizeOfCodeGeneratedSince(Label* label) { | 1181 int SizeOfCodeGeneratedSince(Label* label) { |
1187 return pc_offset() - label->pos(); | 1182 return pc_offset() - label->pos(); |
1188 } | 1183 } |
1189 | 1184 |
1190 // Check the number of instructions generated from label to here. | 1185 // Check the number of instructions generated from label to here. |
1191 int InstructionsGeneratedSince(Label* label) { | 1186 int InstructionsGeneratedSince(Label* label) { |
1192 return SizeOfCodeGeneratedSince(label) / kInstrSize; | 1187 return SizeOfCodeGeneratedSince(label) / kInstrSize; |
1193 } | 1188 } |
1194 | 1189 |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1295 static bool IsLdrRegFpOffset(Instr instr); | 1290 static bool IsLdrRegFpOffset(Instr instr); |
1296 static bool IsStrRegFpNegOffset(Instr instr); | 1291 static bool IsStrRegFpNegOffset(Instr instr); |
1297 static bool IsLdrRegFpNegOffset(Instr instr); | 1292 static bool IsLdrRegFpNegOffset(Instr instr); |
1298 static bool IsLdrPcImmediateOffset(Instr instr); | 1293 static bool IsLdrPcImmediateOffset(Instr instr); |
1299 static bool IsTstImmediate(Instr instr); | 1294 static bool IsTstImmediate(Instr instr); |
1300 static bool IsCmpRegister(Instr instr); | 1295 static bool IsCmpRegister(Instr instr); |
1301 static bool IsCmpImmediate(Instr instr); | 1296 static bool IsCmpImmediate(Instr instr); |
1302 static Register GetCmpImmediateRegister(Instr instr); | 1297 static Register GetCmpImmediateRegister(Instr instr); |
1303 static int GetCmpImmediateRawImmediate(Instr instr); | 1298 static int GetCmpImmediateRawImmediate(Instr instr); |
1304 static bool IsNop(Instr instr, int type = NON_MARKING_NOP); | 1299 static bool IsNop(Instr instr, int type = NON_MARKING_NOP); |
1300 static bool IsMovT(Instr instr); | |
1301 static bool IsMovW(Instr instr); | |
1305 | 1302 |
1306 // Constants in pools are accessed via pc relative addressing, which can | 1303 // Constants in pools are accessed via pc relative addressing, which can |
1307 // reach +/-4KB thereby defining a maximum distance between the instruction | 1304 // reach +/-4KB thereby defining a maximum distance between the instruction |
1308 // and the accessed constant. | 1305 // and the accessed constant. |
1309 static const int kMaxDistToPool = 4*KB; | 1306 static const int kMaxDistToPool = 4*KB; |
1310 static const int kMaxNumPendingRelocInfo = kMaxDistToPool/kInstrSize; | 1307 static const int kMaxNumPendingRelocInfo = kMaxDistToPool/kInstrSize; |
1311 | 1308 |
1312 // Postpone the generation of the constant pool for the specified number of | 1309 // Postpone the generation of the constant pool for the specified number of |
1313 // instructions. | 1310 // instructions. |
1314 void BlockConstPoolFor(int instructions); | 1311 void BlockConstPoolFor(int instructions); |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1433 int num_pending_reloc_info_; | 1430 int num_pending_reloc_info_; |
1434 | 1431 |
1435 // The bound position, before this we cannot do instruction elimination. | 1432 // The bound position, before this we cannot do instruction elimination. |
1436 int last_bound_pos_; | 1433 int last_bound_pos_; |
1437 | 1434 |
1438 // Code emission | 1435 // Code emission |
1439 inline void CheckBuffer(); | 1436 inline void CheckBuffer(); |
1440 void GrowBuffer(); | 1437 void GrowBuffer(); |
1441 inline void emit(Instr x); | 1438 inline void emit(Instr x); |
1442 | 1439 |
1440 // 32-bit immediate values | |
1441 void move_32_bit_immediate(Condition cond, | |
1442 Register rd, | |
1443 SBit s, | |
1444 const Operand& x); | |
1445 | |
1443 // Instruction generation | 1446 // Instruction generation |
1444 void addrmod1(Instr instr, Register rn, Register rd, const Operand& x); | 1447 void addrmod1(Instr instr, Register rn, Register rd, const Operand& x); |
1445 void addrmod2(Instr instr, Register rd, const MemOperand& x); | 1448 void addrmod2(Instr instr, Register rd, const MemOperand& x); |
1446 void addrmod3(Instr instr, Register rd, const MemOperand& x); | 1449 void addrmod3(Instr instr, Register rd, const MemOperand& x); |
1447 void addrmod4(Instr instr, Register rn, RegList rl); | 1450 void addrmod4(Instr instr, Register rn, RegList rl); |
1448 void addrmod5(Instr instr, CRegister crd, const MemOperand& x); | 1451 void addrmod5(Instr instr, CRegister crd, const MemOperand& x); |
1449 | 1452 |
1450 // Labels | 1453 // Labels |
1451 void print(Label* L); | 1454 void print(Label* L); |
1452 void bind_to(Label* L, int pos); | 1455 void bind_to(Label* L, int pos); |
1453 void link_to(Label* L, Label* appendix); | 1456 void link_to(Label* L, Label* appendix); |
1454 void next(Label* L); | 1457 void next(Label* L); |
1455 | 1458 |
1459 enum UseConstantPoolMode { | |
1460 USE_CONSTANT_POOL, | |
1461 DONT_USE_CONSTANT_POOL | |
1462 }; | |
1463 | |
1456 // Record reloc info for current pc_ | 1464 // Record reloc info for current pc_ |
1457 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); | 1465 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0, |
1466 UseConstantPoolMode mode = USE_CONSTANT_POOL); | |
1458 | 1467 |
1459 friend class RegExpMacroAssemblerARM; | 1468 friend class RegExpMacroAssemblerARM; |
1460 friend class RelocInfo; | 1469 friend class RelocInfo; |
1461 friend class CodePatcher; | 1470 friend class CodePatcher; |
1462 friend class BlockConstPoolScope; | 1471 friend class BlockConstPoolScope; |
1463 | 1472 |
1464 PositionsRecorder positions_recorder_; | 1473 PositionsRecorder positions_recorder_; |
1465 | 1474 |
1466 bool emit_debug_code_; | 1475 bool emit_debug_code_; |
1467 bool predictable_code_size_; | 1476 bool predictable_code_size_; |
1468 | 1477 |
1469 friend class PositionsRecorder; | 1478 friend class PositionsRecorder; |
1470 friend class EnsureSpace; | 1479 friend class EnsureSpace; |
1471 }; | 1480 }; |
1472 | 1481 |
1473 | 1482 |
1474 class EnsureSpace BASE_EMBEDDED { | 1483 class EnsureSpace BASE_EMBEDDED { |
1475 public: | 1484 public: |
1476 explicit EnsureSpace(Assembler* assembler) { | 1485 explicit EnsureSpace(Assembler* assembler) { |
1477 assembler->CheckBuffer(); | 1486 assembler->CheckBuffer(); |
1478 } | 1487 } |
1479 }; | 1488 }; |
1480 | 1489 |
1481 | 1490 |
1491 class ScopedPredictableCodeSize { | |
Michael Starzinger
2012/10/10 14:19:29
I would call this PredictableCodeSizeScope instead
danno
2012/10/17 10:04:44
Done.
| |
1492 public: | |
1493 explicit ScopedPredictableCodeSize(Assembler* assembler) | |
1494 : asm_(assembler) { | |
1495 old_value_ = assembler->predictable_code_size(); | |
1496 assembler->set_predictable_code_size(true); | |
1497 } | |
1498 | |
1499 ~ScopedPredictableCodeSize() { | |
1500 if (!old_value_) { | |
1501 asm_->set_predictable_code_size(false); | |
1502 } | |
1503 } | |
1504 | |
1505 private: | |
1506 Assembler* asm_; | |
1507 bool old_value_; | |
1508 }; | |
1509 | |
1510 | |
1482 } } // namespace v8::internal | 1511 } } // namespace v8::internal |
1483 | 1512 |
1484 #endif // V8_ARM_ASSEMBLER_ARM_H_ | 1513 #endif // V8_ARM_ASSEMBLER_ARM_H_ |
OLD | NEW |