macromem.isa revision 10037
1// -*- mode:c++ -*- 2 3// Copyright (c) 2010-2013 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// Copyright (c) 2007-2008 The Florida State University 16// All rights reserved. 17// 18// Redistribution and use in source and binary forms, with or without 19// modification, are permitted provided that the following conditions are 20// met: redistributions of source code must retain the above copyright 21// notice, this list of conditions and the following disclaimer; 22// redistributions in binary form must reproduce the above copyright 23// notice, this list of conditions and the following disclaimer in the 24// documentation and/or other materials provided with the distribution; 25// neither the name of the copyright holders nor the names of its 26// contributors may be used to endorse or promote products derived from 27// this software without specific prior written permission. 28// 29// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 31// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 32// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 33// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 34// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 35// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 39// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40// 41// Authors: Stephen Hines 42// Gabe Black 43 44//////////////////////////////////////////////////////////////////// 45// 46// Load/store microops 47// 48 49let {{ 50 microLdrUopCode = "IWRa = cSwap(Mem_uw, ((CPSR)Cpsr).e);" 51 microLdrUopIop = InstObjParams('ldr_uop', 'MicroLdrUop', 52 'MicroMemOp', 53 {'memacc_code': microLdrUopCode, 54 'ea_code': 'EA = URb + (up ? imm : -imm);', 55 'predicate_test': predicateTest}, 56 ['IsMicroop']) 57 58 microLdrFpUopCode = "Fa_uw = cSwap(Mem_uw, ((CPSR)Cpsr).e);" 59 microLdrFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrFpUop', 60 'MicroMemOp', 61 {'memacc_code': microLdrFpUopCode, 62 'ea_code': vfpEnabledCheckCode + 63 'EA = URb + (up ? imm : -imm);', 64 'predicate_test': predicateTest}, 65 ['IsMicroop']) 66 67 microLdrDBFpUopCode = "Fa_uw = cSwap(Mem_uw, ((CPSR)Cpsr).e);" 68 microLdrDBFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrDBFpUop', 69 'MicroMemOp', 70 {'memacc_code': microLdrFpUopCode, 71 'ea_code': vfpEnabledCheckCode + ''' 72 EA = URb + (up ? imm : -imm) + 73 (((CPSR)Cpsr).e ? 4 : 0); 74 ''', 75 'predicate_test': predicateTest}, 76 ['IsMicroop']) 77 78 microLdrDTFpUopCode = "Fa_uw = cSwap(Mem_uw, ((CPSR)Cpsr).e);" 79 microLdrDTFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrDTFpUop', 80 'MicroMemOp', 81 {'memacc_code': microLdrFpUopCode, 82 'ea_code': vfpEnabledCheckCode + ''' 83 EA = URb + (up ? imm : -imm) - 84 (((CPSR)Cpsr).e ? 4 : 0); 85 ''', 86 'predicate_test': predicateTest}, 87 ['IsMicroop']) 88 89 microRetUopCode = ''' 90 CPSR old_cpsr = Cpsr; 91 SCTLR sctlr = Sctlr; 92 93 CPSR new_cpsr = 94 cpsrWriteByInstr(old_cpsr, Spsr, Scr, Nsacr, 0xF, true, 95 sctlr.nmfi, xc->tcBase()); 96 Cpsr = ~CondCodesMask & new_cpsr; 97 CondCodesNZ = new_cpsr.nz; 98 CondCodesC = new_cpsr.c; 99 CondCodesV = new_cpsr.v; 100 CondCodesGE = new_cpsr.ge; 101 IWNPC = cSwap(%s, old_cpsr.e) | ((Spsr & 0x20) ? 1 : 0); 102 NextItState = ((((CPSR)Spsr).it2 << 2) & 0xFC) 103 | (((CPSR)Spsr).it1 & 0x3); 104 SevMailbox = 1; 105 ''' 106 107 microLdrRetUopIop = InstObjParams('ldr_ret_uop', 'MicroLdrRetUop', 108 'MicroMemOp', 109 {'memacc_code': 110 microRetUopCode % 'Mem_uw', 111 'ea_code': 112 'EA = URb + (up ? imm : -imm);', 113 'predicate_test': condPredicateTest}, 114 ['IsMicroop','IsNonSpeculative', 115 'IsSerializeAfter']) 116 117 microStrUopCode = "Mem = cSwap(URa_uw, ((CPSR)Cpsr).e);" 118 microStrUopIop = InstObjParams('str_uop', 'MicroStrUop', 119 'MicroMemOp', 120 {'memacc_code': microStrUopCode, 121 'postacc_code': "", 122 'ea_code': 'EA = URb + (up ? imm : -imm);', 123 'predicate_test': predicateTest}, 124 ['IsMicroop']) 125 126 microStrFpUopCode = "Mem = cSwap(Fa_uw, ((CPSR)Cpsr).e);" 127 microStrFpUopIop = InstObjParams('strfp_uop', 'MicroStrFpUop', 128 'MicroMemOp', 129 {'memacc_code': microStrFpUopCode, 130 'postacc_code': "", 131 'ea_code': vfpEnabledCheckCode + 132 'EA = URb + (up ? imm : -imm);', 133 'predicate_test': predicateTest}, 134 ['IsMicroop']) 135 136 microStrDBFpUopCode = "Mem = cSwap(Fa_uw, ((CPSR)Cpsr).e);" 137 microStrDBFpUopIop = InstObjParams('strfp_uop', 'MicroStrDBFpUop', 138 'MicroMemOp', 139 {'memacc_code': microStrFpUopCode, 140 'postacc_code': "", 141 'ea_code': vfpEnabledCheckCode + ''' 142 EA = URb + (up ? imm : -imm) + 143 (((CPSR)Cpsr).e ? 4 : 0); 144 ''', 145 'predicate_test': predicateTest}, 146 ['IsMicroop']) 147 148 microStrDTFpUopCode = "Mem = cSwap(Fa_uw, ((CPSR)Cpsr).e);" 149 microStrDTFpUopIop = InstObjParams('strfp_uop', 'MicroStrDTFpUop', 150 'MicroMemOp', 151 {'memacc_code': microStrFpUopCode, 152 'postacc_code': "", 153 'ea_code': vfpEnabledCheckCode + ''' 154 EA = URb + (up ? imm : -imm) - 155 (((CPSR)Cpsr).e ? 4 : 0); 156 ''', 157 'predicate_test': predicateTest}, 158 ['IsMicroop']) 159 160 header_output = decoder_output = exec_output = '' 161 162 loadIops = (microLdrUopIop, microLdrRetUopIop, microLdrFpUopIop, 163 microLdrDBFpUopIop, microLdrDTFpUopIop) 164 storeIops = (microStrUopIop, microStrFpUopIop, 165 microStrDBFpUopIop, microStrDTFpUopIop) 166 for iop in loadIops + storeIops: 167 header_output += MicroMemDeclare.subst(iop) 168 decoder_output += MicroMemConstructor.subst(iop) 169 for iop in loadIops: 170 exec_output += LoadExecute.subst(iop) + \ 171 LoadInitiateAcc.subst(iop) + \ 172 LoadCompleteAcc.subst(iop) 173 for iop in storeIops: 174 exec_output += StoreExecute.subst(iop) + \ 175 StoreInitiateAcc.subst(iop) + \ 176 StoreCompleteAcc.subst(iop) 177}}; 178 179let {{ 180 exec_output = header_output = '' 181 182 eaCode = 'EA = XURa + imm;' 183 184 for size in (1, 2, 3, 4, 6, 8, 12, 16): 185 # Set up the memory access. 186 regs = (size + 3) // 4 187 subst = { "size" : size, "regs" : regs } 188 memDecl = ''' 189 union MemUnion { 190 uint8_t bytes[%(size)d]; 191 Element elements[%(size)d / sizeof(Element)]; 192 uint32_t floatRegBits[%(regs)d]; 193 }; 194 ''' % subst 195 196 # Do endian conversion for all the elements. 197 convCode = ''' 198 const unsigned eCount = sizeof(memUnion.elements) / 199 sizeof(memUnion.elements[0]); 200 if (((CPSR)Cpsr).e) { 201 for (unsigned i = 0; i < eCount; i++) { 202 memUnion.elements[i] = gtobe(memUnion.elements[i]); 203 } 204 } else { 205 for (unsigned i = 0; i < eCount; i++) { 206 memUnion.elements[i] = gtole(memUnion.elements[i]); 207 } 208 } 209 ''' 210 211 # Offload everything into registers 212 regSetCode = '' 213 for reg in range(regs): 214 mask = '' 215 if reg == regs - 1: 216 mask = ' & mask(%d)' % (32 - 8 * (regs * 4 - size)) 217 regSetCode += ''' 218 FpDestP%(reg)d_uw = gtoh(memUnion.floatRegBits[%(reg)d])%(mask)s; 219 ''' % { "reg" : reg, "mask" : mask } 220 221 # Pull everything in from registers 222 regGetCode = '' 223 for reg in range(regs): 224 regGetCode += ''' 225 memUnion.floatRegBits[%(reg)d] = htog(FpDestP%(reg)d_uw); 226 ''' % { "reg" : reg } 227 228 loadMemAccCode = convCode + regSetCode 229 storeMemAccCode = regGetCode + convCode 230 231 loadIop = InstObjParams('ldrneon%(size)d_uop' % subst, 232 'MicroLdrNeon%(size)dUop' % subst, 233 'MicroNeonMemOp', 234 { 'mem_decl' : memDecl, 235 'size' : size, 236 'memacc_code' : loadMemAccCode, 237 'ea_code' : simdEnabledCheckCode + eaCode, 238 'predicate_test' : predicateTest }, 239 [ 'IsMicroop', 'IsMemRef', 'IsLoad' ]) 240 storeIop = InstObjParams('strneon%(size)d_uop' % subst, 241 'MicroStrNeon%(size)dUop' % subst, 242 'MicroNeonMemOp', 243 { 'mem_decl' : memDecl, 244 'size' : size, 245 'memacc_code' : storeMemAccCode, 246 'ea_code' : simdEnabledCheckCode + eaCode, 247 'predicate_test' : predicateTest }, 248 [ 'IsMicroop', 'IsMemRef', 'IsStore' ]) 249 250 exec_output += NeonLoadExecute.subst(loadIop) + \ 251 NeonLoadInitiateAcc.subst(loadIop) + \ 252 NeonLoadCompleteAcc.subst(loadIop) + \ 253 NeonStoreExecute.subst(storeIop) + \ 254 NeonStoreInitiateAcc.subst(storeIop) + \ 255 NeonStoreCompleteAcc.subst(storeIop) 256 header_output += MicroNeonMemDeclare.subst(loadIop) + \ 257 MicroNeonMemDeclare.subst(storeIop) 258}}; 259 260let {{ 261 exec_output = '' 262 for eSize, type in (1, 'uint8_t'), \ 263 (2, 'uint16_t'), \ 264 (4, 'uint32_t'), \ 265 (8, 'uint64_t'): 266 size = eSize 267 # An instruction handles no more than 16 bytes and no more than 268 # 4 elements, or the number of elements needed to fill 8 or 16 bytes. 269 sizes = set((16, 8)) 270 for count in 1, 2, 3, 4: 271 size = count * eSize 272 if size <= 16: 273 sizes.add(size) 274 for size in sizes: 275 substDict = { 276 "class_name" : "MicroLdrNeon%dUop" % size, 277 "targs" : type 278 } 279 exec_output += MicroNeonMemExecDeclare.subst(substDict) 280 substDict["class_name"] = "MicroStrNeon%dUop" % size 281 exec_output += MicroNeonMemExecDeclare.subst(substDict) 282 size += eSize 283}}; 284 285//////////////////////////////////////////////////////////////////// 286// 287// Neon (de)interlacing microops 288// 289 290let {{ 291 header_output = exec_output = '' 292 for dRegs in (2, 3, 4): 293 loadConv = '' 294 unloadConv = '' 295 for dReg in range(dRegs): 296 loadConv += ''' 297 conv1.cRegs[%(sReg0)d] = htog(FpOp1P%(sReg0)d_uw); 298 conv1.cRegs[%(sReg1)d] = htog(FpOp1P%(sReg1)d_uw); 299 ''' % { "sReg0" : (dReg * 2), "sReg1" : (dReg * 2 + 1) } 300 unloadConv += ''' 301 FpDestS%(dReg)dP0_uw = gtoh(conv2.cRegs[2 * %(dReg)d + 0]); 302 FpDestS%(dReg)dP1_uw = gtoh(conv2.cRegs[2 * %(dReg)d + 1]); 303 ''' % { "dReg" : dReg } 304 microDeintNeonCode = ''' 305 const unsigned dRegs = %(dRegs)d; 306 const unsigned regs = 2 * dRegs; 307 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 308 sizeof(Element); 309 union convStruct { 310 FloatRegBits cRegs[regs]; 311 Element elements[dRegs * perDReg]; 312 } conv1, conv2; 313 314 %(loadConv)s 315 316 unsigned srcElem = 0; 317 for (unsigned destOffset = 0; 318 destOffset < perDReg; destOffset++) { 319 for (unsigned dReg = 0; dReg < dRegs; dReg++) { 320 conv2.elements[dReg * perDReg + destOffset] = 321 conv1.elements[srcElem++]; 322 } 323 } 324 325 %(unloadConv)s 326 ''' % { "dRegs" : dRegs, 327 "loadConv" : loadConv, 328 "unloadConv" : unloadConv } 329 microDeintNeonIop = \ 330 InstObjParams('deintneon%duop' % (dRegs * 2), 331 'MicroDeintNeon%dUop' % (dRegs * 2), 332 'MicroNeonMixOp', 333 { 'predicate_test': predicateTest, 334 'code' : microDeintNeonCode }, 335 ['IsMicroop']) 336 header_output += MicroNeonMixDeclare.subst(microDeintNeonIop) 337 exec_output += MicroNeonMixExecute.subst(microDeintNeonIop) 338 339 loadConv = '' 340 unloadConv = '' 341 for dReg in range(dRegs): 342 loadConv += ''' 343 conv1.cRegs[2 * %(dReg)d + 0] = htog(FpOp1S%(dReg)dP0_uw); 344 conv1.cRegs[2 * %(dReg)d + 1] = htog(FpOp1S%(dReg)dP1_uw); 345 ''' % { "dReg" : dReg } 346 unloadConv += ''' 347 FpDestP%(sReg0)d_uw = gtoh(conv2.cRegs[%(sReg0)d]); 348 FpDestP%(sReg1)d_uw = gtoh(conv2.cRegs[%(sReg1)d]); 349 ''' % { "sReg0" : (dReg * 2), "sReg1" : (dReg * 2 + 1) } 350 microInterNeonCode = ''' 351 const unsigned dRegs = %(dRegs)d; 352 const unsigned regs = 2 * dRegs; 353 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 354 sizeof(Element); 355 union convStruct { 356 FloatRegBits cRegs[regs]; 357 Element elements[dRegs * perDReg]; 358 } conv1, conv2; 359 360 %(loadConv)s 361 362 unsigned destElem = 0; 363 for (unsigned srcOffset = 0; 364 srcOffset < perDReg; srcOffset++) { 365 for (unsigned dReg = 0; dReg < dRegs; dReg++) { 366 conv2.elements[destElem++] = 367 conv1.elements[dReg * perDReg + srcOffset]; 368 } 369 } 370 371 %(unloadConv)s 372 ''' % { "dRegs" : dRegs, 373 "loadConv" : loadConv, 374 "unloadConv" : unloadConv } 375 microInterNeonIop = \ 376 InstObjParams('interneon%duop' % (dRegs * 2), 377 'MicroInterNeon%dUop' % (dRegs * 2), 378 'MicroNeonMixOp', 379 { 'predicate_test': predicateTest, 380 'code' : microInterNeonCode }, 381 ['IsMicroop']) 382 header_output += MicroNeonMixDeclare.subst(microInterNeonIop) 383 exec_output += MicroNeonMixExecute.subst(microInterNeonIop) 384}}; 385 386let {{ 387 exec_output = '' 388 for type in ('uint8_t', 'uint16_t', 'uint32_t', 'uint64_t'): 389 for dRegs in (2, 3, 4): 390 Name = "MicroDeintNeon%dUop" % (dRegs * 2) 391 substDict = { "class_name" : Name, "targs" : type } 392 exec_output += MicroNeonExecDeclare.subst(substDict) 393 Name = "MicroInterNeon%dUop" % (dRegs * 2) 394 substDict = { "class_name" : Name, "targs" : type } 395 exec_output += MicroNeonExecDeclare.subst(substDict) 396}}; 397 398//////////////////////////////////////////////////////////////////// 399// 400// Neon microops to pack/unpack a single lane 401// 402 403let {{ 404 header_output = exec_output = '' 405 for sRegs in 1, 2: 406 baseLoadRegs = '' 407 for reg in range(sRegs): 408 baseLoadRegs += ''' 409 sourceRegs.fRegs[%(reg0)d] = htog(FpOp1P%(reg0)d_uw); 410 sourceRegs.fRegs[%(reg1)d] = htog(FpOp1P%(reg1)d_uw); 411 ''' % { "reg0" : (2 * reg + 0), 412 "reg1" : (2 * reg + 1) } 413 for dRegs in range(sRegs, 5): 414 unloadRegs = '' 415 loadRegs = baseLoadRegs 416 for reg in range(dRegs): 417 loadRegs += ''' 418 destRegs[%(reg)d].fRegs[0] = htog(FpDestS%(reg)dP0_uw); 419 destRegs[%(reg)d].fRegs[1] = htog(FpDestS%(reg)dP1_uw); 420 ''' % { "reg" : reg } 421 unloadRegs += ''' 422 FpDestS%(reg)dP0_uw = gtoh(destRegs[%(reg)d].fRegs[0]); 423 FpDestS%(reg)dP1_uw = gtoh(destRegs[%(reg)d].fRegs[1]); 424 ''' % { "reg" : reg } 425 microUnpackNeonCode = ''' 426 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 427 sizeof(Element); 428 429 union SourceRegs { 430 FloatRegBits fRegs[2 * %(sRegs)d]; 431 Element elements[%(sRegs)d * perDReg]; 432 } sourceRegs; 433 434 union DestReg { 435 FloatRegBits fRegs[2]; 436 Element elements[perDReg]; 437 } destRegs[%(dRegs)d]; 438 439 %(loadRegs)s 440 441 for (unsigned i = 0; i < %(dRegs)d; i++) { 442 destRegs[i].elements[lane] = sourceRegs.elements[i]; 443 } 444 445 %(unloadRegs)s 446 ''' % { "sRegs" : sRegs, "dRegs" : dRegs, 447 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs } 448 449 microUnpackNeonIop = \ 450 InstObjParams('unpackneon%dto%duop' % (sRegs * 2, dRegs * 2), 451 'MicroUnpackNeon%dto%dUop' % 452 (sRegs * 2, dRegs * 2), 453 'MicroNeonMixLaneOp', 454 { 'predicate_test': predicateTest, 455 'code' : microUnpackNeonCode }, 456 ['IsMicroop']) 457 header_output += MicroNeonMixLaneDeclare.subst(microUnpackNeonIop) 458 exec_output += MicroNeonMixExecute.subst(microUnpackNeonIop) 459 460 for sRegs in 1, 2: 461 loadRegs = '' 462 for reg in range(sRegs): 463 loadRegs += ''' 464 sourceRegs.fRegs[%(reg0)d] = htog(FpOp1P%(reg0)d_uw); 465 sourceRegs.fRegs[%(reg1)d] = htog(FpOp1P%(reg1)d_uw); 466 ''' % { "reg0" : (2 * reg + 0), 467 "reg1" : (2 * reg + 1) } 468 for dRegs in range(sRegs, 5): 469 unloadRegs = '' 470 for reg in range(dRegs): 471 unloadRegs += ''' 472 FpDestS%(reg)dP0_uw = gtoh(destRegs[%(reg)d].fRegs[0]); 473 FpDestS%(reg)dP1_uw = gtoh(destRegs[%(reg)d].fRegs[1]); 474 ''' % { "reg" : reg } 475 microUnpackAllNeonCode = ''' 476 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 477 sizeof(Element); 478 479 union SourceRegs { 480 FloatRegBits fRegs[2 * %(sRegs)d]; 481 Element elements[%(sRegs)d * perDReg]; 482 } sourceRegs; 483 484 union DestReg { 485 FloatRegBits fRegs[2]; 486 Element elements[perDReg]; 487 } destRegs[%(dRegs)d]; 488 489 %(loadRegs)s 490 491 for (unsigned i = 0; i < %(dRegs)d; i++) { 492 for (unsigned j = 0; j < perDReg; j++) 493 destRegs[i].elements[j] = sourceRegs.elements[i]; 494 } 495 496 %(unloadRegs)s 497 ''' % { "sRegs" : sRegs, "dRegs" : dRegs, 498 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs } 499 500 microUnpackAllNeonIop = \ 501 InstObjParams('unpackallneon%dto%duop' % (sRegs * 2, dRegs * 2), 502 'MicroUnpackAllNeon%dto%dUop' % 503 (sRegs * 2, dRegs * 2), 504 'MicroNeonMixOp', 505 { 'predicate_test': predicateTest, 506 'code' : microUnpackAllNeonCode }, 507 ['IsMicroop']) 508 header_output += MicroNeonMixDeclare.subst(microUnpackAllNeonIop) 509 exec_output += MicroNeonMixExecute.subst(microUnpackAllNeonIop) 510 511 for dRegs in 1, 2: 512 unloadRegs = '' 513 for reg in range(dRegs): 514 unloadRegs += ''' 515 FpDestP%(reg0)d_uw = gtoh(destRegs.fRegs[%(reg0)d]); 516 FpDestP%(reg1)d_uw = gtoh(destRegs.fRegs[%(reg1)d]); 517 ''' % { "reg0" : (2 * reg + 0), 518 "reg1" : (2 * reg + 1) } 519 for sRegs in range(dRegs, 5): 520 loadRegs = '' 521 for reg in range(sRegs): 522 loadRegs += ''' 523 sourceRegs[%(reg)d].fRegs[0] = htog(FpOp1S%(reg)dP0_uw); 524 sourceRegs[%(reg)d].fRegs[1] = htog(FpOp1S%(reg)dP1_uw); 525 ''' % { "reg" : reg } 526 microPackNeonCode = ''' 527 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 528 sizeof(Element); 529 530 union SourceReg { 531 FloatRegBits fRegs[2]; 532 Element elements[perDReg]; 533 } sourceRegs[%(sRegs)d]; 534 535 union DestRegs { 536 FloatRegBits fRegs[2 * %(dRegs)d]; 537 Element elements[%(dRegs)d * perDReg]; 538 } destRegs; 539 540 %(loadRegs)s 541 542 for (unsigned i = 0; i < %(sRegs)d; i++) { 543 destRegs.elements[i] = sourceRegs[i].elements[lane]; 544 } 545 for (unsigned i = %(sRegs)d; i < %(dRegs)d * perDReg; ++i) { 546 destRegs.elements[i] = 0; 547 } 548 549 %(unloadRegs)s 550 ''' % { "sRegs" : sRegs, "dRegs" : dRegs, 551 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs } 552 553 microPackNeonIop = \ 554 InstObjParams('packneon%dto%duop' % (sRegs * 2, dRegs * 2), 555 'MicroPackNeon%dto%dUop' % 556 (sRegs * 2, dRegs * 2), 557 'MicroNeonMixLaneOp', 558 { 'predicate_test': predicateTest, 559 'code' : microPackNeonCode }, 560 ['IsMicroop']) 561 header_output += MicroNeonMixLaneDeclare.subst(microPackNeonIop) 562 exec_output += MicroNeonMixExecute.subst(microPackNeonIop) 563}}; 564 565let {{ 566 exec_output = '' 567 for typeSize in (8, 16, 32): 568 for sRegs in 1, 2: 569 for dRegs in range(sRegs, min(sRegs * 64 / typeSize + 1, 5)): 570 for format in ("MicroUnpackNeon%(sRegs)dto%(dRegs)dUop", 571 "MicroUnpackAllNeon%(sRegs)dto%(dRegs)dUop", 572 "MicroPackNeon%(dRegs)dto%(sRegs)dUop"): 573 Name = format % { "sRegs" : sRegs * 2, 574 "dRegs" : dRegs * 2 } 575 substDict = { "class_name" : Name, 576 "targs" : "uint%d_t" % typeSize } 577 exec_output += MicroNeonExecDeclare.subst(substDict) 578}}; 579 580//////////////////////////////////////////////////////////////////// 581// 582// Integer = Integer op Immediate microops 583// 584 585let {{ 586 microAddiUopIop = InstObjParams('addi_uop', 'MicroAddiUop', 587 'MicroIntImmOp', 588 {'code': 'URa = URb + imm;', 589 'predicate_test': predicateTest}, 590 ['IsMicroop']) 591 592 microAddUopCode = ''' 593 URa = URb + shift_rm_imm(URc, shiftAmt, shiftType, OptShiftRmCondCodesC); 594 ''' 595 596 microAddXiUopIop = InstObjParams('addxi_uop', 'MicroAddXiUop', 597 'MicroIntImmXOp', 598 'XURa = XURb + imm;', 599 ['IsMicroop']) 600 601 microAddXiSpAlignUopIop = InstObjParams('addxi_uop', 'MicroAddXiSpAlignUop', 602 'MicroIntImmXOp', ''' 603 if (isSP((IntRegIndex) urb) && bits(XURb, 3, 0) && 604 SPAlignmentCheckEnabled(xc->tcBase())) { 605 return new SPAlignmentFault(); 606 } 607 XURa = XURb + imm; 608 ''', ['IsMicroop']) 609 610 microAddXERegUopIop = InstObjParams('addxr_uop', 'MicroAddXERegUop', 611 'MicroIntRegXOp', 612 'XURa = XURb + ' + \ 613 'extendReg64(XURc, type, shiftAmt, 64);', 614 ['IsMicroop']) 615 616 microAddUopIop = InstObjParams('add_uop', 'MicroAddUop', 617 'MicroIntRegOp', 618 {'code': microAddUopCode, 619 'predicate_test': pickPredicate(microAddUopCode)}, 620 ['IsMicroop']) 621 622 microSubiUopIop = InstObjParams('subi_uop', 'MicroSubiUop', 623 'MicroIntImmOp', 624 {'code': 'URa = URb - imm;', 625 'predicate_test': predicateTest}, 626 ['IsMicroop']) 627 628 microSubXiUopIop = InstObjParams('subxi_uop', 'MicroSubXiUop', 629 'MicroIntImmXOp', 630 'XURa = XURb - imm;', 631 ['IsMicroop']) 632 633 microSubUopCode = ''' 634 URa = URb - shift_rm_imm(URc, shiftAmt, shiftType, OptShiftRmCondCodesC); 635 ''' 636 microSubUopIop = InstObjParams('sub_uop', 'MicroSubUop', 637 'MicroIntRegOp', 638 {'code': microSubUopCode, 639 'predicate_test': pickPredicate(microSubUopCode)}, 640 ['IsMicroop']) 641 642 microUopRegMovIop = InstObjParams('uopReg_uop', 'MicroUopRegMov', 643 'MicroIntMov', 644 {'code': 'IWRa = URb;', 645 'predicate_test': predicateTest}, 646 ['IsMicroop']) 647 648 microUopRegMovRetIop = InstObjParams('movret_uop', 'MicroUopRegMovRet', 649 'MicroIntMov', 650 {'code': microRetUopCode % 'URb', 651 'predicate_test': predicateTest}, 652 ['IsMicroop', 'IsNonSpeculative', 653 'IsSerializeAfter']) 654 655 setPCCPSRDecl = ''' 656 CPSR cpsrOrCondCodes = URc; 657 SCTLR sctlr = Sctlr; 658 pNPC = URa; 659 CPSR new_cpsr = 660 cpsrWriteByInstr(cpsrOrCondCodes, URb, Scr, Nsacr, 661 0xF, true, sctlr.nmfi, xc->tcBase()); 662 Cpsr = ~CondCodesMask & new_cpsr; 663 NextThumb = new_cpsr.t; 664 NextJazelle = new_cpsr.j; 665 NextItState = ((((CPSR)URb).it2 << 2) & 0xFC) 666 | (((CPSR)URb).it1 & 0x3); 667 CondCodesNZ = new_cpsr.nz; 668 CondCodesC = new_cpsr.c; 669 CondCodesV = new_cpsr.v; 670 CondCodesGE = new_cpsr.ge; 671 ''' 672 673 microUopSetPCCPSRIop = InstObjParams('uopSet_uop', 'MicroUopSetPCCPSR', 674 'MicroSetPCCPSR', 675 {'code': setPCCPSRDecl, 676 'predicate_test': predicateTest}, 677 ['IsMicroop']) 678 679 header_output = MicroIntImmDeclare.subst(microAddiUopIop) + \ 680 MicroIntImmDeclare.subst(microAddXiUopIop) + \ 681 MicroIntImmDeclare.subst(microAddXiSpAlignUopIop) + \ 682 MicroIntImmDeclare.subst(microSubiUopIop) + \ 683 MicroIntImmDeclare.subst(microSubXiUopIop) + \ 684 MicroIntRegDeclare.subst(microAddUopIop) + \ 685 MicroIntRegDeclare.subst(microSubUopIop) + \ 686 MicroIntXERegDeclare.subst(microAddXERegUopIop) + \ 687 MicroIntMovDeclare.subst(microUopRegMovIop) + \ 688 MicroIntMovDeclare.subst(microUopRegMovRetIop) + \ 689 MicroSetPCCPSRDeclare.subst(microUopSetPCCPSRIop) 690 691 decoder_output = MicroIntImmConstructor.subst(microAddiUopIop) + \ 692 MicroIntImmXConstructor.subst(microAddXiUopIop) + \ 693 MicroIntImmXConstructor.subst(microAddXiSpAlignUopIop) + \ 694 MicroIntImmConstructor.subst(microSubiUopIop) + \ 695 MicroIntImmXConstructor.subst(microSubXiUopIop) + \ 696 MicroIntRegConstructor.subst(microAddUopIop) + \ 697 MicroIntRegConstructor.subst(microSubUopIop) + \ 698 MicroIntXERegConstructor.subst(microAddXERegUopIop) + \ 699 MicroIntMovConstructor.subst(microUopRegMovIop) + \ 700 MicroIntMovConstructor.subst(microUopRegMovRetIop) + \ 701 MicroSetPCCPSRConstructor.subst(microUopSetPCCPSRIop) 702 703 exec_output = PredOpExecute.subst(microAddiUopIop) + \ 704 BasicExecute.subst(microAddXiUopIop) + \ 705 BasicExecute.subst(microAddXiSpAlignUopIop) + \ 706 PredOpExecute.subst(microSubiUopIop) + \ 707 BasicExecute.subst(microSubXiUopIop) + \ 708 PredOpExecute.subst(microAddUopIop) + \ 709 PredOpExecute.subst(microSubUopIop) + \ 710 BasicExecute.subst(microAddXERegUopIop) + \ 711 PredOpExecute.subst(microUopRegMovIop) + \ 712 PredOpExecute.subst(microUopRegMovRetIop) + \ 713 PredOpExecute.subst(microUopSetPCCPSRIop) 714 715}}; 716 717let {{ 718 iop = InstObjParams("ldmstm", "LdmStm", 'MacroMemOp', "", []) 719 header_output = MacroMemDeclare.subst(iop) 720 decoder_output = MacroMemConstructor.subst(iop) 721 722 iop = InstObjParams("ldpstp", "LdpStp", 'PairMemOp', "", []) 723 header_output += PairMemDeclare.subst(iop) 724 decoder_output += PairMemConstructor.subst(iop) 725 726 iopImm = InstObjParams("bigfpmemimm", "BigFpMemImm", "BigFpMemImmOp", "") 727 iopPre = InstObjParams("bigfpmempre", "BigFpMemPre", "BigFpMemPreOp", "") 728 iopPost = InstObjParams("bigfpmempost", "BigFpMemPost", "BigFpMemPostOp", "") 729 for iop in (iopImm, iopPre, iopPost): 730 header_output += BigFpMemImmDeclare.subst(iop) 731 decoder_output += BigFpMemImmConstructor.subst(iop) 732 733 iop = InstObjParams("bigfpmemreg", "BigFpMemReg", "BigFpMemRegOp", "") 734 header_output += BigFpMemRegDeclare.subst(iop) 735 decoder_output += BigFpMemRegConstructor.subst(iop) 736 737 iop = InstObjParams("bigfpmemlit", "BigFpMemLit", "BigFpMemLitOp", "") 738 header_output += BigFpMemLitDeclare.subst(iop) 739 decoder_output += BigFpMemLitConstructor.subst(iop) 740 741 iop = InstObjParams("vldmult", "VldMult", 'VldMultOp', "", []) 742 header_output += VMemMultDeclare.subst(iop) 743 decoder_output += VMemMultConstructor.subst(iop) 744 745 iop = InstObjParams("vldsingle", "VldSingle", 'VldSingleOp', "", []) 746 header_output += VMemSingleDeclare.subst(iop) 747 decoder_output += VMemSingleConstructor.subst(iop) 748 749 iop = InstObjParams("vstmult", "VstMult", 'VstMultOp', "", []) 750 header_output += VMemMultDeclare.subst(iop) 751 decoder_output += VMemMultConstructor.subst(iop) 752 753 iop = InstObjParams("vstsingle", "VstSingle", 'VstSingleOp', "", []) 754 header_output += VMemSingleDeclare.subst(iop) 755 decoder_output += VMemSingleConstructor.subst(iop) 756 757 vfpIop = InstObjParams("vldmstm", "VLdmStm", 'MacroVFPMemOp', "", []) 758 header_output += MacroVFPMemDeclare.subst(vfpIop) 759 decoder_output += MacroVFPMemConstructor.subst(vfpIop) 760}}; 761