1// -*- mode: c++ -*- 2 3// Copyright (c) 2012-2013 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// Redistribution and use in source and binary forms, with or without 16// modification, are permitted provided that the following conditions are 17// met: redistributions of source code must retain the above copyright 18// notice, this list of conditions and the following disclaimer; 19// redistributions in binary form must reproduce the above copyright 20// notice, this list of conditions and the following disclaimer in the 21// documentation and/or other materials provided with the distribution; 22// neither the name of the copyright holders nor the names of its 23// contributors may be used to endorse or promote products derived from 24// this software without specific prior written permission. 25// 26// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37// 38// Authors: Mbou Eyole 39// Giacomo Gabrielli 40 41let {{ 42 simd64EnabledCheckCode = vfp64EnabledCheckCode 43}}; 44 45def template NeonX2RegOpDeclare {{ 46template <class _Element> 47class %(class_name)s : public %(base_class)s 48{ 49 protected: 50 typedef _Element Element; 51 public: 52 // Constructor 53 %(class_name)s(ExtMachInst machInst, 54 IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2) 55 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, 56 _dest, _op1, _op2) 57 { 58 %(constructor)s; 59 } 60 61 Fault execute(ExecContext *, Trace::InstRecord *) const override; 62}; 63}}; 64 65def template NeonX2RegImmOpDeclare {{ 66template <class _Element> 67class %(class_name)s : public %(base_class)s 68{ 69 protected: 70 typedef _Element Element; 71 public: 72 // Constructor 73 %(class_name)s(ExtMachInst machInst, 74 IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2, 75 uint64_t _imm) 76 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, 77 _dest, _op1, _op2, _imm) 78 { 79 %(constructor)s; 80 } 81 82 Fault execute(ExecContext *, Trace::InstRecord *) const override; 83}; 84}}; 85 86def template NeonX1RegOpDeclare {{ 87template <class _Element> 88class %(class_name)s : public %(base_class)s 89{ 90 protected: 91 typedef _Element Element; 92 public: 93 // Constructor 94 %(class_name)s(ExtMachInst machInst, 95 IntRegIndex _dest, IntRegIndex _op1) 96 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, 97 _dest, _op1) 98 { 99 %(constructor)s; 100 } 101 102 Fault execute(ExecContext *, Trace::InstRecord *) const override; 103}; 104}}; 105 106def template NeonX1RegImmOpDeclare {{ 107template <class _Element> 108class %(class_name)s : public %(base_class)s 109{ 110 protected: 111 typedef _Element Element; 112 public: 113 // Constructor 114 %(class_name)s(ExtMachInst machInst, 115 IntRegIndex _dest, IntRegIndex _op1, uint64_t _imm) 116 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, 117 _dest, _op1, _imm) 118 { 119 %(constructor)s; 120 } 121 122 Fault execute(ExecContext *, Trace::InstRecord *) const override; 123}; 124}}; 125 126def template NeonX1Reg2ImmOpDeclare {{ 127template <class _Element> 128class %(class_name)s : public %(base_class)s 129{ 130 protected: 131 typedef _Element Element; 132 public: 133 // Constructor 134 %(class_name)s(ExtMachInst machInst, 135 IntRegIndex _dest, IntRegIndex _op1, uint64_t _imm1, 136 uint64_t _imm2) 137 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, 138 _dest, _op1, _imm1, _imm2) 139 { 140 %(constructor)s; 141 } 142 143 Fault execute(ExecContext *, Trace::InstRecord *) const override; 144}; 145}}; 146 147def template NeonX1RegImmOnlyOpDeclare {{ 148template <class _Element> 149class %(class_name)s : public %(base_class)s 150{ 151 protected: 152 typedef _Element Element; 153 public: 154 // Constructor 155 %(class_name)s(ExtMachInst machInst, 156 IntRegIndex _dest, uint64_t _imm) 157 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, 158 _dest, _imm) 159 { 160 %(constructor)s; 161 } 162 163 Fault execute(ExecContext *, Trace::InstRecord *) const override; 164}; 165}}; 166 167def template NeonXExecDeclare {{ 168 template 169 Fault %(class_name)s<%(targs)s>::execute( 170 ExecContext *, Trace::InstRecord *) const; 171}}; 172 173def template NeonXEqualRegOpExecute {{ 174 template <class Element> 175 Fault %(class_name)s<Element>::execute(ExecContext *xc, 176 Trace::InstRecord *traceData) const 177 { 178 Fault fault = NoFault; 179 %(op_decl)s; 180 %(op_rd)s; 181 182 const unsigned rCount = %(r_count)d; 183 const unsigned eCount = rCount * sizeof(uint32_t) / sizeof(Element); 184 const unsigned eCountFull = 4 * sizeof(uint32_t) / sizeof(Element); 185 186 union RegVect { 187 uint32_t regs[rCount]; 188 Element elements[eCount]; 189 }; 190 191 union FullRegVect { 192 uint32_t regs[4]; 193 Element elements[eCountFull]; 194 }; 195 196 %(code)s; 197 if (fault == NoFault) 198 { 199 %(op_wb)s; 200 } 201 202 return fault; 203 } 204}}; 205 206def template NeonXUnequalRegOpExecute {{ 207 template <class Element> 208 Fault %(class_name)s<Element>::execute(ExecContext *xc, 209 Trace::InstRecord *traceData) const 210 { 211 typedef typename bigger_type_t<Element>::type BigElement; 212 Fault fault = NoFault; 213 %(op_decl)s; 214 %(op_rd)s; 215 216 const unsigned rCount = %(r_count)d; 217 const unsigned eCount = rCount * sizeof(uint32_t) / sizeof(Element); 218 const unsigned eCountFull = 4 * sizeof(uint32_t) / sizeof(Element); 219 220 union RegVect { 221 uint32_t regs[rCount]; 222 Element elements[eCount]; 223 BigElement bigElements[eCount / 2]; 224 }; 225 226 union BigRegVect { 227 uint32_t regs[2 * rCount]; 228 BigElement elements[eCount]; 229 }; 230 231 union FullRegVect { 232 uint32_t regs[4]; 233 Element elements[eCountFull]; 234 }; 235 236 %(code)s; 237 if (fault == NoFault) 238 { 239 %(op_wb)s; 240 } 241 242 return fault; 243 } 244}}; 245 246def template MicroNeonMemDeclare64 {{ 247 class %(class_name)s : public %(base_class)s 248 { 249 protected: 250 // True if the base register is SP (used for SP alignment checking) 251 bool baseIsSP; 252 // Access size in bytes 253 uint8_t accSize; 254 // Vector element size (0 -> 8-bit, 1 -> 16-bit, 2 -> 32-bit, 255 // 3 -> 64-bit) 256 uint8_t eSize; 257 258 public: 259 %(class_name)s(ExtMachInst machInst, RegIndex _dest, RegIndex _ura, 260 uint32_t _imm, unsigned extraMemFlags, bool _baseIsSP, 261 uint8_t _accSize, uint8_t _eSize) 262 : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, _dest, 263 _ura, _imm), 264 baseIsSP(_baseIsSP), accSize(_accSize), eSize(_eSize) 265 { 266 memAccessFlags |= extraMemFlags; 267 %(constructor)s; 268 } 269 270 Fault execute(ExecContext *, Trace::InstRecord *) const override; 271 Fault initiateAcc(ExecContext *, Trace::InstRecord *) const override; 272 Fault completeAcc(PacketPtr, ExecContext *, 273 Trace::InstRecord *) const override; 274 }; 275}}; 276 277def template NeonLoadExecute64 {{ 278 Fault %(class_name)s::execute( 279 ExecContext *xc, Trace::InstRecord *traceData) const 280 { 281 Addr EA; 282 Fault fault = NoFault; 283 284 %(op_decl)s; 285 %(mem_decl)s; 286 %(op_rd)s; 287 %(ea_code)s; 288 289 MemUnion memUnion; 290 uint8_t *dataPtr = memUnion.bytes; 291 292 if (fault == NoFault) { 293 fault = xc->readMem(EA, dataPtr, accSize, memAccessFlags); 294 %(memacc_code)s; 295 } 296 297 if (fault == NoFault) { 298 %(op_wb)s; 299 } 300 301 return fault; 302 } 303}}; 304 305def template NeonLoadInitiateAcc64 {{ 306 Fault %(class_name)s::initiateAcc( 307 ExecContext *xc, Trace::InstRecord *traceData) const 308 { 309 Addr EA; 310 Fault fault = NoFault; 311 312 %(op_decl)s; 313 %(mem_decl)s; 314 %(op_rd)s; 315 %(ea_code)s; 316 317 if (fault == NoFault) { 318 fault = xc->initiateMemRead(EA, accSize, memAccessFlags); 319 } 320 321 return fault; 322 } 323}}; 324 325def template NeonLoadCompleteAcc64 {{ 326 Fault %(class_name)s::completeAcc( 327 PacketPtr pkt, ExecContext *xc, Trace::InstRecord *traceData) const 328 { 329 Fault fault = NoFault; 330 331 %(mem_decl)s; 332 %(op_decl)s; 333 %(op_rd)s; 334 335 MemUnion memUnion { { } }; 336 memcpy(&memUnion, pkt->getPtr<uint8_t>(), pkt->getSize()); 337 338 if (fault == NoFault) { 339 %(memacc_code)s; 340 } 341 342 if (fault == NoFault) { 343 %(op_wb)s; 344 } 345 346 return fault; 347 } 348}}; 349 350def template NeonStoreExecute64 {{ 351 Fault %(class_name)s::execute( 352 ExecContext *xc, Trace::InstRecord *traceData) const 353 { 354 Addr EA; 355 Fault fault = NoFault; 356 357 %(op_decl)s; 358 %(mem_decl)s; 359 %(op_rd)s; 360 %(ea_code)s; 361 362 MemUnion memUnion; 363 uint8_t *dataPtr = memUnion.bytes; 364 365 if (fault == NoFault) { 366 %(memacc_code)s; 367 } 368 369 if (fault == NoFault) { 370 fault = xc->writeMem(dataPtr, accSize, EA, memAccessFlags, 371 NULL); 372 } 373 374 if (fault == NoFault) { 375 %(op_wb)s; 376 } 377 378 return fault; 379 } 380}}; 381 382def template NeonStoreInitiateAcc64 {{ 383 Fault %(class_name)s::initiateAcc( 384 ExecContext *xc, Trace::InstRecord *traceData) const 385 { 386 Addr EA; 387 Fault fault = NoFault; 388 389 %(op_decl)s; 390 %(mem_decl)s; 391 %(op_rd)s; 392 %(ea_code)s; 393 394 MemUnion memUnion; 395 if (fault == NoFault) { 396 %(memacc_code)s; 397 } 398 399 if (fault == NoFault) { 400 fault = xc->writeMem(memUnion.bytes, accSize, EA, memAccessFlags, 401 NULL); 402 } 403 404 return fault; 405 } 406}}; 407 408def template NeonStoreCompleteAcc64 {{ 409 Fault %(class_name)s::completeAcc( 410 PacketPtr pkt, ExecContext *xc, Trace::InstRecord *traceData) const 411 { 412 return NoFault; 413 } 414}}; 415 416def template VMemMultDeclare64 {{ 417 class %(class_name)s : public %(base_class)s 418 { 419 public: 420 // Constructor 421 %(class_name)s(ExtMachInst machInst, RegIndex rn, RegIndex vd, 422 RegIndex rm, uint8_t eSize, uint8_t dataSize, 423 uint8_t numStructElems, uint8_t numRegs, bool wb); 424 }; 425}}; 426 427def template VMemSingleDeclare64 {{ 428 class %(class_name)s : public %(base_class)s 429 { 430 public: 431 // Constructor 432 %(class_name)s(ExtMachInst machInst, RegIndex rn, RegIndex vd, 433 RegIndex rm, uint8_t eSize, uint8_t dataSize, 434 uint8_t numStructElems, uint8_t index, bool wb, 435 bool replicate = false); 436 }; 437}}; 438 439def template VMemMultConstructor64 {{ 440 %(class_name)s::%(class_name)s( 441 ExtMachInst machInst, RegIndex rn, RegIndex vd, RegIndex rm, 442 uint8_t _eSize, uint8_t _dataSize, uint8_t _numStructElems, 443 uint8_t _numRegs, bool _wb) : 444 %(base_class)s( 445 "%(mnemonic)s", machInst, %(op_class)s, rn, vd, rm, 446 _eSize, _dataSize, _numStructElems, _numRegs, _wb) 447 { 448 %(constructor)s; 449 } 450}}; 451 452def template VMemSingleConstructor64 {{ 453 %(class_name)s::%(class_name)s( 454 ExtMachInst machInst, RegIndex rn, RegIndex vd, RegIndex rm, 455 uint8_t _eSize, uint8_t _dataSize, uint8_t _numStructElems, 456 uint8_t _index, bool _wb, bool _replicate) : 457 %(base_class)s( 458 "%(mnemonic)s", machInst, %(op_class)s, rn, vd, rm, 459 _eSize, _dataSize, _numStructElems, _index, _wb, 460 _replicate) 461 { 462 %(constructor)s; 463 } 464}}; 465 466def template MicroNeonMixDeclare64 {{ 467 class %(class_name)s : public %(base_class)s 468 { 469 public: 470 %(class_name)s(ExtMachInst machInst, RegIndex _dest, RegIndex _op1, 471 uint8_t _eSize, uint8_t _dataSize, 472 uint8_t _numStructElems, uint8_t _numRegs, 473 uint8_t _step) : 474 %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, 475 _dest, _op1, _eSize, _dataSize, _numStructElems, 476 _numRegs, _step) 477 { 478 %(constructor)s; 479 } 480 481 Fault execute(ExecContext *, Trace::InstRecord *) const override; 482 }; 483}}; 484 485def template MicroNeonMixLaneDeclare64 {{ 486 class %(class_name)s : public %(base_class)s 487 { 488 public: 489 %(class_name)s(ExtMachInst machInst, RegIndex _dest, RegIndex _op1, 490 uint8_t _eSize, uint8_t _dataSize, 491 uint8_t _numStructElems, uint8_t _lane, uint8_t _step, 492 bool _replicate = false) : 493 %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, 494 _dest, _op1, _eSize, _dataSize, _numStructElems, 495 _lane, _step, _replicate) 496 { 497 %(constructor)s; 498 } 499 500 Fault execute(ExecContext *, Trace::InstRecord *) const override; 501 }; 502}}; 503 504def template MicroNeonMixExecute64 {{ 505 Fault %(class_name)s::execute(ExecContext *xc, 506 Trace::InstRecord *traceData) const 507 { 508 Fault fault = NoFault; 509 uint64_t resTemp = 0; 510 resTemp = resTemp; 511 %(op_decl)s; 512 %(op_rd)s; 513 514 %(code)s; 515 if (fault == NoFault) 516 { 517 %(op_wb)s; 518 } 519 520 return fault; 521 } 522}}; 523