1d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org// Copyright 2013 the V8 project authors. All rights reserved. 2d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org// Use of this source code is governed by a BSD-style license that can be 3d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org// found in the LICENSE file. 4d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org 5d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org#ifndef V8_CRANKSHAFT_ARM64_DELAYED_MASM_ARM64_H_ 6d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org#define V8_CRANKSHAFT_ARM64_DELAYED_MASM_ARM64_H_ 7d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org 8d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org#include "src/crankshaft/lithium.h" 9d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org 10d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgnamespace v8 { 119c55f0f957534144d2b8a64154f0a479249b34behenrik.lundin@webrtc.orgnamespace internal { 129c55f0f957534144d2b8a64154f0a479249b34behenrik.lundin@webrtc.org 13d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgclass LCodeGen; 14d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org 1512dc1a38ca54a000e4fecfbc6d41138b895c9ca5pbos@webrtc.org// This class delays the generation of some instructions. This way, we have a 16d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org// chance to merge two instructions in one (with load/store pair). 1788fbb2d86b33a3886bba1af4d098efa2c19eb1e7henrike@webrtc.org// Each instruction must either: 189c55f0f957534144d2b8a64154f0a479249b34behenrik.lundin@webrtc.org// - merge with the pending instruction and generate just one instruction. 19d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org// - emit the pending instruction and then generate the instruction (or set the 20d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org// pending instruction). 21d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgclass DelayedMasm BASE_EMBEDDED { 22d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org public: 23d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org DelayedMasm(LCodeGen* owner, 24d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org MacroAssembler* masm, 25d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org const Register& scratch_register) 26d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org : cgen_(owner), masm_(masm), scratch_register_(scratch_register), 27d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org scratch_register_used_(false), pending_(kNone), saved_value_(0) { 28d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org#ifdef DEBUG 29d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org pending_register_ = no_reg; 30d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org pending_value_ = 0; 31d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org pending_pc_ = 0; 32d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org scratch_register_acquired_ = false; 33d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org#endif 34d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org } 35d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org ~DelayedMasm() { 36d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org DCHECK(!scratch_register_acquired_); 37d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org DCHECK(!scratch_register_used_); 38d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org DCHECK(!pending()); 39d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org } 40d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org inline void EndDelayedUse(); 41d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org 42dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting const Register& ScratchRegister() { 43d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org scratch_register_used_ = true; 44d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org return scratch_register_; 45d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org } 46d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org bool IsScratchRegister(const CPURegister& reg) { 47d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org return reg.Is(scratch_register_); 48d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org } 49d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org bool scratch_register_used() const { return scratch_register_used_; } 50d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org void reset_scratch_register_used() { scratch_register_used_ = false; } 51dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting // Acquire/Release scratch register for use outside this class. 52d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org void AcquireScratchRegister() { 53d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org EmitPending(); 54d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org ResetSavedValue(); 55d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org#ifdef DEBUG 56d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org DCHECK(!scratch_register_acquired_); 57d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org scratch_register_acquired_ = true; 58d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org#endif 59d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org } 60d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org void ReleaseScratchRegister() { 61cf808d2366e58b33540931d182f36800d9a15b0dHenrik Lundin#ifdef DEBUG 62fd11bbfb56b42f82e18a744a414325db7a56013fhenrik.lundin@webrtc.org DCHECK(scratch_register_acquired_); 63dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting scratch_register_acquired_ = false; 64d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org#endif 65d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org } 66d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org bool pending() { return pending_ != kNone; } 67d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org 68d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org // Extra layer over the macro-assembler instructions (which emits the 69362a55e7b0852a7be95f0d627321503258152551turaj@webrtc.org // potential pending instruction). 70d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org inline void Mov(const Register& rd, 71dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting const Operand& operand, 72d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org DiscardMoveMode discard_mode = kDontDiscardForSameWReg); 73d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org inline void Fmov(FPRegister fd, FPRegister fn); 74d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org inline void Fmov(FPRegister fd, double imm); 75d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org inline void LoadObject(Register result, Handle<Object> object); 76d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org // Instructions which try to merge which the pending instructions. 77cf808d2366e58b33540931d182f36800d9a15b0dHenrik Lundin void StackSlotMove(LOperand* src, LOperand* dst); 78cf808d2366e58b33540931d182f36800d9a15b0dHenrik Lundin // StoreConstant can only be used if the scratch register is not acquired. 79cf808d2366e58b33540931d182f36800d9a15b0dHenrik Lundin void StoreConstant(uint64_t value, const MemOperand& operand); 80cf808d2366e58b33540931d182f36800d9a15b0dHenrik Lundin void Load(const CPURegister& rd, const MemOperand& operand); 81cf808d2366e58b33540931d182f36800d9a15b0dHenrik Lundin void Store(const CPURegister& rd, const MemOperand& operand); 82cf808d2366e58b33540931d182f36800d9a15b0dHenrik Lundin // Emit the potential pending instruction. 83fd11bbfb56b42f82e18a744a414325db7a56013fhenrik.lundin@webrtc.org void EmitPending(); 84d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org // Reset the pending state. 85dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting void ResetPending() { 86dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting pending_ = kNone; 87dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting#ifdef DEBUG 88dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting pending_register_ = no_reg; 89dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting MemOperand tmp; 90d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org pending_address_src_ = tmp; 91d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org pending_address_dst_ = tmp; 92d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org pending_value_ = 0; 93d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org pending_pc_ = 0; 94dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting#endif 95d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org } 96d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org void InitializeRootRegister() { 97d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org masm_->InitializeRootRegister(); 98d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org } 99d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org 100d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org private: 101d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org // Set the saved value and load the ScratchRegister with it. 102d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org void SetSavedValue(uint64_t saved_value) { 103d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org DCHECK(saved_value != 0); 104d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org if (saved_value_ != saved_value) { 105d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org masm_->Mov(ScratchRegister(), saved_value); 106d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org saved_value_ = saved_value; 107d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org } 108d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org } 109d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org // Reset the saved value (i.e. the value of ScratchRegister is no longer 110dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting // known). 111d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org void ResetSavedValue() { 1123c089d751ede283e21e186885eaf705c3257ccd2henrikg saved_value_ = 0; 113d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org } 114d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org 115d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org LCodeGen* cgen_; 1169c55f0f957534144d2b8a64154f0a479249b34behenrik.lundin@webrtc.org MacroAssembler* masm_; 117 118 // Register used to store a constant. 119 Register scratch_register_; 120 bool scratch_register_used_; 121 122 // Sometimes we store or load two values in two contiguous stack slots. 123 // In this case, we try to use the ldp/stp instructions to reduce code size. 124 // To be able to do that, instead of generating directly the instructions, 125 // we register with the following fields that an instruction needs to be 126 // generated. Then with the next instruction, if the instruction is 127 // consistent with the pending one for stp/ldp we generate ldp/stp. Else, 128 // if they are not consistent, we generate the pending instruction and we 129 // register the new instruction (which becomes pending). 130 131 // Enumeration of instructions which can be pending. 132 enum Pending { 133 kNone, 134 kStoreConstant, 135 kLoad, kStore, 136 kStackSlotMove 137 }; 138 // The pending instruction. 139 Pending pending_; 140 // For kLoad, kStore: register which must be loaded/stored. 141 CPURegister pending_register_; 142 // For kLoad, kStackSlotMove: address of the load. 143 MemOperand pending_address_src_; 144 // For kStoreConstant, kStore, kStackSlotMove: address of the store. 145 MemOperand pending_address_dst_; 146 // For kStoreConstant: value to be stored. 147 uint64_t pending_value_; 148 // Value held into the ScratchRegister if the saved_value_ is not 0. 149 // For 0, we use xzr. 150 uint64_t saved_value_; 151#ifdef DEBUG 152 // Address where the pending instruction must be generated. It's only used to 153 // check that nothing else has been generated since we set the pending 154 // instruction. 155 int pending_pc_; 156 // If true, the scratch register has been acquired outside this class. The 157 // scratch register can no longer be used for constants. 158 bool scratch_register_acquired_; 159#endif 160}; 161 162} // namespace internal 163} // namespace v8 164 165#endif // V8_CRANKSHAFT_ARM64_DELAYED_MASM_ARM64_H_ 166