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 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
682 // Returns the branch offset to the given label from the current code position | 682 // Returns the branch offset to the given label from the current code position |
683 // Links the label to the current position if it is still unbound | 683 // Links the label to the current position if it is still unbound |
684 // Manages the jump elimination optimization if the second parameter is true. | 684 // Manages the jump elimination optimization if the second parameter is true. |
685 int branch_offset(Label* L, bool jump_elimination_allowed); | 685 int branch_offset(Label* L, bool jump_elimination_allowed); |
686 | 686 |
687 // Puts a labels target address at the given position. | 687 // Puts a labels target address at the given position. |
688 // The high 8 bits are set to zero. | 688 // The high 8 bits are set to zero. |
689 void label_at_put(Label* L, int at_offset); | 689 void label_at_put(Label* L, int at_offset); |
690 | 690 |
691 // Return the address in the constant pool of the code target address used by | 691 // Return the address in the constant pool of the code target address used by |
692 // the branch/call instruction at pc. | 692 // the branch/call instruction at pc, or the object in a mov. |
693 INLINE(static Address target_address_address_at(Address pc)); | 693 INLINE(static Address target_pointer_address_at(Address pc)); |
| 694 |
| 695 // Read/Modify the pointer in the branch/call/move instruction at pc. |
| 696 INLINE(static Address target_pointer_at(Address pc)); |
| 697 INLINE(static void set_target_pointer_at(Address pc, Address target)); |
694 | 698 |
695 // Read/Modify the code target address in the branch/call instruction at pc. | 699 // Read/Modify the code target address in the branch/call instruction at pc. |
696 INLINE(static Address target_address_at(Address pc)); | 700 INLINE(static Address target_address_at(Address pc)); |
697 INLINE(static void set_target_address_at(Address pc, Address target)); | 701 INLINE(static void set_target_address_at(Address pc, Address target)); |
698 | 702 |
| 703 // Return the code target address at a call site from the return address |
| 704 // of that call in the instruction stream. |
| 705 INLINE(static Address target_address_from_return_address(Address pc)); |
| 706 |
| 707 // Given the address of the beginning of a call, return the address |
| 708 // in the instruction stream that the call will return from. |
| 709 INLINE(static Address return_address_from_call_start(Address pc)); |
| 710 |
699 // This sets the branch destination (which is in the constant pool on ARM). | 711 // This sets the branch destination (which is in the constant pool on ARM). |
700 // This is for calls and branches within generated code. | 712 // This is for calls and branches within generated code. |
701 inline static void deserialization_set_special_target_at( | 713 inline static void deserialization_set_special_target_at( |
702 Address constant_pool_entry, Address target); | 714 Address constant_pool_entry, Address target); |
703 | 715 |
704 // This sets the branch destination (which is in the constant pool on ARM). | 716 // This sets the branch destination (which is in the constant pool on ARM). |
705 // This is for calls and branches to runtime code. | 717 // This is for calls and branches to runtime code. |
706 inline static void set_external_target_at(Address constant_pool_entry, | 718 inline static void set_external_target_at(Address constant_pool_entry, |
707 Address target); | 719 Address target); |
708 | 720 |
709 // Here we are patching the address in the constant pool, not the actual call | 721 // Here we are patching the address in the constant pool, not the actual call |
710 // instruction. The address in the constant pool is the same size as a | 722 // instruction. The address in the constant pool is the same size as a |
711 // pointer. | 723 // pointer. |
712 static const int kSpecialTargetSize = kPointerSize; | 724 static const int kSpecialTargetSize = kPointerSize; |
713 | 725 |
714 // Size of an instruction. | 726 // Size of an instruction. |
715 static const int kInstrSize = sizeof(Instr); | 727 static const int kInstrSize = sizeof(Instr); |
716 | 728 |
717 // Distance between the instruction referring to the address of the call | |
718 // target and the return address. | |
719 #ifdef USE_BLX | |
720 // Call sequence is: | |
721 // ldr ip, [pc, #...] @ call address | |
722 // blx ip | |
723 // @ return address | |
724 static const int kCallTargetAddressOffset = 2 * kInstrSize; | |
725 #else | |
726 // Call sequence is: | |
727 // mov lr, pc | |
728 // ldr pc, [pc, #...] @ call address | |
729 // @ return address | |
730 static const int kCallTargetAddressOffset = kInstrSize; | |
731 #endif | |
732 | |
733 // Distance between start of patched return sequence and the emitted address | 729 // Distance between start of patched return sequence and the emitted address |
734 // to jump to. | 730 // to jump to. |
735 #ifdef USE_BLX | 731 #ifdef USE_BLX |
736 // Patched return sequence is: | 732 // Patched return sequence is: |
737 // ldr ip, [pc, #0] @ emited address and start | 733 // ldr ip, [pc, #0] @ emited address and start |
738 // blx ip | 734 // blx ip |
739 static const int kPatchReturnSequenceAddressOffset = 0 * kInstrSize; | 735 static const int kPatchReturnSequenceAddressOffset = 0 * kInstrSize; |
740 #else | 736 #else |
741 // Patched return sequence is: | 737 // Patched return sequence is: |
742 // mov lr, pc @ start of sequence | 738 // mov lr, pc @ start of sequence |
743 // ldr pc, [pc, #-4] @ emited address | 739 // ldr pc, [pc, #-4] @ emited address |
744 static const int kPatchReturnSequenceAddressOffset = kInstrSize; | 740 static const int kPatchReturnSequenceAddressOffset = kInstrSize; |
745 #endif | 741 #endif |
746 | 742 |
747 // Distance between start of patched debug break slot and the emitted address | 743 // Distance between start of patched debug break slot and the emitted address |
748 // to jump to. | 744 // to jump to. |
749 #ifdef USE_BLX | 745 #ifdef USE_BLX |
750 // Patched debug break slot code is: | 746 // Patched debug break slot code is: |
751 // ldr ip, [pc, #0] @ emited address and start | 747 // ldr ip, [pc, #0] @ emited address and start |
752 // blx ip | 748 // blx ip |
753 static const int kPatchDebugBreakSlotAddressOffset = 0 * kInstrSize; | 749 static const int kPatchDebugBreakSlotAddressOffset = 0 * kInstrSize; |
754 #else | 750 #else |
755 // Patched debug break slot code is: | 751 // Patched debug break slot code is: |
756 // mov lr, pc @ start of sequence | 752 // mov lr, pc @ start of sequence |
757 // ldr pc, [pc, #-4] @ emited address | 753 // ldr pc, [pc, #-4] @ emited address |
758 static const int kPatchDebugBreakSlotAddressOffset = kInstrSize; | 754 static const int kPatchDebugBreakSlotAddressOffset = kInstrSize; |
759 #endif | 755 #endif |
760 | 756 |
| 757 #ifdef USE_BLX |
| 758 static const int kPatchDebugBreakSlotReturnOffset = 2 * kInstrSize; |
| 759 #else |
| 760 static const int kPatchDebugBreakSlotReturnOffset = kInstrSize; |
| 761 #endif |
| 762 |
761 // Difference between address of current opcode and value read from pc | 763 // Difference between address of current opcode and value read from pc |
762 // register. | 764 // register. |
763 static const int kPcLoadDelta = 8; | 765 static const int kPcLoadDelta = 8; |
764 | 766 |
765 static const int kJSReturnSequenceInstructions = 4; | 767 static const int kJSReturnSequenceInstructions = 4; |
766 static const int kDebugBreakSlotInstructions = 3; | 768 static const int kDebugBreakSlotInstructions = 3; |
767 static const int kDebugBreakSlotLength = | 769 static const int kDebugBreakSlotLength = |
768 kDebugBreakSlotInstructions * kInstrSize; | 770 kDebugBreakSlotInstructions * kInstrSize; |
769 | 771 |
770 // --------------------------------------------------------------------------- | 772 // --------------------------------------------------------------------------- |
(...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1178 | 1180 |
1179 void pop() { | 1181 void pop() { |
1180 add(sp, sp, Operand(kPointerSize)); | 1182 add(sp, sp, Operand(kPointerSize)); |
1181 } | 1183 } |
1182 | 1184 |
1183 // Jump unconditionally to given label. | 1185 // Jump unconditionally to given label. |
1184 void jmp(Label* L) { b(L, al); } | 1186 void jmp(Label* L) { b(L, al); } |
1185 | 1187 |
1186 bool predictable_code_size() const { return predictable_code_size_; } | 1188 bool predictable_code_size() const { return predictable_code_size_; } |
1187 | 1189 |
| 1190 static bool allow_immediate_constant_pool_loads( |
| 1191 const Assembler* assembler) { |
| 1192 return CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) && |
| 1193 (assembler == NULL || !assembler->predictable_code_size()); |
| 1194 } |
| 1195 |
1188 // Check the code size generated from label to here. | 1196 // Check the code size generated from label to here. |
1189 int SizeOfCodeGeneratedSince(Label* label) { | 1197 int SizeOfCodeGeneratedSince(Label* label) { |
1190 return pc_offset() - label->pos(); | 1198 return pc_offset() - label->pos(); |
1191 } | 1199 } |
1192 | 1200 |
1193 // Check the number of instructions generated from label to here. | 1201 // Check the number of instructions generated from label to here. |
1194 int InstructionsGeneratedSince(Label* label) { | 1202 int InstructionsGeneratedSince(Label* label) { |
1195 return SizeOfCodeGeneratedSince(label) / kInstrSize; | 1203 return SizeOfCodeGeneratedSince(label) / kInstrSize; |
1196 } | 1204 } |
1197 | 1205 |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1298 static bool IsLdrRegFpOffset(Instr instr); | 1306 static bool IsLdrRegFpOffset(Instr instr); |
1299 static bool IsStrRegFpNegOffset(Instr instr); | 1307 static bool IsStrRegFpNegOffset(Instr instr); |
1300 static bool IsLdrRegFpNegOffset(Instr instr); | 1308 static bool IsLdrRegFpNegOffset(Instr instr); |
1301 static bool IsLdrPcImmediateOffset(Instr instr); | 1309 static bool IsLdrPcImmediateOffset(Instr instr); |
1302 static bool IsTstImmediate(Instr instr); | 1310 static bool IsTstImmediate(Instr instr); |
1303 static bool IsCmpRegister(Instr instr); | 1311 static bool IsCmpRegister(Instr instr); |
1304 static bool IsCmpImmediate(Instr instr); | 1312 static bool IsCmpImmediate(Instr instr); |
1305 static Register GetCmpImmediateRegister(Instr instr); | 1313 static Register GetCmpImmediateRegister(Instr instr); |
1306 static int GetCmpImmediateRawImmediate(Instr instr); | 1314 static int GetCmpImmediateRawImmediate(Instr instr); |
1307 static bool IsNop(Instr instr, int type = NON_MARKING_NOP); | 1315 static bool IsNop(Instr instr, int type = NON_MARKING_NOP); |
| 1316 static bool IsMovT(Instr instr); |
| 1317 static bool IsMovW(Instr instr); |
1308 | 1318 |
1309 // Constants in pools are accessed via pc relative addressing, which can | 1319 // Constants in pools are accessed via pc relative addressing, which can |
1310 // reach +/-4KB thereby defining a maximum distance between the instruction | 1320 // reach +/-4KB thereby defining a maximum distance between the instruction |
1311 // and the accessed constant. | 1321 // and the accessed constant. |
1312 static const int kMaxDistToPool = 4*KB; | 1322 static const int kMaxDistToPool = 4*KB; |
1313 static const int kMaxNumPendingRelocInfo = kMaxDistToPool/kInstrSize; | 1323 static const int kMaxNumPendingRelocInfo = kMaxDistToPool/kInstrSize; |
1314 | 1324 |
1315 // Postpone the generation of the constant pool for the specified number of | 1325 // Postpone the generation of the constant pool for the specified number of |
1316 // instructions. | 1326 // instructions. |
1317 void BlockConstPoolFor(int instructions); | 1327 void BlockConstPoolFor(int instructions); |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1436 int num_pending_reloc_info_; | 1446 int num_pending_reloc_info_; |
1437 | 1447 |
1438 // The bound position, before this we cannot do instruction elimination. | 1448 // The bound position, before this we cannot do instruction elimination. |
1439 int last_bound_pos_; | 1449 int last_bound_pos_; |
1440 | 1450 |
1441 // Code emission | 1451 // Code emission |
1442 inline void CheckBuffer(); | 1452 inline void CheckBuffer(); |
1443 void GrowBuffer(); | 1453 void GrowBuffer(); |
1444 inline void emit(Instr x); | 1454 inline void emit(Instr x); |
1445 | 1455 |
| 1456 // 32-bit immediate values |
| 1457 void move_32_bit_immediate(Condition cond, |
| 1458 Register rd, |
| 1459 SBit s, |
| 1460 const Operand& x); |
| 1461 |
1446 // Instruction generation | 1462 // Instruction generation |
1447 void addrmod1(Instr instr, Register rn, Register rd, const Operand& x); | 1463 void addrmod1(Instr instr, Register rn, Register rd, const Operand& x); |
1448 void addrmod2(Instr instr, Register rd, const MemOperand& x); | 1464 void addrmod2(Instr instr, Register rd, const MemOperand& x); |
1449 void addrmod3(Instr instr, Register rd, const MemOperand& x); | 1465 void addrmod3(Instr instr, Register rd, const MemOperand& x); |
1450 void addrmod4(Instr instr, Register rn, RegList rl); | 1466 void addrmod4(Instr instr, Register rn, RegList rl); |
1451 void addrmod5(Instr instr, CRegister crd, const MemOperand& x); | 1467 void addrmod5(Instr instr, CRegister crd, const MemOperand& x); |
1452 | 1468 |
1453 // Labels | 1469 // Labels |
1454 void print(Label* L); | 1470 void print(Label* L); |
1455 void bind_to(Label* L, int pos); | 1471 void bind_to(Label* L, int pos); |
1456 void link_to(Label* L, Label* appendix); | 1472 void link_to(Label* L, Label* appendix); |
1457 void next(Label* L); | 1473 void next(Label* L); |
1458 | 1474 |
| 1475 enum UseConstantPoolMode { |
| 1476 USE_CONSTANT_POOL, |
| 1477 DONT_USE_CONSTANT_POOL |
| 1478 }; |
| 1479 |
1459 // Record reloc info for current pc_ | 1480 // Record reloc info for current pc_ |
1460 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); | 1481 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0, |
| 1482 UseConstantPoolMode mode = USE_CONSTANT_POOL); |
1461 | 1483 |
1462 friend class RegExpMacroAssemblerARM; | 1484 friend class RegExpMacroAssemblerARM; |
1463 friend class RelocInfo; | 1485 friend class RelocInfo; |
1464 friend class CodePatcher; | 1486 friend class CodePatcher; |
1465 friend class BlockConstPoolScope; | 1487 friend class BlockConstPoolScope; |
1466 | 1488 |
1467 PositionsRecorder positions_recorder_; | 1489 PositionsRecorder positions_recorder_; |
1468 | 1490 |
1469 bool emit_debug_code_; | 1491 bool emit_debug_code_; |
1470 bool predictable_code_size_; | 1492 bool predictable_code_size_; |
1471 | 1493 |
1472 friend class PositionsRecorder; | 1494 friend class PositionsRecorder; |
1473 friend class EnsureSpace; | 1495 friend class EnsureSpace; |
1474 }; | 1496 }; |
1475 | 1497 |
1476 | 1498 |
1477 class EnsureSpace BASE_EMBEDDED { | 1499 class EnsureSpace BASE_EMBEDDED { |
1478 public: | 1500 public: |
1479 explicit EnsureSpace(Assembler* assembler) { | 1501 explicit EnsureSpace(Assembler* assembler) { |
1480 assembler->CheckBuffer(); | 1502 assembler->CheckBuffer(); |
1481 } | 1503 } |
1482 }; | 1504 }; |
1483 | 1505 |
1484 | 1506 |
| 1507 class PredictableCodeSizeScope { |
| 1508 public: |
| 1509 explicit PredictableCodeSizeScope(Assembler* assembler) |
| 1510 : asm_(assembler) { |
| 1511 old_value_ = assembler->predictable_code_size(); |
| 1512 assembler->set_predictable_code_size(true); |
| 1513 } |
| 1514 |
| 1515 ~PredictableCodeSizeScope() { |
| 1516 if (!old_value_) { |
| 1517 asm_->set_predictable_code_size(false); |
| 1518 } |
| 1519 } |
| 1520 |
| 1521 private: |
| 1522 Assembler* asm_; |
| 1523 bool old_value_; |
| 1524 }; |
| 1525 |
| 1526 |
1485 } } // namespace v8::internal | 1527 } } // namespace v8::internal |
1486 | 1528 |
1487 #endif // V8_ARM_ASSEMBLER_ARM_H_ | 1529 #endif // V8_ARM_ASSEMBLER_ARM_H_ |
OLD | NEW |