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