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"
48 using namespace ArmISAInst
;
53 MacroMemOp::MacroMemOp(const char *mnem
, ExtMachInst machInst
,
54 OpClass __opClass
, IntRegIndex rn
,
55 bool index
, bool up
, bool user
, bool writeback
,
56 bool load
, uint32_t reglist
) :
57 PredMacroOp(mnem
, machInst
, __opClass
)
59 uint32_t regs
= reglist
;
60 uint32_t ones
= number_of_ones(reglist
);
61 // Remember that writeback adds a uop or two and the temp register adds one
62 numMicroops
= ones
+ (writeback
? (load
? 2 : 1) : 0) + 1;
64 // It's technically legal to do a lot of nothing
68 microOps
= new StaticInstPtr
[numMicroops
];
72 addr
= (ones
<< 2) - 4;
77 StaticInstPtr
*uop
= microOps
;
79 // Add 0 to Rn and stick it in ureg0.
80 // This is equivalent to a move.
81 *uop
= new MicroAddiUop(machInst
, INTREG_UREG0
, rn
, 0);
85 bool force_user
= user
& !bits(reglist
, 15);
86 bool exception_ret
= user
& bits(reglist
, 15);
88 for (int i
= 0; i
< ones
; i
++) {
89 // Find the next register.
90 while (!bits(regs
, reg
))
92 replaceBits(regs
, reg
, 0);
96 regIdx
= intRegInMode(MODE_USER
, regIdx
);
100 if (writeback
&& i
== ones
- 1) {
101 // If it's a writeback and this is the last register
102 // do the load into a temporary register which we'll move
103 // into the final one later
104 *++uop
= new MicroLdrUop(machInst
, INTREG_UREG1
, INTREG_UREG0
,
107 // Otherwise just do it normally
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
);
118 *++uop
= new MicroStrUop(machInst
, regIdx
, INTREG_UREG0
, up
, addr
);
127 if (writeback
&& ones
) {
128 // put the register update after we're done all loading
130 *++uop
= new MicroAddiUop(machInst
, rn
, rn
, ones
* 4);
132 *++uop
= new MicroSubiUop(machInst
, rn
, rn
, ones
* 4);
134 // If this was a load move the last temporary value into place
135 // this way we can't take an exception after we update the base
137 if (load
&& reg
== INTREG_PC
&& exception_ret
) {
138 *++uop
= new MicroUopRegMovRet(machInst
, 0, INTREG_UREG1
);
139 warn("creating instruction with exception return at curTick:%d\n",
142 *++uop
= new MicroUopRegMov(machInst
, regIdx
, INTREG_UREG1
);
143 if (reg
== INTREG_PC
) {
144 (*uop
)->setFlag(StaticInstBase::IsControl
);
145 (*uop
)->setFlag(StaticInstBase::IsCondControl
);
146 (*uop
)->setFlag(StaticInstBase::IsIndirectControl
);
147 // This is created as a RAS POP
149 (*uop
)->setFlag(StaticInstBase::IsReturn
);
155 (*uop
)->setLastMicroop();
157 for (StaticInstPtr
*curUop
= microOps
;
158 !(*curUop
)->isLastMicroop(); curUop
++) {
159 MicroOp
* uopPtr
= dynamic_cast<MicroOp
*>(curUop
->get());
161 uopPtr
->setDelayedCommit();
165 VldMultOp::VldMultOp(const char *mnem
, ExtMachInst machInst
, OpClass __opClass
,
166 unsigned elems
, RegIndex rn
, RegIndex vd
, unsigned regs
,
167 unsigned inc
, uint32_t size
, uint32_t align
, RegIndex rm
) :
168 PredMacroOp(mnem
, machInst
, __opClass
)
170 assert(regs
> 0 && regs
<= 4);
171 assert(regs
% elems
== 0);
173 numMicroops
= (regs
> 2) ? 2 : 1;
174 bool wb
= (rm
!= 15);
175 bool deinterleave
= (elems
> 1);
177 if (wb
) numMicroops
++;
178 if (deinterleave
) numMicroops
+= (regs
/ elems
);
179 microOps
= new StaticInstPtr
[numMicroops
];
181 RegIndex rMid
= deinterleave
? NumFloatArchRegs
: vd
* 2;
183 uint32_t noAlign
= TLB::MustBeOne
;
188 microOps
[uopIdx
++] = newNeonMemInst
<MicroLdrNeon16Uop
>(
189 size
, machInst
, rMid
, rn
, 0, align
);
190 microOps
[uopIdx
++] = newNeonMemInst
<MicroLdrNeon16Uop
>(
191 size
, machInst
, rMid
+ 4, rn
, 16, noAlign
);
194 microOps
[uopIdx
++] = newNeonMemInst
<MicroLdrNeon16Uop
>(
195 size
, machInst
, rMid
, rn
, 0, align
);
196 microOps
[uopIdx
++] = newNeonMemInst
<MicroLdrNeon8Uop
>(
197 size
, machInst
, rMid
+ 4, rn
, 16, noAlign
);
200 microOps
[uopIdx
++] = newNeonMemInst
<MicroLdrNeon16Uop
>(
201 size
, machInst
, rMid
, rn
, 0, align
);
204 microOps
[uopIdx
++] = newNeonMemInst
<MicroLdrNeon8Uop
>(
205 size
, machInst
, rMid
, rn
, 0, align
);
208 // Unknown number of registers
209 microOps
[uopIdx
++] = new Unknown(machInst
);
212 if (rm
!= 15 && rm
!= 13) {
214 new MicroAddUop(machInst
, rn
, rn
, rm
, 0, ArmISA::LSL
);
217 new MicroAddiUop(machInst
, rn
, rn
, regs
* 8);
224 microOps
[uopIdx
++] = newNeonMixInst
<MicroDeintNeon8Uop
>(
225 size
, machInst
, vd
* 2, rMid
, inc
* 2);
229 microOps
[uopIdx
++] = newNeonMixInst
<MicroDeintNeon6Uop
>(
230 size
, machInst
, vd
* 2, rMid
, inc
* 2);
233 assert(regs
== 4 || regs
== 2);
235 microOps
[uopIdx
++] = newNeonMixInst
<MicroDeintNeon4Uop
>(
236 size
, machInst
, vd
* 2, rMid
, inc
* 2);
237 microOps
[uopIdx
++] = newNeonMixInst
<MicroDeintNeon4Uop
>(
238 size
, machInst
, vd
* 2 + 2, rMid
+ 4, inc
* 2);
240 microOps
[uopIdx
++] = newNeonMixInst
<MicroDeintNeon4Uop
>(
241 size
, machInst
, vd
* 2, rMid
, inc
* 2);
245 // Bad number of elements to deinterleave
246 microOps
[uopIdx
++] = new Unknown(machInst
);
249 assert(uopIdx
== numMicroops
);
251 for (unsigned i
= 0; i
< numMicroops
- 1; i
++) {
252 MicroOp
* uopPtr
= dynamic_cast<MicroOp
*>(microOps
[i
].get());
254 uopPtr
->setDelayedCommit();
256 microOps
[numMicroops
- 1]->setLastMicroop();
259 VldSingleOp::VldSingleOp(const char *mnem
, ExtMachInst machInst
,
260 OpClass __opClass
, bool all
, unsigned elems
,
261 RegIndex rn
, RegIndex vd
, unsigned regs
,
262 unsigned inc
, uint32_t size
, uint32_t align
,
263 RegIndex rm
, unsigned lane
) :
264 PredMacroOp(mnem
, machInst
, __opClass
)
266 assert(regs
> 0 && regs
<= 4);
267 assert(regs
% elems
== 0);
269 unsigned eBytes
= (1 << size
);
270 unsigned loadSize
= eBytes
* elems
;
271 unsigned loadRegs M5_VAR_USED
= (loadSize
+ sizeof(FloatRegBits
) - 1) /
272 sizeof(FloatRegBits
);
274 assert(loadRegs
> 0 && loadRegs
<= 4);
277 bool wb
= (rm
!= 15);
279 if (wb
) numMicroops
++;
280 numMicroops
+= (regs
/ elems
);
281 microOps
= new StaticInstPtr
[numMicroops
];
283 RegIndex ufp0
= NumFloatArchRegs
;
288 microOps
[uopIdx
++] = new MicroLdrNeon1Uop
<uint8_t>(
289 machInst
, ufp0
, rn
, 0, align
);
293 microOps
[uopIdx
++] = new MicroLdrNeon2Uop
<uint16_t>(
294 machInst
, ufp0
, rn
, 0, align
);
296 microOps
[uopIdx
++] = new MicroLdrNeon2Uop
<uint8_t>(
297 machInst
, ufp0
, rn
, 0, align
);
301 microOps
[uopIdx
++] = new MicroLdrNeon3Uop
<uint8_t>(
302 machInst
, ufp0
, rn
, 0, align
);
307 microOps
[uopIdx
++] = new MicroLdrNeon4Uop
<uint8_t>(
308 machInst
, ufp0
, rn
, 0, align
);
311 microOps
[uopIdx
++] = new MicroLdrNeon4Uop
<uint16_t>(
312 machInst
, ufp0
, rn
, 0, align
);
315 microOps
[uopIdx
++] = new MicroLdrNeon4Uop
<uint32_t>(
316 machInst
, ufp0
, rn
, 0, align
);
321 microOps
[uopIdx
++] = new MicroLdrNeon6Uop
<uint16_t>(
322 machInst
, ufp0
, rn
, 0, align
);
327 microOps
[uopIdx
++] = new MicroLdrNeon8Uop
<uint16_t>(
328 machInst
, ufp0
, rn
, 0, align
);
331 microOps
[uopIdx
++] = new MicroLdrNeon8Uop
<uint32_t>(
332 machInst
, ufp0
, rn
, 0, align
);
337 microOps
[uopIdx
++] = new MicroLdrNeon12Uop
<uint32_t>(
338 machInst
, ufp0
, rn
, 0, align
);
341 microOps
[uopIdx
++] = new MicroLdrNeon16Uop
<uint32_t>(
342 machInst
, ufp0
, rn
, 0, align
);
345 // Unrecognized load size
346 microOps
[uopIdx
++] = new Unknown(machInst
);
349 if (rm
!= 15 && rm
!= 13) {
351 new MicroAddUop(machInst
, rn
, rn
, rm
, 0, ArmISA::LSL
);
354 new MicroAddiUop(machInst
, rn
, rn
, loadSize
);
363 microOps
[uopIdx
++] = new MicroUnpackAllNeon2to8Uop
<uint8_t>(
364 machInst
, vd
* 2, ufp0
, inc
* 2);
366 microOps
[uopIdx
++] = new MicroUnpackNeon2to8Uop
<uint8_t>(
367 machInst
, vd
* 2, ufp0
, inc
* 2, lane
);
372 microOps
[uopIdx
++] = new MicroUnpackAllNeon2to8Uop
<uint16_t>(
373 machInst
, vd
* 2, ufp0
, inc
* 2);
375 microOps
[uopIdx
++] = new MicroUnpackNeon2to8Uop
<uint16_t>(
376 machInst
, vd
* 2, ufp0
, inc
* 2, lane
);
381 microOps
[uopIdx
++] = new MicroUnpackAllNeon4to8Uop
<uint32_t>(
382 machInst
, vd
* 2, ufp0
, inc
* 2);
384 microOps
[uopIdx
++] = new MicroUnpackNeon4to8Uop
<uint32_t>(
385 machInst
, vd
* 2, ufp0
, inc
* 2, lane
);
390 microOps
[uopIdx
++] = new Unknown(machInst
);
399 microOps
[uopIdx
++] = new MicroUnpackAllNeon2to6Uop
<uint8_t>(
400 machInst
, vd
* 2, ufp0
, inc
* 2);
402 microOps
[uopIdx
++] = new MicroUnpackNeon2to6Uop
<uint8_t>(
403 machInst
, vd
* 2, ufp0
, inc
* 2, lane
);
408 microOps
[uopIdx
++] = new MicroUnpackAllNeon2to6Uop
<uint16_t>(
409 machInst
, vd
* 2, ufp0
, inc
* 2);
411 microOps
[uopIdx
++] = new MicroUnpackNeon2to6Uop
<uint16_t>(
412 machInst
, vd
* 2, ufp0
, inc
* 2, lane
);
417 microOps
[uopIdx
++] = new MicroUnpackAllNeon4to6Uop
<uint32_t>(
418 machInst
, vd
* 2, ufp0
, inc
* 2);
420 microOps
[uopIdx
++] = new MicroUnpackNeon4to6Uop
<uint32_t>(
421 machInst
, vd
* 2, ufp0
, inc
* 2, lane
);
426 microOps
[uopIdx
++] = new Unknown(machInst
);
432 assert(loadRegs
<= 2);
436 microOps
[uopIdx
++] = new MicroUnpackAllNeon2to4Uop
<uint8_t>(
437 machInst
, vd
* 2, ufp0
, inc
* 2);
439 microOps
[uopIdx
++] = new MicroUnpackNeon2to4Uop
<uint8_t>(
440 machInst
, vd
* 2, ufp0
, inc
* 2, lane
);
445 microOps
[uopIdx
++] = new MicroUnpackAllNeon2to4Uop
<uint16_t>(
446 machInst
, vd
* 2, ufp0
, inc
* 2);
448 microOps
[uopIdx
++] = new MicroUnpackNeon2to4Uop
<uint16_t>(
449 machInst
, vd
* 2, ufp0
, inc
* 2, lane
);
454 microOps
[uopIdx
++] = new MicroUnpackAllNeon2to4Uop
<uint32_t>(
455 machInst
, vd
* 2, ufp0
, inc
* 2);
457 microOps
[uopIdx
++] = new MicroUnpackNeon2to4Uop
<uint32_t>(
458 machInst
, vd
* 2, ufp0
, inc
* 2, lane
);
463 microOps
[uopIdx
++] = new Unknown(machInst
);
468 assert(regs
== 1 || (all
&& regs
== 2));
469 assert(loadRegs
<= 2);
470 for (unsigned offset
= 0; offset
< regs
; offset
++) {
475 new MicroUnpackAllNeon2to2Uop
<uint8_t>(
476 machInst
, (vd
+ offset
) * 2, ufp0
, inc
* 2);
479 new MicroUnpackNeon2to2Uop
<uint8_t>(
480 machInst
, (vd
+ offset
) * 2, ufp0
, inc
* 2, lane
);
486 new MicroUnpackAllNeon2to2Uop
<uint16_t>(
487 machInst
, (vd
+ offset
) * 2, ufp0
, inc
* 2);
490 new MicroUnpackNeon2to2Uop
<uint16_t>(
491 machInst
, (vd
+ offset
) * 2, ufp0
, inc
* 2, lane
);
497 new MicroUnpackAllNeon2to2Uop
<uint32_t>(
498 machInst
, (vd
+ offset
) * 2, ufp0
, inc
* 2);
501 new MicroUnpackNeon2to2Uop
<uint32_t>(
502 machInst
, (vd
+ offset
) * 2, ufp0
, inc
* 2, lane
);
507 microOps
[uopIdx
++] = new Unknown(machInst
);
513 // Bad number of elements to unpack
514 microOps
[uopIdx
++] = new Unknown(machInst
);
516 assert(uopIdx
== numMicroops
);
518 for (unsigned i
= 0; i
< numMicroops
- 1; i
++) {
519 MicroOp
* uopPtr
= dynamic_cast<MicroOp
*>(microOps
[i
].get());
521 uopPtr
->setDelayedCommit();
523 microOps
[numMicroops
- 1]->setLastMicroop();
526 VstMultOp::VstMultOp(const char *mnem
, ExtMachInst machInst
, OpClass __opClass
,
527 unsigned elems
, RegIndex rn
, RegIndex vd
, unsigned regs
,
528 unsigned inc
, uint32_t size
, uint32_t align
, RegIndex rm
) :
529 PredMacroOp(mnem
, machInst
, __opClass
)
531 assert(regs
> 0 && regs
<= 4);
532 assert(regs
% elems
== 0);
534 numMicroops
= (regs
> 2) ? 2 : 1;
535 bool wb
= (rm
!= 15);
536 bool interleave
= (elems
> 1);
538 if (wb
) numMicroops
++;
539 if (interleave
) numMicroops
+= (regs
/ elems
);
540 microOps
= new StaticInstPtr
[numMicroops
];
542 uint32_t noAlign
= TLB::MustBeOne
;
544 RegIndex rMid
= interleave
? NumFloatArchRegs
: vd
* 2;
551 microOps
[uopIdx
++] = newNeonMixInst
<MicroInterNeon8Uop
>(
552 size
, machInst
, rMid
, vd
* 2, inc
* 2);
556 microOps
[uopIdx
++] = newNeonMixInst
<MicroInterNeon6Uop
>(
557 size
, machInst
, rMid
, vd
* 2, inc
* 2);
560 assert(regs
== 4 || regs
== 2);
562 microOps
[uopIdx
++] = newNeonMixInst
<MicroInterNeon4Uop
>(
563 size
, machInst
, rMid
, vd
* 2, inc
* 2);
564 microOps
[uopIdx
++] = newNeonMixInst
<MicroInterNeon4Uop
>(
565 size
, machInst
, rMid
+ 4, vd
* 2 + 2, inc
* 2);
567 microOps
[uopIdx
++] = newNeonMixInst
<MicroInterNeon4Uop
>(
568 size
, machInst
, rMid
, vd
* 2, inc
* 2);
572 // Bad number of elements to interleave
573 microOps
[uopIdx
++] = new Unknown(machInst
);
578 microOps
[uopIdx
++] = newNeonMemInst
<MicroStrNeon16Uop
>(
579 size
, machInst
, rMid
, rn
, 0, align
);
580 microOps
[uopIdx
++] = newNeonMemInst
<MicroStrNeon16Uop
>(
581 size
, machInst
, rMid
+ 4, rn
, 16, noAlign
);
584 microOps
[uopIdx
++] = newNeonMemInst
<MicroStrNeon16Uop
>(
585 size
, machInst
, rMid
, rn
, 0, align
);
586 microOps
[uopIdx
++] = newNeonMemInst
<MicroStrNeon8Uop
>(
587 size
, machInst
, rMid
+ 4, rn
, 16, noAlign
);
590 microOps
[uopIdx
++] = newNeonMemInst
<MicroStrNeon16Uop
>(
591 size
, machInst
, rMid
, rn
, 0, align
);
594 microOps
[uopIdx
++] = newNeonMemInst
<MicroStrNeon8Uop
>(
595 size
, machInst
, rMid
, rn
, 0, align
);
598 // Unknown number of registers
599 microOps
[uopIdx
++] = new Unknown(machInst
);
602 if (rm
!= 15 && rm
!= 13) {
604 new MicroAddUop(machInst
, rn
, rn
, rm
, 0, ArmISA::LSL
);
607 new MicroAddiUop(machInst
, rn
, rn
, regs
* 8);
610 assert(uopIdx
== numMicroops
);
612 for (unsigned i
= 0; i
< numMicroops
- 1; i
++) {
613 MicroOp
* uopPtr
= dynamic_cast<MicroOp
*>(microOps
[i
].get());
615 uopPtr
->setDelayedCommit();
617 microOps
[numMicroops
- 1]->setLastMicroop();
620 VstSingleOp::VstSingleOp(const char *mnem
, ExtMachInst machInst
,
621 OpClass __opClass
, bool all
, unsigned elems
,
622 RegIndex rn
, RegIndex vd
, unsigned regs
,
623 unsigned inc
, uint32_t size
, uint32_t align
,
624 RegIndex rm
, unsigned lane
) :
625 PredMacroOp(mnem
, machInst
, __opClass
)
628 assert(regs
> 0 && regs
<= 4);
629 assert(regs
% elems
== 0);
631 unsigned eBytes
= (1 << size
);
632 unsigned storeSize
= eBytes
* elems
;
633 unsigned storeRegs M5_VAR_USED
= (storeSize
+ sizeof(FloatRegBits
) - 1) /
634 sizeof(FloatRegBits
);
636 assert(storeRegs
> 0 && storeRegs
<= 4);
639 bool wb
= (rm
!= 15);
641 if (wb
) numMicroops
++;
642 numMicroops
+= (regs
/ elems
);
643 microOps
= new StaticInstPtr
[numMicroops
];
645 RegIndex ufp0
= NumFloatArchRegs
;
653 microOps
[uopIdx
++] = new MicroPackNeon8to2Uop
<uint8_t>(
654 machInst
, ufp0
, vd
* 2, inc
* 2, lane
);
657 microOps
[uopIdx
++] = new MicroPackNeon8to2Uop
<uint16_t>(
658 machInst
, ufp0
, vd
* 2, inc
* 2, lane
);
661 microOps
[uopIdx
++] = new MicroPackNeon8to4Uop
<uint32_t>(
662 machInst
, ufp0
, vd
* 2, inc
* 2, lane
);
666 microOps
[uopIdx
++] = new Unknown(machInst
);
674 microOps
[uopIdx
++] = new MicroPackNeon6to2Uop
<uint8_t>(
675 machInst
, ufp0
, vd
* 2, inc
* 2, lane
);
678 microOps
[uopIdx
++] = new MicroPackNeon6to2Uop
<uint16_t>(
679 machInst
, ufp0
, vd
* 2, inc
* 2, lane
);
682 microOps
[uopIdx
++] = new MicroPackNeon6to4Uop
<uint32_t>(
683 machInst
, ufp0
, vd
* 2, inc
* 2, lane
);
687 microOps
[uopIdx
++] = new Unknown(machInst
);
693 assert(storeRegs
<= 2);
696 microOps
[uopIdx
++] = new MicroPackNeon4to2Uop
<uint8_t>(
697 machInst
, ufp0
, vd
* 2, inc
* 2, lane
);
700 microOps
[uopIdx
++] = new MicroPackNeon4to2Uop
<uint16_t>(
701 machInst
, ufp0
, vd
* 2, inc
* 2, lane
);
704 microOps
[uopIdx
++] = new MicroPackNeon4to2Uop
<uint32_t>(
705 machInst
, ufp0
, vd
* 2, inc
* 2, lane
);
709 microOps
[uopIdx
++] = new Unknown(machInst
);
714 assert(regs
== 1 || (all
&& regs
== 2));
715 assert(storeRegs
<= 2);
716 for (unsigned offset
= 0; offset
< regs
; offset
++) {
719 microOps
[uopIdx
++] = new MicroPackNeon2to2Uop
<uint8_t>(
720 machInst
, ufp0
, (vd
+ offset
) * 2, inc
* 2, lane
);
723 microOps
[uopIdx
++] = new MicroPackNeon2to2Uop
<uint16_t>(
724 machInst
, ufp0
, (vd
+ offset
) * 2, inc
* 2, lane
);
727 microOps
[uopIdx
++] = new MicroPackNeon2to2Uop
<uint32_t>(
728 machInst
, ufp0
, (vd
+ offset
) * 2, inc
* 2, lane
);
732 microOps
[uopIdx
++] = new Unknown(machInst
);
738 // Bad number of elements to unpack
739 microOps
[uopIdx
++] = new Unknown(machInst
);
743 microOps
[uopIdx
++] = new MicroStrNeon1Uop
<uint8_t>(
744 machInst
, ufp0
, rn
, 0, align
);
748 microOps
[uopIdx
++] = new MicroStrNeon2Uop
<uint16_t>(
749 machInst
, ufp0
, rn
, 0, align
);
751 microOps
[uopIdx
++] = new MicroStrNeon2Uop
<uint8_t>(
752 machInst
, ufp0
, rn
, 0, align
);
756 microOps
[uopIdx
++] = new MicroStrNeon3Uop
<uint8_t>(
757 machInst
, ufp0
, rn
, 0, align
);
762 microOps
[uopIdx
++] = new MicroStrNeon4Uop
<uint8_t>(
763 machInst
, ufp0
, rn
, 0, align
);
766 microOps
[uopIdx
++] = new MicroStrNeon4Uop
<uint16_t>(
767 machInst
, ufp0
, rn
, 0, align
);
770 microOps
[uopIdx
++] = new MicroStrNeon4Uop
<uint32_t>(
771 machInst
, ufp0
, rn
, 0, align
);
776 microOps
[uopIdx
++] = new MicroStrNeon6Uop
<uint16_t>(
777 machInst
, ufp0
, rn
, 0, align
);
782 microOps
[uopIdx
++] = new MicroStrNeon8Uop
<uint16_t>(
783 machInst
, ufp0
, rn
, 0, align
);
786 microOps
[uopIdx
++] = new MicroStrNeon8Uop
<uint32_t>(
787 machInst
, ufp0
, rn
, 0, align
);
792 microOps
[uopIdx
++] = new MicroStrNeon12Uop
<uint32_t>(
793 machInst
, ufp0
, rn
, 0, align
);
796 microOps
[uopIdx
++] = new MicroStrNeon16Uop
<uint32_t>(
797 machInst
, ufp0
, rn
, 0, align
);
801 microOps
[uopIdx
++] = new Unknown(machInst
);
804 if (rm
!= 15 && rm
!= 13) {
806 new MicroAddUop(machInst
, rn
, rn
, rm
, 0, ArmISA::LSL
);
809 new MicroAddiUop(machInst
, rn
, rn
, storeSize
);
812 assert(uopIdx
== numMicroops
);
814 for (unsigned i
= 0; i
< numMicroops
- 1; i
++) {
815 MicroOp
* uopPtr
= dynamic_cast<MicroOp
*>(microOps
[i
].get());
817 uopPtr
->setDelayedCommit();
819 microOps
[numMicroops
- 1]->setLastMicroop();
822 MacroVFPMemOp::MacroVFPMemOp(const char *mnem
, ExtMachInst machInst
,
823 OpClass __opClass
, IntRegIndex rn
,
824 RegIndex vd
, bool single
, bool up
,
825 bool writeback
, bool load
, uint32_t offset
) :
826 PredMacroOp(mnem
, machInst
, __opClass
)
830 // The lowest order bit selects fldmx (set) or fldmd (clear). These seem
831 // to be functionally identical except that fldmx is deprecated. For now
832 // we'll assume they're otherwise interchangable.
833 int count
= (single
? offset
: (offset
/ 2));
834 if (count
== 0 || count
> NumFloatArchRegs
)
835 warn_once("Bad offset field for VFP load/store multiple.\n");
837 // Force there to be at least one microop so the macroop makes sense.
840 if (count
> NumFloatArchRegs
)
841 count
= NumFloatArchRegs
;
843 numMicroops
= count
* (single
? 1 : 2) + (writeback
? 1 : 0);
844 microOps
= new StaticInstPtr
[numMicroops
];
852 for (int j
= 0; j
< count
; j
++) {
855 microOps
[i
++] = new MicroLdrFpUop(machInst
, vd
++, rn
,
858 microOps
[i
++] = new MicroLdrDBFpUop(machInst
, vd
++, rn
,
860 microOps
[i
++] = new MicroLdrDTFpUop(machInst
, vd
++, rn
, tempUp
,
861 addr
+ (up
? 4 : -4));
865 microOps
[i
++] = new MicroStrFpUop(machInst
, vd
++, rn
,
868 microOps
[i
++] = new MicroStrDBFpUop(machInst
, vd
++, rn
,
870 microOps
[i
++] = new MicroStrDTFpUop(machInst
, vd
++, rn
, tempUp
,
871 addr
+ (up
? 4 : -4));
875 addr
-= (single
? 4 : 8);
876 // The microops don't handle negative displacement, so turn if we
877 // hit zero, flip polarity and start adding.
883 addr
+= (single
? 4 : 8);
890 new MicroAddiUop(machInst
, rn
, rn
, 4 * offset
);
893 new MicroSubiUop(machInst
, rn
, rn
, 4 * offset
);
897 assert(numMicroops
== i
);
898 microOps
[numMicroops
- 1]->setLastMicroop();
900 for (StaticInstPtr
*curUop
= microOps
;
901 !(*curUop
)->isLastMicroop(); curUop
++) {
902 MicroOp
* uopPtr
= dynamic_cast<MicroOp
*>(curUop
->get());
904 uopPtr
->setDelayedCommit();
909 MicroIntImmOp::generateDisassembly(Addr pc
, const SymbolTable
*symtab
) const
911 std::stringstream ss
;
917 ccprintf(ss
, "#%d", imm
);
922 MicroSetPCCPSR::generateDisassembly(Addr pc
, const SymbolTable
*symtab
) const
924 std::stringstream ss
;
931 MicroIntMov::generateDisassembly(Addr pc
, const SymbolTable
*symtab
) const
933 std::stringstream ss
;
942 MicroIntOp::generateDisassembly(Addr pc
, const SymbolTable
*symtab
) const
944 std::stringstream ss
;
955 MicroMemOp::generateDisassembly(Addr pc
, const SymbolTable
*symtab
) const
957 std::stringstream ss
;
963 ccprintf(ss
, "#%d", imm
);