MozInstructions-vixl.cpp (6449B)
1 // Copyright 2013, ARM Limited 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are met: 6 // 7 // * Redistributions of source code must retain the above copyright notice, 8 // this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above copyright notice, 10 // this list of conditions and the following disclaimer in the documentation 11 // and/or other materials provided with the distribution. 12 // * Neither the name of ARM Limited nor the names of its contributors may be 13 // used to endorse or promote products derived from this software without 14 // specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND 17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 27 #include "jit/arm64/Architecture-arm64.h" 28 #include "jit/arm64/vixl/Assembler-vixl.h" 29 #include "jit/arm64/vixl/Instructions-vixl.h" 30 31 namespace vixl { 32 33 bool Instruction::IsUncondB() const { 34 return Mask(UnconditionalBranchMask) == (UnconditionalBranchFixed | B); 35 } 36 37 38 bool Instruction::IsCondB() const { 39 return Mask(ConditionalBranchMask) == (ConditionalBranchFixed | B_cond); 40 } 41 42 43 bool Instruction::IsBL() const { 44 return Mask(UnconditionalBranchMask) == (UnconditionalBranchFixed | BL); 45 } 46 47 48 bool Instruction::IsBR() const { 49 return Mask(UnconditionalBranchToRegisterMask) == (UnconditionalBranchToRegisterFixed | BR); 50 } 51 52 53 bool Instruction::IsBLR() const { 54 return Mask(UnconditionalBranchToRegisterMask) == (UnconditionalBranchToRegisterFixed | BLR); 55 } 56 57 58 bool Instruction::IsTBZ() const { 59 return Mask(TestBranchMask) == TBZ; 60 } 61 62 63 bool Instruction::IsTBNZ() const { 64 return Mask(TestBranchMask) == TBNZ; 65 } 66 67 68 bool Instruction::IsCBZ() const { 69 return Mask(CompareBranchMask) == CBZ_w || Mask(CompareBranchMask) == CBZ_x; 70 } 71 72 73 bool Instruction::IsCBNZ() const { 74 return Mask(CompareBranchMask) == CBNZ_w || Mask(CompareBranchMask) == CBNZ_x; 75 } 76 77 78 bool Instruction::IsLDR() const { 79 return Mask(LoadLiteralMask) == LDR_x_lit; 80 } 81 82 83 bool Instruction::IsNOP() const { 84 return Mask(SystemHintMask) == HINT && ImmHint() == NOP; 85 } 86 87 88 bool Instruction::IsCSDB() const { 89 return Mask(SystemHintMask) == HINT && ImmHint() == CSDB; 90 } 91 92 93 bool Instruction::IsADR() const { 94 return Mask(PCRelAddressingMask) == ADR; 95 } 96 97 98 bool Instruction::IsADRP() const { 99 return Mask(PCRelAddressingMask) == ADRP; 100 } 101 102 103 bool Instruction::IsMovz() const { 104 return (Mask(MoveWideImmediateMask) == MOVZ_x) || 105 (Mask(MoveWideImmediateMask) == MOVZ_w); 106 } 107 108 109 bool Instruction::IsMovk() const { 110 return (Mask(MoveWideImmediateMask) == MOVK_x) || 111 (Mask(MoveWideImmediateMask) == MOVK_w); 112 } 113 114 bool Instruction::IsBranchLinkImm() const { 115 return Mask(UnconditionalBranchFMask) == (UnconditionalBranchFixed | BL); 116 } 117 118 119 bool Instruction::IsTargetReachable(const Instruction* target) const { 120 VIXL_ASSERT(((target - this) & 3) == 0); 121 int offset = (target - this) >> kInstructionSizeLog2; 122 switch (BranchType()) { 123 case CondBranchType: 124 return IsInt19(offset); 125 case UncondBranchType: 126 return IsInt26(offset); 127 case CompareBranchType: 128 return IsInt19(offset); 129 case TestBranchType: 130 return IsInt14(offset); 131 default: 132 VIXL_UNREACHABLE(); 133 } 134 } 135 136 137 ptrdiff_t Instruction::ImmPCRawOffset() const { 138 ptrdiff_t offset; 139 if (IsPCRelAddressing()) { 140 // ADR and ADRP. 141 offset = ImmPCRel(); 142 } else if (BranchType() == UnknownBranchType) { 143 offset = ImmLLiteral(); 144 } else { 145 offset = ImmBranch(); 146 } 147 return offset; 148 } 149 150 void 151 Instruction::SetImmPCRawOffset(ptrdiff_t offset) 152 { 153 if (IsPCRelAddressing()) { 154 // ADR and ADRP. We're encoding a raw offset here. 155 // See also SetPCRelImmTarget(). 156 Instr imm = vixl::Assembler::ImmPCRelAddress(offset); 157 SetInstructionBits(Mask(~ImmPCRel_mask) | imm); 158 } else { 159 SetBranchImmTarget(this + (offset << kInstructionSizeLog2)); 160 } 161 } 162 163 // Is this a stack pointer synchronization instruction as inserted by 164 // MacroAssembler::syncStackPtr()? 165 bool 166 Instruction::IsStackPtrSync() const 167 { 168 // The stack pointer sync is a move to the stack pointer. 169 // This is encoded as 'add sp, Rs, #0'. 170 return IsAddSubImmediate() && Rd() == js::jit::Registers::sp && ImmAddSub() == 0; 171 } 172 173 // Skip over a constant pool at |this| if there is one. 174 // 175 // If |this| is pointing to the artifical guard branch around a constant pool, 176 // return the instruction after the pool. Otherwise return |this| itself. 177 // 178 // This function does not skip constant pools with a natural guard branch. It 179 // is assumed that anyone inspecting the instruction stream understands about 180 // branches that were inserted naturally. 181 const Instruction* 182 Instruction::skipPool() const 183 { 184 // Artificial pool guards can only be B (rather than BR), and they must be 185 // forward branches. 186 if (!IsUncondB() || ImmUncondBranch() <= 0) 187 return this; 188 189 // Check for a constant pool header which has the high 16 bits set. See 190 // struct PoolHeader. Bit 15 indicates a natural pool guard when set. It 191 // must be clear which indicates an artificial pool guard. 192 const Instruction *header = InstructionAtOffset(kInstructionSize); 193 if (header->Mask(0xffff8000) != 0xffff0000) 194 return this; 195 196 // OK, this is an artificial jump around a constant pool. 197 return ImmPCOffsetTarget(); 198 } 199 200 201 void Instruction::SetBits32(int msb, int lsb, unsigned value) { 202 uint32_t me; 203 memcpy(&me, this, sizeof(me)); 204 uint32_t new_mask = (1 << (msb+1)) - (1 << lsb); 205 uint32_t keep_mask = ~new_mask; 206 me = (me & keep_mask) | ((value << lsb) & new_mask); 207 memcpy(this, &me, sizeof(me)); 208 } 209 210 211 } // namespace vixl