neon64.isa revision 11488
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 %(BasicExecDeclare)s 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 %(BasicExecDeclare)s 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 %(BasicExecDeclare)s 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 %(BasicExecDeclare)s 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 %(BasicExecDeclare)s 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 %(BasicExecDeclare)s 164}; 165}}; 166 167def template NeonXExecDeclare {{ 168 template 169 Fault %(class_name)s<%(targs)s>::execute( 170 CPU_EXEC_CONTEXT *, Trace::InstRecord *) const; 171}}; 172 173def template NeonXEqualRegOpExecute {{ 174 template <class Element> 175 Fault %(class_name)s<Element>::execute(CPU_EXEC_CONTEXT *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(FloatRegBits) / sizeof(Element); 184 const unsigned eCountFull = 4 * sizeof(FloatRegBits) / sizeof(Element); 185 186 union RegVect { 187 FloatRegBits regs[rCount]; 188 Element elements[eCount]; 189 }; 190 191 union FullRegVect { 192 FloatRegBits 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(CPU_EXEC_CONTEXT *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(FloatRegBits) / sizeof(Element); 218 const unsigned eCountFull = 4 * sizeof(FloatRegBits) / sizeof(Element); 219 220 union RegVect { 221 FloatRegBits regs[rCount]; 222 Element elements[eCount]; 223 BigElement bigElements[eCount / 2]; 224 }; 225 226 union BigRegVect { 227 FloatRegBits regs[2 * rCount]; 228 BigElement elements[eCount]; 229 }; 230 231 union FullRegVect { 232 FloatRegBits 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 %(BasicExecDeclare)s 271 %(InitiateAccDeclare)s 272 %(CompleteAccDeclare)s 273 }; 274}}; 275 276def template NeonLoadExecute64 {{ 277 Fault %(class_name)s::execute( 278 CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const 279 { 280 Addr EA; 281 Fault fault = NoFault; 282 283 %(op_decl)s; 284 %(mem_decl)s; 285 %(op_rd)s; 286 %(ea_code)s; 287 288 MemUnion memUnion; 289 uint8_t *dataPtr = memUnion.bytes; 290 291 if (fault == NoFault) { 292 fault = xc->readMem(EA, dataPtr, accSize, memAccessFlags); 293 %(memacc_code)s; 294 } 295 296 if (fault == NoFault) { 297 %(op_wb)s; 298 } 299 300 return fault; 301 } 302}}; 303 304def template NeonLoadInitiateAcc64 {{ 305 Fault %(class_name)s::initiateAcc( 306 CPU_EXEC_CONTEXT *xc, Trace::InstRecord *traceData) const 307 { 308 Addr EA; 309 Fault fault = NoFault; 310 311 %(op_decl)s; 312 %(mem_decl)s; 313 %(op_rd)s; 314 %(ea_code)s; 315 316 if (fault == NoFault) { 317 fault = xc->initiateMemRead(EA, accSize, memAccessFlags); 318 } 319 320 return fault; 321 } 322}}; 323 324def template NeonLoadCompleteAcc64 {{ 325 Fault %(class_name)s::completeAcc( 326 PacketPtr pkt, CPU_EXEC_CONTEXT *xc, 327 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 CPU_EXEC_CONTEXT *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 CPU_EXEC_CONTEXT *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, CPU_EXEC_CONTEXT *xc, 411 Trace::InstRecord *traceData) const 412 { 413 return NoFault; 414 } 415}}; 416 417def template VMemMultDeclare64 {{ 418 class %(class_name)s : public %(base_class)s 419 { 420 public: 421 // Constructor 422 %(class_name)s(ExtMachInst machInst, RegIndex rn, RegIndex vd, 423 RegIndex rm, uint8_t eSize, uint8_t dataSize, 424 uint8_t numStructElems, uint8_t numRegs, bool wb); 425 %(BasicExecPanic)s 426 }; 427}}; 428 429def template VMemSingleDeclare64 {{ 430 class %(class_name)s : public %(base_class)s 431 { 432 public: 433 // Constructor 434 %(class_name)s(ExtMachInst machInst, RegIndex rn, RegIndex vd, 435 RegIndex rm, uint8_t eSize, uint8_t dataSize, 436 uint8_t numStructElems, uint8_t index, bool wb, 437 bool replicate = false); 438 %(BasicExecPanic)s 439 }; 440}}; 441 442def template VMemMultConstructor64 {{ 443 %(class_name)s::%(class_name)s( 444 ExtMachInst machInst, RegIndex rn, RegIndex vd, RegIndex rm, 445 uint8_t _eSize, uint8_t _dataSize, uint8_t _numStructElems, 446 uint8_t _numRegs, bool _wb) : 447 %(base_class)s( 448 "%(mnemonic)s", machInst, %(op_class)s, rn, vd, rm, 449 _eSize, _dataSize, _numStructElems, _numRegs, _wb) 450 { 451 %(constructor)s; 452 } 453}}; 454 455def template VMemSingleConstructor64 {{ 456 %(class_name)s::%(class_name)s( 457 ExtMachInst machInst, RegIndex rn, RegIndex vd, RegIndex rm, 458 uint8_t _eSize, uint8_t _dataSize, uint8_t _numStructElems, 459 uint8_t _index, bool _wb, bool _replicate) : 460 %(base_class)s( 461 "%(mnemonic)s", machInst, %(op_class)s, rn, vd, rm, 462 _eSize, _dataSize, _numStructElems, _index, _wb, 463 _replicate) 464 { 465 %(constructor)s; 466 } 467}}; 468 469def template MicroNeonMixDeclare64 {{ 470 class %(class_name)s : public %(base_class)s 471 { 472 public: 473 %(class_name)s(ExtMachInst machInst, RegIndex _dest, RegIndex _op1, 474 uint8_t _eSize, uint8_t _dataSize, 475 uint8_t _numStructElems, uint8_t _numRegs, 476 uint8_t _step) : 477 %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, 478 _dest, _op1, _eSize, _dataSize, _numStructElems, 479 _numRegs, _step) 480 { 481 %(constructor)s; 482 } 483 484 %(BasicExecDeclare)s 485 }; 486}}; 487 488def template MicroNeonMixLaneDeclare64 {{ 489 class %(class_name)s : public %(base_class)s 490 { 491 public: 492 %(class_name)s(ExtMachInst machInst, RegIndex _dest, RegIndex _op1, 493 uint8_t _eSize, uint8_t _dataSize, 494 uint8_t _numStructElems, uint8_t _lane, uint8_t _step, 495 bool _replicate = false) : 496 %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, 497 _dest, _op1, _eSize, _dataSize, _numStructElems, 498 _lane, _step, _replicate) 499 { 500 %(constructor)s; 501 } 502 503 %(BasicExecDeclare)s 504 }; 505}}; 506 507def template MicroNeonMixExecute64 {{ 508 Fault %(class_name)s::execute(CPU_EXEC_CONTEXT *xc, 509 Trace::InstRecord *traceData) const 510 { 511 Fault fault = NoFault; 512 uint64_t resTemp = 0; 513 resTemp = resTemp; 514 %(op_decl)s; 515 %(op_rd)s; 516 517 %(code)s; 518 if (fault == NoFault) 519 { 520 %(op_wb)s; 521 } 522 523 return fault; 524 } 525}}; 526