Chromium Code Reviews| 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 |