2 * Copyright (c) 2010 ARM Limited
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.
14 * Copyright (c) 2007-2008 The Florida State University
15 * All rights reserved.
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.
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.
40 * Authors: Stephen Hines
43 #include "arch/arm/insts/macromem.hh"
44 #include "arch/arm/decoder.hh"
46 using namespace ArmISAInst
;
51 MacroMemOp::MacroMemOp(const char *mnem
, ExtMachInst machInst
,
52 OpClass __opClass
, IntRegIndex rn
,
53 bool index
, bool up
, bool user
, bool writeback
,
54 bool load
, uint32_t reglist
) :
55 PredMacroOp(mnem
, machInst
, __opClass
)
57 uint32_t regs
= reglist
;
58 uint32_t ones
= number_of_ones(reglist
);
59 // Remember that writeback adds a uop
60 numMicroops
= ones
+ (writeback
? 1 : 0) + 1;
61 microOps
= new StaticInstPtr
[numMicroops
];
65 addr
= (ones
<< 2) - 4;
70 StaticInstPtr
*uop
= microOps
;
74 wbUop
= new MicroAddiUop(machInst
, rn
, rn
, ones
* 4);
76 wbUop
= new MicroSubiUop(machInst
, rn
, rn
, ones
* 4);
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);
84 // Write back at the start for loads. This covers the ldm exception return
85 // case where the base needs to be written in the old mode. Stores may need
86 // the original value of the base, but they don't change mode and can
87 // write back at the end like before.
88 if (load
&& writeback
) {
93 bool force_user
= user
& !bits(reglist
, 15);
94 bool exception_ret
= user
& bits(reglist
, 15);
96 for (int i
= 0; i
< ones
; i
++) {
97 // Find the next register.
98 while (!bits(regs
, reg
))
100 replaceBits(regs
, reg
, 0);
102 unsigned regIdx
= reg
;
104 regIdx
= intRegInMode(MODE_USER
, regIdx
);
108 if (reg
== INTREG_PC
&& exception_ret
) {
109 // This must be the exception return form of ldm.
110 *++uop
= new MicroLdrRetUop(machInst
, regIdx
,
111 INTREG_UREG0
, up
, addr
);
113 *++uop
= new MicroLdrUop(machInst
, regIdx
,
114 INTREG_UREG0
, up
, addr
);
117 *++uop
= new MicroStrUop(machInst
, regIdx
, INTREG_UREG0
, up
, addr
);
126 if (!load
&& writeback
) {
130 (*uop
)->setLastMicroop();
132 for (StaticInstPtr
*curUop
= microOps
;
133 !(*curUop
)->isLastMicroop(); curUop
++) {
134 MicroOp
* uopPtr
= dynamic_cast<MicroOp
*>(curUop
->get());
136 uopPtr
->setDelayedCommit();
140 VldMultOp::VldMultOp(const char *mnem
, ExtMachInst machInst
, OpClass __opClass
,
141 unsigned elems
, RegIndex rn
, RegIndex vd
, unsigned regs
,
142 unsigned inc
, uint32_t size
, uint32_t align
, RegIndex rm
) :
143 PredMacroOp(mnem
, machInst
, __opClass
)
145 assert(regs
> 0 && regs
<= 4);
146 assert(regs
% elems
== 0);
148 numMicroops
= (regs
> 2) ? 2 : 1;
149 bool wb
= (rm
!= 15);
150 bool deinterleave
= (elems
> 1);
152 if (wb
) numMicroops
++;
153 if (deinterleave
) numMicroops
+= (regs
/ elems
);
154 microOps
= new StaticInstPtr
[numMicroops
];
156 RegIndex rMid
= deinterleave
? NumFloatArchRegs
: vd
* 2;
158 uint32_t noAlign
= TLB::MustBeOne
;
163 microOps
[uopIdx
++] = newNeonMemInst
<MicroLdrNeon16Uop
>(
164 size
, machInst
, rMid
, rn
, 0, align
);
165 microOps
[uopIdx
++] = newNeonMemInst
<MicroLdrNeon16Uop
>(
166 size
, machInst
, rMid
+ 4, rn
, 16, noAlign
);
169 microOps
[uopIdx
++] = newNeonMemInst
<MicroLdrNeon16Uop
>(
170 size
, machInst
, rMid
, rn
, 0, align
);
171 microOps
[uopIdx
++] = newNeonMemInst
<MicroLdrNeon8Uop
>(
172 size
, machInst
, rMid
+ 4, rn
, 16, noAlign
);
175 microOps
[uopIdx
++] = newNeonMemInst
<MicroLdrNeon16Uop
>(
176 size
, machInst
, rMid
, rn
, 0, align
);
179 microOps
[uopIdx
++] = newNeonMemInst
<MicroLdrNeon8Uop
>(
180 size
, machInst
, rMid
, rn
, 0, align
);
183 panic("Unrecognized number of registers %d.\n", regs
);
186 if (rm
!= 15 && rm
!= 13) {
188 new MicroAddUop(machInst
, rn
, rn
, rm
, 0, ArmISA::LSL
);
191 new MicroAddiUop(machInst
, rn
, rn
, regs
* 8);
198 microOps
[uopIdx
++] = newNeonMixInst
<MicroDeintNeon8Uop
>(
199 size
, machInst
, vd
* 2, rMid
, inc
* 2);
203 microOps
[uopIdx
++] = newNeonMixInst
<MicroDeintNeon6Uop
>(
204 size
, machInst
, vd
* 2, rMid
, inc
* 2);
207 assert(regs
== 4 || regs
== 2);
209 microOps
[uopIdx
++] = newNeonMixInst
<MicroDeintNeon4Uop
>(
210 size
, machInst
, vd
* 2, rMid
, inc
* 2);
211 microOps
[uopIdx
++] = newNeonMixInst
<MicroDeintNeon4Uop
>(
212 size
, machInst
, vd
* 2 + 2, rMid
+ 4, inc
* 2);
214 microOps
[uopIdx
++] = newNeonMixInst
<MicroDeintNeon4Uop
>(
215 size
, machInst
, vd
* 2, rMid
, inc
* 2);
219 panic("Bad number of elements to deinterleave %d.\n", elems
);
222 assert(uopIdx
== numMicroops
);
224 for (unsigned i
= 0; i
< numMicroops
- 1; i
++) {
225 MicroOp
* uopPtr
= dynamic_cast<MicroOp
*>(microOps
[i
].get());
227 uopPtr
->setDelayedCommit();
229 microOps
[numMicroops
- 1]->setLastMicroop();
232 VldSingleOp::VldSingleOp(const char *mnem
, ExtMachInst machInst
,
233 OpClass __opClass
, bool all
, unsigned elems
,
234 RegIndex rn
, RegIndex vd
, unsigned regs
,
235 unsigned inc
, uint32_t size
, uint32_t align
,
236 RegIndex rm
, unsigned lane
) :
237 PredMacroOp(mnem
, machInst
, __opClass
)
239 assert(regs
> 0 && regs
<= 4);
240 assert(regs
% elems
== 0);
242 unsigned eBytes
= (1 << size
);
243 unsigned loadSize
= eBytes
* elems
;
244 unsigned loadRegs M5_VAR_USED
= (loadSize
+ sizeof(FloatRegBits
) - 1) /
245 sizeof(FloatRegBits
);
247 assert(loadRegs
> 0 && loadRegs
<= 4);
250 bool wb
= (rm
!= 15);
252 if (wb
) numMicroops
++;
253 numMicroops
+= (regs
/ elems
);
254 microOps
= new StaticInstPtr
[numMicroops
];
256 RegIndex ufp0
= NumFloatArchRegs
;
261 microOps
[uopIdx
++] = new MicroLdrNeon1Uop
<uint8_t>(
262 machInst
, ufp0
, rn
, 0, align
);
266 microOps
[uopIdx
++] = new MicroLdrNeon2Uop
<uint16_t>(
267 machInst
, ufp0
, rn
, 0, align
);
269 microOps
[uopIdx
++] = new MicroLdrNeon2Uop
<uint8_t>(
270 machInst
, ufp0
, rn
, 0, align
);
274 microOps
[uopIdx
++] = new MicroLdrNeon3Uop
<uint8_t>(
275 machInst
, ufp0
, rn
, 0, align
);
280 microOps
[uopIdx
++] = new MicroLdrNeon4Uop
<uint8_t>(
281 machInst
, ufp0
, rn
, 0, align
);
284 microOps
[uopIdx
++] = new MicroLdrNeon4Uop
<uint16_t>(
285 machInst
, ufp0
, rn
, 0, align
);
288 microOps
[uopIdx
++] = new MicroLdrNeon4Uop
<uint32_t>(
289 machInst
, ufp0
, rn
, 0, align
);
294 microOps
[uopIdx
++] = new MicroLdrNeon6Uop
<uint16_t>(
295 machInst
, ufp0
, rn
, 0, align
);
300 microOps
[uopIdx
++] = new MicroLdrNeon8Uop
<uint16_t>(
301 machInst
, ufp0
, rn
, 0, align
);
304 microOps
[uopIdx
++] = new MicroLdrNeon8Uop
<uint32_t>(
305 machInst
, ufp0
, rn
, 0, align
);
310 microOps
[uopIdx
++] = new MicroLdrNeon12Uop
<uint32_t>(
311 machInst
, ufp0
, rn
, 0, align
);
314 microOps
[uopIdx
++] = new MicroLdrNeon16Uop
<uint32_t>(
315 machInst
, ufp0
, rn
, 0, align
);
318 panic("Unrecognized load size %d.\n", regs
);
321 if (rm
!= 15 && rm
!= 13) {
323 new MicroAddUop(machInst
, rn
, rn
, rm
, 0, ArmISA::LSL
);
326 new MicroAddiUop(machInst
, rn
, rn
, loadSize
);
335 microOps
[uopIdx
++] = new MicroUnpackAllNeon2to8Uop
<uint8_t>(
336 machInst
, vd
* 2, ufp0
, inc
* 2);
338 microOps
[uopIdx
++] = new MicroUnpackNeon2to8Uop
<uint8_t>(
339 machInst
, vd
* 2, ufp0
, inc
* 2, lane
);
344 microOps
[uopIdx
++] = new MicroUnpackAllNeon2to8Uop
<uint16_t>(
345 machInst
, vd
* 2, ufp0
, inc
* 2);
347 microOps
[uopIdx
++] = new MicroUnpackNeon2to8Uop
<uint16_t>(
348 machInst
, vd
* 2, ufp0
, inc
* 2, lane
);
353 microOps
[uopIdx
++] = new MicroUnpackAllNeon4to8Uop
<uint32_t>(
354 machInst
, vd
* 2, ufp0
, inc
* 2);
356 microOps
[uopIdx
++] = new MicroUnpackNeon4to8Uop
<uint32_t>(
357 machInst
, vd
* 2, ufp0
, inc
* 2, lane
);
361 panic("Bad size %d.\n", size
);
370 microOps
[uopIdx
++] = new MicroUnpackAllNeon2to6Uop
<uint8_t>(
371 machInst
, vd
* 2, ufp0
, inc
* 2);
373 microOps
[uopIdx
++] = new MicroUnpackNeon2to6Uop
<uint8_t>(
374 machInst
, vd
* 2, ufp0
, inc
* 2, lane
);
379 microOps
[uopIdx
++] = new MicroUnpackAllNeon2to6Uop
<uint16_t>(
380 machInst
, vd
* 2, ufp0
, inc
* 2);
382 microOps
[uopIdx
++] = new MicroUnpackNeon2to6Uop
<uint16_t>(
383 machInst
, vd
* 2, ufp0
, inc
* 2, lane
);
388 microOps
[uopIdx
++] = new MicroUnpackAllNeon4to6Uop
<uint32_t>(
389 machInst
, vd
* 2, ufp0
, inc
* 2);
391 microOps
[uopIdx
++] = new MicroUnpackNeon4to6Uop
<uint32_t>(
392 machInst
, vd
* 2, ufp0
, inc
* 2, lane
);
396 panic("Bad size %d.\n", size
);
402 assert(loadRegs
<= 2);
406 microOps
[uopIdx
++] = new MicroUnpackAllNeon2to4Uop
<uint8_t>(
407 machInst
, vd
* 2, ufp0
, inc
* 2);
409 microOps
[uopIdx
++] = new MicroUnpackNeon2to4Uop
<uint8_t>(
410 machInst
, vd
* 2, ufp0
, inc
* 2, lane
);
415 microOps
[uopIdx
++] = new MicroUnpackAllNeon2to4Uop
<uint16_t>(
416 machInst
, vd
* 2, ufp0
, inc
* 2);
418 microOps
[uopIdx
++] = new MicroUnpackNeon2to4Uop
<uint16_t>(
419 machInst
, vd
* 2, ufp0
, inc
* 2, lane
);
424 microOps
[uopIdx
++] = new MicroUnpackAllNeon2to4Uop
<uint32_t>(
425 machInst
, vd
* 2, ufp0
, inc
* 2);
427 microOps
[uopIdx
++] = new MicroUnpackNeon2to4Uop
<uint32_t>(
428 machInst
, vd
* 2, ufp0
, inc
* 2, lane
);
432 panic("Bad size %d.\n", size
);
437 assert(regs
== 1 || (all
&& regs
== 2));
438 assert(loadRegs
<= 2);
439 for (unsigned offset
= 0; offset
< regs
; offset
++) {
444 new MicroUnpackAllNeon2to2Uop
<uint8_t>(
445 machInst
, (vd
+ offset
) * 2, ufp0
, inc
* 2);
448 new MicroUnpackNeon2to2Uop
<uint8_t>(
449 machInst
, (vd
+ offset
) * 2, ufp0
, inc
* 2, lane
);
455 new MicroUnpackAllNeon2to2Uop
<uint16_t>(
456 machInst
, (vd
+ offset
) * 2, ufp0
, inc
* 2);
459 new MicroUnpackNeon2to2Uop
<uint16_t>(
460 machInst
, (vd
+ offset
) * 2, ufp0
, inc
* 2, lane
);
466 new MicroUnpackAllNeon2to2Uop
<uint32_t>(
467 machInst
, (vd
+ offset
) * 2, ufp0
, inc
* 2);
470 new MicroUnpackNeon2to2Uop
<uint32_t>(
471 machInst
, (vd
+ offset
) * 2, ufp0
, inc
* 2, lane
);
475 panic("Bad size %d.\n", size
);
481 panic("Bad number of elements to unpack %d.\n", elems
);
483 assert(uopIdx
== numMicroops
);
485 for (unsigned i
= 0; i
< numMicroops
- 1; i
++) {
486 MicroOp
* uopPtr
= dynamic_cast<MicroOp
*>(microOps
[i
].get());
488 uopPtr
->setDelayedCommit();
490 microOps
[numMicroops
- 1]->setLastMicroop();
493 VstMultOp::VstMultOp(const char *mnem
, ExtMachInst machInst
, OpClass __opClass
,
494 unsigned elems
, RegIndex rn
, RegIndex vd
, unsigned regs
,
495 unsigned inc
, uint32_t size
, uint32_t align
, RegIndex rm
) :
496 PredMacroOp(mnem
, machInst
, __opClass
)
498 assert(regs
> 0 && regs
<= 4);
499 assert(regs
% elems
== 0);
501 numMicroops
= (regs
> 2) ? 2 : 1;
502 bool wb
= (rm
!= 15);
503 bool interleave
= (elems
> 1);
505 if (wb
) numMicroops
++;
506 if (interleave
) numMicroops
+= (regs
/ elems
);
507 microOps
= new StaticInstPtr
[numMicroops
];
509 uint32_t noAlign
= TLB::MustBeOne
;
511 RegIndex rMid
= interleave
? NumFloatArchRegs
: vd
* 2;
518 microOps
[uopIdx
++] = newNeonMixInst
<MicroInterNeon8Uop
>(
519 size
, machInst
, rMid
, vd
* 2, inc
* 2);
523 microOps
[uopIdx
++] = newNeonMixInst
<MicroInterNeon6Uop
>(
524 size
, machInst
, rMid
, vd
* 2, inc
* 2);
527 assert(regs
== 4 || regs
== 2);
529 microOps
[uopIdx
++] = newNeonMixInst
<MicroInterNeon4Uop
>(
530 size
, machInst
, rMid
, vd
* 2, inc
* 2);
531 microOps
[uopIdx
++] = newNeonMixInst
<MicroInterNeon4Uop
>(
532 size
, machInst
, rMid
+ 4, vd
* 2 + 2, inc
* 2);
534 microOps
[uopIdx
++] = newNeonMixInst
<MicroInterNeon4Uop
>(
535 size
, machInst
, rMid
, vd
* 2, inc
* 2);
539 panic("Bad number of elements to interleave %d.\n", elems
);
544 microOps
[uopIdx
++] = newNeonMemInst
<MicroStrNeon16Uop
>(
545 size
, machInst
, rMid
, rn
, 0, align
);
546 microOps
[uopIdx
++] = newNeonMemInst
<MicroStrNeon16Uop
>(
547 size
, machInst
, rMid
+ 4, rn
, 16, noAlign
);
550 microOps
[uopIdx
++] = newNeonMemInst
<MicroStrNeon16Uop
>(
551 size
, machInst
, rMid
, rn
, 0, align
);
552 microOps
[uopIdx
++] = newNeonMemInst
<MicroStrNeon8Uop
>(
553 size
, machInst
, rMid
+ 4, rn
, 16, noAlign
);
556 microOps
[uopIdx
++] = newNeonMemInst
<MicroStrNeon16Uop
>(
557 size
, machInst
, rMid
, rn
, 0, align
);
560 microOps
[uopIdx
++] = newNeonMemInst
<MicroStrNeon8Uop
>(
561 size
, machInst
, rMid
, rn
, 0, align
);
564 panic("Unrecognized number of registers %d.\n", regs
);
567 if (rm
!= 15 && rm
!= 13) {
569 new MicroAddUop(machInst
, rn
, rn
, rm
, 0, ArmISA::LSL
);
572 new MicroAddiUop(machInst
, rn
, rn
, regs
* 8);
575 assert(uopIdx
== numMicroops
);
577 for (unsigned i
= 0; i
< numMicroops
- 1; i
++) {
578 MicroOp
* uopPtr
= dynamic_cast<MicroOp
*>(microOps
[i
].get());
580 uopPtr
->setDelayedCommit();
582 microOps
[numMicroops
- 1]->setLastMicroop();
585 VstSingleOp::VstSingleOp(const char *mnem
, ExtMachInst machInst
,
586 OpClass __opClass
, bool all
, unsigned elems
,
587 RegIndex rn
, RegIndex vd
, unsigned regs
,
588 unsigned inc
, uint32_t size
, uint32_t align
,
589 RegIndex rm
, unsigned lane
) :
590 PredMacroOp(mnem
, machInst
, __opClass
)
593 assert(regs
> 0 && regs
<= 4);
594 assert(regs
% elems
== 0);
596 unsigned eBytes
= (1 << size
);
597 unsigned storeSize
= eBytes
* elems
;
598 unsigned storeRegs M5_VAR_USED
= (storeSize
+ sizeof(FloatRegBits
) - 1) /
599 sizeof(FloatRegBits
);
601 assert(storeRegs
> 0 && storeRegs
<= 4);
604 bool wb
= (rm
!= 15);
606 if (wb
) numMicroops
++;
607 numMicroops
+= (regs
/ elems
);
608 microOps
= new StaticInstPtr
[numMicroops
];
610 RegIndex ufp0
= NumFloatArchRegs
;
618 microOps
[uopIdx
++] = new MicroPackNeon8to2Uop
<uint8_t>(
619 machInst
, ufp0
, vd
* 2, inc
* 2, lane
);
622 microOps
[uopIdx
++] = new MicroPackNeon8to2Uop
<uint16_t>(
623 machInst
, ufp0
, vd
* 2, inc
* 2, lane
);
626 microOps
[uopIdx
++] = new MicroPackNeon8to4Uop
<uint32_t>(
627 machInst
, ufp0
, vd
* 2, inc
* 2, lane
);
630 panic("Bad size %d.\n", size
);
638 microOps
[uopIdx
++] = new MicroPackNeon6to2Uop
<uint8_t>(
639 machInst
, ufp0
, vd
* 2, inc
* 2, lane
);
642 microOps
[uopIdx
++] = new MicroPackNeon6to2Uop
<uint16_t>(
643 machInst
, ufp0
, vd
* 2, inc
* 2, lane
);
646 microOps
[uopIdx
++] = new MicroPackNeon6to4Uop
<uint32_t>(
647 machInst
, ufp0
, vd
* 2, inc
* 2, lane
);
650 panic("Bad size %d.\n", size
);
656 assert(storeRegs
<= 2);
659 microOps
[uopIdx
++] = new MicroPackNeon4to2Uop
<uint8_t>(
660 machInst
, ufp0
, vd
* 2, inc
* 2, lane
);
663 microOps
[uopIdx
++] = new MicroPackNeon4to2Uop
<uint16_t>(
664 machInst
, ufp0
, vd
* 2, inc
* 2, lane
);
667 microOps
[uopIdx
++] = new MicroPackNeon4to2Uop
<uint32_t>(
668 machInst
, ufp0
, vd
* 2, inc
* 2, lane
);
671 panic("Bad size %d.\n", size
);
676 assert(regs
== 1 || (all
&& regs
== 2));
677 assert(storeRegs
<= 2);
678 for (unsigned offset
= 0; offset
< regs
; offset
++) {
681 microOps
[uopIdx
++] = new MicroPackNeon2to2Uop
<uint8_t>(
682 machInst
, ufp0
, (vd
+ offset
) * 2, inc
* 2, lane
);
685 microOps
[uopIdx
++] = new MicroPackNeon2to2Uop
<uint16_t>(
686 machInst
, ufp0
, (vd
+ offset
) * 2, inc
* 2, lane
);
689 microOps
[uopIdx
++] = new MicroPackNeon2to2Uop
<uint32_t>(
690 machInst
, ufp0
, (vd
+ offset
) * 2, inc
* 2, lane
);
693 panic("Bad size %d.\n", size
);
699 panic("Bad number of elements to pack %d.\n", elems
);
703 microOps
[uopIdx
++] = new MicroStrNeon1Uop
<uint8_t>(
704 machInst
, ufp0
, rn
, 0, align
);
708 microOps
[uopIdx
++] = new MicroStrNeon2Uop
<uint16_t>(
709 machInst
, ufp0
, rn
, 0, align
);
711 microOps
[uopIdx
++] = new MicroStrNeon2Uop
<uint8_t>(
712 machInst
, ufp0
, rn
, 0, align
);
716 microOps
[uopIdx
++] = new MicroStrNeon3Uop
<uint8_t>(
717 machInst
, ufp0
, rn
, 0, align
);
722 microOps
[uopIdx
++] = new MicroStrNeon4Uop
<uint8_t>(
723 machInst
, ufp0
, rn
, 0, align
);
726 microOps
[uopIdx
++] = new MicroStrNeon4Uop
<uint16_t>(
727 machInst
, ufp0
, rn
, 0, align
);
730 microOps
[uopIdx
++] = new MicroStrNeon4Uop
<uint32_t>(
731 machInst
, ufp0
, rn
, 0, align
);
736 microOps
[uopIdx
++] = new MicroStrNeon6Uop
<uint16_t>(
737 machInst
, ufp0
, rn
, 0, align
);
742 microOps
[uopIdx
++] = new MicroStrNeon8Uop
<uint16_t>(
743 machInst
, ufp0
, rn
, 0, align
);
746 microOps
[uopIdx
++] = new MicroStrNeon8Uop
<uint32_t>(
747 machInst
, ufp0
, rn
, 0, align
);
752 microOps
[uopIdx
++] = new MicroStrNeon12Uop
<uint32_t>(
753 machInst
, ufp0
, rn
, 0, align
);
756 microOps
[uopIdx
++] = new MicroStrNeon16Uop
<uint32_t>(
757 machInst
, ufp0
, rn
, 0, align
);
760 panic("Unrecognized store size %d.\n", regs
);
763 if (rm
!= 15 && rm
!= 13) {
765 new MicroAddUop(machInst
, rn
, rn
, rm
, 0, ArmISA::LSL
);
768 new MicroAddiUop(machInst
, rn
, rn
, storeSize
);
771 assert(uopIdx
== numMicroops
);
773 for (unsigned i
= 0; i
< numMicroops
- 1; i
++) {
774 MicroOp
* uopPtr
= dynamic_cast<MicroOp
*>(microOps
[i
].get());
776 uopPtr
->setDelayedCommit();
778 microOps
[numMicroops
- 1]->setLastMicroop();
781 MacroVFPMemOp::MacroVFPMemOp(const char *mnem
, ExtMachInst machInst
,
782 OpClass __opClass
, IntRegIndex rn
,
783 RegIndex vd
, bool single
, bool up
,
784 bool writeback
, bool load
, uint32_t offset
) :
785 PredMacroOp(mnem
, machInst
, __opClass
)
789 // The lowest order bit selects fldmx (set) or fldmd (clear). These seem
790 // to be functionally identical except that fldmx is deprecated. For now
791 // we'll assume they're otherwise interchangable.
792 int count
= (single
? offset
: (offset
/ 2));
793 if (count
== 0 || count
> NumFloatArchRegs
)
794 warn_once("Bad offset field for VFP load/store multiple.\n");
796 // Force there to be at least one microop so the macroop makes sense.
799 if (count
> NumFloatArchRegs
)
800 count
= NumFloatArchRegs
;
802 numMicroops
= count
* (single
? 1 : 2) + (writeback
? 1 : 0);
803 microOps
= new StaticInstPtr
[numMicroops
];
811 for (int j
= 0; j
< count
; j
++) {
814 microOps
[i
++] = new MicroLdrFpUop(machInst
, vd
++, rn
,
817 microOps
[i
++] = new MicroLdrDBFpUop(machInst
, vd
++, rn
,
819 microOps
[i
++] = new MicroLdrDTFpUop(machInst
, vd
++, rn
, tempUp
,
820 addr
+ (up
? 4 : -4));
824 microOps
[i
++] = new MicroStrFpUop(machInst
, vd
++, rn
,
827 microOps
[i
++] = new MicroStrDBFpUop(machInst
, vd
++, rn
,
829 microOps
[i
++] = new MicroStrDTFpUop(machInst
, vd
++, rn
, tempUp
,
830 addr
+ (up
? 4 : -4));
834 addr
-= (single
? 4 : 8);
835 // The microops don't handle negative displacement, so turn if we
836 // hit zero, flip polarity and start adding.
842 addr
+= (single
? 4 : 8);
849 new MicroAddiUop(machInst
, rn
, rn
, 4 * offset
);
852 new MicroSubiUop(machInst
, rn
, rn
, 4 * offset
);
856 assert(numMicroops
== i
);
857 microOps
[numMicroops
- 1]->setLastMicroop();
859 for (StaticInstPtr
*curUop
= microOps
;
860 !(*curUop
)->isLastMicroop(); curUop
++) {
861 MicroOp
* uopPtr
= dynamic_cast<MicroOp
*>(curUop
->get());
863 uopPtr
->setDelayedCommit();
868 MicroIntImmOp::generateDisassembly(Addr pc
, const SymbolTable
*symtab
) const
870 std::stringstream ss
;
876 ccprintf(ss
, "#%d", imm
);
881 MicroIntMov::generateDisassembly(Addr pc
, const SymbolTable
*symtab
) const
883 std::stringstream ss
;
892 MicroIntOp::generateDisassembly(Addr pc
, const SymbolTable
*symtab
) const
894 std::stringstream ss
;
905 MicroMemOp::generateDisassembly(Addr pc
, const SymbolTable
*symtab
) const
907 std::stringstream ss
;
913 ccprintf(ss
, "#%d", imm
);