integer.isa revision 10184
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// Integer ALU instructions 34// 35 36 37// Instruction class constructor template when Rc is set. 38def template IntRcConstructor {{ 39 %(class_name)s::%(class_name)s(ExtMachInst machInst) : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) 40 { 41 %(constructor)s; 42 rcSet = true; 43 } 44}}; 45 46 47// Instruction class constructor template when OE is set. 48def template IntOeConstructor {{ 49 %(class_name)s::%(class_name)s(ExtMachInst machInst) : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) 50 { 51 %(constructor)s; 52 oeSet = true; 53 } 54}}; 55 56 57// Instruction class constructor template when both Rc and OE are set. 58def template IntRcOeConstructor {{ 59 %(class_name)s::%(class_name)s(ExtMachInst machInst) : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) 60 { 61 %(constructor)s; 62 rcSet = true; 63 oeSet = true; 64 } 65}}; 66 67 68let {{ 69 70readXERCode = 'Xer xer = XER;' 71 72setXERCode = 'XER = xer;' 73 74computeCR0Code = ''' 75 Cr cr = CR; 76 cr.cr0 = makeCRField((int32_t)%(result)s, (int32_t)0, xer.so); 77 CR = cr; 78''' 79 80computeCACode = ''' 81 if (findCarry(32, %(result)s, %(inputa)s, %(inputb)s)) { 82 xer.ca = 1; 83 } else { 84 xer.ca = 0; 85 } 86''' 87 88computeOVCode = ''' 89 if (findOverflow(32, %(result)s, %(inputa)s, %(inputb)s)) { 90 xer.ov = 1; 91 xer.so = 1; 92 } else { 93 xer.ov = 0; 94 } 95''' 96 97computeDivOVCode = ''' 98 if (divSetOV) { 99 xer.ov = 1; 100 xer.so = 1; 101 } else { 102 if (findOverflow(32, %(result)s, %(inputa)s, %(inputb)s)) { 103 xer.ov = 1; 104 xer.so = 1; 105 } else { 106 xer.ov = 0; 107 } 108 } 109''' 110 111}}; 112 113 114// A basic integer instruction. 115def format IntOp(code, inst_flags = []) {{ 116 (header_output, decoder_output, decode_block, exec_output) = \ 117 GenAluOp(name, Name, 'IntOp', code, inst_flags, BasicDecode, 118 BasicConstructor) 119}}; 120 121 122// Integer instructions with immediate (signed or unsigned). 123def format IntImmOp(code, inst_flags = []) {{ 124 (header_output, decoder_output, decode_block, exec_output) = \ 125 GenAluOp(name, Name, 'IntImmOp', code, inst_flags, BasicDecode, 126 BasicConstructor) 127}}; 128 129 130// Integer instructions with immediate that perform arithmetic. 131// These instructions all write to Rt and use an altered form of the 132// value in source register Ra, hence the use of src to hold the actual 133// value. The control flags include the use of code to compute the 134// carry bit or the CR0 code. 135def format IntImmArithOp(code, ctrl_flags = [], inst_flags = []) {{ 136 137 # Set up the dictionary and deal with control flags 138 dict = {'result':'Rt', 'inputa':'src', 'inputb':'imm'} 139 if ctrl_flags: 140 code += readXERCode 141 for val in ctrl_flags: 142 if val == 'computeCA': 143 code += computeCACode % dict + setXERCode 144 elif val == 'computeCR0': 145 code += computeCR0Code % dict 146 147 # Generate the class 148 (header_output, decoder_output, decode_block, exec_output) = \ 149 GenAluOp(name, Name, 'IntImmOp', code, inst_flags, BasicDecode, 150 BasicConstructor) 151}}; 152 153 154// Integer instructions with immediate that perform arithmetic but use 155// the value 0 when Ra == 0. We generate two versions of each instruction 156// corresponding to these two different scenarios. The correct version is 157// determined at decode (see the CheckRaDecode template). 158def format IntImmArithCheckRaOp(code, code_ra0, inst_flags = []) {{ 159 160 # First the version where Ra is non-zero 161 (header_output, decoder_output, decode_block, exec_output) = \ 162 GenAluOp(name, Name, 'IntImmOp', code, inst_flags, 163 CheckRaDecode, BasicConstructor) 164 165 # Now another version where Ra == 0 166 (header_output_ra0, decoder_output_ra0, _, exec_output_ra0) = \ 167 GenAluOp(name, Name + 'RaZero', 'IntImmOp', code_ra0, inst_flags, 168 CheckRaDecode, BasicConstructor) 169 170 # Finally, add to the other outputs 171 header_output += header_output_ra0 172 decoder_output += decoder_output_ra0 173 exec_output += exec_output_ra0 174}}; 175 176 177// Integer instructions with immediate that perform logic operations. 178// All instructions write to Ra and use Rs as a source register. Some 179// also compute the CR0 code too. 180def format IntImmLogicOp(code, computeCR0 = 0, inst_flags = []) {{ 181 182 # Set up the dictionary and deal with computing CR0 183 dict = {'result':'Ra'} 184 if computeCR0: 185 code += readXERCode + computeCR0Code % dict 186 187 # Generate the class 188 (header_output, decoder_output, decode_block, exec_output) = \ 189 GenAluOp(name, Name, 'IntImmOp', code, inst_flags, BasicDecode, 190 BasicConstructor) 191}}; 192 193 194// Integer instructions that perform logic operations. The result is 195// always written into Ra. All instructions have 2 versions depending on 196// whether the Rc bit is set to compute the CR0 code. This is determined 197// at decode as before. 198def format IntLogicOp(code, inst_flags = []) {{ 199 dict = {'result':'Ra'} 200 201 # Code when Rc is set 202 code_rc1 = code + readXERCode + computeCR0Code % dict 203 204 # Generate the first class 205 (header_output, decoder_output, decode_block, exec_output) = \ 206 GenAluOp(name, Name, 'IntOp', code, inst_flags, 207 CheckRcDecode, BasicConstructor) 208 209 # Generate the second class 210 (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \ 211 GenAluOp(name, Name + 'RcSet', 'IntOp', code_rc1, inst_flags, 212 CheckRcDecode, IntRcConstructor) 213 214 # Finally, add to the other outputs 215 header_output += header_output_rc1 216 decoder_output += decoder_output_rc1 217 exec_output += exec_output_rc1 218}}; 219 220 221// Integer instructions with a shift amount. As above, except inheriting 222// from the IntShiftOp class. 223def format IntShiftOp(code, inst_flags = []) {{ 224 dict = {'result':'Ra'} 225 226 # Code when Rc is set 227 code_rc1 = code + readXERCode + computeCR0Code % dict 228 229 # Generate the first class 230 (header_output, decoder_output, decode_block, exec_output) = \ 231 GenAluOp(name, Name, 'IntShiftOp', code, inst_flags, 232 CheckRcDecode, BasicConstructor) 233 234 # Generate the second class 235 (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \ 236 GenAluOp(name, Name + 'RcSet', 'IntShiftOp', code_rc1, inst_flags, 237 CheckRcDecode, IntRcConstructor) 238 239 # Finally, add to the other outputs 240 header_output += header_output_rc1 241 decoder_output += decoder_output_rc1 242 exec_output += exec_output_rc1 243}}; 244 245 246// Instructions in this format are all reduced to the form Rt = src1 + src2, 247// therefore we just give src1 and src2 definitions. In working out the 248// template we first put in the definitions of the variables and then 249// the code for the addition. We also deal with computing the carry flag 250// if required. 251// 252// We generate 4 versions of each instruction. This correspond to the 253// different combinations of having the OE bit set or unset (which controls 254// whether the overflow flag is computed) and the Rc bit set or unset too 255// (which controls whether the CR0 code is computed). 256def format IntSumOp(src1, src2, ca = {{ 0 }}, computeCA = 0, 257 inst_flags = []) {{ 258 259 # The result is always in Rt, but the source values vary 260 dict = {'result':'Rt', 'inputa':'src1', 'inputb':'src2'} 261 262 # Add code to set up variables and do the sum 263 code = 'uint32_t src1 = ' + src1 + ';\n' 264 code += 'uint32_t src2 = ' + src2 + ';\n' 265 code += 'uint32_t ca = ' + ca + ';\n' 266 code += 'Rt = src1 + src2 + ca;\n' 267 268 # Add code for calculating the carry, if needed 269 if computeCA: 270 code += computeCACode % dict + setXERCode 271 272 # Setup the 4 code versions and add code to access XER if necessary 273 code_rc1 = readXERCode + code 274 code_oe1 = readXERCode + code + computeOVCode % dict + setXERCode 275 code_rc1_oe1 = readXERCode + code + computeOVCode % dict + setXERCode 276 if (computeCA or ca == 'xer.ca'): 277 code = readXERCode + code 278 code_rc1 += computeCR0Code % dict 279 code_rc1_oe1 += computeCR0Code % dict 280 281 # Generate the classes 282 (header_output, decoder_output, decode_block, exec_output) = \ 283 GenAluOp(name, Name, 'IntOp', code, inst_flags, 284 CheckRcOeDecode, BasicConstructor) 285 (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \ 286 GenAluOp(name, Name + 'RcSet', 'IntOp', code_rc1, inst_flags, 287 CheckRcOeDecode, IntRcConstructor) 288 (header_output_oe1, decoder_output_oe1, _, exec_output_oe1) = \ 289 GenAluOp(name, Name + 'OeSet', 'IntOp', code_oe1, inst_flags, 290 CheckRcOeDecode, IntOeConstructor) 291 (header_output_rc1_oe1, decoder_output_rc1_oe1, _, exec_output_rc1_oe1) = \ 292 GenAluOp(name, Name + 'RcSetOeSet', 'IntOp', code_rc1_oe1, 293 inst_flags, CheckRcOeDecode, IntRcOeConstructor) 294 295 # Finally, add to the other outputs 296 header_output += \ 297 header_output_rc1 + header_output_oe1 + header_output_rc1_oe1 298 decoder_output += \ 299 decoder_output_rc1 + decoder_output_oe1 + decoder_output_rc1_oe1 300 exec_output += \ 301 exec_output_rc1 + exec_output_oe1 + exec_output_rc1_oe1 302 303}}; 304 305 306// Instructions that use source registers Ra and Rb, with the result 307// placed into Rt. Basically multiply and divide instructions. The 308// carry bit is never set, but overflow can be calculated. Division 309// explicitly sets the overflow bit in certain situations and this is 310// dealt with using the 'divSetOV' boolean in decoder.isa. We generate 311// two versions of each instruction to deal with the Rc bit. 312def format IntArithOp(code, computeOV = 0, inst_flags = []) {{ 313 314 # The result is always in Rt, but the source values vary 315 dict = {'result':'Rt', 'inputa':'src1', 'inputb':'src2'} 316 317 # Deal with setting the overflow flag 318 if computeOV: 319 code = 'bool divSetOV = false;\n' + code 320 code += computeDivOVCode % dict + setXERCode 321 322 # Setup the 2 code versions and add code to access XER if necessary 323 code_rc1 = readXERCode + code + computeCR0Code % dict 324 if computeOV: 325 code = readXERCode + code 326 327 # Generate the classes 328 (header_output, decoder_output, decode_block, exec_output) = \ 329 GenAluOp(name, Name, 'IntOp', code, inst_flags, 330 CheckRcDecode, BasicConstructor) 331 332 # Generate the second class 333 (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \ 334 GenAluOp(name, Name + 'RcSet', 'IntOp', code_rc1, inst_flags, 335 CheckRcDecode, IntRcConstructor) 336 337 # Finally, add to the other outputs 338 header_output += header_output_rc1 339 decoder_output += decoder_output_rc1 340 exec_output += exec_output_rc1 341}}; 342 343 344// A special format for rotate instructions which use certain fields 345// from the instruction's binary encoding. We need two versions for each 346// instruction to deal with the Rc bit. 347def format IntRotateOp(code, inst_flags = []) {{ 348 349 # The result is always in Ra 350 dict = {'result':'Ra'} 351 352 # Setup the code for when Rc is set 353 code_rc1 = readXERCode + code + computeCR0Code % dict 354 355 # Generate the first class 356 (header_output, decoder_output, decode_block, exec_output) = \ 357 GenAluOp(name, Name, 'IntRotateOp', code, inst_flags, 358 CheckRcDecode, BasicConstructor) 359 360 # Generate the second class 361 (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \ 362 GenAluOp(name, Name + 'RcSet', 'IntRotateOp', code_rc1, inst_flags, 363 CheckRcDecode, IntRcConstructor) 364 365 # Finally, add to the other outputs 366 header_output += header_output_rc1 367 decoder_output += decoder_output_rc1 368 exec_output += exec_output_rc1 369}}; 370