Deleted Added
sdiff udiff text old ( 9250:dab0f29394f0 ) new ( 9368:3cd40209af8d )
full compact
1/*
2 * Copyright (c) 2010 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 * Copyright (c) 2007-2008 The Florida State University
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Stephen Hines
41 */
42
43#include <sstream>
44
45#include "arch/arm/insts/macromem.hh"
46#include "arch/arm/generated/decoder.hh"
47
48using namespace std;
49using namespace ArmISAInst;
50
51namespace ArmISA
52{
53
54MacroMemOp::MacroMemOp(const char *mnem, ExtMachInst machInst,
55 OpClass __opClass, IntRegIndex rn,
56 bool index, bool up, bool user, bool writeback,
57 bool load, uint32_t reglist) :
58 PredMacroOp(mnem, machInst, __opClass)
59{
60 uint32_t regs = reglist;
61 uint32_t ones = number_of_ones(reglist);
62 // Remember that writeback adds a uop or two and the temp register adds one
63 numMicroops = ones + (writeback ? (load ? 2 : 1) : 0) + 1;
64
65 // It's technically legal to do a lot of nothing
66 if (!ones)
67 numMicroops = 1;
68
69 microOps = new StaticInstPtr[numMicroops];
70 uint32_t addr = 0;
71
72 if (!up)
73 addr = (ones << 2) - 4;
74
75 if (!index)
76 addr += 4;
77
78 StaticInstPtr *uop = microOps;
79
80 // Add 0 to Rn and stick it in ureg0.
81 // This is equivalent to a move.
82 *uop = new MicroAddiUop(machInst, INTREG_UREG0, rn, 0);
83
84 unsigned reg = 0;
85 unsigned regIdx = 0;
86 bool force_user = user & !bits(reglist, 15);
87 bool exception_ret = user & bits(reglist, 15);
88
89 for (int i = 0; i < ones; i++) {
90 // Find the next register.
91 while (!bits(regs, reg))
92 reg++;
93 replaceBits(regs, reg, 0);
94
95 regIdx = reg;
96 if (force_user) {
97 regIdx = intRegInMode(MODE_USER, regIdx);
98 }
99
100 if (load) {
101 if (writeback && i == ones - 1) {
102 // If it's a writeback and this is the last register
103 // do the load into a temporary register which we'll move
104 // into the final one later
105 *++uop = new MicroLdrUop(machInst, INTREG_UREG1, INTREG_UREG0,
106 up, addr);
107 } else {
108 // Otherwise just do it normally
109 if (reg == INTREG_PC && exception_ret) {
110 // This must be the exception return form of ldm.
111 *++uop = new MicroLdrRetUop(machInst, regIdx,
112 INTREG_UREG0, up, addr);
113 } else {
114 *++uop = new MicroLdrUop(machInst, regIdx,
115 INTREG_UREG0, up, addr);
116 if (reg == INTREG_PC) {
117 (*uop)->setFlag(StaticInst::IsControl);
118 if (!(condCode == COND_AL || condCode == COND_UC))
119 (*uop)->setFlag(StaticInst::IsCondControl);
120 else
121 (*uop)->setFlag(StaticInst::IsUncondControl);
122 (*uop)->setFlag(StaticInst::IsIndirectControl);
123 }
124 }
125 }
126 } else {
127 *++uop = new MicroStrUop(machInst, regIdx, INTREG_UREG0, up, addr);
128 }
129
130 if (up)
131 addr += 4;
132 else
133 addr -= 4;
134 }
135
136 if (writeback && ones) {
137 // put the register update after we're done all loading
138 if (up)
139 *++uop = new MicroAddiUop(machInst, rn, rn, ones * 4);
140 else
141 *++uop = new MicroSubiUop(machInst, rn, rn, ones * 4);
142
143 // If this was a load move the last temporary value into place
144 // this way we can't take an exception after we update the base
145 // register.
146 if (load && reg == INTREG_PC && exception_ret) {
147 *++uop = new MicroUopRegMovRet(machInst, 0, INTREG_UREG1);
148 } else if (load) {
149 *++uop = new MicroUopRegMov(machInst, regIdx, INTREG_UREG1);
150 if (reg == INTREG_PC) {
151 (*uop)->setFlag(StaticInst::IsControl);
152 (*uop)->setFlag(StaticInst::IsCondControl);
153 (*uop)->setFlag(StaticInst::IsIndirectControl);
154 // This is created as a RAS POP
155 if (rn == INTREG_SP)
156 (*uop)->setFlag(StaticInst::IsReturn);
157
158 }
159 }
160 }
161
162 (*uop)->setLastMicroop();
163
164 for (StaticInstPtr *curUop = microOps;
165 !(*curUop)->isLastMicroop(); curUop++) {
166 MicroOp * uopPtr = dynamic_cast<MicroOp *>(curUop->get());
167 assert(uopPtr);
168 uopPtr->setDelayedCommit();
169 }
170}
171
172VldMultOp::VldMultOp(const char *mnem, ExtMachInst machInst, OpClass __opClass,
173 unsigned elems, RegIndex rn, RegIndex vd, unsigned regs,
174 unsigned inc, uint32_t size, uint32_t align, RegIndex rm) :
175 PredMacroOp(mnem, machInst, __opClass)
176{
177 assert(regs > 0 && regs <= 4);
178 assert(regs % elems == 0);
179
180 numMicroops = (regs > 2) ? 2 : 1;
181 bool wb = (rm != 15);
182 bool deinterleave = (elems > 1);
183
184 if (wb) numMicroops++;
185 if (deinterleave) numMicroops += (regs / elems);
186 microOps = new StaticInstPtr[numMicroops];
187
188 RegIndex rMid = deinterleave ? NumFloatArchRegs : vd * 2;
189
190 uint32_t noAlign = TLB::MustBeOne;
191
192 unsigned uopIdx = 0;
193 switch (regs) {
194 case 4:
195 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>(
196 size, machInst, rMid, rn, 0, align);
197 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>(
198 size, machInst, rMid + 4, rn, 16, noAlign);
199 break;
200 case 3:
201 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>(
202 size, machInst, rMid, rn, 0, align);
203 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon8Uop>(
204 size, machInst, rMid + 4, rn, 16, noAlign);
205 break;
206 case 2:
207 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>(
208 size, machInst, rMid, rn, 0, align);
209 break;
210 case 1:
211 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon8Uop>(
212 size, machInst, rMid, rn, 0, align);
213 break;
214 default:
215 // Unknown number of registers
216 microOps[uopIdx++] = new Unknown(machInst);
217 }
218 if (wb) {
219 if (rm != 15 && rm != 13) {
220 microOps[uopIdx++] =
221 new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL);
222 } else {
223 microOps[uopIdx++] =
224 new MicroAddiUop(machInst, rn, rn, regs * 8);
225 }
226 }
227 if (deinterleave) {
228 switch (elems) {
229 case 4:
230 assert(regs == 4);
231 microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon8Uop>(
232 size, machInst, vd * 2, rMid, inc * 2);
233 break;
234 case 3:
235 assert(regs == 3);
236 microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon6Uop>(
237 size, machInst, vd * 2, rMid, inc * 2);
238 break;
239 case 2:
240 assert(regs == 4 || regs == 2);
241 if (regs == 4) {
242 microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon4Uop>(
243 size, machInst, vd * 2, rMid, inc * 2);
244 microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon4Uop>(
245 size, machInst, vd * 2 + 2, rMid + 4, inc * 2);
246 } else {
247 microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon4Uop>(
248 size, machInst, vd * 2, rMid, inc * 2);
249 }
250 break;
251 default:
252 // Bad number of elements to deinterleave
253 microOps[uopIdx++] = new Unknown(machInst);
254 }
255 }
256 assert(uopIdx == numMicroops);
257
258 for (unsigned i = 0; i < numMicroops - 1; i++) {
259 MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get());
260 assert(uopPtr);
261 uopPtr->setDelayedCommit();
262 }
263 microOps[numMicroops - 1]->setLastMicroop();
264}
265
266VldSingleOp::VldSingleOp(const char *mnem, ExtMachInst machInst,
267 OpClass __opClass, bool all, unsigned elems,
268 RegIndex rn, RegIndex vd, unsigned regs,
269 unsigned inc, uint32_t size, uint32_t align,
270 RegIndex rm, unsigned lane) :
271 PredMacroOp(mnem, machInst, __opClass)
272{
273 assert(regs > 0 && regs <= 4);
274 assert(regs % elems == 0);
275
276 unsigned eBytes = (1 << size);
277 unsigned loadSize = eBytes * elems;
278 unsigned loadRegs M5_VAR_USED = (loadSize + sizeof(FloatRegBits) - 1) /
279 sizeof(FloatRegBits);
280
281 assert(loadRegs > 0 && loadRegs <= 4);
282
283 numMicroops = 1;
284 bool wb = (rm != 15);
285
286 if (wb) numMicroops++;
287 numMicroops += (regs / elems);
288 microOps = new StaticInstPtr[numMicroops];
289
290 RegIndex ufp0 = NumFloatArchRegs;
291
292 unsigned uopIdx = 0;
293 switch (loadSize) {
294 case 1:
295 microOps[uopIdx++] = new MicroLdrNeon1Uop<uint8_t>(
296 machInst, ufp0, rn, 0, align);
297 break;
298 case 2:
299 if (eBytes == 2) {
300 microOps[uopIdx++] = new MicroLdrNeon2Uop<uint16_t>(
301 machInst, ufp0, rn, 0, align);
302 } else {
303 microOps[uopIdx++] = new MicroLdrNeon2Uop<uint8_t>(
304 machInst, ufp0, rn, 0, align);
305 }
306 break;
307 case 3:
308 microOps[uopIdx++] = new MicroLdrNeon3Uop<uint8_t>(
309 machInst, ufp0, rn, 0, align);
310 break;
311 case 4:
312 switch (eBytes) {
313 case 1:
314 microOps[uopIdx++] = new MicroLdrNeon4Uop<uint8_t>(
315 machInst, ufp0, rn, 0, align);
316 break;
317 case 2:
318 microOps[uopIdx++] = new MicroLdrNeon4Uop<uint16_t>(
319 machInst, ufp0, rn, 0, align);
320 break;
321 case 4:
322 microOps[uopIdx++] = new MicroLdrNeon4Uop<uint32_t>(
323 machInst, ufp0, rn, 0, align);
324 break;
325 }
326 break;
327 case 6:
328 microOps[uopIdx++] = new MicroLdrNeon6Uop<uint16_t>(
329 machInst, ufp0, rn, 0, align);
330 break;
331 case 8:
332 switch (eBytes) {
333 case 2:
334 microOps[uopIdx++] = new MicroLdrNeon8Uop<uint16_t>(
335 machInst, ufp0, rn, 0, align);
336 break;
337 case 4:
338 microOps[uopIdx++] = new MicroLdrNeon8Uop<uint32_t>(
339 machInst, ufp0, rn, 0, align);
340 break;
341 }
342 break;
343 case 12:
344 microOps[uopIdx++] = new MicroLdrNeon12Uop<uint32_t>(
345 machInst, ufp0, rn, 0, align);
346 break;
347 case 16:
348 microOps[uopIdx++] = new MicroLdrNeon16Uop<uint32_t>(
349 machInst, ufp0, rn, 0, align);
350 break;
351 default:
352 // Unrecognized load size
353 microOps[uopIdx++] = new Unknown(machInst);
354 }
355 if (wb) {
356 if (rm != 15 && rm != 13) {
357 microOps[uopIdx++] =
358 new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL);
359 } else {
360 microOps[uopIdx++] =
361 new MicroAddiUop(machInst, rn, rn, loadSize);
362 }
363 }
364 switch (elems) {
365 case 4:
366 assert(regs == 4);
367 switch (size) {
368 case 0:
369 if (all) {
370 microOps[uopIdx++] = new MicroUnpackAllNeon2to8Uop<uint8_t>(
371 machInst, vd * 2, ufp0, inc * 2);
372 } else {
373 microOps[uopIdx++] = new MicroUnpackNeon2to8Uop<uint8_t>(
374 machInst, vd * 2, ufp0, inc * 2, lane);
375 }
376 break;
377 case 1:
378 if (all) {
379 microOps[uopIdx++] = new MicroUnpackAllNeon2to8Uop<uint16_t>(
380 machInst, vd * 2, ufp0, inc * 2);
381 } else {
382 microOps[uopIdx++] = new MicroUnpackNeon2to8Uop<uint16_t>(
383 machInst, vd * 2, ufp0, inc * 2, lane);
384 }
385 break;
386 case 2:
387 if (all) {
388 microOps[uopIdx++] = new MicroUnpackAllNeon4to8Uop<uint32_t>(
389 machInst, vd * 2, ufp0, inc * 2);
390 } else {
391 microOps[uopIdx++] = new MicroUnpackNeon4to8Uop<uint32_t>(
392 machInst, vd * 2, ufp0, inc * 2, lane);
393 }
394 break;
395 default:
396 // Bad size
397 microOps[uopIdx++] = new Unknown(machInst);
398 break;
399 }
400 break;
401 case 3:
402 assert(regs == 3);
403 switch (size) {
404 case 0:
405 if (all) {
406 microOps[uopIdx++] = new MicroUnpackAllNeon2to6Uop<uint8_t>(
407 machInst, vd * 2, ufp0, inc * 2);
408 } else {
409 microOps[uopIdx++] = new MicroUnpackNeon2to6Uop<uint8_t>(
410 machInst, vd * 2, ufp0, inc * 2, lane);
411 }
412 break;
413 case 1:
414 if (all) {
415 microOps[uopIdx++] = new MicroUnpackAllNeon2to6Uop<uint16_t>(
416 machInst, vd * 2, ufp0, inc * 2);
417 } else {
418 microOps[uopIdx++] = new MicroUnpackNeon2to6Uop<uint16_t>(
419 machInst, vd * 2, ufp0, inc * 2, lane);
420 }
421 break;
422 case 2:
423 if (all) {
424 microOps[uopIdx++] = new MicroUnpackAllNeon4to6Uop<uint32_t>(
425 machInst, vd * 2, ufp0, inc * 2);
426 } else {
427 microOps[uopIdx++] = new MicroUnpackNeon4to6Uop<uint32_t>(
428 machInst, vd * 2, ufp0, inc * 2, lane);
429 }
430 break;
431 default:
432 // Bad size
433 microOps[uopIdx++] = new Unknown(machInst);
434 break;
435 }
436 break;
437 case 2:
438 assert(regs == 2);
439 assert(loadRegs <= 2);
440 switch (size) {
441 case 0:
442 if (all) {
443 microOps[uopIdx++] = new MicroUnpackAllNeon2to4Uop<uint8_t>(
444 machInst, vd * 2, ufp0, inc * 2);
445 } else {
446 microOps[uopIdx++] = new MicroUnpackNeon2to4Uop<uint8_t>(
447 machInst, vd * 2, ufp0, inc * 2, lane);
448 }
449 break;
450 case 1:
451 if (all) {
452 microOps[uopIdx++] = new MicroUnpackAllNeon2to4Uop<uint16_t>(
453 machInst, vd * 2, ufp0, inc * 2);
454 } else {
455 microOps[uopIdx++] = new MicroUnpackNeon2to4Uop<uint16_t>(
456 machInst, vd * 2, ufp0, inc * 2, lane);
457 }
458 break;
459 case 2:
460 if (all) {
461 microOps[uopIdx++] = new MicroUnpackAllNeon2to4Uop<uint32_t>(
462 machInst, vd * 2, ufp0, inc * 2);
463 } else {
464 microOps[uopIdx++] = new MicroUnpackNeon2to4Uop<uint32_t>(
465 machInst, vd * 2, ufp0, inc * 2, lane);
466 }
467 break;
468 default:
469 // Bad size
470 microOps[uopIdx++] = new Unknown(machInst);
471 break;
472 }
473 break;
474 case 1:
475 assert(regs == 1 || (all && regs == 2));
476 assert(loadRegs <= 2);
477 for (unsigned offset = 0; offset < regs; offset++) {
478 switch (size) {
479 case 0:
480 if (all) {
481 microOps[uopIdx++] =
482 new MicroUnpackAllNeon2to2Uop<uint8_t>(
483 machInst, (vd + offset) * 2, ufp0, inc * 2);
484 } else {
485 microOps[uopIdx++] =
486 new MicroUnpackNeon2to2Uop<uint8_t>(
487 machInst, (vd + offset) * 2, ufp0, inc * 2, lane);
488 }
489 break;
490 case 1:
491 if (all) {
492 microOps[uopIdx++] =
493 new MicroUnpackAllNeon2to2Uop<uint16_t>(
494 machInst, (vd + offset) * 2, ufp0, inc * 2);
495 } else {
496 microOps[uopIdx++] =
497 new MicroUnpackNeon2to2Uop<uint16_t>(
498 machInst, (vd + offset) * 2, ufp0, inc * 2, lane);
499 }
500 break;
501 case 2:
502 if (all) {
503 microOps[uopIdx++] =
504 new MicroUnpackAllNeon2to2Uop<uint32_t>(
505 machInst, (vd + offset) * 2, ufp0, inc * 2);
506 } else {
507 microOps[uopIdx++] =
508 new MicroUnpackNeon2to2Uop<uint32_t>(
509 machInst, (vd + offset) * 2, ufp0, inc * 2, lane);
510 }
511 break;
512 default:
513 // Bad size
514 microOps[uopIdx++] = new Unknown(machInst);
515 break;
516 }
517 }
518 break;
519 default:
520 // Bad number of elements to unpack
521 microOps[uopIdx++] = new Unknown(machInst);
522 }
523 assert(uopIdx == numMicroops);
524
525 for (unsigned i = 0; i < numMicroops - 1; i++) {
526 MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get());
527 assert(uopPtr);
528 uopPtr->setDelayedCommit();
529 }
530 microOps[numMicroops - 1]->setLastMicroop();
531}
532
533VstMultOp::VstMultOp(const char *mnem, ExtMachInst machInst, OpClass __opClass,
534 unsigned elems, RegIndex rn, RegIndex vd, unsigned regs,
535 unsigned inc, uint32_t size, uint32_t align, RegIndex rm) :
536 PredMacroOp(mnem, machInst, __opClass)
537{
538 assert(regs > 0 && regs <= 4);
539 assert(regs % elems == 0);
540
541 numMicroops = (regs > 2) ? 2 : 1;
542 bool wb = (rm != 15);
543 bool interleave = (elems > 1);
544
545 if (wb) numMicroops++;
546 if (interleave) numMicroops += (regs / elems);
547 microOps = new StaticInstPtr[numMicroops];
548
549 uint32_t noAlign = TLB::MustBeOne;
550
551 RegIndex rMid = interleave ? NumFloatArchRegs : vd * 2;
552
553 unsigned uopIdx = 0;
554 if (interleave) {
555 switch (elems) {
556 case 4:
557 assert(regs == 4);
558 microOps[uopIdx++] = newNeonMixInst<MicroInterNeon8Uop>(
559 size, machInst, rMid, vd * 2, inc * 2);
560 break;
561 case 3:
562 assert(regs == 3);
563 microOps[uopIdx++] = newNeonMixInst<MicroInterNeon6Uop>(
564 size, machInst, rMid, vd * 2, inc * 2);
565 break;
566 case 2:
567 assert(regs == 4 || regs == 2);
568 if (regs == 4) {
569 microOps[uopIdx++] = newNeonMixInst<MicroInterNeon4Uop>(
570 size, machInst, rMid, vd * 2, inc * 2);
571 microOps[uopIdx++] = newNeonMixInst<MicroInterNeon4Uop>(
572 size, machInst, rMid + 4, vd * 2 + 2, inc * 2);
573 } else {
574 microOps[uopIdx++] = newNeonMixInst<MicroInterNeon4Uop>(
575 size, machInst, rMid, vd * 2, inc * 2);
576 }
577 break;
578 default:
579 // Bad number of elements to interleave
580 microOps[uopIdx++] = new Unknown(machInst);
581 }
582 }
583 switch (regs) {
584 case 4:
585 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>(
586 size, machInst, rMid, rn, 0, align);
587 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>(
588 size, machInst, rMid + 4, rn, 16, noAlign);
589 break;
590 case 3:
591 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>(
592 size, machInst, rMid, rn, 0, align);
593 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon8Uop>(
594 size, machInst, rMid + 4, rn, 16, noAlign);
595 break;
596 case 2:
597 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>(
598 size, machInst, rMid, rn, 0, align);
599 break;
600 case 1:
601 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon8Uop>(
602 size, machInst, rMid, rn, 0, align);
603 break;
604 default:
605 // Unknown number of registers
606 microOps[uopIdx++] = new Unknown(machInst);
607 }
608 if (wb) {
609 if (rm != 15 && rm != 13) {
610 microOps[uopIdx++] =
611 new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL);
612 } else {
613 microOps[uopIdx++] =
614 new MicroAddiUop(machInst, rn, rn, regs * 8);
615 }
616 }
617 assert(uopIdx == numMicroops);
618
619 for (unsigned i = 0; i < numMicroops - 1; i++) {
620 MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get());
621 assert(uopPtr);
622 uopPtr->setDelayedCommit();
623 }
624 microOps[numMicroops - 1]->setLastMicroop();
625}
626
627VstSingleOp::VstSingleOp(const char *mnem, ExtMachInst machInst,
628 OpClass __opClass, bool all, unsigned elems,
629 RegIndex rn, RegIndex vd, unsigned regs,
630 unsigned inc, uint32_t size, uint32_t align,
631 RegIndex rm, unsigned lane) :
632 PredMacroOp(mnem, machInst, __opClass)
633{
634 assert(!all);
635 assert(regs > 0 && regs <= 4);
636 assert(regs % elems == 0);
637
638 unsigned eBytes = (1 << size);
639 unsigned storeSize = eBytes * elems;
640 unsigned storeRegs M5_VAR_USED = (storeSize + sizeof(FloatRegBits) - 1) /
641 sizeof(FloatRegBits);
642
643 assert(storeRegs > 0 && storeRegs <= 4);
644
645 numMicroops = 1;
646 bool wb = (rm != 15);
647
648 if (wb) numMicroops++;
649 numMicroops += (regs / elems);
650 microOps = new StaticInstPtr[numMicroops];
651
652 RegIndex ufp0 = NumFloatArchRegs;
653
654 unsigned uopIdx = 0;
655 switch (elems) {
656 case 4:
657 assert(regs == 4);
658 switch (size) {
659 case 0:
660 microOps[uopIdx++] = new MicroPackNeon8to2Uop<uint8_t>(
661 machInst, ufp0, vd * 2, inc * 2, lane);
662 break;
663 case 1:
664 microOps[uopIdx++] = new MicroPackNeon8to2Uop<uint16_t>(
665 machInst, ufp0, vd * 2, inc * 2, lane);
666 break;
667 case 2:
668 microOps[uopIdx++] = new MicroPackNeon8to4Uop<uint32_t>(
669 machInst, ufp0, vd * 2, inc * 2, lane);
670 break;
671 default:
672 // Bad size
673 microOps[uopIdx++] = new Unknown(machInst);
674 break;
675 }
676 break;
677 case 3:
678 assert(regs == 3);
679 switch (size) {
680 case 0:
681 microOps[uopIdx++] = new MicroPackNeon6to2Uop<uint8_t>(
682 machInst, ufp0, vd * 2, inc * 2, lane);
683 break;
684 case 1:
685 microOps[uopIdx++] = new MicroPackNeon6to2Uop<uint16_t>(
686 machInst, ufp0, vd * 2, inc * 2, lane);
687 break;
688 case 2:
689 microOps[uopIdx++] = new MicroPackNeon6to4Uop<uint32_t>(
690 machInst, ufp0, vd * 2, inc * 2, lane);
691 break;
692 default:
693 // Bad size
694 microOps[uopIdx++] = new Unknown(machInst);
695 break;
696 }
697 break;
698 case 2:
699 assert(regs == 2);
700 assert(storeRegs <= 2);
701 switch (size) {
702 case 0:
703 microOps[uopIdx++] = new MicroPackNeon4to2Uop<uint8_t>(
704 machInst, ufp0, vd * 2, inc * 2, lane);
705 break;
706 case 1:
707 microOps[uopIdx++] = new MicroPackNeon4to2Uop<uint16_t>(
708 machInst, ufp0, vd * 2, inc * 2, lane);
709 break;
710 case 2:
711 microOps[uopIdx++] = new MicroPackNeon4to2Uop<uint32_t>(
712 machInst, ufp0, vd * 2, inc * 2, lane);
713 break;
714 default:
715 // Bad size
716 microOps[uopIdx++] = new Unknown(machInst);
717 break;
718 }
719 break;
720 case 1:
721 assert(regs == 1 || (all && regs == 2));
722 assert(storeRegs <= 2);
723 for (unsigned offset = 0; offset < regs; offset++) {
724 switch (size) {
725 case 0:
726 microOps[uopIdx++] = new MicroPackNeon2to2Uop<uint8_t>(
727 machInst, ufp0, (vd + offset) * 2, inc * 2, lane);
728 break;
729 case 1:
730 microOps[uopIdx++] = new MicroPackNeon2to2Uop<uint16_t>(
731 machInst, ufp0, (vd + offset) * 2, inc * 2, lane);
732 break;
733 case 2:
734 microOps[uopIdx++] = new MicroPackNeon2to2Uop<uint32_t>(
735 machInst, ufp0, (vd + offset) * 2, inc * 2, lane);
736 break;
737 default:
738 // Bad size
739 microOps[uopIdx++] = new Unknown(machInst);
740 break;
741 }
742 }
743 break;
744 default:
745 // Bad number of elements to unpack
746 microOps[uopIdx++] = new Unknown(machInst);
747 }
748 switch (storeSize) {
749 case 1:
750 microOps[uopIdx++] = new MicroStrNeon1Uop<uint8_t>(
751 machInst, ufp0, rn, 0, align);
752 break;
753 case 2:
754 if (eBytes == 2) {
755 microOps[uopIdx++] = new MicroStrNeon2Uop<uint16_t>(
756 machInst, ufp0, rn, 0, align);
757 } else {
758 microOps[uopIdx++] = new MicroStrNeon2Uop<uint8_t>(
759 machInst, ufp0, rn, 0, align);
760 }
761 break;
762 case 3:
763 microOps[uopIdx++] = new MicroStrNeon3Uop<uint8_t>(
764 machInst, ufp0, rn, 0, align);
765 break;
766 case 4:
767 switch (eBytes) {
768 case 1:
769 microOps[uopIdx++] = new MicroStrNeon4Uop<uint8_t>(
770 machInst, ufp0, rn, 0, align);
771 break;
772 case 2:
773 microOps[uopIdx++] = new MicroStrNeon4Uop<uint16_t>(
774 machInst, ufp0, rn, 0, align);
775 break;
776 case 4:
777 microOps[uopIdx++] = new MicroStrNeon4Uop<uint32_t>(
778 machInst, ufp0, rn, 0, align);
779 break;
780 }
781 break;
782 case 6:
783 microOps[uopIdx++] = new MicroStrNeon6Uop<uint16_t>(
784 machInst, ufp0, rn, 0, align);
785 break;
786 case 8:
787 switch (eBytes) {
788 case 2:
789 microOps[uopIdx++] = new MicroStrNeon8Uop<uint16_t>(
790 machInst, ufp0, rn, 0, align);
791 break;
792 case 4:
793 microOps[uopIdx++] = new MicroStrNeon8Uop<uint32_t>(
794 machInst, ufp0, rn, 0, align);
795 break;
796 }
797 break;
798 case 12:
799 microOps[uopIdx++] = new MicroStrNeon12Uop<uint32_t>(
800 machInst, ufp0, rn, 0, align);
801 break;
802 case 16:
803 microOps[uopIdx++] = new MicroStrNeon16Uop<uint32_t>(
804 machInst, ufp0, rn, 0, align);
805 break;
806 default:
807 // Bad store size
808 microOps[uopIdx++] = new Unknown(machInst);
809 }
810 if (wb) {
811 if (rm != 15 && rm != 13) {
812 microOps[uopIdx++] =
813 new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL);
814 } else {
815 microOps[uopIdx++] =
816 new MicroAddiUop(machInst, rn, rn, storeSize);
817 }
818 }
819 assert(uopIdx == numMicroops);
820
821 for (unsigned i = 0; i < numMicroops - 1; i++) {
822 MicroOp * uopPtr = dynamic_cast<MicroOp *>(microOps[i].get());
823 assert(uopPtr);
824 uopPtr->setDelayedCommit();
825 }
826 microOps[numMicroops - 1]->setLastMicroop();
827}
828
829MacroVFPMemOp::MacroVFPMemOp(const char *mnem, ExtMachInst machInst,
830 OpClass __opClass, IntRegIndex rn,
831 RegIndex vd, bool single, bool up,
832 bool writeback, bool load, uint32_t offset) :
833 PredMacroOp(mnem, machInst, __opClass)
834{
835 int i = 0;
836
837 // The lowest order bit selects fldmx (set) or fldmd (clear). These seem
838 // to be functionally identical except that fldmx is deprecated. For now
839 // we'll assume they're otherwise interchangable.
840 int count = (single ? offset : (offset / 2));
841 if (count == 0 || count > NumFloatArchRegs)
842 warn_once("Bad offset field for VFP load/store multiple.\n");
843 if (count == 0) {
844 // Force there to be at least one microop so the macroop makes sense.
845 writeback = true;
846 }
847 if (count > NumFloatArchRegs)
848 count = NumFloatArchRegs;
849
850 numMicroops = count * (single ? 1 : 2) + (writeback ? 1 : 0);
851 microOps = new StaticInstPtr[numMicroops];
852
853 int64_t addr = 0;
854
855 if (!up)
856 addr = 4 * offset;
857
858 bool tempUp = up;
859 for (int j = 0; j < count; j++) {
860 if (load) {
861 if (single) {
862 microOps[i++] = new MicroLdrFpUop(machInst, vd++, rn,
863 tempUp, addr);
864 } else {
865 microOps[i++] = new MicroLdrDBFpUop(machInst, vd++, rn,
866 tempUp, addr);
867 microOps[i++] = new MicroLdrDTFpUop(machInst, vd++, rn, tempUp,
868 addr + (up ? 4 : -4));
869 }
870 } else {
871 if (single) {
872 microOps[i++] = new MicroStrFpUop(machInst, vd++, rn,
873 tempUp, addr);
874 } else {
875 microOps[i++] = new MicroStrDBFpUop(machInst, vd++, rn,
876 tempUp, addr);
877 microOps[i++] = new MicroStrDTFpUop(machInst, vd++, rn, tempUp,
878 addr + (up ? 4 : -4));
879 }
880 }
881 if (!tempUp) {
882 addr -= (single ? 4 : 8);
883 // The microops don't handle negative displacement, so turn if we
884 // hit zero, flip polarity and start adding.
885 if (addr <= 0) {
886 tempUp = true;
887 addr = -addr;
888 }
889 } else {
890 addr += (single ? 4 : 8);
891 }
892 }
893
894 if (writeback) {
895 if (up) {
896 microOps[i++] =
897 new MicroAddiUop(machInst, rn, rn, 4 * offset);
898 } else {
899 microOps[i++] =
900 new MicroSubiUop(machInst, rn, rn, 4 * offset);
901 }
902 }
903
904 assert(numMicroops == i);
905 microOps[numMicroops - 1]->setLastMicroop();
906
907 for (StaticInstPtr *curUop = microOps;
908 !(*curUop)->isLastMicroop(); curUop++) {
909 MicroOp * uopPtr = dynamic_cast<MicroOp *>(curUop->get());
910 assert(uopPtr);
911 uopPtr->setDelayedCommit();
912 }
913}
914
915std::string
916MicroIntImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
917{
918 std::stringstream ss;
919 printMnemonic(ss);
920 printReg(ss, ura);
921 ss << ", ";
922 printReg(ss, urb);
923 ss << ", ";
924 ccprintf(ss, "#%d", imm);
925 return ss.str();
926}
927
928std::string
929MicroSetPCCPSR::generateDisassembly(Addr pc, const SymbolTable *symtab) const
930{
931 std::stringstream ss;
932 printMnemonic(ss);
933 ss << "[PC,CPSR]";
934 return ss.str();
935}
936
937std::string
938MicroIntMov::generateDisassembly(Addr pc, const SymbolTable *symtab) const
939{
940 std::stringstream ss;
941 printMnemonic(ss);
942 printReg(ss, ura);
943 ss << ", ";
944 printReg(ss, urb);
945 return ss.str();
946}
947
948std::string
949MicroIntOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
950{
951 std::stringstream ss;
952 printMnemonic(ss);
953 printReg(ss, ura);
954 ss << ", ";
955 printReg(ss, urb);
956 ss << ", ";
957 printReg(ss, urc);
958 return ss.str();
959}
960
961std::string
962MicroMemOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
963{
964 std::stringstream ss;
965 printMnemonic(ss);
966 printReg(ss, ura);
967 ss << ", [";
968 printReg(ss, urb);
969 ss << ", ";
970 ccprintf(ss, "#%d", imm);
971 ss << "]";
972 return ss.str();
973}
974
975}