macromem.isa revision 7644:62873d5c2bfc
16019SN/A// -*- mode:c++ -*- 26019SN/A 37134Sgblack@eecs.umich.edu// Copyright (c) 2010 ARM Limited 47134Sgblack@eecs.umich.edu// All rights reserved 57134Sgblack@eecs.umich.edu// 67134Sgblack@eecs.umich.edu// The license below extends only to copyright in the software and shall 77134Sgblack@eecs.umich.edu// not be construed as granting a license to any other intellectual 87134Sgblack@eecs.umich.edu// property including but not limited to intellectual property relating 97134Sgblack@eecs.umich.edu// to a hardware implementation of the functionality of the software 107134Sgblack@eecs.umich.edu// licensed hereunder. You may use the software subject to the license 117134Sgblack@eecs.umich.edu// terms below provided that you ensure that this notice is replicated 127134Sgblack@eecs.umich.edu// unmodified and in its entirety in all distributions of the software, 137134Sgblack@eecs.umich.edu// modified or unmodified, in source code or in binary form. 147134Sgblack@eecs.umich.edu// 156019SN/A// Copyright (c) 2007-2008 The Florida State University 166019SN/A// All rights reserved. 176019SN/A// 186019SN/A// Redistribution and use in source and binary forms, with or without 196019SN/A// modification, are permitted provided that the following conditions are 206019SN/A// met: redistributions of source code must retain the above copyright 216019SN/A// notice, this list of conditions and the following disclaimer; 226019SN/A// redistributions in binary form must reproduce the above copyright 236019SN/A// notice, this list of conditions and the following disclaimer in the 246019SN/A// documentation and/or other materials provided with the distribution; 256019SN/A// neither the name of the copyright holders nor the names of its 266019SN/A// contributors may be used to endorse or promote products derived from 276019SN/A// this software without specific prior written permission. 286019SN/A// 296019SN/A// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 306019SN/A// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 316019SN/A// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 326019SN/A// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 336019SN/A// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 346019SN/A// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 356019SN/A// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 366019SN/A// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 376019SN/A// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 386019SN/A// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 396019SN/A// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 406019SN/A// 416019SN/A// Authors: Stephen Hines 426308SN/A// Gabe Black 436308SN/A 446309SN/A//////////////////////////////////////////////////////////////////// 456309SN/A// 466309SN/A// Load/store microops 476309SN/A// 486309SN/A 497134Sgblack@eecs.umich.edulet {{ 507134Sgblack@eecs.umich.edu microLdrUopCode = "IWRa = cSwap(Mem.uw, ((CPSR)Cpsr).e);" 516309SN/A microLdrUopIop = InstObjParams('ldr_uop', 'MicroLdrUop', 526309SN/A 'MicroMemOp', 536309SN/A {'memacc_code': microLdrUopCode, 547296Sgblack@eecs.umich.edu 'ea_code': 'EA = Rb + (up ? imm : -imm);', 556309SN/A 'predicate_test': predicateTest}, 566309SN/A ['IsMicroop']) 577296Sgblack@eecs.umich.edu 587134Sgblack@eecs.umich.edu microLdrFpUopCode = "Fa.uw = cSwap(Mem.uw, ((CPSR)Cpsr).e);" 596309SN/A microLdrFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrFpUop', 606309SN/A 'MicroMemOp', 616309SN/A {'memacc_code': microLdrFpUopCode, 627342Sgblack@eecs.umich.edu 'ea_code': vfpEnabledCheckCode + 637174Sgblack@eecs.umich.edu 'EA = Rb + (up ? imm : -imm);', 647174Sgblack@eecs.umich.edu 'predicate_test': predicateTest}, 657296Sgblack@eecs.umich.edu ['IsMicroop']) 667174Sgblack@eecs.umich.edu 677174Sgblack@eecs.umich.edu microLdrDBFpUopCode = "Fa.uw = cSwap(Mem.uw, ((CPSR)Cpsr).e);" 687174Sgblack@eecs.umich.edu microLdrDBFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrDBFpUop', 697174Sgblack@eecs.umich.edu 'MicroMemOp', 706754SN/A {'memacc_code': microLdrFpUopCode, 717296Sgblack@eecs.umich.edu 'ea_code': vfpEnabledCheckCode + ''' 727400SAli.Saidi@ARM.com EA = Rb + (up ? imm : -imm) + 737134Sgblack@eecs.umich.edu (((CPSR)Cpsr).e ? 4 : 0); 747400SAli.Saidi@ARM.com ''', 757134Sgblack@eecs.umich.edu 'predicate_test': predicateTest}, 767134Sgblack@eecs.umich.edu ['IsMicroop']) 777296Sgblack@eecs.umich.edu 786754SN/A microLdrDTFpUopCode = "Fa.uw = cSwap(Mem.uw, ((CPSR)Cpsr).e);" 796754SN/A microLdrDTFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrDTFpUop', 806754SN/A 'MicroMemOp', 816754SN/A {'memacc_code': microLdrFpUopCode, 826754SN/A 'ea_code': vfpEnabledCheckCode + ''' 837134Sgblack@eecs.umich.edu EA = Rb + (up ? imm : -imm) - 846754SN/A (((CPSR)Cpsr).e ? 4 : 0); 856754SN/A ''', 866754SN/A 'predicate_test': predicateTest}, 877296Sgblack@eecs.umich.edu ['IsMicroop']) 886309SN/A 896309SN/A microLdrRetUopCode = ''' 907296Sgblack@eecs.umich.edu CPSR cpsr = Cpsr; 917303Sgblack@eecs.umich.edu SCTLR sctlr = Sctlr; 927134Sgblack@eecs.umich.edu uint32_t newCpsr = 936309SN/A cpsrWriteByInstr(cpsr | CondCodes, Spsr, 0xF, true, sctlr.nmfi); 946309SN/A Cpsr = ~CondCodesMask & newCpsr; 956309SN/A CondCodes = CondCodesMask & newCpsr; 967296Sgblack@eecs.umich.edu IWNPC = cSwap(Mem.uw, cpsr.e) | ((Spsr & 0x20) ? 1 : 0); 977174Sgblack@eecs.umich.edu ''' 987174Sgblack@eecs.umich.edu microLdrRetUopIop = InstObjParams('ldr_ret_uop', 'MicroLdrRetUop', 997296Sgblack@eecs.umich.edu 'MicroMemOp', 1007303Sgblack@eecs.umich.edu {'memacc_code': microLdrRetUopCode, 1017174Sgblack@eecs.umich.edu 'ea_code': 1027174Sgblack@eecs.umich.edu 'EA = Rb + (up ? imm : -imm);', 1037174Sgblack@eecs.umich.edu 'predicate_test': condPredicateTest}, 1047174Sgblack@eecs.umich.edu ['IsMicroop']) 1057174Sgblack@eecs.umich.edu 1067174Sgblack@eecs.umich.edu microStrUopCode = "Mem = cSwap(Ra.uw, ((CPSR)Cpsr).e);" 1077174Sgblack@eecs.umich.edu microStrUopIop = InstObjParams('str_uop', 'MicroStrUop', 1087174Sgblack@eecs.umich.edu 'MicroMemOp', 1097174Sgblack@eecs.umich.edu {'memacc_code': microStrUopCode, 1107174Sgblack@eecs.umich.edu 'postacc_code': "", 1117174Sgblack@eecs.umich.edu 'ea_code': 'EA = Rb + (up ? imm : -imm);', 1127174Sgblack@eecs.umich.edu 'predicate_test': predicateTest}, 1137174Sgblack@eecs.umich.edu ['IsMicroop']) 1147174Sgblack@eecs.umich.edu 1157174Sgblack@eecs.umich.edu microStrFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);" 1167174Sgblack@eecs.umich.edu microStrFpUopIop = InstObjParams('strfp_uop', 'MicroStrFpUop', 1177174Sgblack@eecs.umich.edu 'MicroMemOp', 1187174Sgblack@eecs.umich.edu {'memacc_code': microStrFpUopCode, 1197174Sgblack@eecs.umich.edu 'postacc_code': "", 1206309SN/A 'ea_code': vfpEnabledCheckCode + 1216308SN/A 'EA = Rb + (up ? imm : -imm);', 1226308SN/A 'predicate_test': predicateTest}, 1236308SN/A ['IsMicroop']) 1246308SN/A 1256308SN/A microStrDBFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);" 1266308SN/A microStrDBFpUopIop = InstObjParams('strfp_uop', 'MicroStrDBFpUop', 1276308SN/A 'MicroMemOp', 1286308SN/A {'memacc_code': microStrFpUopCode, 1296308SN/A 'postacc_code': "", 1306308SN/A 'ea_code': vfpEnabledCheckCode + ''' 1316308SN/A EA = Rb + (up ? imm : -imm) + 1326308SN/A (((CPSR)Cpsr).e ? 4 : 0); 1336308SN/A ''', 1346308SN/A 'predicate_test': predicateTest}, 1356308SN/A ['IsMicroop']) 1366308SN/A 1376308SN/A microStrDTFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);" 1386308SN/A microStrDTFpUopIop = InstObjParams('strfp_uop', 'MicroStrDTFpUop', 1396308SN/A 'MicroMemOp', 1406308SN/A {'memacc_code': microStrFpUopCode, 1416308SN/A 'postacc_code': "", 1427134Sgblack@eecs.umich.edu 'ea_code': vfpEnabledCheckCode + ''' 1437134Sgblack@eecs.umich.edu EA = Rb + (up ? imm : -imm) - 1446308SN/A (((CPSR)Cpsr).e ? 4 : 0); 1456308SN/A ''', 1466308SN/A 'predicate_test': predicateTest}, 1476019SN/A ['IsMicroop']) 1487134Sgblack@eecs.umich.edu 1497170Sgblack@eecs.umich.edu header_output = decoder_output = exec_output = '' 1507134Sgblack@eecs.umich.edu 1517134Sgblack@eecs.umich.edu loadIops = (microLdrUopIop, microLdrRetUopIop, 1527179Sgblack@eecs.umich.edu microLdrFpUopIop, microLdrDBFpUopIop, microLdrDTFpUopIop) 1537179Sgblack@eecs.umich.edu storeIops = (microStrUopIop, microStrFpUopIop, 1547179Sgblack@eecs.umich.edu microStrDBFpUopIop, microStrDTFpUopIop) 1557179Sgblack@eecs.umich.edu for iop in loadIops + storeIops: 1566019SN/A header_output += MicroMemDeclare.subst(iop) 157 decoder_output += MicroMemConstructor.subst(iop) 158 for iop in loadIops: 159 exec_output += LoadExecute.subst(iop) + \ 160 LoadInitiateAcc.subst(iop) + \ 161 LoadCompleteAcc.subst(iop) 162 for iop in storeIops: 163 exec_output += StoreExecute.subst(iop) + \ 164 StoreInitiateAcc.subst(iop) + \ 165 StoreCompleteAcc.subst(iop) 166}}; 167 168let {{ 169 exec_output = header_output = '' 170 171 eaCode = 'EA = Ra + imm;' 172 173 for size in (1, 2, 3, 4, 6, 8, 12, 16): 174 # Set up the memory access. 175 regs = (size + 3) // 4 176 subst = { "size" : size, "regs" : regs } 177 memDecl = ''' 178 union MemUnion { 179 uint8_t bytes[%(size)d]; 180 Element elements[%(size)d / sizeof(Element)]; 181 uint32_t floatRegBits[%(regs)d]; 182 }; 183 ''' % subst 184 185 # Do endian conversion for all the elements. 186 convCode = ''' 187 const unsigned eCount = sizeof(memUnion.elements) / 188 sizeof(memUnion.elements[0]); 189 if (((CPSR)Cpsr).e) { 190 for (unsigned i = 0; i < eCount; i++) { 191 memUnion.elements[i] = gtobe(memUnion.elements[i]); 192 } 193 } else { 194 for (unsigned i = 0; i < eCount; i++) { 195 memUnion.elements[i] = gtole(memUnion.elements[i]); 196 } 197 } 198 ''' 199 200 # Offload everything into registers 201 regSetCode = '' 202 for reg in range(regs): 203 mask = '' 204 if reg == regs - 1: 205 mask = ' & mask(%d)' % (32 - 8 * (regs * 4 - size)) 206 regSetCode += ''' 207 FpDestP%(reg)d.uw = gtoh(memUnion.floatRegBits[%(reg)d])%(mask)s; 208 ''' % { "reg" : reg, "mask" : mask } 209 210 # Pull everything in from registers 211 regGetCode = '' 212 for reg in range(regs): 213 regGetCode += ''' 214 memUnion.floatRegBits[%(reg)d] = htog(FpDestP%(reg)d.uw); 215 ''' % { "reg" : reg } 216 217 loadMemAccCode = convCode + regSetCode 218 storeMemAccCode = regGetCode + convCode 219 220 loadIop = InstObjParams('ldrneon%(size)d_uop' % subst, 221 'MicroLdrNeon%(size)dUop' % subst, 222 'MicroNeonMemOp', 223 { 'mem_decl' : memDecl, 224 'size' : size, 225 'memacc_code' : loadMemAccCode, 226 'ea_code' : simdEnabledCheckCode + eaCode, 227 'predicate_test' : predicateTest }, 228 [ 'IsMicroop', 'IsMemRef', 'IsLoad' ]) 229 storeIop = InstObjParams('strneon%(size)d_uop' % subst, 230 'MicroStrNeon%(size)dUop' % subst, 231 'MicroNeonMemOp', 232 { 'mem_decl' : memDecl, 233 'size' : size, 234 'memacc_code' : storeMemAccCode, 235 'ea_code' : simdEnabledCheckCode + eaCode, 236 'predicate_test' : predicateTest }, 237 [ 'IsMicroop', 'IsMemRef', 'IsStore' ]) 238 239 exec_output += NeonLoadExecute.subst(loadIop) + \ 240 NeonLoadInitiateAcc.subst(loadIop) + \ 241 NeonLoadCompleteAcc.subst(loadIop) + \ 242 NeonStoreExecute.subst(storeIop) + \ 243 NeonStoreInitiateAcc.subst(storeIop) + \ 244 NeonStoreCompleteAcc.subst(storeIop) 245 header_output += MicroNeonMemDeclare.subst(loadIop) + \ 246 MicroNeonMemDeclare.subst(storeIop) 247}}; 248 249let {{ 250 exec_output = '' 251 for eSize, type in (1, 'uint8_t'), \ 252 (2, 'uint16_t'), \ 253 (4, 'uint32_t'), \ 254 (8, 'uint64_t'): 255 size = eSize 256 # An instruction handles no more than 16 bytes and no more than 257 # 4 elements, or the number of elements needed to fill 8 or 16 bytes. 258 sizes = set((16, 8)) 259 for count in 1, 2, 3, 4: 260 size = count * eSize 261 if size <= 16: 262 sizes.add(size) 263 for size in sizes: 264 substDict = { 265 "class_name" : "MicroLdrNeon%dUop" % size, 266 "targs" : type 267 } 268 exec_output += MicroNeonMemExecDeclare.subst(substDict) 269 substDict["class_name"] = "MicroStrNeon%dUop" % size 270 exec_output += MicroNeonMemExecDeclare.subst(substDict) 271 size += eSize 272}}; 273 274//////////////////////////////////////////////////////////////////// 275// 276// Neon (de)interlacing microops 277// 278 279let {{ 280 header_output = exec_output = '' 281 for dRegs in (2, 3, 4): 282 loadConv = '' 283 unloadConv = '' 284 for dReg in range(dRegs): 285 loadConv += ''' 286 conv1.cRegs[%(sReg0)d] = htog(FpOp1P%(sReg0)d.uw); 287 conv1.cRegs[%(sReg1)d] = htog(FpOp1P%(sReg1)d.uw); 288 ''' % { "sReg0" : (dReg * 2), "sReg1" : (dReg * 2 + 1) } 289 unloadConv += ''' 290 FpDestS%(dReg)dP0.uw = gtoh(conv2.cRegs[2 * %(dReg)d + 0]); 291 FpDestS%(dReg)dP1.uw = gtoh(conv2.cRegs[2 * %(dReg)d + 1]); 292 ''' % { "dReg" : dReg } 293 microDeintNeonCode = ''' 294 const unsigned dRegs = %(dRegs)d; 295 const unsigned regs = 2 * dRegs; 296 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 297 sizeof(Element); 298 union convStruct { 299 FloatRegBits cRegs[regs]; 300 Element elements[dRegs * perDReg]; 301 } conv1, conv2; 302 303 %(loadConv)s 304 305 unsigned srcElem = 0; 306 for (unsigned destOffset = 0; 307 destOffset < perDReg; destOffset++) { 308 for (unsigned dReg = 0; dReg < dRegs; dReg++) { 309 conv2.elements[dReg * perDReg + destOffset] = 310 conv1.elements[srcElem++]; 311 } 312 } 313 314 %(unloadConv)s 315 ''' % { "dRegs" : dRegs, 316 "loadConv" : loadConv, 317 "unloadConv" : unloadConv } 318 microDeintNeonIop = \ 319 InstObjParams('deintneon%duop' % (dRegs * 2), 320 'MicroDeintNeon%dUop' % (dRegs * 2), 321 'MicroNeonMixOp', 322 { 'predicate_test': predicateTest, 323 'code' : microDeintNeonCode }, 324 ['IsMicroop']) 325 header_output += MicroNeonMixDeclare.subst(microDeintNeonIop) 326 exec_output += MicroNeonMixExecute.subst(microDeintNeonIop) 327 328 loadConv = '' 329 unloadConv = '' 330 for dReg in range(dRegs): 331 loadConv += ''' 332 conv1.cRegs[2 * %(dReg)d + 0] = htog(FpOp1S%(dReg)dP0.uw); 333 conv1.cRegs[2 * %(dReg)d + 1] = htog(FpOp1S%(dReg)dP1.uw); 334 ''' % { "dReg" : dReg } 335 unloadConv += ''' 336 FpDestP%(sReg0)d.uw = gtoh(conv2.cRegs[%(sReg0)d]); 337 FpDestP%(sReg1)d.uw = gtoh(conv2.cRegs[%(sReg1)d]); 338 ''' % { "sReg0" : (dReg * 2), "sReg1" : (dReg * 2 + 1) } 339 microInterNeonCode = ''' 340 const unsigned dRegs = %(dRegs)d; 341 const unsigned regs = 2 * dRegs; 342 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 343 sizeof(Element); 344 union convStruct { 345 FloatRegBits cRegs[regs]; 346 Element elements[dRegs * perDReg]; 347 } conv1, conv2; 348 349 %(loadConv)s 350 351 unsigned destElem = 0; 352 for (unsigned srcOffset = 0; 353 srcOffset < perDReg; srcOffset++) { 354 for (unsigned dReg = 0; dReg < dRegs; dReg++) { 355 conv2.elements[destElem++] = 356 conv1.elements[dReg * perDReg + srcOffset]; 357 } 358 } 359 360 %(unloadConv)s 361 ''' % { "dRegs" : dRegs, 362 "loadConv" : loadConv, 363 "unloadConv" : unloadConv } 364 microInterNeonIop = \ 365 InstObjParams('interneon%duop' % (dRegs * 2), 366 'MicroInterNeon%dUop' % (dRegs * 2), 367 'MicroNeonMixOp', 368 { 'predicate_test': predicateTest, 369 'code' : microInterNeonCode }, 370 ['IsMicroop']) 371 header_output += MicroNeonMixDeclare.subst(microInterNeonIop) 372 exec_output += MicroNeonMixExecute.subst(microInterNeonIop) 373}}; 374 375let {{ 376 exec_output = '' 377 for type in ('uint8_t', 'uint16_t', 'uint32_t', 'uint64_t'): 378 for dRegs in (2, 3, 4): 379 Name = "MicroDeintNeon%dUop" % (dRegs * 2) 380 substDict = { "class_name" : Name, "targs" : type } 381 exec_output += MicroNeonExecDeclare.subst(substDict) 382 Name = "MicroInterNeon%dUop" % (dRegs * 2) 383 substDict = { "class_name" : Name, "targs" : type } 384 exec_output += MicroNeonExecDeclare.subst(substDict) 385}}; 386 387//////////////////////////////////////////////////////////////////// 388// 389// Neon microops to pack/unpack a single lane 390// 391 392let {{ 393 header_output = exec_output = '' 394 for sRegs in 1, 2: 395 baseLoadRegs = '' 396 for reg in range(sRegs): 397 baseLoadRegs += ''' 398 sourceRegs.fRegs[%(reg0)d] = htog(FpOp1P%(reg0)d.uw); 399 sourceRegs.fRegs[%(reg1)d] = htog(FpOp1P%(reg1)d.uw); 400 ''' % { "reg0" : (2 * reg + 0), 401 "reg1" : (2 * reg + 1) } 402 for dRegs in range(sRegs, 5): 403 unloadRegs = '' 404 loadRegs = baseLoadRegs 405 for reg in range(dRegs): 406 loadRegs += ''' 407 destRegs[%(reg)d].fRegs[0] = htog(FpDestS%(reg)dP0.uw); 408 destRegs[%(reg)d].fRegs[1] = htog(FpDestS%(reg)dP1.uw); 409 ''' % { "reg" : reg } 410 unloadRegs += ''' 411 FpDestS%(reg)dP0.uw = gtoh(destRegs[%(reg)d].fRegs[0]); 412 FpDestS%(reg)dP1.uw = gtoh(destRegs[%(reg)d].fRegs[1]); 413 ''' % { "reg" : reg } 414 microUnpackNeonCode = ''' 415 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 416 sizeof(Element); 417 418 union SourceRegs { 419 FloatRegBits fRegs[2 * %(sRegs)d]; 420 Element elements[%(sRegs)d * perDReg]; 421 } sourceRegs; 422 423 union DestReg { 424 FloatRegBits fRegs[2]; 425 Element elements[perDReg]; 426 } destRegs[%(dRegs)d]; 427 428 %(loadRegs)s 429 430 for (unsigned i = 0; i < %(dRegs)d; i++) { 431 destRegs[i].elements[lane] = sourceRegs.elements[i]; 432 } 433 434 %(unloadRegs)s 435 ''' % { "sRegs" : sRegs, "dRegs" : dRegs, 436 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs } 437 438 microUnpackNeonIop = \ 439 InstObjParams('unpackneon%dto%duop' % (sRegs * 2, dRegs * 2), 440 'MicroUnpackNeon%dto%dUop' % 441 (sRegs * 2, dRegs * 2), 442 'MicroNeonMixLaneOp', 443 { 'predicate_test': predicateTest, 444 'code' : microUnpackNeonCode }, 445 ['IsMicroop']) 446 header_output += MicroNeonMixLaneDeclare.subst(microUnpackNeonIop) 447 exec_output += MicroNeonMixExecute.subst(microUnpackNeonIop) 448 449 for sRegs in 1, 2: 450 loadRegs = '' 451 for reg in range(sRegs): 452 loadRegs += ''' 453 sourceRegs.fRegs[%(reg0)d] = htog(FpOp1P%(reg0)d.uw); 454 sourceRegs.fRegs[%(reg1)d] = htog(FpOp1P%(reg1)d.uw); 455 ''' % { "reg0" : (2 * reg + 0), 456 "reg1" : (2 * reg + 1) } 457 for dRegs in range(sRegs, 5): 458 unloadRegs = '' 459 for reg in range(dRegs): 460 unloadRegs += ''' 461 FpDestS%(reg)dP0.uw = gtoh(destRegs[%(reg)d].fRegs[0]); 462 FpDestS%(reg)dP1.uw = gtoh(destRegs[%(reg)d].fRegs[1]); 463 ''' % { "reg" : reg } 464 microUnpackAllNeonCode = ''' 465 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 466 sizeof(Element); 467 468 union SourceRegs { 469 FloatRegBits fRegs[2 * %(sRegs)d]; 470 Element elements[%(sRegs)d * perDReg]; 471 } sourceRegs; 472 473 union DestReg { 474 FloatRegBits fRegs[2]; 475 Element elements[perDReg]; 476 } destRegs[%(dRegs)d]; 477 478 %(loadRegs)s 479 480 for (unsigned i = 0; i < %(dRegs)d; i++) { 481 for (unsigned j = 0; j < perDReg; j++) 482 destRegs[i].elements[j] = sourceRegs.elements[i]; 483 } 484 485 %(unloadRegs)s 486 ''' % { "sRegs" : sRegs, "dRegs" : dRegs, 487 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs } 488 489 microUnpackAllNeonIop = \ 490 InstObjParams('unpackallneon%dto%duop' % (sRegs * 2, dRegs * 2), 491 'MicroUnpackAllNeon%dto%dUop' % 492 (sRegs * 2, dRegs * 2), 493 'MicroNeonMixOp', 494 { 'predicate_test': predicateTest, 495 'code' : microUnpackAllNeonCode }, 496 ['IsMicroop']) 497 header_output += MicroNeonMixDeclare.subst(microUnpackAllNeonIop) 498 exec_output += MicroNeonMixExecute.subst(microUnpackAllNeonIop) 499 500 for dRegs in 1, 2: 501 unloadRegs = '' 502 for reg in range(dRegs): 503 unloadRegs += ''' 504 FpDestP%(reg0)d.uw = gtoh(destRegs.fRegs[%(reg0)d]); 505 FpDestP%(reg1)d.uw = gtoh(destRegs.fRegs[%(reg1)d]); 506 ''' % { "reg0" : (2 * reg + 0), 507 "reg1" : (2 * reg + 1) } 508 for sRegs in range(dRegs, 5): 509 loadRegs = '' 510 for reg in range(sRegs): 511 loadRegs += ''' 512 sourceRegs[%(reg)d].fRegs[0] = htog(FpOp1S%(reg)dP0.uw); 513 sourceRegs[%(reg)d].fRegs[1] = htog(FpOp1S%(reg)dP1.uw); 514 ''' % { "reg" : reg } 515 microPackNeonCode = ''' 516 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 517 sizeof(Element); 518 519 union SourceReg { 520 FloatRegBits fRegs[2]; 521 Element elements[perDReg]; 522 } sourceRegs[%(sRegs)d]; 523 524 union DestRegs { 525 FloatRegBits fRegs[2 * %(dRegs)d]; 526 Element elements[%(dRegs)d * perDReg]; 527 } destRegs; 528 529 %(loadRegs)s 530 531 for (unsigned i = 0; i < %(sRegs)d; i++) { 532 destRegs.elements[i] = sourceRegs[i].elements[lane]; 533 } 534 535 %(unloadRegs)s 536 ''' % { "sRegs" : sRegs, "dRegs" : dRegs, 537 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs } 538 539 microPackNeonIop = \ 540 InstObjParams('packneon%dto%duop' % (sRegs * 2, dRegs * 2), 541 'MicroPackNeon%dto%dUop' % 542 (sRegs * 2, dRegs * 2), 543 'MicroNeonMixLaneOp', 544 { 'predicate_test': predicateTest, 545 'code' : microPackNeonCode }, 546 ['IsMicroop']) 547 header_output += MicroNeonMixLaneDeclare.subst(microPackNeonIop) 548 exec_output += MicroNeonMixExecute.subst(microPackNeonIop) 549}}; 550 551let {{ 552 exec_output = '' 553 for type in ('uint8_t', 'uint16_t', 'uint32_t'): 554 for sRegs in 1, 2: 555 for dRegs in range(sRegs, 5): 556 for format in ("MicroUnpackNeon%(sRegs)dto%(dRegs)dUop", 557 "MicroUnpackAllNeon%(sRegs)dto%(dRegs)dUop", 558 "MicroPackNeon%(dRegs)dto%(sRegs)dUop"): 559 Name = format % { "sRegs" : sRegs * 2, 560 "dRegs" : dRegs * 2 } 561 substDict = { "class_name" : Name, "targs" : type } 562 exec_output += MicroNeonExecDeclare.subst(substDict) 563}}; 564 565//////////////////////////////////////////////////////////////////// 566// 567// Integer = Integer op Immediate microops 568// 569 570let {{ 571 microAddiUopIop = InstObjParams('addi_uop', 'MicroAddiUop', 572 'MicroIntImmOp', 573 {'code': 'Ra = Rb + imm;', 574 'predicate_test': predicateTest}, 575 ['IsMicroop']) 576 577 microAddUopIop = InstObjParams('add_uop', 'MicroAddUop', 578 'MicroIntOp', 579 {'code': 'Ra = Rb + Rc;', 580 'predicate_test': predicateTest}, 581 ['IsMicroop']) 582 583 microSubiUopIop = InstObjParams('subi_uop', 'MicroSubiUop', 584 'MicroIntImmOp', 585 {'code': 'Ra = Rb - imm;', 586 'predicate_test': predicateTest}, 587 ['IsMicroop']) 588 589 header_output = MicroIntImmDeclare.subst(microAddiUopIop) + \ 590 MicroIntImmDeclare.subst(microSubiUopIop) + \ 591 MicroIntDeclare.subst(microAddUopIop) 592 decoder_output = MicroIntImmConstructor.subst(microAddiUopIop) + \ 593 MicroIntImmConstructor.subst(microSubiUopIop) + \ 594 MicroIntConstructor.subst(microAddUopIop) 595 exec_output = PredOpExecute.subst(microAddiUopIop) + \ 596 PredOpExecute.subst(microSubiUopIop) + \ 597 PredOpExecute.subst(microAddUopIop) 598}}; 599 600let {{ 601 iop = InstObjParams("ldmstm", "LdmStm", 'MacroMemOp', "", []) 602 header_output = MacroMemDeclare.subst(iop) 603 decoder_output = MacroMemConstructor.subst(iop) 604 605 iop = InstObjParams("vldmult", "VldMult", 'VldMultOp', "", []) 606 header_output += VMemMultDeclare.subst(iop) 607 decoder_output += VMemMultConstructor.subst(iop) 608 609 iop = InstObjParams("vldsingle", "VldSingle", 'VldSingleOp', "", []) 610 header_output += VMemSingleDeclare.subst(iop) 611 decoder_output += VMemSingleConstructor.subst(iop) 612 613 iop = InstObjParams("vstmult", "VstMult", 'VstMultOp', "", []) 614 header_output += VMemMultDeclare.subst(iop) 615 decoder_output += VMemMultConstructor.subst(iop) 616 617 iop = InstObjParams("vstsingle", "VstSingle", 'VstSingleOp', "", []) 618 header_output += VMemSingleDeclare.subst(iop) 619 decoder_output += VMemSingleConstructor.subst(iop) 620 621 vfpIop = InstObjParams("vldmstm", "VLdmStm", 'MacroVFPMemOp', "", []) 622 header_output += MacroVFPMemDeclare.subst(vfpIop) 623 decoder_output += MacroVFPMemConstructor.subst(vfpIop) 624}}; 625