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