macromem.isa revision 8302:9f23d01421de
16019SN/A// -*- mode:c++ -*- 26019SN/A 37110SN/A// Copyright (c) 2010 ARM Limited 47110SN/A// All rights reserved 57110SN/A// 67110SN/A// The license below extends only to copyright in the software and shall 77110SN/A// not be construed as granting a license to any other intellectual 87110SN/A// property including but not limited to intellectual property relating 97110SN/A// to a hardware implementation of the functionality of the software 107110SN/A// licensed hereunder. You may use the software subject to the license 117110SN/A// terms below provided that you ensure that this notice is replicated 127110SN/A// unmodified and in its entirety in all distributions of the software, 137110SN/A// modified or unmodified, in source code or in binary form. 147110SN/A// 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 426019SN/A// Gabe Black 436019SN/A 446019SN/A//////////////////////////////////////////////////////////////////// 456019SN/A// 466019SN/A// Load/store microops 476019SN/A// 486243SN/A 496724SN/Alet {{ 506243SN/A microLdrUopCode = "IWRa = cSwap(Mem.uw, ((CPSR)Cpsr).e);" 516243SN/A microLdrUopIop = InstObjParams('ldr_uop', 'MicroLdrUop', 527138Sgblack@eecs.umich.edu 'MicroMemOp', 537138Sgblack@eecs.umich.edu {'memacc_code': microLdrUopCode, 547138Sgblack@eecs.umich.edu 'ea_code': 'EA = URb + (up ? imm : -imm);', 557138Sgblack@eecs.umich.edu 'predicate_test': predicateTest}, 567138Sgblack@eecs.umich.edu ['IsMicroop']) 577138Sgblack@eecs.umich.edu 587138Sgblack@eecs.umich.edu microLdrFpUopCode = "Fa.uw = cSwap(Mem.uw, ((CPSR)Cpsr).e);" 597138Sgblack@eecs.umich.edu microLdrFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrFpUop', 607138Sgblack@eecs.umich.edu 'MicroMemOp', 617138Sgblack@eecs.umich.edu {'memacc_code': microLdrFpUopCode, 627138Sgblack@eecs.umich.edu 'ea_code': vfpEnabledCheckCode + 637138Sgblack@eecs.umich.edu 'EA = URb + (up ? imm : -imm);', 647138Sgblack@eecs.umich.edu 'predicate_test': predicateTest}, 657138Sgblack@eecs.umich.edu ['IsMicroop']) 667138Sgblack@eecs.umich.edu 677138Sgblack@eecs.umich.edu microLdrDBFpUopCode = "Fa.uw = cSwap(Mem.uw, ((CPSR)Cpsr).e);" 687138Sgblack@eecs.umich.edu microLdrDBFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrDBFpUop', 697138Sgblack@eecs.umich.edu 'MicroMemOp', 707138Sgblack@eecs.umich.edu {'memacc_code': microLdrFpUopCode, 717138Sgblack@eecs.umich.edu 'ea_code': vfpEnabledCheckCode + ''' 727138Sgblack@eecs.umich.edu EA = URb + (up ? imm : -imm) + 737138Sgblack@eecs.umich.edu (((CPSR)Cpsr).e ? 4 : 0); 747138Sgblack@eecs.umich.edu ''', 757138Sgblack@eecs.umich.edu 'predicate_test': predicateTest}, 767138Sgblack@eecs.umich.edu ['IsMicroop']) 777138Sgblack@eecs.umich.edu 787138Sgblack@eecs.umich.edu microLdrDTFpUopCode = "Fa.uw = cSwap(Mem.uw, ((CPSR)Cpsr).e);" 797138Sgblack@eecs.umich.edu microLdrDTFpUopIop = InstObjParams('ldrfp_uop', 'MicroLdrDTFpUop', 807138Sgblack@eecs.umich.edu 'MicroMemOp', 817138Sgblack@eecs.umich.edu {'memacc_code': microLdrFpUopCode, 827138Sgblack@eecs.umich.edu 'ea_code': vfpEnabledCheckCode + ''' 837138Sgblack@eecs.umich.edu EA = URb + (up ? imm : -imm) - 847138Sgblack@eecs.umich.edu (((CPSR)Cpsr).e ? 4 : 0); 857138Sgblack@eecs.umich.edu ''', 867138Sgblack@eecs.umich.edu 'predicate_test': predicateTest}, 877138Sgblack@eecs.umich.edu ['IsMicroop']) 887138Sgblack@eecs.umich.edu 897138Sgblack@eecs.umich.edu microRetUopCode = ''' 907138Sgblack@eecs.umich.edu CPSR cpsr = Cpsr; 917138Sgblack@eecs.umich.edu SCTLR sctlr = Sctlr; 927138Sgblack@eecs.umich.edu uint32_t newCpsr = 937138Sgblack@eecs.umich.edu cpsrWriteByInstr(cpsr | CondCodesF | CondCodesGE, 947138Sgblack@eecs.umich.edu Spsr, 0xF, true, sctlr.nmfi); 957138Sgblack@eecs.umich.edu Cpsr = ~CondCodesMask & newCpsr; 967138Sgblack@eecs.umich.edu CondCodesF = CondCodesMaskF & newCpsr; 977138Sgblack@eecs.umich.edu CondCodesGE = CondCodesMaskGE & newCpsr; 987138Sgblack@eecs.umich.edu IWNPC = cSwap(%s, cpsr.e) | ((Spsr & 0x20) ? 1 : 0); 997138Sgblack@eecs.umich.edu NextItState = ((((CPSR)Spsr).it2 << 2) & 0xFC) 1007138Sgblack@eecs.umich.edu | (((CPSR)Spsr).it1 & 0x3); 1017138Sgblack@eecs.umich.edu SevMailbox = 1; 1027138Sgblack@eecs.umich.edu ''' 1037138Sgblack@eecs.umich.edu 1047138Sgblack@eecs.umich.edu microLdrRetUopIop = InstObjParams('ldr_ret_uop', 'MicroLdrRetUop', 1057138Sgblack@eecs.umich.edu 'MicroMemOp', 1067138Sgblack@eecs.umich.edu {'memacc_code': 1077138Sgblack@eecs.umich.edu microRetUopCode % 'Mem.uw', 1087138Sgblack@eecs.umich.edu 'ea_code': 1097138Sgblack@eecs.umich.edu 'EA = URb + (up ? imm : -imm);', 1107138Sgblack@eecs.umich.edu 'predicate_test': condPredicateTest}, 1117138Sgblack@eecs.umich.edu ['IsMicroop','IsNonSpeculative', 1127138Sgblack@eecs.umich.edu 'IsSerializeAfter']) 1137138Sgblack@eecs.umich.edu 1147138Sgblack@eecs.umich.edu microStrUopCode = "Mem = cSwap(URa.uw, ((CPSR)Cpsr).e);" 1157138Sgblack@eecs.umich.edu microStrUopIop = InstObjParams('str_uop', 'MicroStrUop', 1167138Sgblack@eecs.umich.edu 'MicroMemOp', 1177138Sgblack@eecs.umich.edu {'memacc_code': microStrUopCode, 1187138Sgblack@eecs.umich.edu 'postacc_code': "", 1197138Sgblack@eecs.umich.edu 'ea_code': 'EA = URb + (up ? imm : -imm);', 1207138Sgblack@eecs.umich.edu 'predicate_test': predicateTest}, 1217138Sgblack@eecs.umich.edu ['IsMicroop']) 1227138Sgblack@eecs.umich.edu 1237138Sgblack@eecs.umich.edu microStrFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);" 1247138Sgblack@eecs.umich.edu microStrFpUopIop = InstObjParams('strfp_uop', 'MicroStrFpUop', 1257138Sgblack@eecs.umich.edu 'MicroMemOp', 1267138Sgblack@eecs.umich.edu {'memacc_code': microStrFpUopCode, 1277138Sgblack@eecs.umich.edu 'postacc_code': "", 1286019SN/A 'ea_code': vfpEnabledCheckCode + 1296019SN/A 'EA = URb + (up ? imm : -imm);', 1306019SN/A 'predicate_test': predicateTest}, 1316019SN/A ['IsMicroop']) 1326271SN/A 1336271SN/A microStrDBFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);" 1346019SN/A microStrDBFpUopIop = InstObjParams('strfp_uop', 'MicroStrDBFpUop', 1356019SN/A 'MicroMemOp', 1366019SN/A {'memacc_code': microStrFpUopCode, 1376243SN/A 'postacc_code': "", 1386019SN/A 'ea_code': vfpEnabledCheckCode + ''' 1396243SN/A EA = URb + (up ? imm : -imm) + 1406019SN/A (((CPSR)Cpsr).e ? 4 : 0); 1416019SN/A ''', 1426019SN/A 'predicate_test': predicateTest}, 1436019SN/A ['IsMicroop']) 1446019SN/A 1456019SN/A microStrDTFpUopCode = "Mem = cSwap(Fa.uw, ((CPSR)Cpsr).e);" 1466019SN/A microStrDTFpUopIop = InstObjParams('strfp_uop', 'MicroStrDTFpUop', 1476019SN/A 'MicroMemOp', 1486019SN/A {'memacc_code': microStrFpUopCode, 1496019SN/A 'postacc_code': "", 1506265SN/A 'ea_code': vfpEnabledCheckCode + ''' 1516265SN/A EA = URb + (up ? imm : -imm) - 1526265SN/A (((CPSR)Cpsr).e ? 4 : 0); 1536265SN/A ''', 1546265SN/A 'predicate_test': predicateTest}, 1556265SN/A ['IsMicroop']) 1566265SN/A 1576265SN/A header_output = decoder_output = exec_output = '' 1586265SN/A 1596265SN/A loadIops = (microLdrUopIop, microLdrRetUopIop, 1606265SN/A microLdrFpUopIop, microLdrDBFpUopIop, microLdrDTFpUopIop) 1616265SN/A storeIops = (microStrUopIop, microStrFpUopIop, 1626265SN/A microStrDBFpUopIop, microStrDTFpUopIop) 1636265SN/A for iop in loadIops + storeIops: 1646270SN/A header_output += MicroMemDeclare.subst(iop) 1656270SN/A decoder_output += MicroMemConstructor.subst(iop) 1666270SN/A for iop in loadIops: 1676270SN/A exec_output += LoadExecute.subst(iop) + \ 1686270SN/A LoadInitiateAcc.subst(iop) + \ 1696270SN/A LoadCompleteAcc.subst(iop) 170 for iop in storeIops: 171 exec_output += StoreExecute.subst(iop) + \ 172 StoreInitiateAcc.subst(iop) + \ 173 StoreCompleteAcc.subst(iop) 174}}; 175 176let {{ 177 exec_output = header_output = '' 178 179 eaCode = 'EA = URa + imm;' 180 181 for size in (1, 2, 3, 4, 6, 8, 12, 16): 182 # Set up the memory access. 183 regs = (size + 3) // 4 184 subst = { "size" : size, "regs" : regs } 185 memDecl = ''' 186 union MemUnion { 187 uint8_t bytes[%(size)d]; 188 Element elements[%(size)d / sizeof(Element)]; 189 uint32_t floatRegBits[%(regs)d]; 190 }; 191 ''' % subst 192 193 # Do endian conversion for all the elements. 194 convCode = ''' 195 const unsigned eCount = sizeof(memUnion.elements) / 196 sizeof(memUnion.elements[0]); 197 if (((CPSR)Cpsr).e) { 198 for (unsigned i = 0; i < eCount; i++) { 199 memUnion.elements[i] = gtobe(memUnion.elements[i]); 200 } 201 } else { 202 for (unsigned i = 0; i < eCount; i++) { 203 memUnion.elements[i] = gtole(memUnion.elements[i]); 204 } 205 } 206 ''' 207 208 # Offload everything into registers 209 regSetCode = '' 210 for reg in range(regs): 211 mask = '' 212 if reg == regs - 1: 213 mask = ' & mask(%d)' % (32 - 8 * (regs * 4 - size)) 214 regSetCode += ''' 215 FpDestP%(reg)d.uw = gtoh(memUnion.floatRegBits[%(reg)d])%(mask)s; 216 ''' % { "reg" : reg, "mask" : mask } 217 218 # Pull everything in from registers 219 regGetCode = '' 220 for reg in range(regs): 221 regGetCode += ''' 222 memUnion.floatRegBits[%(reg)d] = htog(FpDestP%(reg)d.uw); 223 ''' % { "reg" : reg } 224 225 loadMemAccCode = convCode + regSetCode 226 storeMemAccCode = regGetCode + convCode 227 228 loadIop = InstObjParams('ldrneon%(size)d_uop' % subst, 229 'MicroLdrNeon%(size)dUop' % subst, 230 'MicroNeonMemOp', 231 { 'mem_decl' : memDecl, 232 'size' : size, 233 'memacc_code' : loadMemAccCode, 234 'ea_code' : simdEnabledCheckCode + eaCode, 235 'predicate_test' : predicateTest }, 236 [ 'IsMicroop', 'IsMemRef', 'IsLoad' ]) 237 storeIop = InstObjParams('strneon%(size)d_uop' % subst, 238 'MicroStrNeon%(size)dUop' % subst, 239 'MicroNeonMemOp', 240 { 'mem_decl' : memDecl, 241 'size' : size, 242 'memacc_code' : storeMemAccCode, 243 'ea_code' : simdEnabledCheckCode + eaCode, 244 'predicate_test' : predicateTest }, 245 [ 'IsMicroop', 'IsMemRef', 'IsStore' ]) 246 247 exec_output += NeonLoadExecute.subst(loadIop) + \ 248 NeonLoadInitiateAcc.subst(loadIop) + \ 249 NeonLoadCompleteAcc.subst(loadIop) + \ 250 NeonStoreExecute.subst(storeIop) + \ 251 NeonStoreInitiateAcc.subst(storeIop) + \ 252 NeonStoreCompleteAcc.subst(storeIop) 253 header_output += MicroNeonMemDeclare.subst(loadIop) + \ 254 MicroNeonMemDeclare.subst(storeIop) 255}}; 256 257let {{ 258 exec_output = '' 259 for eSize, type in (1, 'uint8_t'), \ 260 (2, 'uint16_t'), \ 261 (4, 'uint32_t'), \ 262 (8, 'uint64_t'): 263 size = eSize 264 # An instruction handles no more than 16 bytes and no more than 265 # 4 elements, or the number of elements needed to fill 8 or 16 bytes. 266 sizes = set((16, 8)) 267 for count in 1, 2, 3, 4: 268 size = count * eSize 269 if size <= 16: 270 sizes.add(size) 271 for size in sizes: 272 substDict = { 273 "class_name" : "MicroLdrNeon%dUop" % size, 274 "targs" : type 275 } 276 exec_output += MicroNeonMemExecDeclare.subst(substDict) 277 substDict["class_name"] = "MicroStrNeon%dUop" % size 278 exec_output += MicroNeonMemExecDeclare.subst(substDict) 279 size += eSize 280}}; 281 282//////////////////////////////////////////////////////////////////// 283// 284// Neon (de)interlacing microops 285// 286 287let {{ 288 header_output = exec_output = '' 289 for dRegs in (2, 3, 4): 290 loadConv = '' 291 unloadConv = '' 292 for dReg in range(dRegs): 293 loadConv += ''' 294 conv1.cRegs[%(sReg0)d] = htog(FpOp1P%(sReg0)d.uw); 295 conv1.cRegs[%(sReg1)d] = htog(FpOp1P%(sReg1)d.uw); 296 ''' % { "sReg0" : (dReg * 2), "sReg1" : (dReg * 2 + 1) } 297 unloadConv += ''' 298 FpDestS%(dReg)dP0.uw = gtoh(conv2.cRegs[2 * %(dReg)d + 0]); 299 FpDestS%(dReg)dP1.uw = gtoh(conv2.cRegs[2 * %(dReg)d + 1]); 300 ''' % { "dReg" : dReg } 301 microDeintNeonCode = ''' 302 const unsigned dRegs = %(dRegs)d; 303 const unsigned regs = 2 * dRegs; 304 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 305 sizeof(Element); 306 union convStruct { 307 FloatRegBits cRegs[regs]; 308 Element elements[dRegs * perDReg]; 309 } conv1, conv2; 310 311 %(loadConv)s 312 313 unsigned srcElem = 0; 314 for (unsigned destOffset = 0; 315 destOffset < perDReg; destOffset++) { 316 for (unsigned dReg = 0; dReg < dRegs; dReg++) { 317 conv2.elements[dReg * perDReg + destOffset] = 318 conv1.elements[srcElem++]; 319 } 320 } 321 322 %(unloadConv)s 323 ''' % { "dRegs" : dRegs, 324 "loadConv" : loadConv, 325 "unloadConv" : unloadConv } 326 microDeintNeonIop = \ 327 InstObjParams('deintneon%duop' % (dRegs * 2), 328 'MicroDeintNeon%dUop' % (dRegs * 2), 329 'MicroNeonMixOp', 330 { 'predicate_test': predicateTest, 331 'code' : microDeintNeonCode }, 332 ['IsMicroop']) 333 header_output += MicroNeonMixDeclare.subst(microDeintNeonIop) 334 exec_output += MicroNeonMixExecute.subst(microDeintNeonIop) 335 336 loadConv = '' 337 unloadConv = '' 338 for dReg in range(dRegs): 339 loadConv += ''' 340 conv1.cRegs[2 * %(dReg)d + 0] = htog(FpOp1S%(dReg)dP0.uw); 341 conv1.cRegs[2 * %(dReg)d + 1] = htog(FpOp1S%(dReg)dP1.uw); 342 ''' % { "dReg" : dReg } 343 unloadConv += ''' 344 FpDestP%(sReg0)d.uw = gtoh(conv2.cRegs[%(sReg0)d]); 345 FpDestP%(sReg1)d.uw = gtoh(conv2.cRegs[%(sReg1)d]); 346 ''' % { "sReg0" : (dReg * 2), "sReg1" : (dReg * 2 + 1) } 347 microInterNeonCode = ''' 348 const unsigned dRegs = %(dRegs)d; 349 const unsigned regs = 2 * dRegs; 350 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 351 sizeof(Element); 352 union convStruct { 353 FloatRegBits cRegs[regs]; 354 Element elements[dRegs * perDReg]; 355 } conv1, conv2; 356 357 %(loadConv)s 358 359 unsigned destElem = 0; 360 for (unsigned srcOffset = 0; 361 srcOffset < perDReg; srcOffset++) { 362 for (unsigned dReg = 0; dReg < dRegs; dReg++) { 363 conv2.elements[destElem++] = 364 conv1.elements[dReg * perDReg + srcOffset]; 365 } 366 } 367 368 %(unloadConv)s 369 ''' % { "dRegs" : dRegs, 370 "loadConv" : loadConv, 371 "unloadConv" : unloadConv } 372 microInterNeonIop = \ 373 InstObjParams('interneon%duop' % (dRegs * 2), 374 'MicroInterNeon%dUop' % (dRegs * 2), 375 'MicroNeonMixOp', 376 { 'predicate_test': predicateTest, 377 'code' : microInterNeonCode }, 378 ['IsMicroop']) 379 header_output += MicroNeonMixDeclare.subst(microInterNeonIop) 380 exec_output += MicroNeonMixExecute.subst(microInterNeonIop) 381}}; 382 383let {{ 384 exec_output = '' 385 for type in ('uint8_t', 'uint16_t', 'uint32_t', 'uint64_t'): 386 for dRegs in (2, 3, 4): 387 Name = "MicroDeintNeon%dUop" % (dRegs * 2) 388 substDict = { "class_name" : Name, "targs" : type } 389 exec_output += MicroNeonExecDeclare.subst(substDict) 390 Name = "MicroInterNeon%dUop" % (dRegs * 2) 391 substDict = { "class_name" : Name, "targs" : type } 392 exec_output += MicroNeonExecDeclare.subst(substDict) 393}}; 394 395//////////////////////////////////////////////////////////////////// 396// 397// Neon microops to pack/unpack a single lane 398// 399 400let {{ 401 header_output = exec_output = '' 402 for sRegs in 1, 2: 403 baseLoadRegs = '' 404 for reg in range(sRegs): 405 baseLoadRegs += ''' 406 sourceRegs.fRegs[%(reg0)d] = htog(FpOp1P%(reg0)d.uw); 407 sourceRegs.fRegs[%(reg1)d] = htog(FpOp1P%(reg1)d.uw); 408 ''' % { "reg0" : (2 * reg + 0), 409 "reg1" : (2 * reg + 1) } 410 for dRegs in range(sRegs, 5): 411 unloadRegs = '' 412 loadRegs = baseLoadRegs 413 for reg in range(dRegs): 414 loadRegs += ''' 415 destRegs[%(reg)d].fRegs[0] = htog(FpDestS%(reg)dP0.uw); 416 destRegs[%(reg)d].fRegs[1] = htog(FpDestS%(reg)dP1.uw); 417 ''' % { "reg" : reg } 418 unloadRegs += ''' 419 FpDestS%(reg)dP0.uw = gtoh(destRegs[%(reg)d].fRegs[0]); 420 FpDestS%(reg)dP1.uw = gtoh(destRegs[%(reg)d].fRegs[1]); 421 ''' % { "reg" : reg } 422 microUnpackNeonCode = ''' 423 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 424 sizeof(Element); 425 426 union SourceRegs { 427 FloatRegBits fRegs[2 * %(sRegs)d]; 428 Element elements[%(sRegs)d * perDReg]; 429 } sourceRegs; 430 431 union DestReg { 432 FloatRegBits fRegs[2]; 433 Element elements[perDReg]; 434 } destRegs[%(dRegs)d]; 435 436 %(loadRegs)s 437 438 for (unsigned i = 0; i < %(dRegs)d; i++) { 439 destRegs[i].elements[lane] = sourceRegs.elements[i]; 440 } 441 442 %(unloadRegs)s 443 ''' % { "sRegs" : sRegs, "dRegs" : dRegs, 444 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs } 445 446 microUnpackNeonIop = \ 447 InstObjParams('unpackneon%dto%duop' % (sRegs * 2, dRegs * 2), 448 'MicroUnpackNeon%dto%dUop' % 449 (sRegs * 2, dRegs * 2), 450 'MicroNeonMixLaneOp', 451 { 'predicate_test': predicateTest, 452 'code' : microUnpackNeonCode }, 453 ['IsMicroop']) 454 header_output += MicroNeonMixLaneDeclare.subst(microUnpackNeonIop) 455 exec_output += MicroNeonMixExecute.subst(microUnpackNeonIop) 456 457 for sRegs in 1, 2: 458 loadRegs = '' 459 for reg in range(sRegs): 460 loadRegs += ''' 461 sourceRegs.fRegs[%(reg0)d] = htog(FpOp1P%(reg0)d.uw); 462 sourceRegs.fRegs[%(reg1)d] = htog(FpOp1P%(reg1)d.uw); 463 ''' % { "reg0" : (2 * reg + 0), 464 "reg1" : (2 * reg + 1) } 465 for dRegs in range(sRegs, 5): 466 unloadRegs = '' 467 for reg in range(dRegs): 468 unloadRegs += ''' 469 FpDestS%(reg)dP0.uw = gtoh(destRegs[%(reg)d].fRegs[0]); 470 FpDestS%(reg)dP1.uw = gtoh(destRegs[%(reg)d].fRegs[1]); 471 ''' % { "reg" : reg } 472 microUnpackAllNeonCode = ''' 473 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 474 sizeof(Element); 475 476 union SourceRegs { 477 FloatRegBits fRegs[2 * %(sRegs)d]; 478 Element elements[%(sRegs)d * perDReg]; 479 } sourceRegs; 480 481 union DestReg { 482 FloatRegBits fRegs[2]; 483 Element elements[perDReg]; 484 } destRegs[%(dRegs)d]; 485 486 %(loadRegs)s 487 488 for (unsigned i = 0; i < %(dRegs)d; i++) { 489 for (unsigned j = 0; j < perDReg; j++) 490 destRegs[i].elements[j] = sourceRegs.elements[i]; 491 } 492 493 %(unloadRegs)s 494 ''' % { "sRegs" : sRegs, "dRegs" : dRegs, 495 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs } 496 497 microUnpackAllNeonIop = \ 498 InstObjParams('unpackallneon%dto%duop' % (sRegs * 2, dRegs * 2), 499 'MicroUnpackAllNeon%dto%dUop' % 500 (sRegs * 2, dRegs * 2), 501 'MicroNeonMixOp', 502 { 'predicate_test': predicateTest, 503 'code' : microUnpackAllNeonCode }, 504 ['IsMicroop']) 505 header_output += MicroNeonMixDeclare.subst(microUnpackAllNeonIop) 506 exec_output += MicroNeonMixExecute.subst(microUnpackAllNeonIop) 507 508 for dRegs in 1, 2: 509 unloadRegs = '' 510 for reg in range(dRegs): 511 unloadRegs += ''' 512 FpDestP%(reg0)d.uw = gtoh(destRegs.fRegs[%(reg0)d]); 513 FpDestP%(reg1)d.uw = gtoh(destRegs.fRegs[%(reg1)d]); 514 ''' % { "reg0" : (2 * reg + 0), 515 "reg1" : (2 * reg + 1) } 516 for sRegs in range(dRegs, 5): 517 loadRegs = '' 518 for reg in range(sRegs): 519 loadRegs += ''' 520 sourceRegs[%(reg)d].fRegs[0] = htog(FpOp1S%(reg)dP0.uw); 521 sourceRegs[%(reg)d].fRegs[1] = htog(FpOp1S%(reg)dP1.uw); 522 ''' % { "reg" : reg } 523 microPackNeonCode = ''' 524 const unsigned perDReg = (2 * sizeof(FloatRegBits)) / 525 sizeof(Element); 526 527 union SourceReg { 528 FloatRegBits fRegs[2]; 529 Element elements[perDReg]; 530 } sourceRegs[%(sRegs)d]; 531 532 union DestRegs { 533 FloatRegBits fRegs[2 * %(dRegs)d]; 534 Element elements[%(dRegs)d * perDReg]; 535 } destRegs; 536 537 %(loadRegs)s 538 539 for (unsigned i = 0; i < %(sRegs)d; i++) { 540 destRegs.elements[i] = sourceRegs[i].elements[lane]; 541 } 542 543 %(unloadRegs)s 544 ''' % { "sRegs" : sRegs, "dRegs" : dRegs, 545 "loadRegs" : loadRegs, "unloadRegs" : unloadRegs } 546 547 microPackNeonIop = \ 548 InstObjParams('packneon%dto%duop' % (sRegs * 2, dRegs * 2), 549 'MicroPackNeon%dto%dUop' % 550 (sRegs * 2, dRegs * 2), 551 'MicroNeonMixLaneOp', 552 { 'predicate_test': predicateTest, 553 'code' : microPackNeonCode }, 554 ['IsMicroop']) 555 header_output += MicroNeonMixLaneDeclare.subst(microPackNeonIop) 556 exec_output += MicroNeonMixExecute.subst(microPackNeonIop) 557}}; 558 559let {{ 560 exec_output = '' 561 for type in ('uint8_t', 'uint16_t', 'uint32_t'): 562 for sRegs in 1, 2: 563 for dRegs in range(sRegs, 5): 564 for format in ("MicroUnpackNeon%(sRegs)dto%(dRegs)dUop", 565 "MicroUnpackAllNeon%(sRegs)dto%(dRegs)dUop", 566 "MicroPackNeon%(dRegs)dto%(sRegs)dUop"): 567 Name = format % { "sRegs" : sRegs * 2, 568 "dRegs" : dRegs * 2 } 569 substDict = { "class_name" : Name, "targs" : type } 570 exec_output += MicroNeonExecDeclare.subst(substDict) 571}}; 572 573//////////////////////////////////////////////////////////////////// 574// 575// Integer = Integer op Immediate microops 576// 577 578let {{ 579 microAddiUopIop = InstObjParams('addi_uop', 'MicroAddiUop', 580 'MicroIntImmOp', 581 {'code': 'URa = URb + imm;', 582 'predicate_test': predicateTest}, 583 ['IsMicroop']) 584 585 microAddUopIop = InstObjParams('add_uop', 'MicroAddUop', 586 'MicroIntRegOp', 587 {'code': 588 '''URa = URb + shift_rm_imm(URc, shiftAmt, 589 shiftType, 590 CondCodesF<29:>); 591 ''', 592 'predicate_test': predicateTest}, 593 ['IsMicroop']) 594 595 microSubiUopIop = InstObjParams('subi_uop', 'MicroSubiUop', 596 'MicroIntImmOp', 597 {'code': 'URa = URb - imm;', 598 'predicate_test': predicateTest}, 599 ['IsMicroop']) 600 601 microSubUopIop = InstObjParams('sub_uop', 'MicroSubUop', 602 'MicroIntRegOp', 603 {'code': 604 '''URa = URb - shift_rm_imm(URc, shiftAmt, 605 shiftType, 606 CondCodesF<29:>); 607 ''', 608 'predicate_test': predicateTest}, 609 ['IsMicroop']) 610 611 microUopRegMovIop = InstObjParams('uopReg_uop', 'MicroUopRegMov', 612 'MicroIntMov', 613 {'code': 'IWRa = URb;', 614 'predicate_test': predicateTest}, 615 ['IsMicroop']) 616 617 microUopRegMovRetIop = InstObjParams('movret_uop', 'MicroUopRegMovRet', 618 'MicroIntMov', 619 {'code': microRetUopCode % 'URb', 620 'predicate_test': predicateTest}, 621 ['IsMicroop', 'IsNonSpeculative', 622 'IsSerializeAfter']) 623 624 setPCCPSRDecl = ''' 625 CPSR cpsrOrCondCodes = URc; 626 SCTLR sctlr = Sctlr; 627 pNPC = URa; 628 uint32_t newCpsr = 629 cpsrWriteByInstr(cpsrOrCondCodes, URb, 630 0xF, true, sctlr.nmfi); 631 Cpsr = ~CondCodesMask & newCpsr; 632 NextThumb = ((CPSR)newCpsr).t; 633 NextJazelle = ((CPSR)newCpsr).j; 634 NextItState = ((((CPSR)URb).it2 << 2) & 0xFC) 635 | (((CPSR)URb).it1 & 0x3); 636 CondCodesF = CondCodesMaskF & newCpsr; 637 CondCodesGE = CondCodesMaskGE & newCpsr; 638 ''' 639 640 microUopSetPCCPSRIop = InstObjParams('uopSet_uop', 'MicroUopSetPCCPSR', 641 'MicroSetPCCPSR', 642 {'code': setPCCPSRDecl, 643 'predicate_test': predicateTest}, 644 ['IsMicroop']) 645 646 header_output = MicroIntImmDeclare.subst(microAddiUopIop) + \ 647 MicroIntImmDeclare.subst(microSubiUopIop) + \ 648 MicroIntRegDeclare.subst(microAddUopIop) + \ 649 MicroIntRegDeclare.subst(microSubUopIop) + \ 650 MicroIntMovDeclare.subst(microUopRegMovIop) + \ 651 MicroIntMovDeclare.subst(microUopRegMovRetIop) + \ 652 MicroSetPCCPSRDeclare.subst(microUopSetPCCPSRIop) 653 654 decoder_output = MicroIntImmConstructor.subst(microAddiUopIop) + \ 655 MicroIntImmConstructor.subst(microSubiUopIop) + \ 656 MicroIntRegConstructor.subst(microAddUopIop) + \ 657 MicroIntRegConstructor.subst(microSubUopIop) + \ 658 MicroIntMovConstructor.subst(microUopRegMovIop) + \ 659 MicroIntMovConstructor.subst(microUopRegMovRetIop) + \ 660 MicroSetPCCPSRConstructor.subst(microUopSetPCCPSRIop) 661 662 exec_output = PredOpExecute.subst(microAddiUopIop) + \ 663 PredOpExecute.subst(microSubiUopIop) + \ 664 PredOpExecute.subst(microAddUopIop) + \ 665 PredOpExecute.subst(microSubUopIop) + \ 666 PredOpExecute.subst(microUopRegMovIop) + \ 667 PredOpExecute.subst(microUopRegMovRetIop) + \ 668 PredOpExecute.subst(microUopSetPCCPSRIop) 669 670}}; 671 672let {{ 673 iop = InstObjParams("ldmstm", "LdmStm", 'MacroMemOp', "", []) 674 header_output = MacroMemDeclare.subst(iop) 675 decoder_output = MacroMemConstructor.subst(iop) 676 677 iop = InstObjParams("vldmult", "VldMult", 'VldMultOp', "", []) 678 header_output += VMemMultDeclare.subst(iop) 679 decoder_output += VMemMultConstructor.subst(iop) 680 681 iop = InstObjParams("vldsingle", "VldSingle", 'VldSingleOp', "", []) 682 header_output += VMemSingleDeclare.subst(iop) 683 decoder_output += VMemSingleConstructor.subst(iop) 684 685 iop = InstObjParams("vstmult", "VstMult", 'VstMultOp', "", []) 686 header_output += VMemMultDeclare.subst(iop) 687 decoder_output += VMemMultConstructor.subst(iop) 688 689 iop = InstObjParams("vstsingle", "VstSingle", 'VstSingleOp', "", []) 690 header_output += VMemSingleDeclare.subst(iop) 691 decoder_output += VMemSingleConstructor.subst(iop) 692 693 vfpIop = InstObjParams("vldmstm", "VLdmStm", 'MacroVFPMemOp', "", []) 694 header_output += MacroVFPMemDeclare.subst(vfpIop) 695 decoder_output += MacroVFPMemConstructor.subst(vfpIop) 696}}; 697