1// -*- mode:c++ -*- 2 3// Copyright (c) 2010 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 cpsr = Cpsr; 91 SCTLR sctlr = Sctlr; 92 uint32_t newCpsr =
| 1// -*- mode:c++ -*- 2 3// Copyright (c) 2010 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 cpsr = Cpsr; 91 SCTLR sctlr = Sctlr; 92 uint32_t newCpsr =
|
96 IWNPC = cSwap(%s, cpsr.e) | ((Spsr & 0x20) ? 1 : 0); 97 NextItState = ((((CPSR)Spsr).it2 << 2) & 0xFC) 98 | (((CPSR)Spsr).it1 & 0x3); 99 SevMailbox = 1; 100 ''' 101 102 microLdrRetUopIop = InstObjParams('ldr_ret_uop', 'MicroLdrRetUop', 103 'MicroMemOp', 104 {'memacc_code': 105 microRetUopCode % 'Mem.uw', 106 'ea_code': 107 'EA = URb + (up ? imm : -imm);', 108 'predicate_test': condPredicateTest}, 109 ['IsMicroop','IsNonSpeculative', 110 'IsSerializeAfter']) 111 112 microStrUopCode = "Mem = cSwap(URa.uw, ((CPSR)Cpsr).e);" 113 microStrUopIop = InstObjParams('str_uop', 'MicroStrUop', 114 'MicroMemOp', 115 {'memacc_code': microStrUopCode, 116 'postacc_code': "", 117 'ea_code': 'EA = URb + (up ? imm : -imm);', 118 'predicate_test': predicateTest}, 119 ['IsMicroop']) 120 121 microStrFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);" 122 microStrFpUopIop = InstObjParams('strfp_uop', 'MicroStrFpUop', 123 'MicroMemOp', 124 {'memacc_code': microStrFpUopCode, 125 'postacc_code': "", 126 'ea_code': vfpEnabledCheckCode + 127 'EA = URb + (up ? imm : -imm);', 128 'predicate_test': predicateTest}, 129 ['IsMicroop']) 130 131 microStrDBFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);" 132 microStrDBFpUopIop = InstObjParams('strfp_uop', 'MicroStrDBFpUop', 133 'MicroMemOp', 134 {'memacc_code': microStrFpUopCode, 135 'postacc_code': "", 136 'ea_code': vfpEnabledCheckCode + ''' 137 EA = URb + (up ? imm : -imm) + 138 (((CPSR)Cpsr).e ? 4 : 0); 139 ''', 140 'predicate_test': predicateTest}, 141 ['IsMicroop']) 142 143 microStrDTFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);" 144 microStrDTFpUopIop = InstObjParams('strfp_uop', 'MicroStrDTFpUop', 145 'MicroMemOp', 146 {'memacc_code': microStrFpUopCode, 147 'postacc_code': "", 148 'ea_code': vfpEnabledCheckCode + ''' 149 EA = URb + (up ? imm : -imm) - 150 (((CPSR)Cpsr).e ? 4 : 0); 151 ''', 152 'predicate_test': predicateTest}, 153 ['IsMicroop']) 154 155 header_output = decoder_output = exec_output = '' 156 157 loadIops = (microLdrUopIop, microLdrRetUopIop, 158 microLdrFpUopIop, microLdrDBFpUopIop, microLdrDTFpUopIop) 159 storeIops = (microStrUopIop, microStrFpUopIop, 160 microStrDBFpUopIop, microStrDTFpUopIop) 161 for iop in loadIops + storeIops: 162 header_output += MicroMemDeclare.subst(iop) 163 decoder_output += MicroMemConstructor.subst(iop) 164 for iop in loadIops: 165 exec_output += LoadExecute.subst(iop) + \ 166 LoadInitiateAcc.subst(iop) + \ 167 LoadCompleteAcc.subst(iop) 168 for iop in storeIops: 169 exec_output += StoreExecute.subst(iop) + \ 170 StoreInitiateAcc.subst(iop) + \ 171 StoreCompleteAcc.subst(iop) 172}}; 173 174let {{ 175 exec_output = header_output = '' 176 177 eaCode = 'EA = URa + imm;' 178 179 for size in (1, 2, 3, 4, 6, 8, 12, 16): 180 # Set up the memory access. 181 regs = (size + 3) // 4 182 subst = { "size" : size, "regs" : regs } 183 memDecl = ''' 184 union MemUnion { 185 uint8_t bytes[%(size)d]; 186 Element elements[%(size)d / sizeof(Element)]; 187 uint32_t floatRegBits[%(regs)d]; 188 }; 189 ''' % subst 190 191 # Do endian conversion for all the elements. 192 convCode = ''' 193 const unsigned eCount = sizeof(memUnion.elements) / 194 sizeof(memUnion.elements[0]); 195 if (((CPSR)Cpsr).e) { 196 for (unsigned i = 0; i < eCount; i++) { 197 memUnion.elements[i] = gtobe(memUnion.elements[i]); 198 } 199 } else { 200 for (unsigned i = 0; i < eCount; i++) { 201 memUnion.elements[i] = gtole(memUnion.elements[i]); 202 } 203 } 204 ''' 205 206 # Offload everything into registers 207 regSetCode = '' 208 for reg in range(regs): 209 mask = '' 210 if reg == regs - 1: 211 mask = ' & mask(%d)' % (32 - 8 * (regs * 4 - size)) 212 regSetCode += ''' 213 FpDestP%(reg)d.uw = gtoh(memUnion.floatRegBits[%(reg)d])%(mask)s; 214 ''' % { "reg" : reg, "mask" : mask } 215 216 # Pull everything in from registers 217 regGetCode = '' 218 for reg in range(regs): 219 regGetCode += ''' 220 memUnion.floatRegBits[%(reg)d] = htog(FpDestP%(reg)d.uw); 221 ''' % { "reg" : reg } 222 223 loadMemAccCode = convCode + regSetCode 224 storeMemAccCode = regGetCode + convCode 225 226 loadIop = InstObjParams('ldrneon%(size)d_uop' % subst, 227 'MicroLdrNeon%(size)dUop' % subst, 228 'MicroNeonMemOp', 229 { 'mem_decl' : memDecl, 230 'size' : size, 231 'memacc_code' : loadMemAccCode, 232 'ea_code' : simdEnabledCheckCode + eaCode, 233 'predicate_test' : predicateTest }, 234 [ 'IsMicroop', 'IsMemRef', 'IsLoad' ]) 235 storeIop = InstObjParams('strneon%(size)d_uop' % subst, 236 'MicroStrNeon%(size)dUop' % subst, 237 'MicroNeonMemOp', 238 { 'mem_decl' : memDecl, 239 'size' : size, 240 'memacc_code' : storeMemAccCode, 241 'ea_code' : simdEnabledCheckCode + eaCode, 242 'predicate_test' : predicateTest }, 243 [ 'IsMicroop', 'IsMemRef', 'IsStore' ]) 244 245 exec_output += NeonLoadExecute.subst(loadIop) + \ 246 NeonLoadInitiateAcc.subst(loadIop) + \ 247 NeonLoadCompleteAcc.subst(loadIop) + \ 248 NeonStoreExecute.subst(storeIop) + \ 249 NeonStoreInitiateAcc.subst(storeIop) + \ 250 NeonStoreCompleteAcc.subst(storeIop) 251 header_output += MicroNeonMemDeclare.subst(loadIop) + \ 252 MicroNeonMemDeclare.subst(storeIop) 253}}; 254 255let {{ 256 exec_output = '' 257 for eSize, type in (1, 'uint8_t'), \ 258 (2, 'uint16_t'), \ 259 (4, 'uint32_t'), \ 260 (8, 'uint64_t'): 261 size = eSize 262 # An instruction handles no more than 16 bytes and no more than 263 # 4 elements, or the number of elements needed to fill 8 or 16 bytes. 264 sizes = set((16, 8)) 265 for count in 1, 2, 3, 4: 266 size = count * eSize 267 if size <= 16: 268 sizes.add(size) 269 for size in sizes: 270 substDict = { 271 "class_name" : "MicroLdrNeon%dUop" % size, 272 "targs" : type 273 } 274 exec_output += MicroNeonMemExecDeclare.subst(substDict) 275 substDict["class_name"] = "MicroStrNeon%dUop" % size 276 exec_output += MicroNeonMemExecDeclare.subst(substDict) 277 size += eSize 278}}; 279 280//////////////////////////////////////////////////////////////////// 281// 282// Neon (de)interlacing microops 283// 284 285let {{ 286 header_output = exec_output = '' 287 for dRegs in (2, 3, 4): 288 loadConv = '' 289 unloadConv = '' 290 for dReg in range(dRegs): 291 loadConv += ''' 292 conv1.cRegs[%(sReg0)d] = htog(FpOp1P%(sReg0)d.uw); 293 conv1.cRegs[%(sReg1)d] = htog(FpOp1P%(sReg1)d.uw); 294 ''' % { "sReg0" : (dReg * 2), "sReg1" : (dReg * 2 + 1) } 295 unloadConv += ''' 296 FpDestS%(dReg)dP0.uw = gtoh(conv2.cRegs[2 * %(dReg)d + 0]); 297 FpDestS%(dReg)dP1.uw = gtoh(conv2.cRegs[2 * %(dReg)d + 1]); 298 ''' % { "dReg" : dReg } 299 microDeintNeonCode = ''' 300 const unsigned dRegs = %(dRegs)d; 301 const unsigned regs = 2 * dRegs; 302 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 303 sizeof(Element); 304 union convStruct { 305 FloatRegBits cRegs[regs]; 306 Element elements[dRegs * perDReg]; 307 } conv1, conv2; 308 309 %(loadConv)s 310 311 unsigned srcElem = 0; 312 for (unsigned destOffset = 0; 313 destOffset < perDReg; destOffset++) { 314 for (unsigned dReg = 0; dReg < dRegs; dReg++) { 315 conv2.elements[dReg * perDReg + destOffset] = 316 conv1.elements[srcElem++]; 317 } 318 } 319 320 %(unloadConv)s 321 ''' % { "dRegs" : dRegs, 322 "loadConv" : loadConv, 323 "unloadConv" : unloadConv } 324 microDeintNeonIop = \ 325 InstObjParams('deintneon%duop' % (dRegs * 2), 326 'MicroDeintNeon%dUop' % (dRegs * 2), 327 'MicroNeonMixOp', 328 { 'predicate_test': predicateTest, 329 'code' : microDeintNeonCode }, 330 ['IsMicroop']) 331 header_output += MicroNeonMixDeclare.subst(microDeintNeonIop) 332 exec_output += MicroNeonMixExecute.subst(microDeintNeonIop) 333 334 loadConv = '' 335 unloadConv = '' 336 for dReg in range(dRegs): 337 loadConv += ''' 338 conv1.cRegs[2 * %(dReg)d + 0] = htog(FpOp1S%(dReg)dP0.uw); 339 conv1.cRegs[2 * %(dReg)d + 1] = htog(FpOp1S%(dReg)dP1.uw); 340 ''' % { "dReg" : dReg } 341 unloadConv += ''' 342 FpDestP%(sReg0)d.uw = gtoh(conv2.cRegs[%(sReg0)d]); 343 FpDestP%(sReg1)d.uw = gtoh(conv2.cRegs[%(sReg1)d]); 344 ''' % { "sReg0" : (dReg * 2), "sReg1" : (dReg * 2 + 1) } 345 microInterNeonCode = ''' 346 const unsigned dRegs = %(dRegs)d; 347 const unsigned regs = 2 * dRegs; 348 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 349 sizeof(Element); 350 union convStruct { 351 FloatRegBits cRegs[regs]; 352 Element elements[dRegs * perDReg]; 353 } conv1, conv2; 354 355 %(loadConv)s 356 357 unsigned destElem = 0; 358 for (unsigned srcOffset = 0; 359 srcOffset < perDReg; srcOffset++) { 360 for (unsigned dReg = 0; dReg < dRegs; dReg++) { 361 conv2.elements[destElem++] = 362 conv1.elements[dReg * perDReg + srcOffset]; 363 } 364 } 365 366 %(unloadConv)s 367 ''' % { "dRegs" : dRegs, 368 "loadConv" : loadConv, 369 "unloadConv" : unloadConv } 370 microInterNeonIop = \ 371 InstObjParams('interneon%duop' % (dRegs * 2), 372 'MicroInterNeon%dUop' % (dRegs * 2), 373 'MicroNeonMixOp', 374 { 'predicate_test': predicateTest, 375 'code' : microInterNeonCode }, 376 ['IsMicroop']) 377 header_output += MicroNeonMixDeclare.subst(microInterNeonIop) 378 exec_output += MicroNeonMixExecute.subst(microInterNeonIop) 379}}; 380 381let {{ 382 exec_output = '' 383 for type in ('uint8_t', 'uint16_t', 'uint32_t', 'uint64_t'): 384 for dRegs in (2, 3, 4): 385 Name = "MicroDeintNeon%dUop" % (dRegs * 2) 386 substDict = { "class_name" : Name, "targs" : type } 387 exec_output += MicroNeonExecDeclare.subst(substDict) 388 Name = "MicroInterNeon%dUop" % (dRegs * 2) 389 substDict = { "class_name" : Name, "targs" : type } 390 exec_output += MicroNeonExecDeclare.subst(substDict) 391}}; 392 393//////////////////////////////////////////////////////////////////// 394// 395// Neon microops to pack/unpack a single lane 396// 397 398let {{ 399 header_output = exec_output = '' 400 for sRegs in 1, 2: 401 baseLoadRegs = '' 402 for reg in range(sRegs): 403 baseLoadRegs += ''' 404 sourceRegs.fRegs[%(reg0)d] = htog(FpOp1P%(reg0)d.uw); 405 sourceRegs.fRegs[%(reg1)d] = htog(FpOp1P%(reg1)d.uw); 406 ''' % { "reg0" : (2 * reg + 0), 407 "reg1" : (2 * reg + 1) } 408 for dRegs in range(sRegs, 5): 409 unloadRegs = '' 410 loadRegs = baseLoadRegs 411 for reg in range(dRegs): 412 loadRegs += ''' 413 destRegs[%(reg)d].fRegs[0] = htog(FpDestS%(reg)dP0.uw); 414 destRegs[%(reg)d].fRegs[1] = htog(FpDestS%(reg)dP1.uw); 415 ''' % { "reg" : reg } 416 unloadRegs += ''' 417 FpDestS%(reg)dP0.uw = gtoh(destRegs[%(reg)d].fRegs[0]); 418 FpDestS%(reg)dP1.uw = gtoh(destRegs[%(reg)d].fRegs[1]); 419 ''' % { "reg" : reg } 420 microUnpackNeonCode = ''' 421 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 422 sizeof(Element); 423 424 union SourceRegs { 425 FloatRegBits fRegs[2 * %(sRegs)d]; 426 Element elements[%(sRegs)d * perDReg]; 427 } sourceRegs; 428 429 union DestReg { 430 FloatRegBits fRegs[2]; 431 Element elements[perDReg]; 432 } destRegs[%(dRegs)d]; 433 434 %(loadRegs)s 435 436 for (unsigned i = 0; i < %(dRegs)d; i++) { 437 destRegs[i].elements[lane] = sourceRegs.elements[i]; 438 } 439 440 %(unloadRegs)s 441 ''' % { "sRegs" : sRegs, "dRegs" : dRegs, 442 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs } 443 444 microUnpackNeonIop = \ 445 InstObjParams('unpackneon%dto%duop' % (sRegs * 2, dRegs * 2), 446 'MicroUnpackNeon%dto%dUop' % 447 (sRegs * 2, dRegs * 2), 448 'MicroNeonMixLaneOp', 449 { 'predicate_test': predicateTest, 450 'code' : microUnpackNeonCode }, 451 ['IsMicroop']) 452 header_output += MicroNeonMixLaneDeclare.subst(microUnpackNeonIop) 453 exec_output += MicroNeonMixExecute.subst(microUnpackNeonIop) 454 455 for sRegs in 1, 2: 456 loadRegs = '' 457 for reg in range(sRegs): 458 loadRegs += ''' 459 sourceRegs.fRegs[%(reg0)d] = htog(FpOp1P%(reg0)d.uw); 460 sourceRegs.fRegs[%(reg1)d] = htog(FpOp1P%(reg1)d.uw); 461 ''' % { "reg0" : (2 * reg + 0), 462 "reg1" : (2 * reg + 1) } 463 for dRegs in range(sRegs, 5): 464 unloadRegs = '' 465 for reg in range(dRegs): 466 unloadRegs += ''' 467 FpDestS%(reg)dP0.uw = gtoh(destRegs[%(reg)d].fRegs[0]); 468 FpDestS%(reg)dP1.uw = gtoh(destRegs[%(reg)d].fRegs[1]); 469 ''' % { "reg" : reg } 470 microUnpackAllNeonCode = ''' 471 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 472 sizeof(Element); 473 474 union SourceRegs { 475 FloatRegBits fRegs[2 * %(sRegs)d]; 476 Element elements[%(sRegs)d * perDReg]; 477 } sourceRegs; 478 479 union DestReg { 480 FloatRegBits fRegs[2]; 481 Element elements[perDReg]; 482 } destRegs[%(dRegs)d]; 483 484 %(loadRegs)s 485 486 for (unsigned i = 0; i < %(dRegs)d; i++) { 487 for (unsigned j = 0; j < perDReg; j++) 488 destRegs[i].elements[j] = sourceRegs.elements[i]; 489 } 490 491 %(unloadRegs)s 492 ''' % { "sRegs" : sRegs, "dRegs" : dRegs, 493 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs } 494 495 microUnpackAllNeonIop = \ 496 InstObjParams('unpackallneon%dto%duop' % (sRegs * 2, dRegs * 2), 497 'MicroUnpackAllNeon%dto%dUop' % 498 (sRegs * 2, dRegs * 2), 499 'MicroNeonMixOp', 500 { 'predicate_test': predicateTest, 501 'code' : microUnpackAllNeonCode }, 502 ['IsMicroop']) 503 header_output += MicroNeonMixDeclare.subst(microUnpackAllNeonIop) 504 exec_output += MicroNeonMixExecute.subst(microUnpackAllNeonIop) 505 506 for dRegs in 1, 2: 507 unloadRegs = '' 508 for reg in range(dRegs): 509 unloadRegs += ''' 510 FpDestP%(reg0)d.uw = gtoh(destRegs.fRegs[%(reg0)d]); 511 FpDestP%(reg1)d.uw = gtoh(destRegs.fRegs[%(reg1)d]); 512 ''' % { "reg0" : (2 * reg + 0), 513 "reg1" : (2 * reg + 1) } 514 for sRegs in range(dRegs, 5): 515 loadRegs = '' 516 for reg in range(sRegs): 517 loadRegs += ''' 518 sourceRegs[%(reg)d].fRegs[0] = htog(FpOp1S%(reg)dP0.uw); 519 sourceRegs[%(reg)d].fRegs[1] = htog(FpOp1S%(reg)dP1.uw); 520 ''' % { "reg" : reg } 521 microPackNeonCode = ''' 522 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 523 sizeof(Element); 524 525 union SourceReg { 526 FloatRegBits fRegs[2]; 527 Element elements[perDReg]; 528 } sourceRegs[%(sRegs)d]; 529 530 union DestRegs { 531 FloatRegBits fRegs[2 * %(dRegs)d]; 532 Element elements[%(dRegs)d * perDReg]; 533 } destRegs; 534 535 %(loadRegs)s 536 537 for (unsigned i = 0; i < %(sRegs)d; i++) { 538 destRegs.elements[i] = sourceRegs[i].elements[lane]; 539 } 540 541 %(unloadRegs)s 542 ''' % { "sRegs" : sRegs, "dRegs" : dRegs, 543 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs } 544 545 microPackNeonIop = \ 546 InstObjParams('packneon%dto%duop' % (sRegs * 2, dRegs * 2), 547 'MicroPackNeon%dto%dUop' % 548 (sRegs * 2, dRegs * 2), 549 'MicroNeonMixLaneOp', 550 { 'predicate_test': predicateTest, 551 'code' : microPackNeonCode }, 552 ['IsMicroop']) 553 header_output += MicroNeonMixLaneDeclare.subst(microPackNeonIop) 554 exec_output += MicroNeonMixExecute.subst(microPackNeonIop) 555}}; 556 557let {{ 558 exec_output = '' 559 for type in ('uint8_t', 'uint16_t', 'uint32_t'): 560 for sRegs in 1, 2: 561 for dRegs in range(sRegs, 5): 562 for format in ("MicroUnpackNeon%(sRegs)dto%(dRegs)dUop", 563 "MicroUnpackAllNeon%(sRegs)dto%(dRegs)dUop", 564 "MicroPackNeon%(dRegs)dto%(sRegs)dUop"): 565 Name = format % { "sRegs" : sRegs * 2, 566 "dRegs" : dRegs * 2 } 567 substDict = { "class_name" : Name, "targs" : type } 568 exec_output += MicroNeonExecDeclare.subst(substDict) 569}}; 570 571//////////////////////////////////////////////////////////////////// 572// 573// Integer = Integer op Immediate microops 574// 575 576let {{ 577 microAddiUopIop = InstObjParams('addi_uop', 'MicroAddiUop', 578 'MicroIntImmOp', 579 {'code': 'URa = URb + imm;', 580 'predicate_test': predicateTest}, 581 ['IsMicroop']) 582 583 microAddUopIop = InstObjParams('add_uop', 'MicroAddUop', 584 'MicroIntRegOp', 585 {'code': 586 '''URa = URb + shift_rm_imm(URc, shiftAmt, 587 shiftType,
| 99 IWNPC = cSwap(%s, cpsr.e) | ((Spsr & 0x20) ? 1 : 0); 100 NextItState = ((((CPSR)Spsr).it2 << 2) & 0xFC) 101 | (((CPSR)Spsr).it1 & 0x3); 102 SevMailbox = 1; 103 ''' 104 105 microLdrRetUopIop = InstObjParams('ldr_ret_uop', 'MicroLdrRetUop', 106 'MicroMemOp', 107 {'memacc_code': 108 microRetUopCode % 'Mem.uw', 109 'ea_code': 110 'EA = URb + (up ? imm : -imm);', 111 'predicate_test': condPredicateTest}, 112 ['IsMicroop','IsNonSpeculative', 113 'IsSerializeAfter']) 114 115 microStrUopCode = "Mem = cSwap(URa.uw, ((CPSR)Cpsr).e);" 116 microStrUopIop = InstObjParams('str_uop', 'MicroStrUop', 117 'MicroMemOp', 118 {'memacc_code': microStrUopCode, 119 'postacc_code': "", 120 'ea_code': 'EA = URb + (up ? imm : -imm);', 121 'predicate_test': predicateTest}, 122 ['IsMicroop']) 123 124 microStrFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);" 125 microStrFpUopIop = InstObjParams('strfp_uop', 'MicroStrFpUop', 126 'MicroMemOp', 127 {'memacc_code': microStrFpUopCode, 128 'postacc_code': "", 129 'ea_code': vfpEnabledCheckCode + 130 'EA = URb + (up ? imm : -imm);', 131 'predicate_test': predicateTest}, 132 ['IsMicroop']) 133 134 microStrDBFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);" 135 microStrDBFpUopIop = InstObjParams('strfp_uop', 'MicroStrDBFpUop', 136 'MicroMemOp', 137 {'memacc_code': microStrFpUopCode, 138 'postacc_code': "", 139 'ea_code': vfpEnabledCheckCode + ''' 140 EA = URb + (up ? imm : -imm) + 141 (((CPSR)Cpsr).e ? 4 : 0); 142 ''', 143 'predicate_test': predicateTest}, 144 ['IsMicroop']) 145 146 microStrDTFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);" 147 microStrDTFpUopIop = InstObjParams('strfp_uop', 'MicroStrDTFpUop', 148 'MicroMemOp', 149 {'memacc_code': microStrFpUopCode, 150 'postacc_code': "", 151 'ea_code': vfpEnabledCheckCode + ''' 152 EA = URb + (up ? imm : -imm) - 153 (((CPSR)Cpsr).e ? 4 : 0); 154 ''', 155 'predicate_test': predicateTest}, 156 ['IsMicroop']) 157 158 header_output = decoder_output = exec_output = '' 159 160 loadIops = (microLdrUopIop, microLdrRetUopIop, 161 microLdrFpUopIop, microLdrDBFpUopIop, microLdrDTFpUopIop) 162 storeIops = (microStrUopIop, microStrFpUopIop, 163 microStrDBFpUopIop, microStrDTFpUopIop) 164 for iop in loadIops + storeIops: 165 header_output += MicroMemDeclare.subst(iop) 166 decoder_output += MicroMemConstructor.subst(iop) 167 for iop in loadIops: 168 exec_output += LoadExecute.subst(iop) + \ 169 LoadInitiateAcc.subst(iop) + \ 170 LoadCompleteAcc.subst(iop) 171 for iop in storeIops: 172 exec_output += StoreExecute.subst(iop) + \ 173 StoreInitiateAcc.subst(iop) + \ 174 StoreCompleteAcc.subst(iop) 175}}; 176 177let {{ 178 exec_output = header_output = '' 179 180 eaCode = 'EA = URa + imm;' 181 182 for size in (1, 2, 3, 4, 6, 8, 12, 16): 183 # Set up the memory access. 184 regs = (size + 3) // 4 185 subst = { "size" : size, "regs" : regs } 186 memDecl = ''' 187 union MemUnion { 188 uint8_t bytes[%(size)d]; 189 Element elements[%(size)d / sizeof(Element)]; 190 uint32_t floatRegBits[%(regs)d]; 191 }; 192 ''' % subst 193 194 # Do endian conversion for all the elements. 195 convCode = ''' 196 const unsigned eCount = sizeof(memUnion.elements) / 197 sizeof(memUnion.elements[0]); 198 if (((CPSR)Cpsr).e) { 199 for (unsigned i = 0; i < eCount; i++) { 200 memUnion.elements[i] = gtobe(memUnion.elements[i]); 201 } 202 } else { 203 for (unsigned i = 0; i < eCount; i++) { 204 memUnion.elements[i] = gtole(memUnion.elements[i]); 205 } 206 } 207 ''' 208 209 # Offload everything into registers 210 regSetCode = '' 211 for reg in range(regs): 212 mask = '' 213 if reg == regs - 1: 214 mask = ' & mask(%d)' % (32 - 8 * (regs * 4 - size)) 215 regSetCode += ''' 216 FpDestP%(reg)d.uw = gtoh(memUnion.floatRegBits[%(reg)d])%(mask)s; 217 ''' % { "reg" : reg, "mask" : mask } 218 219 # Pull everything in from registers 220 regGetCode = '' 221 for reg in range(regs): 222 regGetCode += ''' 223 memUnion.floatRegBits[%(reg)d] = htog(FpDestP%(reg)d.uw); 224 ''' % { "reg" : reg } 225 226 loadMemAccCode = convCode + regSetCode 227 storeMemAccCode = regGetCode + convCode 228 229 loadIop = InstObjParams('ldrneon%(size)d_uop' % subst, 230 'MicroLdrNeon%(size)dUop' % subst, 231 'MicroNeonMemOp', 232 { 'mem_decl' : memDecl, 233 'size' : size, 234 'memacc_code' : loadMemAccCode, 235 'ea_code' : simdEnabledCheckCode + eaCode, 236 'predicate_test' : predicateTest }, 237 [ 'IsMicroop', 'IsMemRef', 'IsLoad' ]) 238 storeIop = InstObjParams('strneon%(size)d_uop' % subst, 239 'MicroStrNeon%(size)dUop' % subst, 240 'MicroNeonMemOp', 241 { 'mem_decl' : memDecl, 242 'size' : size, 243 'memacc_code' : storeMemAccCode, 244 'ea_code' : simdEnabledCheckCode + eaCode, 245 'predicate_test' : predicateTest }, 246 [ 'IsMicroop', 'IsMemRef', 'IsStore' ]) 247 248 exec_output += NeonLoadExecute.subst(loadIop) + \ 249 NeonLoadInitiateAcc.subst(loadIop) + \ 250 NeonLoadCompleteAcc.subst(loadIop) + \ 251 NeonStoreExecute.subst(storeIop) + \ 252 NeonStoreInitiateAcc.subst(storeIop) + \ 253 NeonStoreCompleteAcc.subst(storeIop) 254 header_output += MicroNeonMemDeclare.subst(loadIop) + \ 255 MicroNeonMemDeclare.subst(storeIop) 256}}; 257 258let {{ 259 exec_output = '' 260 for eSize, type in (1, 'uint8_t'), \ 261 (2, 'uint16_t'), \ 262 (4, 'uint32_t'), \ 263 (8, 'uint64_t'): 264 size = eSize 265 # An instruction handles no more than 16 bytes and no more than 266 # 4 elements, or the number of elements needed to fill 8 or 16 bytes. 267 sizes = set((16, 8)) 268 for count in 1, 2, 3, 4: 269 size = count * eSize 270 if size <= 16: 271 sizes.add(size) 272 for size in sizes: 273 substDict = { 274 "class_name" : "MicroLdrNeon%dUop" % size, 275 "targs" : type 276 } 277 exec_output += MicroNeonMemExecDeclare.subst(substDict) 278 substDict["class_name"] = "MicroStrNeon%dUop" % size 279 exec_output += MicroNeonMemExecDeclare.subst(substDict) 280 size += eSize 281}}; 282 283//////////////////////////////////////////////////////////////////// 284// 285// Neon (de)interlacing microops 286// 287 288let {{ 289 header_output = exec_output = '' 290 for dRegs in (2, 3, 4): 291 loadConv = '' 292 unloadConv = '' 293 for dReg in range(dRegs): 294 loadConv += ''' 295 conv1.cRegs[%(sReg0)d] = htog(FpOp1P%(sReg0)d.uw); 296 conv1.cRegs[%(sReg1)d] = htog(FpOp1P%(sReg1)d.uw); 297 ''' % { "sReg0" : (dReg * 2), "sReg1" : (dReg * 2 + 1) } 298 unloadConv += ''' 299 FpDestS%(dReg)dP0.uw = gtoh(conv2.cRegs[2 * %(dReg)d + 0]); 300 FpDestS%(dReg)dP1.uw = gtoh(conv2.cRegs[2 * %(dReg)d + 1]); 301 ''' % { "dReg" : dReg } 302 microDeintNeonCode = ''' 303 const unsigned dRegs = %(dRegs)d; 304 const unsigned regs = 2 * dRegs; 305 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 306 sizeof(Element); 307 union convStruct { 308 FloatRegBits cRegs[regs]; 309 Element elements[dRegs * perDReg]; 310 } conv1, conv2; 311 312 %(loadConv)s 313 314 unsigned srcElem = 0; 315 for (unsigned destOffset = 0; 316 destOffset < perDReg; destOffset++) { 317 for (unsigned dReg = 0; dReg < dRegs; dReg++) { 318 conv2.elements[dReg * perDReg + destOffset] = 319 conv1.elements[srcElem++]; 320 } 321 } 322 323 %(unloadConv)s 324 ''' % { "dRegs" : dRegs, 325 "loadConv" : loadConv, 326 "unloadConv" : unloadConv } 327 microDeintNeonIop = \ 328 InstObjParams('deintneon%duop' % (dRegs * 2), 329 'MicroDeintNeon%dUop' % (dRegs * 2), 330 'MicroNeonMixOp', 331 { 'predicate_test': predicateTest, 332 'code' : microDeintNeonCode }, 333 ['IsMicroop']) 334 header_output += MicroNeonMixDeclare.subst(microDeintNeonIop) 335 exec_output += MicroNeonMixExecute.subst(microDeintNeonIop) 336 337 loadConv = '' 338 unloadConv = '' 339 for dReg in range(dRegs): 340 loadConv += ''' 341 conv1.cRegs[2 * %(dReg)d + 0] = htog(FpOp1S%(dReg)dP0.uw); 342 conv1.cRegs[2 * %(dReg)d + 1] = htog(FpOp1S%(dReg)dP1.uw); 343 ''' % { "dReg" : dReg } 344 unloadConv += ''' 345 FpDestP%(sReg0)d.uw = gtoh(conv2.cRegs[%(sReg0)d]); 346 FpDestP%(sReg1)d.uw = gtoh(conv2.cRegs[%(sReg1)d]); 347 ''' % { "sReg0" : (dReg * 2), "sReg1" : (dReg * 2 + 1) } 348 microInterNeonCode = ''' 349 const unsigned dRegs = %(dRegs)d; 350 const unsigned regs = 2 * dRegs; 351 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 352 sizeof(Element); 353 union convStruct { 354 FloatRegBits cRegs[regs]; 355 Element elements[dRegs * perDReg]; 356 } conv1, conv2; 357 358 %(loadConv)s 359 360 unsigned destElem = 0; 361 for (unsigned srcOffset = 0; 362 srcOffset < perDReg; srcOffset++) { 363 for (unsigned dReg = 0; dReg < dRegs; dReg++) { 364 conv2.elements[destElem++] = 365 conv1.elements[dReg * perDReg + srcOffset]; 366 } 367 } 368 369 %(unloadConv)s 370 ''' % { "dRegs" : dRegs, 371 "loadConv" : loadConv, 372 "unloadConv" : unloadConv } 373 microInterNeonIop = \ 374 InstObjParams('interneon%duop' % (dRegs * 2), 375 'MicroInterNeon%dUop' % (dRegs * 2), 376 'MicroNeonMixOp', 377 { 'predicate_test': predicateTest, 378 'code' : microInterNeonCode }, 379 ['IsMicroop']) 380 header_output += MicroNeonMixDeclare.subst(microInterNeonIop) 381 exec_output += MicroNeonMixExecute.subst(microInterNeonIop) 382}}; 383 384let {{ 385 exec_output = '' 386 for type in ('uint8_t', 'uint16_t', 'uint32_t', 'uint64_t'): 387 for dRegs in (2, 3, 4): 388 Name = "MicroDeintNeon%dUop" % (dRegs * 2) 389 substDict = { "class_name" : Name, "targs" : type } 390 exec_output += MicroNeonExecDeclare.subst(substDict) 391 Name = "MicroInterNeon%dUop" % (dRegs * 2) 392 substDict = { "class_name" : Name, "targs" : type } 393 exec_output += MicroNeonExecDeclare.subst(substDict) 394}}; 395 396//////////////////////////////////////////////////////////////////// 397// 398// Neon microops to pack/unpack a single lane 399// 400 401let {{ 402 header_output = exec_output = '' 403 for sRegs in 1, 2: 404 baseLoadRegs = '' 405 for reg in range(sRegs): 406 baseLoadRegs += ''' 407 sourceRegs.fRegs[%(reg0)d] = htog(FpOp1P%(reg0)d.uw); 408 sourceRegs.fRegs[%(reg1)d] = htog(FpOp1P%(reg1)d.uw); 409 ''' % { "reg0" : (2 * reg + 0), 410 "reg1" : (2 * reg + 1) } 411 for dRegs in range(sRegs, 5): 412 unloadRegs = '' 413 loadRegs = baseLoadRegs 414 for reg in range(dRegs): 415 loadRegs += ''' 416 destRegs[%(reg)d].fRegs[0] = htog(FpDestS%(reg)dP0.uw); 417 destRegs[%(reg)d].fRegs[1] = htog(FpDestS%(reg)dP1.uw); 418 ''' % { "reg" : reg } 419 unloadRegs += ''' 420 FpDestS%(reg)dP0.uw = gtoh(destRegs[%(reg)d].fRegs[0]); 421 FpDestS%(reg)dP1.uw = gtoh(destRegs[%(reg)d].fRegs[1]); 422 ''' % { "reg" : reg } 423 microUnpackNeonCode = ''' 424 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 425 sizeof(Element); 426 427 union SourceRegs { 428 FloatRegBits fRegs[2 * %(sRegs)d]; 429 Element elements[%(sRegs)d * perDReg]; 430 } sourceRegs; 431 432 union DestReg { 433 FloatRegBits fRegs[2]; 434 Element elements[perDReg]; 435 } destRegs[%(dRegs)d]; 436 437 %(loadRegs)s 438 439 for (unsigned i = 0; i < %(dRegs)d; i++) { 440 destRegs[i].elements[lane] = sourceRegs.elements[i]; 441 } 442 443 %(unloadRegs)s 444 ''' % { "sRegs" : sRegs, "dRegs" : dRegs, 445 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs } 446 447 microUnpackNeonIop = \ 448 InstObjParams('unpackneon%dto%duop' % (sRegs * 2, dRegs * 2), 449 'MicroUnpackNeon%dto%dUop' % 450 (sRegs * 2, dRegs * 2), 451 'MicroNeonMixLaneOp', 452 { 'predicate_test': predicateTest, 453 'code' : microUnpackNeonCode }, 454 ['IsMicroop']) 455 header_output += MicroNeonMixLaneDeclare.subst(microUnpackNeonIop) 456 exec_output += MicroNeonMixExecute.subst(microUnpackNeonIop) 457 458 for sRegs in 1, 2: 459 loadRegs = '' 460 for reg in range(sRegs): 461 loadRegs += ''' 462 sourceRegs.fRegs[%(reg0)d] = htog(FpOp1P%(reg0)d.uw); 463 sourceRegs.fRegs[%(reg1)d] = htog(FpOp1P%(reg1)d.uw); 464 ''' % { "reg0" : (2 * reg + 0), 465 "reg1" : (2 * reg + 1) } 466 for dRegs in range(sRegs, 5): 467 unloadRegs = '' 468 for reg in range(dRegs): 469 unloadRegs += ''' 470 FpDestS%(reg)dP0.uw = gtoh(destRegs[%(reg)d].fRegs[0]); 471 FpDestS%(reg)dP1.uw = gtoh(destRegs[%(reg)d].fRegs[1]); 472 ''' % { "reg" : reg } 473 microUnpackAllNeonCode = ''' 474 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 475 sizeof(Element); 476 477 union SourceRegs { 478 FloatRegBits fRegs[2 * %(sRegs)d]; 479 Element elements[%(sRegs)d * perDReg]; 480 } sourceRegs; 481 482 union DestReg { 483 FloatRegBits fRegs[2]; 484 Element elements[perDReg]; 485 } destRegs[%(dRegs)d]; 486 487 %(loadRegs)s 488 489 for (unsigned i = 0; i < %(dRegs)d; i++) { 490 for (unsigned j = 0; j < perDReg; j++) 491 destRegs[i].elements[j] = sourceRegs.elements[i]; 492 } 493 494 %(unloadRegs)s 495 ''' % { "sRegs" : sRegs, "dRegs" : dRegs, 496 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs } 497 498 microUnpackAllNeonIop = \ 499 InstObjParams('unpackallneon%dto%duop' % (sRegs * 2, dRegs * 2), 500 'MicroUnpackAllNeon%dto%dUop' % 501 (sRegs * 2, dRegs * 2), 502 'MicroNeonMixOp', 503 { 'predicate_test': predicateTest, 504 'code' : microUnpackAllNeonCode }, 505 ['IsMicroop']) 506 header_output += MicroNeonMixDeclare.subst(microUnpackAllNeonIop) 507 exec_output += MicroNeonMixExecute.subst(microUnpackAllNeonIop) 508 509 for dRegs in 1, 2: 510 unloadRegs = '' 511 for reg in range(dRegs): 512 unloadRegs += ''' 513 FpDestP%(reg0)d.uw = gtoh(destRegs.fRegs[%(reg0)d]); 514 FpDestP%(reg1)d.uw = gtoh(destRegs.fRegs[%(reg1)d]); 515 ''' % { "reg0" : (2 * reg + 0), 516 "reg1" : (2 * reg + 1) } 517 for sRegs in range(dRegs, 5): 518 loadRegs = '' 519 for reg in range(sRegs): 520 loadRegs += ''' 521 sourceRegs[%(reg)d].fRegs[0] = htog(FpOp1S%(reg)dP0.uw); 522 sourceRegs[%(reg)d].fRegs[1] = htog(FpOp1S%(reg)dP1.uw); 523 ''' % { "reg" : reg } 524 microPackNeonCode = ''' 525 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 526 sizeof(Element); 527 528 union SourceReg { 529 FloatRegBits fRegs[2]; 530 Element elements[perDReg]; 531 } sourceRegs[%(sRegs)d]; 532 533 union DestRegs { 534 FloatRegBits fRegs[2 * %(dRegs)d]; 535 Element elements[%(dRegs)d * perDReg]; 536 } destRegs; 537 538 %(loadRegs)s 539 540 for (unsigned i = 0; i < %(sRegs)d; i++) { 541 destRegs.elements[i] = sourceRegs[i].elements[lane]; 542 } 543 544 %(unloadRegs)s 545 ''' % { "sRegs" : sRegs, "dRegs" : dRegs, 546 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs } 547 548 microPackNeonIop = \ 549 InstObjParams('packneon%dto%duop' % (sRegs * 2, dRegs * 2), 550 'MicroPackNeon%dto%dUop' % 551 (sRegs * 2, dRegs * 2), 552 'MicroNeonMixLaneOp', 553 { 'predicate_test': predicateTest, 554 'code' : microPackNeonCode }, 555 ['IsMicroop']) 556 header_output += MicroNeonMixLaneDeclare.subst(microPackNeonIop) 557 exec_output += MicroNeonMixExecute.subst(microPackNeonIop) 558}}; 559 560let {{ 561 exec_output = '' 562 for type in ('uint8_t', 'uint16_t', 'uint32_t'): 563 for sRegs in 1, 2: 564 for dRegs in range(sRegs, 5): 565 for format in ("MicroUnpackNeon%(sRegs)dto%(dRegs)dUop", 566 "MicroUnpackAllNeon%(sRegs)dto%(dRegs)dUop", 567 "MicroPackNeon%(dRegs)dto%(sRegs)dUop"): 568 Name = format % { "sRegs" : sRegs * 2, 569 "dRegs" : dRegs * 2 } 570 substDict = { "class_name" : Name, "targs" : type } 571 exec_output += MicroNeonExecDeclare.subst(substDict) 572}}; 573 574//////////////////////////////////////////////////////////////////// 575// 576// Integer = Integer op Immediate microops 577// 578 579let {{ 580 microAddiUopIop = InstObjParams('addi_uop', 'MicroAddiUop', 581 'MicroIntImmOp', 582 {'code': 'URa = URb + imm;', 583 'predicate_test': predicateTest}, 584 ['IsMicroop']) 585 586 microAddUopIop = InstObjParams('add_uop', 'MicroAddUop', 587 'MicroIntRegOp', 588 {'code': 589 '''URa = URb + shift_rm_imm(URc, shiftAmt, 590 shiftType,
|