static_inst.cc (11514:eb53b59ea625) static_inst.cc (11793:ef606668d247)
1/*
2 * Copyright (c) 2010-2014, 2016 ARM Limited
3 * Copyright (c) 2013 Advanced Micro Devices, Inc.
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 * Copyright (c) 2007-2008 The Florida State University
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Authors: Stephen Hines
42 */
43
44#include "arch/arm/insts/static_inst.hh"
1/*
2 * Copyright (c) 2010-2014, 2016 ARM Limited
3 * Copyright (c) 2013 Advanced Micro Devices, Inc.
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 * Copyright (c) 2007-2008 The Florida State University
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Authors: Stephen Hines
42 */
43
44#include "arch/arm/insts/static_inst.hh"
45
45#include "arch/arm/faults.hh"
46#include "arch/arm/faults.hh"
46#include "base/loader/symtab.hh"
47#include "base/condcodes.hh"
48#include "base/cprintf.hh"
47#include "base/condcodes.hh"
48#include "base/cprintf.hh"
49#include "base/loader/symtab.hh"
49#include "cpu/reg_class.hh"
50
51namespace ArmISA
52{
53// Shift Rm by an immediate value
54int32_t
55ArmStaticInst::shift_rm_imm(uint32_t base, uint32_t shamt,
56 uint32_t type, uint32_t cfval) const
57{
58 assert(shamt < 32);
59 ArmShiftType shiftType;
60 shiftType = (ArmShiftType)type;
61
62 switch (shiftType)
63 {
64 case LSL:
65 return base << shamt;
66 case LSR:
67 if (shamt == 0)
68 return 0;
69 else
70 return base >> shamt;
71 case ASR:
72 if (shamt == 0)
73 return (base >> 31) | -((base & (1 << 31)) >> 31);
74 else
75 return (base >> shamt) | -((base & (1 << 31)) >> shamt);
76 case ROR:
77 if (shamt == 0)
78 return (cfval << 31) | (base >> 1); // RRX
79 else
80 return (base << (32 - shamt)) | (base >> shamt);
81 default:
82 ccprintf(std::cerr, "Unhandled shift type\n");
83 exit(1);
84 break;
85 }
86 return 0;
87}
88
89int64_t
90ArmStaticInst::shiftReg64(uint64_t base, uint64_t shiftAmt,
91 ArmShiftType type, uint8_t width) const
92{
93 shiftAmt = shiftAmt % width;
94 ArmShiftType shiftType;
95 shiftType = (ArmShiftType)type;
96
97 switch (shiftType)
98 {
99 case LSL:
100 return base << shiftAmt;
101 case LSR:
102 if (shiftAmt == 0)
103 return base;
104 else
105 return (base & mask(width)) >> shiftAmt;
106 case ASR:
107 if (shiftAmt == 0) {
108 return base;
109 } else {
110 int sign_bit = bits(base, intWidth - 1);
111 base >>= shiftAmt;
112 base = sign_bit ? (base | ~mask(intWidth - shiftAmt)) : base;
113 return base & mask(intWidth);
114 }
115 case ROR:
116 if (shiftAmt == 0)
117 return base;
118 else
119 return (base << (width - shiftAmt)) | (base >> shiftAmt);
120 default:
121 ccprintf(std::cerr, "Unhandled shift type\n");
122 exit(1);
123 break;
124 }
125 return 0;
126}
127
128int64_t
129ArmStaticInst::extendReg64(uint64_t base, ArmExtendType type,
130 uint64_t shiftAmt, uint8_t width) const
131{
132 bool sign_extend = false;
133 int len = 0;
134 switch (type) {
135 case UXTB:
136 len = 8;
137 break;
138 case UXTH:
139 len = 16;
140 break;
141 case UXTW:
142 len = 32;
143 break;
144 case UXTX:
145 len = 64;
146 break;
147 case SXTB:
148 len = 8;
149 sign_extend = true;
150 break;
151 case SXTH:
152 len = 16;
153 sign_extend = true;
154 break;
155 case SXTW:
156 len = 32;
157 sign_extend = true;
158 break;
159 case SXTX:
160 len = 64;
161 sign_extend = true;
162 break;
163 }
164 len = len <= width - shiftAmt ? len : width - shiftAmt;
165 uint64_t tmp = (uint64_t) bits(base, len - 1, 0) << shiftAmt;
166 if (sign_extend) {
167 int sign_bit = bits(tmp, len + shiftAmt - 1);
168 tmp = sign_bit ? (tmp | ~mask(len + shiftAmt)) : tmp;
169 }
170 return tmp & mask(width);
171}
172
173// Shift Rm by Rs
174int32_t
175ArmStaticInst::shift_rm_rs(uint32_t base, uint32_t shamt,
176 uint32_t type, uint32_t cfval) const
177{
178 enum ArmShiftType shiftType;
179 shiftType = (enum ArmShiftType) type;
180
181 switch (shiftType)
182 {
183 case LSL:
184 if (shamt >= 32)
185 return 0;
186 else
187 return base << shamt;
188 case LSR:
189 if (shamt >= 32)
190 return 0;
191 else
192 return base >> shamt;
193 case ASR:
194 if (shamt >= 32)
195 return (base >> 31) | -((base & (1 << 31)) >> 31);
196 else
197 return (base >> shamt) | -((base & (1 << 31)) >> shamt);
198 case ROR:
199 shamt = shamt & 0x1f;
200 if (shamt == 0)
201 return base;
202 else
203 return (base << (32 - shamt)) | (base >> shamt);
204 default:
205 ccprintf(std::cerr, "Unhandled shift type\n");
206 exit(1);
207 break;
208 }
209 return 0;
210}
211
212
213// Generate C for a shift by immediate
214bool
215ArmStaticInst::shift_carry_imm(uint32_t base, uint32_t shamt,
216 uint32_t type, uint32_t cfval) const
217{
218 enum ArmShiftType shiftType;
219 shiftType = (enum ArmShiftType) type;
220
221 switch (shiftType)
222 {
223 case LSL:
224 if (shamt == 0)
225 return cfval;
226 else
227 return (base >> (32 - shamt)) & 1;
228 case LSR:
229 if (shamt == 0)
230 return (base >> 31);
231 else
232 return (base >> (shamt - 1)) & 1;
233 case ASR:
234 if (shamt == 0)
235 return (base >> 31);
236 else
237 return (base >> (shamt - 1)) & 1;
238 case ROR:
239 shamt = shamt & 0x1f;
240 if (shamt == 0)
241 return (base & 1); // RRX
242 else
243 return (base >> (shamt - 1)) & 1;
244 default:
245 ccprintf(std::cerr, "Unhandled shift type\n");
246 exit(1);
247 break;
248 }
249 return 0;
250}
251
252
253// Generate C for a shift by Rs
254bool
255ArmStaticInst::shift_carry_rs(uint32_t base, uint32_t shamt,
256 uint32_t type, uint32_t cfval) const
257{
258 enum ArmShiftType shiftType;
259 shiftType = (enum ArmShiftType) type;
260
261 if (shamt == 0)
262 return cfval;
263
264 switch (shiftType)
265 {
266 case LSL:
267 if (shamt > 32)
268 return 0;
269 else
270 return (base >> (32 - shamt)) & 1;
271 case LSR:
272 if (shamt > 32)
273 return 0;
274 else
275 return (base >> (shamt - 1)) & 1;
276 case ASR:
277 if (shamt > 32)
278 shamt = 32;
279 return (base >> (shamt - 1)) & 1;
280 case ROR:
281 shamt = shamt & 0x1f;
282 if (shamt == 0)
283 shamt = 32;
284 return (base >> (shamt - 1)) & 1;
285 default:
286 ccprintf(std::cerr, "Unhandled shift type\n");
287 exit(1);
288 break;
289 }
290 return 0;
291}
292
293
294void
295ArmStaticInst::printReg(std::ostream &os, int reg) const
296{
297 RegIndex rel_reg;
298
299 switch (regIdxToClass(reg, &rel_reg)) {
300 case IntRegClass:
301 if (aarch64) {
302 if (reg == INTREG_UREG0)
303 ccprintf(os, "ureg0");
304 else if (reg == INTREG_SPX)
305 ccprintf(os, "%s%s", (intWidth == 32) ? "w" : "", "sp");
306 else if (reg == INTREG_X31)
307 ccprintf(os, "%szr", (intWidth == 32) ? "w" : "x");
308 else
309 ccprintf(os, "%s%d", (intWidth == 32) ? "w" : "x", reg);
310 } else {
311 switch (rel_reg) {
312 case PCReg:
313 ccprintf(os, "pc");
314 break;
315 case StackPointerReg:
316 ccprintf(os, "sp");
317 break;
318 case FramePointerReg:
319 ccprintf(os, "fp");
320 break;
321 case ReturnAddressReg:
322 ccprintf(os, "lr");
323 break;
324 default:
325 ccprintf(os, "r%d", reg);
326 break;
327 }
328 }
329 break;
330 case FloatRegClass:
331 ccprintf(os, "f%d", rel_reg);
332 break;
333 case MiscRegClass:
334 assert(rel_reg < NUM_MISCREGS);
335 ccprintf(os, "%s", ArmISA::miscRegName[rel_reg]);
336 break;
337 case CCRegClass:
338 ccprintf(os, "cc_%s", ArmISA::ccRegName[rel_reg]);
339 break;
340 }
341}
342
343void
344ArmStaticInst::printMnemonic(std::ostream &os,
345 const std::string &suffix,
346 bool withPred,
347 bool withCond64,
348 ConditionCode cond64) const
349{
350 os << " " << mnemonic;
351 if (withPred && !aarch64) {
352 printCondition(os, machInst.condCode);
353 os << suffix;
354 } else if (withCond64) {
355 os << ".";
356 printCondition(os, cond64);
357 os << suffix;
358 }
359 if (machInst.bigThumb)
360 os << ".w";
361 os << " ";
362}
363
364void
365ArmStaticInst::printTarget(std::ostream &os, Addr target,
366 const SymbolTable *symtab) const
367{
368 Addr symbolAddr;
369 std::string symbol;
370
371 if (symtab && symtab->findNearestSymbol(target, symbol, symbolAddr)) {
372 ccprintf(os, "<%s", symbol);
373 if (symbolAddr != target)
374 ccprintf(os, "+%d>", target - symbolAddr);
375 else
376 ccprintf(os, ">");
377 } else {
378 ccprintf(os, "%#x", target);
379 }
380}
381
382void
383ArmStaticInst::printCondition(std::ostream &os,
384 unsigned code,
385 bool noImplicit) const
386{
387 switch (code) {
388 case COND_EQ:
389 os << "eq";
390 break;
391 case COND_NE:
392 os << "ne";
393 break;
394 case COND_CS:
395 os << "cs";
396 break;
397 case COND_CC:
398 os << "cc";
399 break;
400 case COND_MI:
401 os << "mi";
402 break;
403 case COND_PL:
404 os << "pl";
405 break;
406 case COND_VS:
407 os << "vs";
408 break;
409 case COND_VC:
410 os << "vc";
411 break;
412 case COND_HI:
413 os << "hi";
414 break;
415 case COND_LS:
416 os << "ls";
417 break;
418 case COND_GE:
419 os << "ge";
420 break;
421 case COND_LT:
422 os << "lt";
423 break;
424 case COND_GT:
425 os << "gt";
426 break;
427 case COND_LE:
428 os << "le";
429 break;
430 case COND_AL:
431 // This one is implicit.
432 if (noImplicit)
433 os << "al";
434 break;
435 case COND_UC:
436 // Unconditional.
437 if (noImplicit)
438 os << "uc";
439 break;
440 default:
441 panic("Unrecognized condition code %d.\n", code);
442 }
443}
444
445void
446ArmStaticInst::printMemSymbol(std::ostream &os,
447 const SymbolTable *symtab,
448 const std::string &prefix,
449 const Addr addr,
450 const std::string &suffix) const
451{
452 Addr symbolAddr;
453 std::string symbol;
454 if (symtab && symtab->findNearestSymbol(addr, symbol, symbolAddr)) {
455 ccprintf(os, "%s%s", prefix, symbol);
456 if (symbolAddr != addr)
457 ccprintf(os, "+%d", addr - symbolAddr);
458 ccprintf(os, suffix);
459 }
460}
461
462void
463ArmStaticInst::printShiftOperand(std::ostream &os,
464 IntRegIndex rm,
465 bool immShift,
466 uint32_t shiftAmt,
467 IntRegIndex rs,
468 ArmShiftType type) const
469{
470 bool firstOp = false;
471
472 if (rm != INTREG_ZERO) {
473 printReg(os, rm);
474 }
475
476 bool done = false;
477
478 if ((type == LSR || type == ASR) && immShift && shiftAmt == 0)
479 shiftAmt = 32;
480
481 switch (type) {
482 case LSL:
483 if (immShift && shiftAmt == 0) {
484 done = true;
485 break;
486 }
487 if (!firstOp)
488 os << ", ";
489 os << "LSL";
490 break;
491 case LSR:
492 if (!firstOp)
493 os << ", ";
494 os << "LSR";
495 break;
496 case ASR:
497 if (!firstOp)
498 os << ", ";
499 os << "ASR";
500 break;
501 case ROR:
502 if (immShift && shiftAmt == 0) {
503 if (!firstOp)
504 os << ", ";
505 os << "RRX";
506 done = true;
507 break;
508 }
509 if (!firstOp)
510 os << ", ";
511 os << "ROR";
512 break;
513 default:
514 panic("Tried to disassemble unrecognized shift type.\n");
515 }
516 if (!done) {
517 if (!firstOp)
518 os << " ";
519 if (immShift)
520 os << "#" << shiftAmt;
521 else
522 printReg(os, rs);
523 }
524}
525
526void
527ArmStaticInst::printExtendOperand(bool firstOperand, std::ostream &os,
528 IntRegIndex rm, ArmExtendType type,
529 int64_t shiftAmt) const
530{
531 if (!firstOperand)
532 ccprintf(os, ", ");
533 printReg(os, rm);
534 if (type == UXTX && shiftAmt == 0)
535 return;
536 switch (type) {
537 case UXTB: ccprintf(os, ", UXTB");
538 break;
539 case UXTH: ccprintf(os, ", UXTH");
540 break;
541 case UXTW: ccprintf(os, ", UXTW");
542 break;
543 case UXTX: ccprintf(os, ", LSL");
544 break;
545 case SXTB: ccprintf(os, ", SXTB");
546 break;
547 case SXTH: ccprintf(os, ", SXTH");
548 break;
549 case SXTW: ccprintf(os, ", SXTW");
550 break;
551 case SXTX: ccprintf(os, ", SXTW");
552 break;
553 }
554 if (type == UXTX || shiftAmt)
555 ccprintf(os, " #%d", shiftAmt);
556}
557
558void
559ArmStaticInst::printDataInst(std::ostream &os, bool withImm,
560 bool immShift, bool s, IntRegIndex rd, IntRegIndex rn,
561 IntRegIndex rm, IntRegIndex rs, uint32_t shiftAmt,
562 ArmShiftType type, uint64_t imm) const
563{
564 printMnemonic(os, s ? "s" : "");
565 bool firstOp = true;
566
567 // Destination
568 if (rd != INTREG_ZERO) {
569 firstOp = false;
570 printReg(os, rd);
571 }
572
573 // Source 1.
574 if (rn != INTREG_ZERO) {
575 if (!firstOp)
576 os << ", ";
577 firstOp = false;
578 printReg(os, rn);
579 }
580
581 if (!firstOp)
582 os << ", ";
583 if (withImm) {
584 ccprintf(os, "#%ld", imm);
585 } else {
586 printShiftOperand(os, rm, immShift, shiftAmt, rs, type);
587 }
588}
589
590std::string
591ArmStaticInst::generateDisassembly(Addr pc,
592 const SymbolTable *symtab) const
593{
594 std::stringstream ss;
595 printMnemonic(ss);
596 return ss.str();
597}
598
599
600Fault
601ArmStaticInst::advSIMDFPAccessTrap64(ExceptionLevel el) const
602{
603 switch (el) {
604 case EL1:
605 return std::make_shared<SupervisorTrap>(machInst, 0x1E00000,
606 EC_TRAPPED_SIMD_FP);
607 case EL2:
608 return std::make_shared<HypervisorTrap>(machInst, 0x1E00000,
609 EC_TRAPPED_SIMD_FP);
610 case EL3:
611 return std::make_shared<SecureMonitorTrap>(machInst, 0x1E00000,
612 EC_TRAPPED_SIMD_FP);
613
614 default:
615 panic("Illegal EL in advSIMDFPAccessTrap64\n");
616 }
617}
618
619
620Fault
621ArmStaticInst::checkFPAdvSIMDTrap64(ThreadContext *tc, CPSR cpsr) const
622{
623 const ExceptionLevel el = (ExceptionLevel) (uint8_t)cpsr.el;
624
625 if (ArmSystem::haveVirtualization(tc) && el <= EL2) {
626 HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL2);
627 if (cptrEnCheck.tfp)
628 return advSIMDFPAccessTrap64(EL2);
629 }
630
631 if (ArmSystem::haveSecurity(tc)) {
632 HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL3);
633 if (cptrEnCheck.tfp)
634 return advSIMDFPAccessTrap64(EL3);
635 }
636
637 return NoFault;
638}
639
640Fault
641ArmStaticInst::checkFPAdvSIMDEnabled64(ThreadContext *tc,
642 CPSR cpsr, CPACR cpacr) const
643{
644 const ExceptionLevel el = (ExceptionLevel) (uint8_t)cpsr.el;
645 if ((el == EL0 && cpacr.fpen != 0x3) ||
646 (el == EL1 && !(cpacr.fpen & 0x1)))
647 return advSIMDFPAccessTrap64(EL1);
648
649 return checkFPAdvSIMDTrap64(tc, cpsr);
650}
651
652Fault
653ArmStaticInst::checkAdvSIMDOrFPEnabled32(ThreadContext *tc,
654 CPSR cpsr, CPACR cpacr,
655 NSACR nsacr, FPEXC fpexc,
656 bool fpexc_check, bool advsimd) const
657{
658 const bool have_virtualization = ArmSystem::haveVirtualization(tc);
659 const bool have_security = ArmSystem::haveSecurity(tc);
660 const bool is_secure = inSecureState(tc);
661 const ExceptionLevel cur_el = opModeToEL(currOpMode(tc));
662
663 if (cur_el == EL0 && ELIs64(tc, EL1))
664 return checkFPAdvSIMDEnabled64(tc, cpsr, cpacr);
665
666 uint8_t cpacr_cp10 = cpacr.cp10;
667 bool cpacr_asedis = cpacr.asedis;
668
669 if (have_security && !ELIs64(tc, EL3) && !is_secure) {
670 if (nsacr.nsasedis)
671 cpacr_asedis = true;
672 if (nsacr.cp10 == 0)
673 cpacr_cp10 = 0;
674 }
675
676 if (cur_el != EL2) {
677 if (advsimd && cpacr_asedis)
678 return disabledFault();
679
680 if ((cur_el == EL0 && cpacr_cp10 != 0x3) ||
681 (cur_el != EL0 && !(cpacr_cp10 & 0x1)))
682 return disabledFault();
683 }
684
685 if (fpexc_check && !fpexc.en)
686 return disabledFault();
687
688 // -- aarch32/exceptions/traps/AArch32.CheckFPAdvSIMDTrap --
689
690 if (have_virtualization && !is_secure && ELIs64(tc, EL2))
691 return checkFPAdvSIMDTrap64(tc, cpsr);
692
693 if (have_virtualization && !is_secure) {
694 HCPTR hcptr = tc->readMiscReg(MISCREG_HCPTR);
695 bool hcptr_cp10 = hcptr.tcp10;
696 bool hcptr_tase = hcptr.tase;
697
698 if (have_security && !ELIs64(tc, EL3) && !is_secure) {
699 if (nsacr.nsasedis)
700 hcptr_tase = true;
701 if (nsacr.cp10)
702 hcptr_cp10 = true;
703 }
704
705 if ((advsimd && hcptr_tase) || hcptr_cp10) {
706 const uint32_t iss = advsimd ? (1 << 5) : 0xA;
707 if (cur_el == EL2) {
708 return std::make_shared<UndefinedInstruction>(
709 machInst, iss,
710 EC_TRAPPED_HCPTR, mnemonic);
711 } else {
712 return std::make_shared<HypervisorTrap>(
713 machInst, iss,
714 EC_TRAPPED_HCPTR);
715 }
716
717 }
718 }
719
720 if (have_security && ELIs64(tc, EL3)) {
721 HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL3);
722 if (cptrEnCheck.tfp)
723 return advSIMDFPAccessTrap64(EL3);
724 }
725
726 return NoFault;
727}
728
729
730static uint8_t
731getRestoredITBits(ThreadContext *tc, CPSR spsr)
732{
733 // See: shared/functions/system/RestoredITBits in the ARM ARM
734
735 const ExceptionLevel el = opModeToEL((OperatingMode) (uint8_t)spsr.mode);
736 const uint8_t it = itState(spsr);
737
738 if (!spsr.t || spsr.il)
739 return 0;
740
741 // The IT bits are forced to zero when they are set to a reserved
742 // value.
743 if (bits(it, 7, 4) != 0 && bits(it, 3, 0) == 0)
744 return 0;
745
746 const bool itd = el == EL2 ?
747 ((SCTLR)tc->readMiscReg(MISCREG_HSCTLR)).itd :
748 ((SCTLR)tc->readMiscReg(MISCREG_SCTLR)).itd;
749
750 // The IT bits are forced to zero when returning to A32 state, or
751 // when returning to an EL with the ITD bit set to 1, and the IT
752 // bits are describing a multi-instruction block.
753 if (itd && bits(it, 2, 0) != 0)
754 return 0;
755
756 return it;
757}
758
759static bool
760illegalExceptionReturn(ThreadContext *tc, CPSR cpsr, CPSR spsr)
761{
762 const OperatingMode mode = (OperatingMode) (uint8_t)spsr.mode;
763 if (badMode(mode))
764 return true;
765
766 const OperatingMode cur_mode = (OperatingMode) (uint8_t)cpsr.mode;
767 const ExceptionLevel target_el = opModeToEL(mode);
768 if (target_el > opModeToEL(cur_mode))
769 return true;
770
771 if (target_el == EL3 && !ArmSystem::haveSecurity(tc))
772 return true;
773
774 if (target_el == EL2 && !ArmSystem::haveVirtualization(tc))
775 return true;
776
777 if (!spsr.width) {
778 // aarch64
779 if (!ArmSystem::highestELIs64(tc))
780 return true;
781
782 if (spsr & 0x2)
783 return true;
784 if (target_el == EL0 && spsr.sp)
785 return true;
786 if (target_el == EL2 && !((SCR)tc->readMiscReg(MISCREG_SCR_EL3)).ns)
787 return false;
788 } else {
789 return badMode32(mode);
790 }
791
792 return false;
793}
794
795CPSR
796ArmStaticInst::getPSTATEFromPSR(ThreadContext *tc, CPSR cpsr, CPSR spsr) const
797{
798 CPSR new_cpsr = 0;
799
800 // gem5 doesn't implement single-stepping, so force the SS bit to
801 // 0.
802 new_cpsr.ss = 0;
803
804 if (illegalExceptionReturn(tc, cpsr, spsr)) {
805 new_cpsr.il = 1;
806 } else {
807 new_cpsr.il = spsr.il;
808 if (spsr.width && badMode32((OperatingMode)(uint8_t)spsr.mode)) {
809 new_cpsr.il = 1;
810 } else if (spsr.width) {
811 new_cpsr.mode = spsr.mode;
812 } else {
813 new_cpsr.el = spsr.el;
814 new_cpsr.sp = spsr.sp;
815 }
816 }
817
818 new_cpsr.nz = spsr.nz;
819 new_cpsr.c = spsr.c;
820 new_cpsr.v = spsr.v;
821 if (new_cpsr.width) {
822 // aarch32
823 const ITSTATE it = getRestoredITBits(tc, spsr);
824 new_cpsr.q = spsr.q;
825 new_cpsr.ge = spsr.ge;
826 new_cpsr.e = spsr.e;
827 new_cpsr.aif = spsr.aif;
828 new_cpsr.t = spsr.t;
829 new_cpsr.it2 = it.top6;
830 new_cpsr.it1 = it.bottom2;
831 } else {
832 // aarch64
833 new_cpsr.daif = spsr.daif;
834 }
835
836 return new_cpsr;
837}
838
839
840
841}
50#include "cpu/reg_class.hh"
51
52namespace ArmISA
53{
54// Shift Rm by an immediate value
55int32_t
56ArmStaticInst::shift_rm_imm(uint32_t base, uint32_t shamt,
57 uint32_t type, uint32_t cfval) const
58{
59 assert(shamt < 32);
60 ArmShiftType shiftType;
61 shiftType = (ArmShiftType)type;
62
63 switch (shiftType)
64 {
65 case LSL:
66 return base << shamt;
67 case LSR:
68 if (shamt == 0)
69 return 0;
70 else
71 return base >> shamt;
72 case ASR:
73 if (shamt == 0)
74 return (base >> 31) | -((base & (1 << 31)) >> 31);
75 else
76 return (base >> shamt) | -((base & (1 << 31)) >> shamt);
77 case ROR:
78 if (shamt == 0)
79 return (cfval << 31) | (base >> 1); // RRX
80 else
81 return (base << (32 - shamt)) | (base >> shamt);
82 default:
83 ccprintf(std::cerr, "Unhandled shift type\n");
84 exit(1);
85 break;
86 }
87 return 0;
88}
89
90int64_t
91ArmStaticInst::shiftReg64(uint64_t base, uint64_t shiftAmt,
92 ArmShiftType type, uint8_t width) const
93{
94 shiftAmt = shiftAmt % width;
95 ArmShiftType shiftType;
96 shiftType = (ArmShiftType)type;
97
98 switch (shiftType)
99 {
100 case LSL:
101 return base << shiftAmt;
102 case LSR:
103 if (shiftAmt == 0)
104 return base;
105 else
106 return (base & mask(width)) >> shiftAmt;
107 case ASR:
108 if (shiftAmt == 0) {
109 return base;
110 } else {
111 int sign_bit = bits(base, intWidth - 1);
112 base >>= shiftAmt;
113 base = sign_bit ? (base | ~mask(intWidth - shiftAmt)) : base;
114 return base & mask(intWidth);
115 }
116 case ROR:
117 if (shiftAmt == 0)
118 return base;
119 else
120 return (base << (width - shiftAmt)) | (base >> shiftAmt);
121 default:
122 ccprintf(std::cerr, "Unhandled shift type\n");
123 exit(1);
124 break;
125 }
126 return 0;
127}
128
129int64_t
130ArmStaticInst::extendReg64(uint64_t base, ArmExtendType type,
131 uint64_t shiftAmt, uint8_t width) const
132{
133 bool sign_extend = false;
134 int len = 0;
135 switch (type) {
136 case UXTB:
137 len = 8;
138 break;
139 case UXTH:
140 len = 16;
141 break;
142 case UXTW:
143 len = 32;
144 break;
145 case UXTX:
146 len = 64;
147 break;
148 case SXTB:
149 len = 8;
150 sign_extend = true;
151 break;
152 case SXTH:
153 len = 16;
154 sign_extend = true;
155 break;
156 case SXTW:
157 len = 32;
158 sign_extend = true;
159 break;
160 case SXTX:
161 len = 64;
162 sign_extend = true;
163 break;
164 }
165 len = len <= width - shiftAmt ? len : width - shiftAmt;
166 uint64_t tmp = (uint64_t) bits(base, len - 1, 0) << shiftAmt;
167 if (sign_extend) {
168 int sign_bit = bits(tmp, len + shiftAmt - 1);
169 tmp = sign_bit ? (tmp | ~mask(len + shiftAmt)) : tmp;
170 }
171 return tmp & mask(width);
172}
173
174// Shift Rm by Rs
175int32_t
176ArmStaticInst::shift_rm_rs(uint32_t base, uint32_t shamt,
177 uint32_t type, uint32_t cfval) const
178{
179 enum ArmShiftType shiftType;
180 shiftType = (enum ArmShiftType) type;
181
182 switch (shiftType)
183 {
184 case LSL:
185 if (shamt >= 32)
186 return 0;
187 else
188 return base << shamt;
189 case LSR:
190 if (shamt >= 32)
191 return 0;
192 else
193 return base >> shamt;
194 case ASR:
195 if (shamt >= 32)
196 return (base >> 31) | -((base & (1 << 31)) >> 31);
197 else
198 return (base >> shamt) | -((base & (1 << 31)) >> shamt);
199 case ROR:
200 shamt = shamt & 0x1f;
201 if (shamt == 0)
202 return base;
203 else
204 return (base << (32 - shamt)) | (base >> shamt);
205 default:
206 ccprintf(std::cerr, "Unhandled shift type\n");
207 exit(1);
208 break;
209 }
210 return 0;
211}
212
213
214// Generate C for a shift by immediate
215bool
216ArmStaticInst::shift_carry_imm(uint32_t base, uint32_t shamt,
217 uint32_t type, uint32_t cfval) const
218{
219 enum ArmShiftType shiftType;
220 shiftType = (enum ArmShiftType) type;
221
222 switch (shiftType)
223 {
224 case LSL:
225 if (shamt == 0)
226 return cfval;
227 else
228 return (base >> (32 - shamt)) & 1;
229 case LSR:
230 if (shamt == 0)
231 return (base >> 31);
232 else
233 return (base >> (shamt - 1)) & 1;
234 case ASR:
235 if (shamt == 0)
236 return (base >> 31);
237 else
238 return (base >> (shamt - 1)) & 1;
239 case ROR:
240 shamt = shamt & 0x1f;
241 if (shamt == 0)
242 return (base & 1); // RRX
243 else
244 return (base >> (shamt - 1)) & 1;
245 default:
246 ccprintf(std::cerr, "Unhandled shift type\n");
247 exit(1);
248 break;
249 }
250 return 0;
251}
252
253
254// Generate C for a shift by Rs
255bool
256ArmStaticInst::shift_carry_rs(uint32_t base, uint32_t shamt,
257 uint32_t type, uint32_t cfval) const
258{
259 enum ArmShiftType shiftType;
260 shiftType = (enum ArmShiftType) type;
261
262 if (shamt == 0)
263 return cfval;
264
265 switch (shiftType)
266 {
267 case LSL:
268 if (shamt > 32)
269 return 0;
270 else
271 return (base >> (32 - shamt)) & 1;
272 case LSR:
273 if (shamt > 32)
274 return 0;
275 else
276 return (base >> (shamt - 1)) & 1;
277 case ASR:
278 if (shamt > 32)
279 shamt = 32;
280 return (base >> (shamt - 1)) & 1;
281 case ROR:
282 shamt = shamt & 0x1f;
283 if (shamt == 0)
284 shamt = 32;
285 return (base >> (shamt - 1)) & 1;
286 default:
287 ccprintf(std::cerr, "Unhandled shift type\n");
288 exit(1);
289 break;
290 }
291 return 0;
292}
293
294
295void
296ArmStaticInst::printReg(std::ostream &os, int reg) const
297{
298 RegIndex rel_reg;
299
300 switch (regIdxToClass(reg, &rel_reg)) {
301 case IntRegClass:
302 if (aarch64) {
303 if (reg == INTREG_UREG0)
304 ccprintf(os, "ureg0");
305 else if (reg == INTREG_SPX)
306 ccprintf(os, "%s%s", (intWidth == 32) ? "w" : "", "sp");
307 else if (reg == INTREG_X31)
308 ccprintf(os, "%szr", (intWidth == 32) ? "w" : "x");
309 else
310 ccprintf(os, "%s%d", (intWidth == 32) ? "w" : "x", reg);
311 } else {
312 switch (rel_reg) {
313 case PCReg:
314 ccprintf(os, "pc");
315 break;
316 case StackPointerReg:
317 ccprintf(os, "sp");
318 break;
319 case FramePointerReg:
320 ccprintf(os, "fp");
321 break;
322 case ReturnAddressReg:
323 ccprintf(os, "lr");
324 break;
325 default:
326 ccprintf(os, "r%d", reg);
327 break;
328 }
329 }
330 break;
331 case FloatRegClass:
332 ccprintf(os, "f%d", rel_reg);
333 break;
334 case MiscRegClass:
335 assert(rel_reg < NUM_MISCREGS);
336 ccprintf(os, "%s", ArmISA::miscRegName[rel_reg]);
337 break;
338 case CCRegClass:
339 ccprintf(os, "cc_%s", ArmISA::ccRegName[rel_reg]);
340 break;
341 }
342}
343
344void
345ArmStaticInst::printMnemonic(std::ostream &os,
346 const std::string &suffix,
347 bool withPred,
348 bool withCond64,
349 ConditionCode cond64) const
350{
351 os << " " << mnemonic;
352 if (withPred && !aarch64) {
353 printCondition(os, machInst.condCode);
354 os << suffix;
355 } else if (withCond64) {
356 os << ".";
357 printCondition(os, cond64);
358 os << suffix;
359 }
360 if (machInst.bigThumb)
361 os << ".w";
362 os << " ";
363}
364
365void
366ArmStaticInst::printTarget(std::ostream &os, Addr target,
367 const SymbolTable *symtab) const
368{
369 Addr symbolAddr;
370 std::string symbol;
371
372 if (symtab && symtab->findNearestSymbol(target, symbol, symbolAddr)) {
373 ccprintf(os, "<%s", symbol);
374 if (symbolAddr != target)
375 ccprintf(os, "+%d>", target - symbolAddr);
376 else
377 ccprintf(os, ">");
378 } else {
379 ccprintf(os, "%#x", target);
380 }
381}
382
383void
384ArmStaticInst::printCondition(std::ostream &os,
385 unsigned code,
386 bool noImplicit) const
387{
388 switch (code) {
389 case COND_EQ:
390 os << "eq";
391 break;
392 case COND_NE:
393 os << "ne";
394 break;
395 case COND_CS:
396 os << "cs";
397 break;
398 case COND_CC:
399 os << "cc";
400 break;
401 case COND_MI:
402 os << "mi";
403 break;
404 case COND_PL:
405 os << "pl";
406 break;
407 case COND_VS:
408 os << "vs";
409 break;
410 case COND_VC:
411 os << "vc";
412 break;
413 case COND_HI:
414 os << "hi";
415 break;
416 case COND_LS:
417 os << "ls";
418 break;
419 case COND_GE:
420 os << "ge";
421 break;
422 case COND_LT:
423 os << "lt";
424 break;
425 case COND_GT:
426 os << "gt";
427 break;
428 case COND_LE:
429 os << "le";
430 break;
431 case COND_AL:
432 // This one is implicit.
433 if (noImplicit)
434 os << "al";
435 break;
436 case COND_UC:
437 // Unconditional.
438 if (noImplicit)
439 os << "uc";
440 break;
441 default:
442 panic("Unrecognized condition code %d.\n", code);
443 }
444}
445
446void
447ArmStaticInst::printMemSymbol(std::ostream &os,
448 const SymbolTable *symtab,
449 const std::string &prefix,
450 const Addr addr,
451 const std::string &suffix) const
452{
453 Addr symbolAddr;
454 std::string symbol;
455 if (symtab && symtab->findNearestSymbol(addr, symbol, symbolAddr)) {
456 ccprintf(os, "%s%s", prefix, symbol);
457 if (symbolAddr != addr)
458 ccprintf(os, "+%d", addr - symbolAddr);
459 ccprintf(os, suffix);
460 }
461}
462
463void
464ArmStaticInst::printShiftOperand(std::ostream &os,
465 IntRegIndex rm,
466 bool immShift,
467 uint32_t shiftAmt,
468 IntRegIndex rs,
469 ArmShiftType type) const
470{
471 bool firstOp = false;
472
473 if (rm != INTREG_ZERO) {
474 printReg(os, rm);
475 }
476
477 bool done = false;
478
479 if ((type == LSR || type == ASR) && immShift && shiftAmt == 0)
480 shiftAmt = 32;
481
482 switch (type) {
483 case LSL:
484 if (immShift && shiftAmt == 0) {
485 done = true;
486 break;
487 }
488 if (!firstOp)
489 os << ", ";
490 os << "LSL";
491 break;
492 case LSR:
493 if (!firstOp)
494 os << ", ";
495 os << "LSR";
496 break;
497 case ASR:
498 if (!firstOp)
499 os << ", ";
500 os << "ASR";
501 break;
502 case ROR:
503 if (immShift && shiftAmt == 0) {
504 if (!firstOp)
505 os << ", ";
506 os << "RRX";
507 done = true;
508 break;
509 }
510 if (!firstOp)
511 os << ", ";
512 os << "ROR";
513 break;
514 default:
515 panic("Tried to disassemble unrecognized shift type.\n");
516 }
517 if (!done) {
518 if (!firstOp)
519 os << " ";
520 if (immShift)
521 os << "#" << shiftAmt;
522 else
523 printReg(os, rs);
524 }
525}
526
527void
528ArmStaticInst::printExtendOperand(bool firstOperand, std::ostream &os,
529 IntRegIndex rm, ArmExtendType type,
530 int64_t shiftAmt) const
531{
532 if (!firstOperand)
533 ccprintf(os, ", ");
534 printReg(os, rm);
535 if (type == UXTX && shiftAmt == 0)
536 return;
537 switch (type) {
538 case UXTB: ccprintf(os, ", UXTB");
539 break;
540 case UXTH: ccprintf(os, ", UXTH");
541 break;
542 case UXTW: ccprintf(os, ", UXTW");
543 break;
544 case UXTX: ccprintf(os, ", LSL");
545 break;
546 case SXTB: ccprintf(os, ", SXTB");
547 break;
548 case SXTH: ccprintf(os, ", SXTH");
549 break;
550 case SXTW: ccprintf(os, ", SXTW");
551 break;
552 case SXTX: ccprintf(os, ", SXTW");
553 break;
554 }
555 if (type == UXTX || shiftAmt)
556 ccprintf(os, " #%d", shiftAmt);
557}
558
559void
560ArmStaticInst::printDataInst(std::ostream &os, bool withImm,
561 bool immShift, bool s, IntRegIndex rd, IntRegIndex rn,
562 IntRegIndex rm, IntRegIndex rs, uint32_t shiftAmt,
563 ArmShiftType type, uint64_t imm) const
564{
565 printMnemonic(os, s ? "s" : "");
566 bool firstOp = true;
567
568 // Destination
569 if (rd != INTREG_ZERO) {
570 firstOp = false;
571 printReg(os, rd);
572 }
573
574 // Source 1.
575 if (rn != INTREG_ZERO) {
576 if (!firstOp)
577 os << ", ";
578 firstOp = false;
579 printReg(os, rn);
580 }
581
582 if (!firstOp)
583 os << ", ";
584 if (withImm) {
585 ccprintf(os, "#%ld", imm);
586 } else {
587 printShiftOperand(os, rm, immShift, shiftAmt, rs, type);
588 }
589}
590
591std::string
592ArmStaticInst::generateDisassembly(Addr pc,
593 const SymbolTable *symtab) const
594{
595 std::stringstream ss;
596 printMnemonic(ss);
597 return ss.str();
598}
599
600
601Fault
602ArmStaticInst::advSIMDFPAccessTrap64(ExceptionLevel el) const
603{
604 switch (el) {
605 case EL1:
606 return std::make_shared<SupervisorTrap>(machInst, 0x1E00000,
607 EC_TRAPPED_SIMD_FP);
608 case EL2:
609 return std::make_shared<HypervisorTrap>(machInst, 0x1E00000,
610 EC_TRAPPED_SIMD_FP);
611 case EL3:
612 return std::make_shared<SecureMonitorTrap>(machInst, 0x1E00000,
613 EC_TRAPPED_SIMD_FP);
614
615 default:
616 panic("Illegal EL in advSIMDFPAccessTrap64\n");
617 }
618}
619
620
621Fault
622ArmStaticInst::checkFPAdvSIMDTrap64(ThreadContext *tc, CPSR cpsr) const
623{
624 const ExceptionLevel el = (ExceptionLevel) (uint8_t)cpsr.el;
625
626 if (ArmSystem::haveVirtualization(tc) && el <= EL2) {
627 HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL2);
628 if (cptrEnCheck.tfp)
629 return advSIMDFPAccessTrap64(EL2);
630 }
631
632 if (ArmSystem::haveSecurity(tc)) {
633 HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL3);
634 if (cptrEnCheck.tfp)
635 return advSIMDFPAccessTrap64(EL3);
636 }
637
638 return NoFault;
639}
640
641Fault
642ArmStaticInst::checkFPAdvSIMDEnabled64(ThreadContext *tc,
643 CPSR cpsr, CPACR cpacr) const
644{
645 const ExceptionLevel el = (ExceptionLevel) (uint8_t)cpsr.el;
646 if ((el == EL0 && cpacr.fpen != 0x3) ||
647 (el == EL1 && !(cpacr.fpen & 0x1)))
648 return advSIMDFPAccessTrap64(EL1);
649
650 return checkFPAdvSIMDTrap64(tc, cpsr);
651}
652
653Fault
654ArmStaticInst::checkAdvSIMDOrFPEnabled32(ThreadContext *tc,
655 CPSR cpsr, CPACR cpacr,
656 NSACR nsacr, FPEXC fpexc,
657 bool fpexc_check, bool advsimd) const
658{
659 const bool have_virtualization = ArmSystem::haveVirtualization(tc);
660 const bool have_security = ArmSystem::haveSecurity(tc);
661 const bool is_secure = inSecureState(tc);
662 const ExceptionLevel cur_el = opModeToEL(currOpMode(tc));
663
664 if (cur_el == EL0 && ELIs64(tc, EL1))
665 return checkFPAdvSIMDEnabled64(tc, cpsr, cpacr);
666
667 uint8_t cpacr_cp10 = cpacr.cp10;
668 bool cpacr_asedis = cpacr.asedis;
669
670 if (have_security && !ELIs64(tc, EL3) && !is_secure) {
671 if (nsacr.nsasedis)
672 cpacr_asedis = true;
673 if (nsacr.cp10 == 0)
674 cpacr_cp10 = 0;
675 }
676
677 if (cur_el != EL2) {
678 if (advsimd && cpacr_asedis)
679 return disabledFault();
680
681 if ((cur_el == EL0 && cpacr_cp10 != 0x3) ||
682 (cur_el != EL0 && !(cpacr_cp10 & 0x1)))
683 return disabledFault();
684 }
685
686 if (fpexc_check && !fpexc.en)
687 return disabledFault();
688
689 // -- aarch32/exceptions/traps/AArch32.CheckFPAdvSIMDTrap --
690
691 if (have_virtualization && !is_secure && ELIs64(tc, EL2))
692 return checkFPAdvSIMDTrap64(tc, cpsr);
693
694 if (have_virtualization && !is_secure) {
695 HCPTR hcptr = tc->readMiscReg(MISCREG_HCPTR);
696 bool hcptr_cp10 = hcptr.tcp10;
697 bool hcptr_tase = hcptr.tase;
698
699 if (have_security && !ELIs64(tc, EL3) && !is_secure) {
700 if (nsacr.nsasedis)
701 hcptr_tase = true;
702 if (nsacr.cp10)
703 hcptr_cp10 = true;
704 }
705
706 if ((advsimd && hcptr_tase) || hcptr_cp10) {
707 const uint32_t iss = advsimd ? (1 << 5) : 0xA;
708 if (cur_el == EL2) {
709 return std::make_shared<UndefinedInstruction>(
710 machInst, iss,
711 EC_TRAPPED_HCPTR, mnemonic);
712 } else {
713 return std::make_shared<HypervisorTrap>(
714 machInst, iss,
715 EC_TRAPPED_HCPTR);
716 }
717
718 }
719 }
720
721 if (have_security && ELIs64(tc, EL3)) {
722 HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL3);
723 if (cptrEnCheck.tfp)
724 return advSIMDFPAccessTrap64(EL3);
725 }
726
727 return NoFault;
728}
729
730
731static uint8_t
732getRestoredITBits(ThreadContext *tc, CPSR spsr)
733{
734 // See: shared/functions/system/RestoredITBits in the ARM ARM
735
736 const ExceptionLevel el = opModeToEL((OperatingMode) (uint8_t)spsr.mode);
737 const uint8_t it = itState(spsr);
738
739 if (!spsr.t || spsr.il)
740 return 0;
741
742 // The IT bits are forced to zero when they are set to a reserved
743 // value.
744 if (bits(it, 7, 4) != 0 && bits(it, 3, 0) == 0)
745 return 0;
746
747 const bool itd = el == EL2 ?
748 ((SCTLR)tc->readMiscReg(MISCREG_HSCTLR)).itd :
749 ((SCTLR)tc->readMiscReg(MISCREG_SCTLR)).itd;
750
751 // The IT bits are forced to zero when returning to A32 state, or
752 // when returning to an EL with the ITD bit set to 1, and the IT
753 // bits are describing a multi-instruction block.
754 if (itd && bits(it, 2, 0) != 0)
755 return 0;
756
757 return it;
758}
759
760static bool
761illegalExceptionReturn(ThreadContext *tc, CPSR cpsr, CPSR spsr)
762{
763 const OperatingMode mode = (OperatingMode) (uint8_t)spsr.mode;
764 if (badMode(mode))
765 return true;
766
767 const OperatingMode cur_mode = (OperatingMode) (uint8_t)cpsr.mode;
768 const ExceptionLevel target_el = opModeToEL(mode);
769 if (target_el > opModeToEL(cur_mode))
770 return true;
771
772 if (target_el == EL3 && !ArmSystem::haveSecurity(tc))
773 return true;
774
775 if (target_el == EL2 && !ArmSystem::haveVirtualization(tc))
776 return true;
777
778 if (!spsr.width) {
779 // aarch64
780 if (!ArmSystem::highestELIs64(tc))
781 return true;
782
783 if (spsr & 0x2)
784 return true;
785 if (target_el == EL0 && spsr.sp)
786 return true;
787 if (target_el == EL2 && !((SCR)tc->readMiscReg(MISCREG_SCR_EL3)).ns)
788 return false;
789 } else {
790 return badMode32(mode);
791 }
792
793 return false;
794}
795
796CPSR
797ArmStaticInst::getPSTATEFromPSR(ThreadContext *tc, CPSR cpsr, CPSR spsr) const
798{
799 CPSR new_cpsr = 0;
800
801 // gem5 doesn't implement single-stepping, so force the SS bit to
802 // 0.
803 new_cpsr.ss = 0;
804
805 if (illegalExceptionReturn(tc, cpsr, spsr)) {
806 new_cpsr.il = 1;
807 } else {
808 new_cpsr.il = spsr.il;
809 if (spsr.width && badMode32((OperatingMode)(uint8_t)spsr.mode)) {
810 new_cpsr.il = 1;
811 } else if (spsr.width) {
812 new_cpsr.mode = spsr.mode;
813 } else {
814 new_cpsr.el = spsr.el;
815 new_cpsr.sp = spsr.sp;
816 }
817 }
818
819 new_cpsr.nz = spsr.nz;
820 new_cpsr.c = spsr.c;
821 new_cpsr.v = spsr.v;
822 if (new_cpsr.width) {
823 // aarch32
824 const ITSTATE it = getRestoredITBits(tc, spsr);
825 new_cpsr.q = spsr.q;
826 new_cpsr.ge = spsr.ge;
827 new_cpsr.e = spsr.e;
828 new_cpsr.aif = spsr.aif;
829 new_cpsr.t = spsr.t;
830 new_cpsr.it2 = it.top6;
831 new_cpsr.it1 = it.bottom2;
832 } else {
833 // aarch64
834 new_cpsr.daif = spsr.daif;
835 }
836
837 return new_cpsr;
838}
839
840
841
842}