arm: Delete authors lists from the arm files.
[gem5.git] / src / arch / arm / insts / sve_macromem.hh
1 /*
2 * Copyright (c) 2018 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38 #ifndef __ARCH_ARM_SVE_MACROMEM_HH__
39 #define __ARCH_ARM_SVE_MACROMEM_HH__
40
41 #include "arch/arm/generated/decoder.hh"
42 #include "arch/arm/insts/pred_inst.hh"
43
44 namespace ArmISA {
45
46 template <typename Element,
47 template <typename> class MicroopLdMemType,
48 template <typename> class MicroopDeIntrlvType>
49 class SveLdStructSS : public PredMacroOp
50 {
51 protected:
52 IntRegIndex dest;
53 IntRegIndex gp;
54 IntRegIndex base;
55 IntRegIndex offset;
56 uint8_t numregs;
57
58 public:
59 SveLdStructSS(const char* mnem, ExtMachInst machInst, OpClass __opClass,
60 IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base,
61 IntRegIndex _offset, uint8_t _numregs)
62 : PredMacroOp(mnem, machInst, __opClass),
63 dest(_dest), gp(_gp), base(_base), offset(_offset), numregs(_numregs)
64 {
65 numMicroops = numregs * 2;
66
67 microOps = new StaticInstPtr[numMicroops];
68
69 for (int i = 0; i < numregs; ++i) {
70 microOps[i] = new MicroopLdMemType<Element>(
71 mnem, machInst, static_cast<IntRegIndex>(INTRLVREG0 + i),
72 _gp, _base, _offset, _numregs, i);
73 }
74 for (int i = 0; i < numregs; ++i) {
75 microOps[i + numregs] = new MicroopDeIntrlvType<Element>(
76 mnem, machInst, static_cast<IntRegIndex>((_dest + i) % 32),
77 _numregs, i, this);
78 }
79
80 microOps[0]->setFirstMicroop();
81 microOps[numMicroops - 1]->setLastMicroop();
82
83 for (StaticInstPtr *uop = microOps; !(*uop)->isLastMicroop(); uop++) {
84 (*uop)->setDelayedCommit();
85 }
86 }
87
88 Fault
89 execute(ExecContext *, Trace::InstRecord *) const
90 {
91 panic("Execute method called when it shouldn't!");
92 return NoFault;
93 }
94
95 std::string
96 generateDisassembly(Addr pc, const SymbolTable *symtab) const
97 {
98 std::stringstream ss;
99 printMnemonic(ss, "", false);
100 ccprintf(ss, "{");
101 for (int i = 0; i < numregs; ++i) {
102 printVecReg(ss, (dest + i) % 32, true);
103 if (i < numregs - 1)
104 ccprintf(ss, ", ");
105 }
106 ccprintf(ss, "}, ");
107 printVecPredReg(ss, gp);
108 ccprintf(ss, "/z, [");
109 printIntReg(ss, base);
110 ccprintf(ss, ", ");
111 printIntReg(ss, offset);
112 ccprintf(ss, "]");
113 return ss.str();
114 }
115 };
116
117 template <typename Element,
118 template <typename> class MicroopStMemType,
119 template <typename> class MicroopIntrlvType>
120 class SveStStructSS : public PredMacroOp
121 {
122 protected:
123 IntRegIndex dest;
124 IntRegIndex gp;
125 IntRegIndex base;
126 IntRegIndex offset;
127 uint8_t numregs;
128
129 public:
130 SveStStructSS(const char* mnem, ExtMachInst machInst, OpClass __opClass,
131 IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base,
132 IntRegIndex _offset, uint8_t _numregs)
133 : PredMacroOp(mnem, machInst, __opClass),
134 dest(_dest), gp(_gp), base(_base), offset(_offset), numregs(_numregs)
135 {
136 numMicroops = numregs * 2;
137
138 microOps = new StaticInstPtr[numMicroops];
139
140 for (int i = 0; i < numregs; ++i) {
141 microOps[i] = new MicroopIntrlvType<Element>(
142 mnem, machInst, static_cast<IntRegIndex>(INTRLVREG0 + i),
143 _dest, _numregs, i, this);
144 }
145
146 for (int i = 0; i < numregs; ++i) {
147 microOps[i + numregs] = new MicroopStMemType<Element>(
148 mnem, machInst, static_cast<IntRegIndex>(INTRLVREG0 + i),
149 _gp, _base, _offset, _numregs, i);
150 }
151
152 microOps[0]->setFirstMicroop();
153 microOps[numMicroops - 1]->setLastMicroop();
154
155 for (StaticInstPtr *uop = microOps; !(*uop)->isLastMicroop(); uop++) {
156 (*uop)->setDelayedCommit();
157 }
158 }
159
160 Fault
161 execute(ExecContext *, Trace::InstRecord *) const
162 {
163 panic("Execute method called when it shouldn't!");
164 return NoFault;
165 }
166
167 std::string
168 generateDisassembly(Addr pc, const SymbolTable *symtab) const
169 {
170 std::stringstream ss;
171 printMnemonic(ss, "", false);
172 ccprintf(ss, "{");
173 for (int i = 0; i < numregs; ++i) {
174 printVecReg(ss, (dest + i) % 32, true);
175 if (i < numregs - 1)
176 ccprintf(ss, ", ");
177 }
178 ccprintf(ss, "}, ");
179 printVecPredReg(ss, gp);
180 ccprintf(ss, ", [");
181 printIntReg(ss, base);
182 ccprintf(ss, ", ");
183 printIntReg(ss, offset);
184 ccprintf(ss, "]");
185 return ss.str();
186 }
187 };
188
189
190 template <typename Element,
191 template <typename> class MicroopLdMemType,
192 template <typename> class MicroopDeIntrlvType>
193 class SveLdStructSI : public PredMacroOp
194 {
195 protected:
196 IntRegIndex dest;
197 IntRegIndex gp;
198 IntRegIndex base;
199 int64_t imm;
200 uint8_t numregs;
201
202 public:
203 SveLdStructSI(const char* mnem, ExtMachInst machInst, OpClass __opClass,
204 IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base,
205 int64_t _imm, uint8_t _numregs)
206 : PredMacroOp(mnem, machInst, __opClass),
207 dest(_dest), gp(_gp), base(_base), imm(_imm), numregs(_numregs)
208 {
209 numMicroops = numregs * 2;
210
211 microOps = new StaticInstPtr[numMicroops];
212
213 for (int i = 0; i < numregs; ++i) {
214 microOps[i] = new MicroopLdMemType<Element>(
215 mnem, machInst, static_cast<IntRegIndex>(INTRLVREG0 + i),
216 _gp, _base, _imm, _numregs, i);
217 }
218 for (int i = 0; i < numregs; ++i) {
219 microOps[i + numregs] = new MicroopDeIntrlvType<Element>(
220 mnem, machInst, static_cast<IntRegIndex>((_dest + i) % 32),
221 _numregs, i, this);
222 }
223
224 microOps[0]->setFirstMicroop();
225 microOps[numMicroops - 1]->setLastMicroop();
226
227 for (StaticInstPtr *uop = microOps; !(*uop)->isLastMicroop(); uop++) {
228 (*uop)->setDelayedCommit();
229 }
230 }
231
232 Fault
233 execute(ExecContext *, Trace::InstRecord *) const
234 {
235 panic("Execute method called when it shouldn't!");
236 return NoFault;
237 }
238
239 std::string
240 generateDisassembly(Addr pc, const SymbolTable *symtab) const
241 {
242 std::stringstream ss;
243 printMnemonic(ss, "", false);
244 ccprintf(ss, "{");
245 for (int i = 0; i < numregs; ++i) {
246 printVecReg(ss, (dest + i) % 32, true);
247 if (i < numregs - 1)
248 ccprintf(ss, ", ");
249 }
250 ccprintf(ss, "}, ");
251 printVecPredReg(ss, gp);
252 ccprintf(ss, "/z, [");
253 printIntReg(ss, base);
254 if (imm != 0) {
255 ccprintf(ss, ", #%d, MUL VL", imm);
256 }
257 ccprintf(ss, "]");
258 return ss.str();
259 }
260 };
261
262 template <typename Element,
263 template <typename> class MicroopStMemType,
264 template <typename> class MicroopIntrlvType>
265 class SveStStructSI : public PredMacroOp
266 {
267 protected:
268 IntRegIndex dest;
269 IntRegIndex gp;
270 IntRegIndex base;
271 int64_t imm;
272 uint8_t numregs;
273
274 public:
275 SveStStructSI(const char* mnem, ExtMachInst machInst, OpClass __opClass,
276 IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base,
277 int64_t _imm, uint8_t _numregs)
278 : PredMacroOp(mnem, machInst, __opClass),
279 dest(_dest), gp(_gp), base(_base), imm(_imm), numregs(_numregs)
280 {
281 numMicroops = numregs * 2;
282
283 microOps = new StaticInstPtr[numMicroops];
284
285 for (int i = 0; i < numregs; ++i) {
286 microOps[i] = new MicroopIntrlvType<Element>(
287 mnem, machInst, static_cast<IntRegIndex>(INTRLVREG0 + i),
288 _dest, _numregs, i, this);
289 }
290
291 for (int i = 0; i < numregs; ++i) {
292 microOps[i + numregs] = new MicroopStMemType<Element>(
293 mnem, machInst, static_cast<IntRegIndex>(INTRLVREG0 + i),
294 _gp, _base, _imm, _numregs, i);
295 }
296
297 microOps[0]->setFirstMicroop();
298 microOps[numMicroops - 1]->setLastMicroop();
299
300 for (StaticInstPtr *uop = microOps; !(*uop)->isLastMicroop(); uop++) {
301 (*uop)->setDelayedCommit();
302 }
303 }
304
305 Fault
306 execute(ExecContext *, Trace::InstRecord *) const
307 {
308 panic("Execute method called when it shouldn't!");
309 return NoFault;
310 }
311
312 std::string
313 generateDisassembly(Addr pc, const SymbolTable *symtab) const
314 {
315 std::stringstream ss;
316 printMnemonic(ss, "", false);
317 ccprintf(ss, "{");
318 for (int i = 0; i < numregs; ++i) {
319 printVecReg(ss, (dest + i) % 32, true);
320 if (i < numregs - 1)
321 ccprintf(ss, ", ");
322 }
323 ccprintf(ss, "}, ");
324 printVecPredReg(ss, gp);
325 ccprintf(ss, ", [");
326 printIntReg(ss, base);
327 if (imm != 0) {
328 ccprintf(ss, ", #%d, MUL VL", imm);
329 }
330 ccprintf(ss, "]");
331 return ss.str();
332 }
333 };
334
335 template <typename RegElemType, typename MemElemType,
336 template <typename, typename> class MicroopType,
337 template <typename> class FirstFaultWritebackMicroopType>
338 class SveIndexedMemVI : public PredMacroOp
339 {
340 protected:
341 IntRegIndex dest;
342 IntRegIndex gp;
343 IntRegIndex base;
344 uint64_t imm;
345
346 public:
347 SveIndexedMemVI(const char *mnem, ExtMachInst machInst, OpClass __opClass,
348 IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base,
349 uint64_t _imm, bool firstFault)
350 : PredMacroOp(mnem, machInst, __opClass),
351 dest(_dest), gp(_gp), base(_base), imm(_imm)
352 {
353 bool isLoad = (__opClass == MemReadOp);
354 assert(!firstFault || isLoad);
355
356 int num_elems = ((machInst.sveLen + 1) * 16) / sizeof(RegElemType);
357
358 numMicroops = num_elems;
359 if (isLoad) {
360 if (firstFault) {
361 numMicroops += 2;
362 } else {
363 numMicroops++;
364 }
365 }
366
367 microOps = new StaticInstPtr[numMicroops];
368
369 StaticInstPtr *uop = microOps;
370
371 if (isLoad) {
372 // The first microop of a gather load copies the source vector
373 // register used for address calculation to an auxiliary register,
374 // with all subsequent microops reading from the latter. This is
375 // needed to properly handle cases where the source vector
376 // register is the same as the destination register
377 *uop = new ArmISAInst::SveGatherLoadCpySrcVecMicroop(
378 mnem, machInst, _base, this);
379 uop++;
380 }
381
382 for (int i = 0; i < num_elems; i++, uop++) {
383 *uop = new MicroopType<RegElemType, MemElemType>(
384 mnem, machInst, __opClass, _dest, _gp,
385 isLoad ? (IntRegIndex) VECREG_UREG0 : _base, _imm, i,
386 num_elems, firstFault);
387 }
388
389 if (firstFault) {
390 *uop = new FirstFaultWritebackMicroopType<RegElemType>(
391 mnem, machInst, __opClass, num_elems, this);
392 } else {
393 --uop;
394 }
395
396 (*uop)->setLastMicroop();
397 microOps[0]->setFirstMicroop();
398
399 for (StaticInstPtr *uop = microOps; !(*uop)->isLastMicroop(); uop++) {
400 (*uop)->setDelayedCommit();
401 }
402 }
403
404 Fault
405 execute(ExecContext *, Trace::InstRecord *) const
406 {
407 panic("Execute method called when it shouldn't!");
408 return NoFault;
409 }
410
411 std::string
412 generateDisassembly(Addr pc, const SymbolTable *symtab) const
413 {
414 // TODO: add suffix to transfer and base registers
415 std::stringstream ss;
416 printMnemonic(ss, "", false);
417 ccprintf(ss, "{");
418 printVecReg(ss, dest, true);
419 ccprintf(ss, "}, ");
420 printVecPredReg(ss, gp);
421 ccprintf(ss, "/z, [");
422 printVecReg(ss, base, true);
423 if (imm != 0) {
424 ccprintf(ss, ", #%d", imm * sizeof(MemElemType));
425 }
426 ccprintf(ss, "]");
427 return ss.str();
428 }
429 };
430
431 template <typename RegElemType, typename MemElemType,
432 template <typename, typename> class MicroopType,
433 template <typename> class FirstFaultWritebackMicroopType>
434 class SveIndexedMemSV : public PredMacroOp
435 {
436 protected:
437 IntRegIndex dest;
438 IntRegIndex gp;
439 IntRegIndex base;
440 IntRegIndex offset;
441
442 bool offsetIs32;
443 bool offsetIsSigned;
444 bool offsetIsScaled;
445
446 public:
447 SveIndexedMemSV(const char *mnem, ExtMachInst machInst, OpClass __opClass,
448 IntRegIndex _dest, IntRegIndex _gp, IntRegIndex _base,
449 IntRegIndex _offset, bool _offsetIs32,
450 bool _offsetIsSigned, bool _offsetIsScaled,
451 bool firstFault)
452 : PredMacroOp(mnem, machInst, __opClass),
453 dest(_dest), gp(_gp), base(_base), offset(_offset),
454 offsetIs32(_offsetIs32), offsetIsSigned(_offsetIsSigned),
455 offsetIsScaled(_offsetIsScaled)
456 {
457 bool isLoad = (__opClass == MemReadOp);
458 assert(!firstFault || isLoad);
459
460 int num_elems = ((machInst.sveLen + 1) * 16) / sizeof(RegElemType);
461
462 numMicroops = num_elems;
463 if (isLoad) {
464 if (firstFault) {
465 numMicroops += 2;
466 } else {
467 numMicroops++;
468 }
469 }
470
471 microOps = new StaticInstPtr[numMicroops];
472
473 StaticInstPtr *uop = microOps;
474
475 if (isLoad) {
476 // The first microop of a gather load copies the source vector
477 // register used for address calculation to an auxiliary register,
478 // with all subsequent microops reading from the latter. This is
479 // needed to properly handle cases where the source vector
480 // register is the same as the destination register
481 *uop = new ArmISAInst::SveGatherLoadCpySrcVecMicroop(
482 mnem, machInst, _offset, this);
483 uop++;
484 }
485
486 for (int i = 0; i < num_elems; i++, uop++) {
487 *uop = new MicroopType<RegElemType, MemElemType>(
488 mnem, machInst, __opClass, _dest, _gp, _base,
489 isLoad ? (IntRegIndex) VECREG_UREG0 : _offset, _offsetIs32,
490 _offsetIsSigned, _offsetIsScaled, i, num_elems, firstFault);
491 }
492
493 if (firstFault) {
494 *uop = new FirstFaultWritebackMicroopType<RegElemType>(
495 mnem, machInst, __opClass, num_elems, this);
496 } else {
497 --uop;
498 }
499
500 (*uop)->setLastMicroop();
501 microOps[0]->setFirstMicroop();
502
503 for (StaticInstPtr *uop = microOps; !(*uop)->isLastMicroop(); uop++) {
504 (*uop)->setDelayedCommit();
505 }
506 }
507
508 Fault
509 execute(ExecContext *, Trace::InstRecord *) const
510 {
511 panic("Execute method called when it shouldn't!");
512 return NoFault;
513 }
514
515 std::string
516 generateDisassembly(Addr pc, const SymbolTable *symtab) const
517 {
518 // TODO: add suffix to transfer and base registers
519 std::stringstream ss;
520 printMnemonic(ss, "", false);
521 ccprintf(ss, "{");
522 printVecReg(ss, dest, true);
523 ccprintf(ss, "}, ");
524 printVecPredReg(ss, gp);
525 ccprintf(ss, "/z, [");
526 printIntReg(ss, base);
527 ccprintf(ss, ", ");
528 printVecReg(ss, offset, true);
529 ccprintf(ss, "]");
530 return ss.str();
531 }
532 };
533
534 } // namespace ArmISA
535
536 #endif // __ARCH_ARM_SVE_MACROMEM_HH__