1// -*- mode:c++ -*- 2 3// Copyright (c) 2010-2012, 2014 ARM Limited 4// All rights reserved 5// 6// The license below extends only to copyright in the software and shall 7// not be construed as granting a license to any other intellectual 8// property including but not limited to intellectual property relating 9// to a hardware implementation of the functionality of the software 10// licensed hereunder. You may use the software subject to the license 11// terms below provided that you ensure that this notice is replicated 12// unmodified and in its entirety in all distributions of the software, 13// modified or unmodified, in source code or in binary form. 14// 15// Redistribution and use in source and binary forms, with or without 16// modification, are permitted provided that the following conditions are 17// met: redistributions of source code must retain the above copyright 18// notice, this list of conditions and the following disclaimer; 19// redistributions in binary form must reproduce the above copyright 20// notice, this list of conditions and the following disclaimer in the 21// documentation and/or other materials provided with the distribution; 22// neither the name of the copyright holders nor the names of its 23// contributors may be used to endorse or promote products derived from 24// this software without specific prior written permission. 25// 26// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37// 38// Authors: Gabe Black 39 40let {{ 41 42 header_output = "" 43 decoder_output = "" 44 exec_output = "" 45 46 # B, BL 47 for (mnem, link) in (("b", False), ("bl", True)): 48 bCode = ''' 49 NPC = (uint32_t)(PC + imm); 50 ''' 51 br_tgt_code = '''pcs.instNPC((uint32_t)(branchPC.instPC() + imm));''' 52 instFlags = ["IsDirectControl"] 53 if (link): 54 bCode += ''' 55 if (Thumb) 56 LR = PC | 1; 57 else 58 LR = PC - 4; 59 ''' 60 instFlags += ["IsCall"] 61 62 63 bIop = InstObjParams(mnem, mnem.capitalize(), "BranchImmCond", 64 {"code": bCode, "predicate_test": predicateTest, 65 "brTgtCode" : br_tgt_code}, instFlags) 66 header_output += BranchImmCondDeclare.subst(bIop) 67 decoder_output += BranchImmCondConstructor.subst(bIop) + \ 68 BranchTarget.subst(bIop) 69 exec_output += PredOpExecute.subst(bIop) 70 71 # BX, BLX 72 blxCode = ''' 73 %(link)s 74 // Switch modes 75 %(branch)s 76 ''' 77 78 blxList = (("blx", True, True), 79 ("blx", False, True), 80 ("bx", False, False)) 81 82 for (mnem, imm, link) in blxList: 83 Name = mnem.capitalize() 84 isRasPop = 0 85 if imm: 86 Name += "Imm" 87 # Since we're switching ISAs, the target ISA will be the opposite 88 # of the current ISA. Thumb is whether the target is ARM. 89 newPC = '(uint32_t)(Thumb ? (roundDown(PC, 4) + imm) : (PC + imm))' 90 br_tgt_code = ''' 91 pcs.instNPC((uint32_t)(branchPC.thumb() ? (roundDown(branchPC.instPC(),4) + imm) : 92 (branchPC.instPC() + imm))); 93 ''' 94 base = "BranchImmCond" 95 declare = BranchImmCondDeclare 96 constructor = BranchImmCondConstructor 97 instFlags = ["IsDirectControl"] 98 else: 99 Name += "Reg" 100 newPC = 'Op1' 101 br_tgt_code = '' 102 base = "BranchRegCond" 103 declare = BranchRegCondDeclare 104 constructor = BranchRegCondConstructor 105 instFlags = ["IsIndirectControl"] 106 if link and imm: 107 linkStr = ''' 108 // The immediate version of the blx thumb instruction 109 // is 32 bits wide, but "next pc" doesn't reflect that 110 // so we don't want to substract 2 from it at this point 111 if (Thumb) 112 LR = PC | 1; 113 else 114 LR = PC - 4; 115 ''' 116 instFlags += ["IsCall"] 117 elif link: 118 linkStr = ''' 119 if (Thumb) 120 LR = (PC - 2) | 1; 121 else 122 LR = PC - 4; 123 ''' 124 instFlags += ["IsCall"] 125 else: 126 linkStr = "" 127 isRasPop = "op1 == INTREG_LR" 128 129 if imm and link: #blx with imm 130 branchStr = ''' 131 NextThumb = !Thumb; 132 NPC = %(newPC)s; 133 ''' 134 br_tgt_code = '''pcs.nextThumb(!branchPC.thumb());\n''' + \ 135 br_tgt_code 136 else: 137 branchStr = "IWNPC = %(newPC)s;" 138 branchStr = branchStr % { "newPC" : newPC } 139 140 code = blxCode % {"link": linkStr, 141 "newPC": newPC, 142 "branch": branchStr} 143 blxIop = InstObjParams(mnem, Name, base, 144 {"code": code, "brTgtCode" : br_tgt_code, 145 "predicate_test": predicateTest, 146 "is_ras_pop" : isRasPop }, instFlags) 147 header_output += declare.subst(blxIop) 148 decoder_output += constructor.subst(blxIop) 149 exec_output += PredOpExecute.subst(blxIop) 150 if imm: 151 decoder_output += BranchTarget.subst(blxIop) 152 153 bxjcode = ''' 154 HSTR hstr = Hstr; 155 CPSR cpsr = Cpsr; 156 SCR scr = Scr; 157 158 if (ArmSystem::haveVirtualization(xc->tcBase()) && hstr.tjdbx && 159 !inSecureState(scr, cpsr) && (cpsr.mode != MODE_HYP)) { 160 fault = std::make_shared<HypervisorTrap>(machInst, op1, EC_TRAPPED_BXJ); 161 } 162 IWNPC = Op1; 163 ''' 164 165 bxjIop = InstObjParams("bxj", "BxjReg", "BranchRegCond", 166 {"code": bxjcode, 167 "predicate_test": predicateTest, 168 "is_ras_pop": "op1 == INTREG_LR" }, 169 ["IsIndirectControl"]) 170 header_output += BranchRegCondDeclare.subst(bxjIop) 171 decoder_output += BranchRegCondConstructor.subst(bxjIop) 172 exec_output += PredOpExecute.subst(bxjIop) 173 174 #CBNZ, CBZ. These are always unconditional as far as predicates 175 for (mnem, test) in (("cbz", "=="), ("cbnz", "!=")): 176 code = 'NPC = (uint32_t)(PC + imm);\n' 177 br_tgt_code = '''pcs.instNPC((uint32_t)(branchPC.instPC() + imm));''' 178 predTest = "Op1 %(test)s 0" % {"test": test} 179 iop = InstObjParams(mnem, mnem.capitalize(), "BranchImmReg", 180 {"code": code, "predicate_test": predTest, 181 "brTgtCode" : br_tgt_code}, 182 ["IsDirectControl"]) 183 header_output += BranchImmRegDeclare.subst(iop) 184 decoder_output += BranchImmRegConstructor.subst(iop) + \ 185 BranchTarget.subst(iop) 186 exec_output += PredOpExecute.subst(iop) 187 188 #TBB, TBH 189 for isTbh in (0, 1): 190 if isTbh: 191 eaCode = ''' 192 unsigned memAccessFlags = ArmISA::TLB::AllowUnaligned | 193 ArmISA::TLB::AlignHalfWord | 194 ArmISA::TLB::MustBeOne; 195 EA = Op1 + Op2 * 2 196 ''' 197 accCode = 'NPC = PC + 2 * (Mem_uh);\n' 198 mnem = "tbh" 199 else: 200 eaCode = ''' 201 unsigned memAccessFlags = ArmISA::TLB::AllowUnaligned | 202 ArmISA::TLB::AlignByte | 203 ArmISA::TLB::MustBeOne; 204 EA = Op1 + Op2 205 ''' 206 accCode = 'NPC = PC + 2 * (Mem_ub)' 207 mnem = "tbb" 208 iop = InstObjParams(mnem, mnem.capitalize(), "BranchRegReg", 209 {'ea_code': eaCode, 210 'memacc_code': accCode, 211 'predicate_test': predicateTest}, 212 ["IsIndirectControl"]) 213 header_output += BranchTableDeclare.subst(iop) 214 decoder_output += BranchRegRegConstructor.subst(iop) 215 exec_output += LoadExecute.subst(iop) + \ 216 LoadInitiateAcc.subst(iop) + \ 217 LoadCompleteAcc.subst(iop) 218}}; 219