1// -*- mode:c++ -*- 2 3// Copyright (c) 2009 The University of Edinburgh 4// All rights reserved. 5// 6// Redistribution and use in source and binary forms, with or without 7// modification, are permitted provided that the following conditions are 8// met: redistributions of source code must retain the above copyright 9// notice, this list of conditions and the following disclaimer; 10// redistributions in binary form must reproduce the above copyright 11// notice, this list of conditions and the following disclaimer in the 12// documentation and/or other materials provided with the distribution; 13// neither the name of the copyright holders nor the names of its 14// contributors may be used to endorse or promote products derived from 15// this software without specific prior written permission. 16// 17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28// 29// Authors: Timothy M. Jones 30 31//////////////////////////////////////////////////////////////////// 32// 33// Control transfer instructions 34// 35// From the Power ISA Book I v2.06, page 33, the following rules should 36// be obeyed by programmers: 37// 38// - Use branch instructions where LK == 1 only as subroutine calls. 39// - Pair each subroutine call with a bclr instruction with BH == 00 40// that returns from the subroutine. 41// - Do not use bclrl as a subroutine call. 42// 43// Therefore, I've flagged all versions that update the link register (LR) 44// as calls, except bclrl (BranchLrCtrCond format) which is flagged as 45// a return. 46 47 48let {{ 49 50# Simple code to update link register (LR). 51updateLrCode = 'LR = CIA + 4;' 52 53}}; 54 55// Instructions that unconditionally branch relative to the current PC. 56def format BranchPCRel(br_code, inst_flags = []) {{ 57 inst_flags += ('IsUncondControl', 'IsDirectControl') 58 basic_code = br_code 59 60 # The version that does not update LR 61 (header_output, decoder_output, decode_block, exec_output) = \ 62 GenAluOp(name, Name, 'BranchPCRel', basic_code, inst_flags, 63 CheckLkDecode, BasicConstructor) 64 65 # The version that does the update 66 update_code = basic_code + updateLrCode 67 update_flags = inst_flags + [ 'IsCall' ] 68 (header_output_up, decoder_output_up, _, exec_output_up) = \ 69 GenAluOp(name, Name + 'UpdateLr', 'BranchPCRel', update_code, 70 update_flags, CheckLkDecode, BasicConstructor) 71 72 # Add the outputs together 73 header_output += header_output_up 74 decoder_output += decoder_output_up 75 exec_output += exec_output_up 76}}; 77 78// Instructions that unconditionally branch to a specific address. 79def format BranchNonPCRel(br_code, inst_flags = []) {{ 80 inst_flags += ('IsUncondControl', 'IsDirectControl') 81 basic_code = br_code 82 83 # The version that does not update LR 84 (header_output, decoder_output, decode_block, exec_output) = \ 85 GenAluOp(name, Name, 'BranchNonPCRel', basic_code, inst_flags, 86 CheckLkDecode, BasicConstructor) 87 88 # The version that does the update 89 update_code = basic_code + updateLrCode 90 update_flags = inst_flags + [ 'IsCall' ] 91 (header_output_up, decoder_output_up, _, exec_output_up) = \ 92 GenAluOp(name, Name + 'UpdateLr', 'BranchNonPCRel', update_code, 93 update_flags, CheckLkDecode, BasicConstructor) 94 95 # Add the outputs together 96 header_output += header_output_up 97 decoder_output += decoder_output_up 98 exec_output += exec_output_up 99}}; 100 101let {{ 102 103# Check the condition register (CR) allows the branch to be taken. 104def GetCondCode(br_code): 105 cond_code = 'if(condOk(CR)) {\n' 106 cond_code += ' ' + br_code + '\n' 107 cond_code += '} else {\n' 108 cond_code += ' NIA = NIA;\n' 109 cond_code += '}\n' 110 return cond_code 111 112# Check the condition register (CR) and count register (CTR) allow the 113# branch to be taken. Also, in certain situations, decrement the count 114# register too. This takes place in ctrOk within BranchCond classes. 115def GetCtrCondCode(br_code): 116 cond_code = 'uint32_t ctr = CTR;\n' 117 cond_code += 'bool ctr_ok = ctrOk(ctr);\n' 118 cond_code += 'bool cond_ok = condOk(CR);\n' 119 cond_code += 'if(ctr_ok && cond_ok) {\n' 120 cond_code += ' ' + br_code + '\n' 121 cond_code += '} else {\n' 122 cond_code += ' NIA = NIA;\n' 123 cond_code += '}\n' 124 cond_code += 'CTR = ctr;\n' 125 return cond_code 126 127}}; 128 129// Instructions that conditionally branch relative to the current PC based on 130// the condition register (CR) and count register (CTR). 131def format BranchPCRelCondCtr(br_code, inst_flags = []) {{ 132 inst_flags += ('IsCondControl', 'IsDirectControl') 133 basic_code = GetCtrCondCode(br_code) 134 135 # The version that does not update LR 136 (header_output, decoder_output, decode_block, exec_output) = \ 137 GenAluOp(name, Name, 'BranchPCRelCond', basic_code, inst_flags, 138 CheckLkDecode, BasicConstructor) 139 140 # The version that does the update 141 update_code = basic_code + updateLrCode 142 update_flags = inst_flags + [ 'IsCall' ] 143 (header_output_up, decoder_output_up, _, exec_output_up) = \ 144 GenAluOp(name, Name + 'UpdateLr', 'BranchPCRelCond', update_code, 145 update_flags, CheckLkDecode, BasicConstructor) 146 147 # Add the outputs together 148 header_output += header_output_up 149 decoder_output += decoder_output_up 150 exec_output += exec_output_up 151}}; 152 153// Instructions that conditionally branch to a specific address based on the 154// condition register (CR) and count register (CTR). 155def format BranchNonPCRelCondCtr(br_code, inst_flags = []) {{ 156 inst_flags += ('IsCondControl', 'IsDirectControl') 157 basic_code = GetCtrCondCode(br_code) 158 159 # The version that does not update LR 160 (header_output, decoder_output, decode_block, exec_output) = \ 161 GenAluOp(name, Name, 'BranchNonPCRelCond', basic_code, inst_flags, 162 CheckLkDecode, BasicConstructor) 163 164 # The version that does the update 165 update_code = basic_code + updateLrCode 166 update_flags = inst_flags + [ 'IsCall' ] 167 (header_output_up, decoder_output_up, _, exec_output_up) = \ 168 GenAluOp(name, Name + 'UpdateLr', 'BranchNonPCRelCond', update_code, 169 update_flags, CheckLkDecode, BasicConstructor) 170 171 # Add the outputs together 172 header_output += header_output_up 173 decoder_output += decoder_output_up 174 exec_output += exec_output_up 175}}; 176 177// Instructions that conditionally branch to the address in the link register 178// (LR) based on the condition register (CR) and count register (CTR). 179def format BranchLrCondCtr(br_code, inst_flags = []) {{ 180 inst_flags += ('IsCondControl', 'IsIndirectControl', 'IsReturn') 181 basic_code = GetCtrCondCode(br_code) 182 183 # The version that does not update LR 184 (header_output, decoder_output, decode_block, exec_output) = \ 185 GenAluOp(name, Name, 'BranchRegCond', basic_code, inst_flags, 186 CheckLkDecode, BasicConstructor) 187 188 # The version that does the update 189 update_code = basic_code + updateLrCode 190 (header_output_up, decoder_output_up, _, exec_output_up) = \ 191 GenAluOp(name, Name + 'UpdateLr', 'BranchRegCond', update_code, 192 inst_flags, CheckLkDecode, BasicConstructor) 193 194 # Add the outputs together 195 header_output += header_output_up 196 decoder_output += decoder_output_up 197 exec_output += exec_output_up 198}}; 199 200// Instructions that conditionally branch to the address in the count register 201// (CTR) based on the condition register (CR). 202def format BranchCtrCond(br_code, inst_flags = []) {{ 203 inst_flags += ('IsCondControl', 'IsIndirectControl') 204 basic_code = GetCondCode(br_code) 205 206 # The version that does not update LR 207 (header_output, decoder_output, decode_block, exec_output) = \ 208 GenAluOp(name, Name, 'BranchRegCond', basic_code, inst_flags, 209 CheckLkDecode, BasicConstructor) 210 211 # The version that does the update 212 update_code = basic_code + updateLrCode 213 update_flags = inst_flags + [ 'IsCall' ] 214 (header_output_up, decoder_output_up, _, exec_output_up) = \ 215 GenAluOp(name, Name + 'UpdateLr', 'BranchRegCond', update_code, 216 update_flags, CheckLkDecode, BasicConstructor) 217 218 # Add the outputs together 219 header_output += header_output_up 220 decoder_output += decoder_output_up 221 exec_output += exec_output_up 222}}; 223