macromem.isa revision 12134
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 = (2 * sizeof(FloatRegBits)) / 327 sizeof(Element); 328 union convStruct { 329 FloatRegBits 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 = (2 * sizeof(FloatRegBits)) / 373 sizeof(Element); 374 union convStruct { 375 FloatRegBits 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(FloatRegBits)) / 446 sizeof(Element); 447 448 union SourceRegs { 449 FloatRegBits fRegs[2 * %(sRegs)d]; 450 Element elements[%(sRegs)d * perDReg]; 451 } sourceRegs; 452 453 union DestReg { 454 FloatRegBits fRegs[2]; 455 Element elements[perDReg]; 456 } destRegs[%(dRegs)d]; 457 458 %(loadRegs)s 459 460 for (unsigned i = 0; i < %(dRegs)d; i++) { 461 destRegs[i].elements[lane] = sourceRegs.elements[i]; 462 } 463 464 %(unloadRegs)s 465 ''' % { "sRegs" : sRegs, "dRegs" : dRegs, 466 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs } 467 468 microUnpackNeonIop = \ 469 InstObjParams('unpackneon%dto%duop' % (sRegs * 2, dRegs * 2), 470 'MicroUnpackNeon%dto%dUop' % 471 (sRegs * 2, dRegs * 2), 472 'MicroNeonMixLaneOp', 473 { 'predicate_test': predicateTest, 474 'code' : microUnpackNeonCode }, 475 ['IsMicroop']) 476 header_output += MicroNeonMixLaneDeclare.subst(microUnpackNeonIop) 477 exec_output += MicroNeonMixExecute.subst(microUnpackNeonIop) 478 479 for sRegs in 1, 2: 480 loadRegs = '' 481 for reg in range(sRegs): 482 loadRegs += ''' 483 sourceRegs.fRegs[%(reg0)d] = htog(FpOp1P%(reg0)d_uw); 484 sourceRegs.fRegs[%(reg1)d] = htog(FpOp1P%(reg1)d_uw); 485 ''' % { "reg0" : (2 * reg + 0), 486 "reg1" : (2 * reg + 1) } 487 for dRegs in range(sRegs, 5): 488 unloadRegs = '' 489 for reg in range(dRegs): 490 unloadRegs += ''' 491 FpDestS%(reg)dP0_uw = gtoh(destRegs[%(reg)d].fRegs[0]); 492 FpDestS%(reg)dP1_uw = gtoh(destRegs[%(reg)d].fRegs[1]); 493 ''' % { "reg" : reg } 494 microUnpackAllNeonCode = ''' 495 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 496 sizeof(Element); 497 498 union SourceRegs { 499 FloatRegBits fRegs[2 * %(sRegs)d]; 500 Element elements[%(sRegs)d * perDReg]; 501 } sourceRegs; 502 503 union DestReg { 504 FloatRegBits fRegs[2]; 505 Element elements[perDReg]; 506 } destRegs[%(dRegs)d]; 507 508 %(loadRegs)s 509 510 for (unsigned i = 0; i < %(dRegs)d; i++) { 511 for (unsigned j = 0; j < perDReg; j++) 512 destRegs[i].elements[j] = sourceRegs.elements[i]; 513 } 514 515 %(unloadRegs)s 516 ''' % { "sRegs" : sRegs, "dRegs" : dRegs, 517 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs } 518 519 microUnpackAllNeonIop = \ 520 InstObjParams('unpackallneon%dto%duop' % (sRegs * 2, dRegs * 2), 521 'MicroUnpackAllNeon%dto%dUop' % 522 (sRegs * 2, dRegs * 2), 523 'MicroNeonMixOp', 524 { 'predicate_test': predicateTest, 525 'code' : microUnpackAllNeonCode }, 526 ['IsMicroop']) 527 header_output += MicroNeonMixDeclare.subst(microUnpackAllNeonIop) 528 exec_output += MicroNeonMixExecute.subst(microUnpackAllNeonIop) 529 530 for dRegs in 1, 2: 531 unloadRegs = '' 532 for reg in range(dRegs): 533 unloadRegs += ''' 534 FpDestP%(reg0)d_uw = gtoh(destRegs.fRegs[%(reg0)d]); 535 FpDestP%(reg1)d_uw = gtoh(destRegs.fRegs[%(reg1)d]); 536 ''' % { "reg0" : (2 * reg + 0), 537 "reg1" : (2 * reg + 1) } 538 for sRegs in range(dRegs, 5): 539 loadRegs = '' 540 for reg in range(sRegs): 541 loadRegs += ''' 542 sourceRegs[%(reg)d].fRegs[0] = htog(FpOp1S%(reg)dP0_uw); 543 sourceRegs[%(reg)d].fRegs[1] = htog(FpOp1S%(reg)dP1_uw); 544 ''' % { "reg" : reg } 545 microPackNeonCode = ''' 546 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 547 sizeof(Element); 548 549 union SourceReg { 550 FloatRegBits fRegs[2]; 551 Element elements[perDReg]; 552 } sourceRegs[%(sRegs)d]; 553 554 union DestRegs { 555 FloatRegBits fRegs[2 * %(dRegs)d]; 556 Element elements[%(dRegs)d * perDReg]; 557 } destRegs; 558 559 %(loadRegs)s 560 561 for (unsigned i = 0; i < %(sRegs)d; i++) { 562 destRegs.elements[i] = sourceRegs[i].elements[lane]; 563 } 564 for (unsigned i = %(sRegs)d; i < %(dRegs)d * perDReg; ++i) { 565 destRegs.elements[i] = 0; 566 } 567 568 %(unloadRegs)s 569 ''' % { "sRegs" : sRegs, "dRegs" : dRegs, 570 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs } 571 572 microPackNeonIop = \ 573 InstObjParams('packneon%dto%duop' % (sRegs * 2, dRegs * 2), 574 'MicroPackNeon%dto%dUop' % 575 (sRegs * 2, dRegs * 2), 576 'MicroNeonMixLaneOp', 577 { 'predicate_test': predicateTest, 578 'code' : microPackNeonCode }, 579 ['IsMicroop']) 580 header_output += MicroNeonMixLaneDeclare.subst(microPackNeonIop) 581 exec_output += MicroNeonMixExecute.subst(microPackNeonIop) 582}}; 583 584let {{ 585 exec_output = '' 586 for typeSize in (8, 16, 32): 587 for sRegs in 1, 2: 588 for dRegs in range(sRegs, min(sRegs * 64 / typeSize + 1, 5)): 589 for format in ("MicroUnpackNeon%(sRegs)dto%(dRegs)dUop", 590 "MicroUnpackAllNeon%(sRegs)dto%(dRegs)dUop", 591 "MicroPackNeon%(dRegs)dto%(sRegs)dUop"): 592 Name = format % { "sRegs" : sRegs * 2, 593 "dRegs" : dRegs * 2 } 594 substDict = { "class_name" : Name, 595 "targs" : "uint%d_t" % typeSize } 596 exec_output += MicroNeonExecDeclare.subst(substDict) 597}}; 598 599//////////////////////////////////////////////////////////////////// 600// 601// Integer = Integer op Immediate microops 602// 603 604let {{ 605 microAddiUopIop = InstObjParams('addi_uop', 'MicroAddiUop', 606 'MicroIntImmOp', 607 {'code': 'URa = URb + imm;', 608 'predicate_test': predicateTest}, 609 ['IsMicroop']) 610 611 microAddUopCode = ''' 612 URa = URb + shift_rm_imm(URc, shiftAmt, shiftType, OptShiftRmCondCodesC); 613 ''' 614 615 microAddXiUopIop = InstObjParams('addxi_uop', 'MicroAddXiUop', 616 'MicroIntImmXOp', 617 'XURa = XURb + imm;', 618 ['IsMicroop']) 619 620 microAddXiSpAlignUopIop = InstObjParams('addxi_uop', 'MicroAddXiSpAlignUop', 621 'MicroIntImmXOp', ''' 622 if (isSP((IntRegIndex) urb) && bits(XURb, 3, 0) && 623 SPAlignmentCheckEnabled(xc->tcBase())) { 624 return std::make_shared<SPAlignmentFault>(); 625 } 626 XURa = XURb + imm; 627 ''', ['IsMicroop']) 628 629 microAddXERegUopIop = InstObjParams('addxr_uop', 'MicroAddXERegUop', 630 'MicroIntRegXOp', 631 'XURa = XURb + ' + \ 632 'extendReg64(XURc, type, shiftAmt, 64);', 633 ['IsMicroop']) 634 635 microAddUopIop = InstObjParams('add_uop', 'MicroAddUop', 636 'MicroIntRegOp', 637 {'code': microAddUopCode, 638 'predicate_test': pickPredicate(microAddUopCode)}, 639 ['IsMicroop']) 640 641 microSubiUopIop = InstObjParams('subi_uop', 'MicroSubiUop', 642 'MicroIntImmOp', 643 {'code': 'URa = URb - imm;', 644 'predicate_test': predicateTest}, 645 ['IsMicroop']) 646 647 microSubXiUopIop = InstObjParams('subxi_uop', 'MicroSubXiUop', 648 'MicroIntImmXOp', 649 'XURa = XURb - imm;', 650 ['IsMicroop']) 651 652 microSubUopCode = ''' 653 URa = URb - shift_rm_imm(URc, shiftAmt, shiftType, OptShiftRmCondCodesC); 654 ''' 655 microSubUopIop = InstObjParams('sub_uop', 'MicroSubUop', 656 'MicroIntRegOp', 657 {'code': microSubUopCode, 658 'predicate_test': pickPredicate(microSubUopCode)}, 659 ['IsMicroop']) 660 661 microUopRegMovIop = InstObjParams('uopReg_uop', 'MicroUopRegMov', 662 'MicroIntMov', 663 {'code': 'IWRa = URb;', 664 'predicate_test': predicateTest}, 665 ['IsMicroop']) 666 667 microUopRegMovRetIop = InstObjParams('movret_uop', 'MicroUopRegMovRet', 668 'MicroIntMov', 669 {'code': microRetUopCode % 'URb', 670 'predicate_test': predicateTest}, 671 ['IsMicroop', 'IsNonSpeculative', 672 'IsSerializeAfter', 'IsSquashAfter']) 673 674 setPCCPSRDecl = ''' 675 CPSR cpsrOrCondCodes = URc; 676 SCTLR sctlr = Sctlr; 677 pNPC = URa; 678 CPSR new_cpsr = 679 cpsrWriteByInstr(cpsrOrCondCodes, URb, Scr, Nsacr, 680 0xF, true, sctlr.nmfi, xc->tcBase()); 681 Cpsr = ~CondCodesMask & new_cpsr; 682 NextThumb = new_cpsr.t; 683 NextJazelle = new_cpsr.j; 684 NextItState = ((((CPSR)URb).it2 << 2) & 0xFC) 685 | (((CPSR)URb).it1 & 0x3); 686 CondCodesNZ = new_cpsr.nz; 687 CondCodesC = new_cpsr.c; 688 CondCodesV = new_cpsr.v; 689 CondCodesGE = new_cpsr.ge; 690 ''' 691 692 microUopSetPCCPSRIop = InstObjParams('uopSet_uop', 'MicroUopSetPCCPSR', 693 'MicroSetPCCPSR', 694 {'code': setPCCPSRDecl, 695 'predicate_test': predicateTest}, 696 ['IsMicroop']) 697 698 header_output = MicroIntImmDeclare.subst(microAddiUopIop) + \ 699 MicroIntImmDeclare.subst(microAddXiUopIop) + \ 700 MicroIntImmDeclare.subst(microAddXiSpAlignUopIop) + \ 701 MicroIntImmDeclare.subst(microSubiUopIop) + \ 702 MicroIntImmDeclare.subst(microSubXiUopIop) + \ 703 MicroIntRegDeclare.subst(microAddUopIop) + \ 704 MicroIntRegDeclare.subst(microSubUopIop) + \ 705 MicroIntXERegDeclare.subst(microAddXERegUopIop) + \ 706 MicroIntMovDeclare.subst(microUopRegMovIop) + \ 707 MicroIntMovDeclare.subst(microUopRegMovRetIop) + \ 708 MicroSetPCCPSRDeclare.subst(microUopSetPCCPSRIop) 709 710 decoder_output = MicroIntImmConstructor.subst(microAddiUopIop) + \ 711 MicroIntImmXConstructor.subst(microAddXiUopIop) + \ 712 MicroIntImmXConstructor.subst(microAddXiSpAlignUopIop) + \ 713 MicroIntImmConstructor.subst(microSubiUopIop) + \ 714 MicroIntImmXConstructor.subst(microSubXiUopIop) + \ 715 MicroIntRegConstructor.subst(microAddUopIop) + \ 716 MicroIntRegConstructor.subst(microSubUopIop) + \ 717 MicroIntXERegConstructor.subst(microAddXERegUopIop) + \ 718 MicroIntMovConstructor.subst(microUopRegMovIop) + \ 719 MicroIntMovConstructor.subst(microUopRegMovRetIop) + \ 720 MicroSetPCCPSRConstructor.subst(microUopSetPCCPSRIop) 721 722 exec_output = PredOpExecute.subst(microAddiUopIop) + \ 723 BasicExecute.subst(microAddXiUopIop) + \ 724 BasicExecute.subst(microAddXiSpAlignUopIop) + \ 725 PredOpExecute.subst(microSubiUopIop) + \ 726 BasicExecute.subst(microSubXiUopIop) + \ 727 PredOpExecute.subst(microAddUopIop) + \ 728 PredOpExecute.subst(microSubUopIop) + \ 729 BasicExecute.subst(microAddXERegUopIop) + \ 730 PredOpExecute.subst(microUopRegMovIop) + \ 731 PredOpExecute.subst(microUopRegMovRetIop) + \ 732 PredOpExecute.subst(microUopSetPCCPSRIop) 733 734}}; 735 736let {{ 737 iop = InstObjParams("ldmstm", "LdmStm", 'MacroMemOp', "", []) 738 header_output = MacroMemDeclare.subst(iop) 739 decoder_output = MacroMemConstructor.subst(iop) 740 741 iop = InstObjParams("ldpstp", "LdpStp", 'PairMemOp', "", []) 742 header_output += PairMemDeclare.subst(iop) 743 decoder_output += PairMemConstructor.subst(iop) 744 745 iopImm = InstObjParams("bigfpmemimm", "BigFpMemImm", "BigFpMemImmOp", "") 746 iopPre = InstObjParams("bigfpmempre", "BigFpMemPre", "BigFpMemPreOp", "") 747 iopPost = InstObjParams("bigfpmempost", "BigFpMemPost", "BigFpMemPostOp", "") 748 for iop in (iopImm, iopPre, iopPost): 749 header_output += BigFpMemImmDeclare.subst(iop) 750 decoder_output += BigFpMemImmConstructor.subst(iop) 751 752 iop = InstObjParams("bigfpmemreg", "BigFpMemReg", "BigFpMemRegOp", "") 753 header_output += BigFpMemRegDeclare.subst(iop) 754 decoder_output += BigFpMemRegConstructor.subst(iop) 755 756 iop = InstObjParams("bigfpmemlit", "BigFpMemLit", "BigFpMemLitOp", "") 757 header_output += BigFpMemLitDeclare.subst(iop) 758 decoder_output += BigFpMemLitConstructor.subst(iop) 759 760 iop = InstObjParams("vldmult", "VldMult", 'VldMultOp', "", []) 761 header_output += VMemMultDeclare.subst(iop) 762 decoder_output += VMemMultConstructor.subst(iop) 763 764 iop = InstObjParams("vldsingle", "VldSingle", 'VldSingleOp', "", []) 765 header_output += VMemSingleDeclare.subst(iop) 766 decoder_output += VMemSingleConstructor.subst(iop) 767 768 iop = InstObjParams("vstmult", "VstMult", 'VstMultOp', "", []) 769 header_output += VMemMultDeclare.subst(iop) 770 decoder_output += VMemMultConstructor.subst(iop) 771 772 iop = InstObjParams("vstsingle", "VstSingle", 'VstSingleOp', "", []) 773 header_output += VMemSingleDeclare.subst(iop) 774 decoder_output += VMemSingleConstructor.subst(iop) 775 776 vfpIop = InstObjParams("vldmstm", "VLdmStm", 'MacroVFPMemOp', "", []) 777 header_output += MacroVFPMemDeclare.subst(vfpIop) 778 decoder_output += MacroVFPMemConstructor.subst(vfpIop) 779}}; 780