gem5  v19.0.0.0
static_inst.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010-2014, 2016-2019 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 
45 
46 #include "arch/arm/faults.hh"
47 #include "arch/arm/isa.hh"
48 #include "base/condcodes.hh"
49 #include "base/cprintf.hh"
50 #include "base/loader/symtab.hh"
51 #include "cpu/reg_class.hh"
52 
53 namespace ArmISA
54 {
55 // Shift Rm by an immediate value
56 int32_t
57 ArmStaticInst::shift_rm_imm(uint32_t base, uint32_t shamt,
58  uint32_t type, uint32_t cfval) const
59 {
60  assert(shamt < 32);
61  ArmShiftType shiftType;
62  shiftType = (ArmShiftType)type;
63 
64  switch (shiftType)
65  {
66  case LSL:
67  return base << shamt;
68  case LSR:
69  if (shamt == 0)
70  return 0;
71  else
72  return base >> shamt;
73  case ASR:
74  if (shamt == 0)
75  return (base >> 31) | -((base & (1 << 31)) >> 31);
76  else
77  return (base >> shamt) | -((base & (1 << 31)) >> shamt);
78  case ROR:
79  if (shamt == 0)
80  return (cfval << 31) | (base >> 1); // RRX
81  else
82  return (base << (32 - shamt)) | (base >> shamt);
83  default:
84  ccprintf(std::cerr, "Unhandled shift type\n");
85  exit(1);
86  break;
87  }
88  return 0;
89 }
90 
91 int64_t
92 ArmStaticInst::shiftReg64(uint64_t base, uint64_t shiftAmt,
93  ArmShiftType type, uint8_t width) const
94 {
95  shiftAmt = shiftAmt % width;
96  ArmShiftType shiftType;
97  shiftType = (ArmShiftType)type;
98 
99  switch (shiftType)
100  {
101  case LSL:
102  return base << shiftAmt;
103  case LSR:
104  if (shiftAmt == 0)
105  return base;
106  else
107  return (base & mask(width)) >> shiftAmt;
108  case ASR:
109  if (shiftAmt == 0) {
110  return base;
111  } else {
112  int sign_bit = bits(base, intWidth - 1);
113  base >>= shiftAmt;
114  base = sign_bit ? (base | ~mask(intWidth - shiftAmt)) : base;
115  return base & mask(intWidth);
116  }
117  case ROR:
118  if (shiftAmt == 0)
119  return base;
120  else
121  return (base << (width - shiftAmt)) | (base >> shiftAmt);
122  default:
123  ccprintf(std::cerr, "Unhandled shift type\n");
124  exit(1);
125  break;
126  }
127  return 0;
128 }
129 
130 int64_t
132  uint64_t shiftAmt, uint8_t width) const
133 {
134  bool sign_extend = false;
135  int len = 0;
136  switch (type) {
137  case UXTB:
138  len = 8;
139  break;
140  case UXTH:
141  len = 16;
142  break;
143  case UXTW:
144  len = 32;
145  break;
146  case UXTX:
147  len = 64;
148  break;
149  case SXTB:
150  len = 8;
151  sign_extend = true;
152  break;
153  case SXTH:
154  len = 16;
155  sign_extend = true;
156  break;
157  case SXTW:
158  len = 32;
159  sign_extend = true;
160  break;
161  case SXTX:
162  len = 64;
163  sign_extend = true;
164  break;
165  }
166  len = len <= width - shiftAmt ? len : width - shiftAmt;
167  uint64_t tmp = (uint64_t) bits(base, len - 1, 0) << shiftAmt;
168  if (sign_extend) {
169  int sign_bit = bits(tmp, len + shiftAmt - 1);
170  tmp = sign_bit ? (tmp | ~mask(len + shiftAmt)) : tmp;
171  }
172  return tmp & mask(width);
173 }
174 
175 // Shift Rm by Rs
176 int32_t
177 ArmStaticInst::shift_rm_rs(uint32_t base, uint32_t shamt,
178  uint32_t type, uint32_t cfval) const
179 {
180  enum ArmShiftType shiftType;
181  shiftType = (enum ArmShiftType) type;
182 
183  switch (shiftType)
184  {
185  case LSL:
186  if (shamt >= 32)
187  return 0;
188  else
189  return base << shamt;
190  case LSR:
191  if (shamt >= 32)
192  return 0;
193  else
194  return base >> shamt;
195  case ASR:
196  if (shamt >= 32)
197  return (base >> 31) | -((base & (1 << 31)) >> 31);
198  else
199  return (base >> shamt) | -((base & (1 << 31)) >> shamt);
200  case ROR:
201  shamt = shamt & 0x1f;
202  if (shamt == 0)
203  return base;
204  else
205  return (base << (32 - shamt)) | (base >> shamt);
206  default:
207  ccprintf(std::cerr, "Unhandled shift type\n");
208  exit(1);
209  break;
210  }
211  return 0;
212 }
213 
214 
215 // Generate C for a shift by immediate
216 bool
217 ArmStaticInst::shift_carry_imm(uint32_t base, uint32_t shamt,
218  uint32_t type, uint32_t cfval) const
219 {
220  enum ArmShiftType shiftType;
221  shiftType = (enum ArmShiftType) type;
222 
223  switch (shiftType)
224  {
225  case LSL:
226  if (shamt == 0)
227  return cfval;
228  else
229  return (base >> (32 - shamt)) & 1;
230  case LSR:
231  if (shamt == 0)
232  return (base >> 31);
233  else
234  return (base >> (shamt - 1)) & 1;
235  case ASR:
236  if (shamt == 0)
237  return (base >> 31);
238  else
239  return (base >> (shamt - 1)) & 1;
240  case ROR:
241  shamt = shamt & 0x1f;
242  if (shamt == 0)
243  return (base & 1); // RRX
244  else
245  return (base >> (shamt - 1)) & 1;
246  default:
247  ccprintf(std::cerr, "Unhandled shift type\n");
248  exit(1);
249  break;
250  }
251  return 0;
252 }
253 
254 
255 // Generate C for a shift by Rs
256 bool
257 ArmStaticInst::shift_carry_rs(uint32_t base, uint32_t shamt,
258  uint32_t type, uint32_t cfval) const
259 {
260  enum ArmShiftType shiftType;
261  shiftType = (enum ArmShiftType) type;
262 
263  if (shamt == 0)
264  return cfval;
265 
266  switch (shiftType)
267  {
268  case LSL:
269  if (shamt > 32)
270  return 0;
271  else
272  return (base >> (32 - shamt)) & 1;
273  case LSR:
274  if (shamt > 32)
275  return 0;
276  else
277  return (base >> (shamt - 1)) & 1;
278  case ASR:
279  if (shamt > 32)
280  shamt = 32;
281  return (base >> (shamt - 1)) & 1;
282  case ROR:
283  shamt = shamt & 0x1f;
284  if (shamt == 0)
285  shamt = 32;
286  return (base >> (shamt - 1)) & 1;
287  default:
288  ccprintf(std::cerr, "Unhandled shift type\n");
289  exit(1);
290  break;
291  }
292  return 0;
293 }
294 
295 void
296 ArmStaticInst::printIntReg(std::ostream &os, RegIndex reg_idx,
297  uint8_t opWidth) const
298 {
299  if (opWidth == 0)
300  opWidth = intWidth;
301  if (aarch64) {
302  if (reg_idx == INTREG_UREG0)
303  ccprintf(os, "ureg0");
304  else if (reg_idx == INTREG_SPX)
305  ccprintf(os, "%s%s", (opWidth == 32) ? "w" : "", "sp");
306  else if (reg_idx == INTREG_X31)
307  ccprintf(os, "%szr", (opWidth == 32) ? "w" : "x");
308  else
309  ccprintf(os, "%s%d", (opWidth == 32) ? "w" : "x", reg_idx);
310  } else {
311  switch (reg_idx) {
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_idx);
326  break;
327  }
328  }
329 }
330 
331 void ArmStaticInst::printPFflags(std::ostream &os, int flag) const
332 {
333  const char *flagtoprfop[]= { "PLD", "PLI", "PST", "Reserved"};
334  const char *flagtotarget[] = { "L1", "L2", "L3", "Reserved"};
335  const char *flagtopolicy[] = { "KEEP", "STRM"};
336 
337  ccprintf(os, "%s%s%s", flagtoprfop[(flag>>3)&3],
338  flagtotarget[(flag>>1)&3], flagtopolicy[flag&1]);
339 }
340 
341 void
342 ArmStaticInst::printFloatReg(std::ostream &os, RegIndex reg_idx) const
343 {
344  ccprintf(os, "f%d", reg_idx);
345 }
346 
347 void
348 ArmStaticInst::printVecReg(std::ostream &os, RegIndex reg_idx,
349  bool isSveVecReg) const
350 {
351  ccprintf(os, "%s%d", isSveVecReg ? "z" : "v", reg_idx);
352 }
353 
354 void
355 ArmStaticInst::printVecPredReg(std::ostream &os, RegIndex reg_idx) const
356 {
357  ccprintf(os, "p%d", reg_idx);
358 }
359 
360 void
361 ArmStaticInst::printCCReg(std::ostream &os, RegIndex reg_idx) const
362 {
363  ccprintf(os, "cc_%s", ArmISA::ccRegName[reg_idx]);
364 }
365 
366 void
367 ArmStaticInst::printMiscReg(std::ostream &os, RegIndex reg_idx) const
368 {
369  assert(reg_idx < NUM_MISCREGS);
370  ccprintf(os, "%s", ArmISA::miscRegName[reg_idx]);
371 }
372 
373 void
375  const std::string &suffix,
376  bool withPred,
377  bool withCond64,
378  ConditionCode cond64) const
379 {
380  os << " " << mnemonic;
381  if (withPred && !aarch64) {
382  printCondition(os, machInst.condCode);
383  os << suffix;
384  } else if (withCond64) {
385  os << ".";
386  printCondition(os, cond64);
387  os << suffix;
388  }
389  if (machInst.bigThumb)
390  os << ".w";
391  os << " ";
392 }
393 
394 void
395 ArmStaticInst::printTarget(std::ostream &os, Addr target,
396  const SymbolTable *symtab) const
397 {
398  Addr symbolAddr;
399  std::string symbol;
400 
401  if (symtab && symtab->findNearestSymbol(target, symbol, symbolAddr)) {
402  ccprintf(os, "<%s", symbol);
403  if (symbolAddr != target)
404  ccprintf(os, "+%d>", target - symbolAddr);
405  else
406  ccprintf(os, ">");
407  } else {
408  ccprintf(os, "%#x", target);
409  }
410 }
411 
412 void
414  unsigned code,
415  bool noImplicit) const
416 {
417  switch (code) {
418  case COND_EQ:
419  os << "eq";
420  break;
421  case COND_NE:
422  os << "ne";
423  break;
424  case COND_CS:
425  os << "cs";
426  break;
427  case COND_CC:
428  os << "cc";
429  break;
430  case COND_MI:
431  os << "mi";
432  break;
433  case COND_PL:
434  os << "pl";
435  break;
436  case COND_VS:
437  os << "vs";
438  break;
439  case COND_VC:
440  os << "vc";
441  break;
442  case COND_HI:
443  os << "hi";
444  break;
445  case COND_LS:
446  os << "ls";
447  break;
448  case COND_GE:
449  os << "ge";
450  break;
451  case COND_LT:
452  os << "lt";
453  break;
454  case COND_GT:
455  os << "gt";
456  break;
457  case COND_LE:
458  os << "le";
459  break;
460  case COND_AL:
461  // This one is implicit.
462  if (noImplicit)
463  os << "al";
464  break;
465  case COND_UC:
466  // Unconditional.
467  if (noImplicit)
468  os << "uc";
469  break;
470  default:
471  panic("Unrecognized condition code %d.\n", code);
472  }
473 }
474 
475 void
477  const SymbolTable *symtab,
478  const std::string &prefix,
479  const Addr addr,
480  const std::string &suffix) const
481 {
482  Addr symbolAddr;
483  std::string symbol;
484  if (symtab && symtab->findNearestSymbol(addr, symbol, symbolAddr)) {
485  ccprintf(os, "%s%s", prefix, symbol);
486  if (symbolAddr != addr)
487  ccprintf(os, "+%d", addr - symbolAddr);
488  ccprintf(os, suffix);
489  }
490 }
491 
492 void
494  IntRegIndex rm,
495  bool immShift,
496  uint32_t shiftAmt,
497  IntRegIndex rs,
498  ArmShiftType type) const
499 {
500  bool firstOp = false;
501 
502  if (rm != INTREG_ZERO) {
503  printIntReg(os, rm);
504  }
505 
506  bool done = false;
507 
508  if ((type == LSR || type == ASR) && immShift && shiftAmt == 0)
509  shiftAmt = 32;
510 
511  switch (type) {
512  case LSL:
513  if (immShift && shiftAmt == 0) {
514  done = true;
515  break;
516  }
517  if (!firstOp)
518  os << ", ";
519  os << "LSL";
520  break;
521  case LSR:
522  if (!firstOp)
523  os << ", ";
524  os << "LSR";
525  break;
526  case ASR:
527  if (!firstOp)
528  os << ", ";
529  os << "ASR";
530  break;
531  case ROR:
532  if (immShift && shiftAmt == 0) {
533  if (!firstOp)
534  os << ", ";
535  os << "RRX";
536  done = true;
537  break;
538  }
539  if (!firstOp)
540  os << ", ";
541  os << "ROR";
542  break;
543  default:
544  panic("Tried to disassemble unrecognized shift type.\n");
545  }
546  if (!done) {
547  if (!firstOp)
548  os << " ";
549  if (immShift)
550  os << "#" << shiftAmt;
551  else
552  printIntReg(os, rs);
553  }
554 }
555 
556 void
557 ArmStaticInst::printExtendOperand(bool firstOperand, std::ostream &os,
559  int64_t shiftAmt) const
560 {
561  if (!firstOperand)
562  ccprintf(os, ", ");
563  printIntReg(os, rm);
564  if (type == UXTX && shiftAmt == 0)
565  return;
566  switch (type) {
567  case UXTB: ccprintf(os, ", UXTB");
568  break;
569  case UXTH: ccprintf(os, ", UXTH");
570  break;
571  case UXTW: ccprintf(os, ", UXTW");
572  break;
573  case UXTX: ccprintf(os, ", LSL");
574  break;
575  case SXTB: ccprintf(os, ", SXTB");
576  break;
577  case SXTH: ccprintf(os, ", SXTH");
578  break;
579  case SXTW: ccprintf(os, ", SXTW");
580  break;
581  case SXTX: ccprintf(os, ", SXTW");
582  break;
583  }
584  if (type == UXTX || shiftAmt)
585  ccprintf(os, " #%d", shiftAmt);
586 }
587 
588 void
589 ArmStaticInst::printDataInst(std::ostream &os, bool withImm,
590  bool immShift, bool s, IntRegIndex rd, IntRegIndex rn,
591  IntRegIndex rm, IntRegIndex rs, uint32_t shiftAmt,
592  ArmShiftType type, uint64_t imm) const
593 {
594  printMnemonic(os, s ? "s" : "");
595  bool firstOp = true;
596 
597  // Destination
598  if (rd != INTREG_ZERO) {
599  firstOp = false;
600  printIntReg(os, rd);
601  }
602 
603  // Source 1.
604  if (rn != INTREG_ZERO) {
605  if (!firstOp)
606  os << ", ";
607  firstOp = false;
608  printIntReg(os, rn);
609  }
610 
611  if (!firstOp)
612  os << ", ";
613  if (withImm) {
614  ccprintf(os, "#%ld", imm);
615  } else {
616  printShiftOperand(os, rm, immShift, shiftAmt, rs, type);
617  }
618 }
619 
620 std::string
622  const SymbolTable *symtab) const
623 {
624  std::stringstream ss;
625  printMnemonic(ss);
626  return ss.str();
627 }
628 
629 Fault
631 {
632  const auto tc = xc->tcBase();
633  const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
634  const HDCR mdcr = tc->readMiscRegNoEffect(MISCREG_MDCR_EL2);
635  if ((ArmSystem::haveEL(tc, EL2) && !inSecureState(tc) &&
636  !ELIs32(tc, EL2) && (hcr.tge == 1 || mdcr.tde == 1)) ||
637  !ELIs32(tc, EL1)) {
638  // Route to AArch64 Software Breakpoint
639  return std::make_shared<SoftwareBreakpoint>(machInst, imm);
640  } else {
641  // Execute AArch32 Software Breakpoint
642  return std::make_shared<PrefetchAbort>(readPC(xc),
644  }
645 }
646 
647 Fault
649 {
650  switch (el) {
651  case EL1:
652  return std::make_shared<SupervisorTrap>(machInst, 0x1E00000,
654  case EL2:
655  return std::make_shared<HypervisorTrap>(machInst, 0x1E00000,
657  case EL3:
658  return std::make_shared<SecureMonitorTrap>(machInst, 0x1E00000,
660 
661  default:
662  panic("Illegal EL in advSIMDFPAccessTrap64\n");
663  }
664 }
665 
666 
667 Fault
669 {
671  HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL2);
672  if (cptrEnCheck.tfp)
673  return advSIMDFPAccessTrap64(EL2);
674  }
675 
676  if (ArmSystem::haveSecurity(tc)) {
677  HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL3);
678  if (cptrEnCheck.tfp)
679  return advSIMDFPAccessTrap64(EL3);
680  }
681 
682  return NoFault;
683 }
684 
685 Fault
687  CPSR cpsr, CPACR cpacr) const
688 {
689  const ExceptionLevel el = currEL(tc);
690  if ((el == EL0 && cpacr.fpen != 0x3) ||
691  (el == EL1 && !(cpacr.fpen & 0x1)))
692  return advSIMDFPAccessTrap64(EL1);
693 
694  return checkFPAdvSIMDTrap64(tc, cpsr);
695 }
696 
697 Fault
699  CPSR cpsr, CPACR cpacr,
700  NSACR nsacr, FPEXC fpexc,
701  bool fpexc_check, bool advsimd) const
702 {
703  const bool have_virtualization = ArmSystem::haveVirtualization(tc);
704  const bool have_security = ArmSystem::haveSecurity(tc);
705  const bool is_secure = inSecureState(tc);
706  const ExceptionLevel cur_el = currEL(tc);
707 
708  if (cur_el == EL0 && ELIs64(tc, EL1))
709  return checkFPAdvSIMDEnabled64(tc, cpsr, cpacr);
710 
711  uint8_t cpacr_cp10 = cpacr.cp10;
712  bool cpacr_asedis = cpacr.asedis;
713 
714  if (have_security && !ELIs64(tc, EL3) && !is_secure) {
715  if (nsacr.nsasedis)
716  cpacr_asedis = true;
717  if (nsacr.cp10 == 0)
718  cpacr_cp10 = 0;
719  }
720 
721  if (cur_el != EL2) {
722  if (advsimd && cpacr_asedis)
723  return disabledFault();
724 
725  if ((cur_el == EL0 && cpacr_cp10 != 0x3) ||
726  (cur_el != EL0 && !(cpacr_cp10 & 0x1)))
727  return disabledFault();
728  }
729 
730  if (fpexc_check && !fpexc.en)
731  return disabledFault();
732 
733  // -- aarch32/exceptions/traps/AArch32.CheckFPAdvSIMDTrap --
734 
735  if (have_virtualization && !is_secure && ELIs64(tc, EL2))
736  return checkFPAdvSIMDTrap64(tc, cpsr);
737 
738  if (have_virtualization && !is_secure) {
739  HCPTR hcptr = tc->readMiscReg(MISCREG_HCPTR);
740  bool hcptr_cp10 = hcptr.tcp10;
741  bool hcptr_tase = hcptr.tase;
742 
743  if (have_security && !ELIs64(tc, EL3) && !is_secure) {
744  if (nsacr.nsasedis)
745  hcptr_tase = true;
746  if (nsacr.cp10)
747  hcptr_cp10 = true;
748  }
749 
750  if ((advsimd && hcptr_tase) || hcptr_cp10) {
751  const uint32_t iss = advsimd ? (1 << 5) : 0xA;
752  if (cur_el == EL2) {
753  return std::make_shared<UndefinedInstruction>(
754  machInst, iss,
756  } else {
757  return std::make_shared<HypervisorTrap>(
758  machInst, iss,
760  }
761 
762  }
763  }
764 
765  if (have_security && ELIs64(tc, EL3)) {
766  HCPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL3);
767  if (cptrEnCheck.tfp)
768  return advSIMDFPAccessTrap64(EL3);
769  }
770 
771  return NoFault;
772 }
773 
774 inline bool
776  ExceptionLevel tgtEl,
777  bool isWfe) const
778 {
779  bool trap = false;
780  SCTLR sctlr = ((SCTLR)tc->readMiscReg(MISCREG_SCTLR_EL1));
781  HCR hcr = ((HCR)tc->readMiscReg(MISCREG_HCR_EL2));
782  SCR scr = ((SCR)tc->readMiscReg(MISCREG_SCR_EL3));
783 
784  switch (tgtEl) {
785  case EL1:
786  trap = isWfe? !sctlr.ntwe : !sctlr.ntwi;
787  break;
788  case EL2:
789  trap = isWfe? hcr.twe : hcr.twi;
790  break;
791  case EL3:
792  trap = isWfe? scr.twe : scr.twi;
793  break;
794  default:
795  break;
796  }
797 
798  return trap;
799 }
800 
801 Fault
803  ExceptionLevel targetEL,
804  bool isWfe) const
805 {
806  // Check if target exception level is implemented.
807  assert(ArmSystem::haveEL(tc, targetEL));
808 
809  // Check for routing to AArch64: this happens if the
810  // target exception level (where the trap will be handled)
811  // is using aarch64
812  if (ELIs64(tc, targetEL)) {
813  return checkForWFxTrap64(tc, targetEL, isWfe);
814  }
815 
816  // Check if processor needs to trap at selected exception level
817  bool trap = isWFxTrapping(tc, targetEL, isWfe);
818 
819  if (trap) {
820  uint32_t iss = isWfe? 0x1E00001 : /* WFE Instruction syndrome */
821  0x1E00000; /* WFI Instruction syndrome */
822  switch (targetEL) {
823  case EL1:
824  return std::make_shared<UndefinedInstruction>(
825  machInst, iss,
827  case EL2:
828  return std::make_shared<HypervisorTrap>(machInst, iss,
830  case EL3:
831  return std::make_shared<SecureMonitorTrap>(machInst, iss,
833  default:
834  panic("Unrecognized Exception Level: %d\n", targetEL);
835  }
836  }
837 
838  return NoFault;
839 }
840 
841 Fault
843  ExceptionLevel targetEL,
844  bool isWfe) const
845 {
846  // Check if target exception level is implemented.
847  assert(ArmSystem::haveEL(tc, targetEL));
848 
849  // Check if processor needs to trap at selected exception level
850  bool trap = isWFxTrapping(tc, targetEL, isWfe);
851 
852  if (trap) {
853  uint32_t iss = isWfe? 0x1E00001 : /* WFE Instruction syndrome */
854  0x1E00000; /* WFI Instruction syndrome */
855  switch (targetEL) {
856  case EL1:
857  return std::make_shared<SupervisorTrap>(machInst, iss,
859  case EL2:
860  return std::make_shared<HypervisorTrap>(machInst, iss,
862  case EL3:
863  return std::make_shared<SecureMonitorTrap>(machInst, iss,
865  default:
866  panic("Unrecognized Exception Level: %d\n", targetEL);
867  }
868  }
869 
870  return NoFault;
871 }
872 
873 Fault
875  CPSR cpsr, SCR scr,
876  bool isWfe) const
877 {
878  Fault fault = NoFault;
879  ExceptionLevel curr_el = currEL(tc);
880 
881  if (curr_el == EL0) {
882  fault = checkForWFxTrap32(tc, EL1, isWfe);
883  }
884 
885  if ((fault == NoFault) &&
886  ArmSystem::haveEL(tc, EL2) && !inSecureState(scr, cpsr) &&
887  ((curr_el == EL0) || (curr_el == EL1))) {
888 
889  fault = checkForWFxTrap32(tc, EL2, isWfe);
890  }
891 
892  if ((fault == NoFault) &&
893  ArmSystem::haveEL(tc, EL3) && curr_el != EL3) {
894  fault = checkForWFxTrap32(tc, EL3, isWfe);
895  }
896 
897  return fault;
898 }
899 
900 Fault
902 {
903  bool setend_disabled(false);
904  ExceptionLevel pstate_el = currEL(tc);
905 
906  if (pstate_el == EL2) {
907  setend_disabled = ((SCTLR)tc->readMiscRegNoEffect(MISCREG_HSCTLR)).sed;
908  } else {
909  // Please note: in the armarm pseudocode there is a distinction
910  // whether EL1 is aarch32 or aarch64:
911  // if ELUsingAArch32(EL1) then SCTLR.SED else SCTLR[].SED;
912  // Considering that SETEND is aarch32 only, ELUsingAArch32(EL1)
913  // will always be true (hence using SCTLR.SED) except for
914  // instruction executed at EL0, and with an AArch64 EL1.
915  // In this case SCTLR_EL1 will be used. In gem5 the register is
916  // mapped to SCTLR_ns. We can safely use SCTLR and choose the
917  // appropriate bank version.
918 
919  // Get the index of the banked version of SCTLR:
920  // SCTLR_s or SCTLR_ns.
921  auto banked_sctlr = snsBankedIndex(
922  MISCREG_SCTLR, tc, !inSecureState(tc));
923 
924  // SCTLR.SED bit is enabling/disabling the ue of SETEND instruction.
925  setend_disabled = ((SCTLR)tc->readMiscRegNoEffect(banked_sctlr)).sed;
926  }
927 
928  return setend_disabled ? undefinedFault32(tc, pstate_el) :
929  NoFault;
930 }
931 
932 Fault
934  ExceptionLevel pstateEL) const
935 {
936  // Even if we are running in aarch32, the fault might be dealt with in
937  // aarch64 ISA.
938  if (generalExceptionsToAArch64(tc, pstateEL)) {
939  return undefinedFault64(tc, pstateEL);
940  } else {
941  // Please note: according to the ARM ARM pseudocode we should handle
942  // the case when EL2 is aarch64 and HCR.TGE is 1 as well.
943  // However this case is already handled by the routeToHyp method in
944  // ArmFault class.
945  return std::make_shared<UndefinedInstruction>(
946  machInst, 0,
948  }
949 }
950 
951 Fault
953  ExceptionLevel pstateEL) const
954 {
955  switch (pstateEL) {
956  case EL0:
957  case EL1:
958  return std::make_shared<SupervisorTrap>(machInst, 0, EC_UNKNOWN);
959  case EL2:
960  return std::make_shared<HypervisorTrap>(machInst, 0, EC_UNKNOWN);
961  case EL3:
962  return std::make_shared<SecureMonitorTrap>(machInst, 0, EC_UNKNOWN);
963  default:
964  panic("Unrecognized Exception Level: %d\n", pstateEL);
965  break;
966  }
967 
968  return NoFault;
969 }
970 
971 Fault
973 {
974  switch (el) {
975  case EL1:
976  return std::make_shared<SupervisorTrap>(machInst, 0, EC_TRAPPED_SVE);
977  case EL2:
978  return std::make_shared<HypervisorTrap>(machInst, 0, EC_TRAPPED_SVE);
979  case EL3:
980  return std::make_shared<SecureMonitorTrap>(machInst, 0,
982 
983  default:
984  panic("Illegal EL in sveAccessTrap\n");
985  }
986 }
987 
988 Fault
990 {
991  const ExceptionLevel el = (ExceptionLevel) (uint8_t) cpsr.el;
992 
993  if (ArmSystem::haveVirtualization(tc) && el <= EL2) {
994  CPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL2);
995  if (cptrEnCheck.tz)
996  return sveAccessTrap(EL2);
997  }
998 
999  if (ArmSystem::haveSecurity(tc)) {
1000  CPTR cptrEnCheck = tc->readMiscReg(MISCREG_CPTR_EL3);
1001  if (!cptrEnCheck.ez)
1002  return sveAccessTrap(EL3);
1003  }
1004 
1005  return NoFault;
1006 }
1007 
1008 Fault
1009 ArmStaticInst::checkSveEnabled(ThreadContext *tc, CPSR cpsr, CPACR cpacr) const
1010 {
1011  const ExceptionLevel el = (ExceptionLevel) (uint8_t) cpsr.el;
1012  if ((el == EL0 && cpacr.zen != 0x3) ||
1013  (el == EL1 && !(cpacr.zen & 0x1)))
1014  return sveAccessTrap(EL1);
1015 
1016  return checkSveTrap(tc, cpsr);
1017 }
1018 
1019 
1020 static uint8_t
1022 {
1023  // See: shared/functions/system/RestoredITBits in the ARM ARM
1024 
1025  const ExceptionLevel el = opModeToEL((OperatingMode) (uint8_t)spsr.mode);
1026  const uint8_t it = itState(spsr);
1027 
1028  if (!spsr.t || spsr.il)
1029  return 0;
1030 
1031  // The IT bits are forced to zero when they are set to a reserved
1032  // value.
1033  if (bits(it, 7, 4) != 0 && bits(it, 3, 0) == 0)
1034  return 0;
1035 
1036  const bool itd = el == EL2 ?
1037  ((SCTLR)tc->readMiscReg(MISCREG_HSCTLR)).itd :
1038  ((SCTLR)tc->readMiscReg(MISCREG_SCTLR)).itd;
1039 
1040  // The IT bits are forced to zero when returning to A32 state, or
1041  // when returning to an EL with the ITD bit set to 1, and the IT
1042  // bits are describing a multi-instruction block.
1043  if (itd && bits(it, 2, 0) != 0)
1044  return 0;
1045 
1046  return it;
1047 }
1048 
1049 static bool
1050 illegalExceptionReturn(ThreadContext *tc, CPSR cpsr, CPSR spsr)
1051 {
1052  const OperatingMode mode = (OperatingMode) (uint8_t)spsr.mode;
1053  if (unknownMode(mode))
1054  return true;
1055 
1056  const OperatingMode cur_mode = (OperatingMode) (uint8_t)cpsr.mode;
1057  const ExceptionLevel target_el = opModeToEL(mode);
1058 
1059  HCR hcr = ((HCR)tc->readMiscReg(MISCREG_HCR_EL2));
1060  SCR scr = ((SCR)tc->readMiscReg(MISCREG_SCR_EL3));
1061 
1062  if (target_el > opModeToEL(cur_mode))
1063  return true;
1064 
1065  if (!ArmSystem::haveEL(tc, target_el))
1066  return true;
1067 
1068  if (target_el == EL1 && ArmSystem::haveEL(tc, EL2) && scr.ns && hcr.tge)
1069  return true;
1070 
1071  if (target_el == EL2 && ArmSystem::haveEL(tc, EL3) && !scr.ns)
1072  return true;
1073 
1074  bool spsr_mode_is_aarch32 = (spsr.width == 1);
1075  bool known, target_el_is_aarch32;
1076  std::tie(known, target_el_is_aarch32) = ELUsingAArch32K(tc, target_el);
1077  assert(known || (target_el == EL0 && ELIs64(tc, EL1)));
1078 
1079  if (known && (spsr_mode_is_aarch32 != target_el_is_aarch32))
1080  return true;
1081 
1082  if (!spsr.width) {
1083  // aarch64
1084  if (!ArmSystem::highestELIs64(tc))
1085  return true;
1086  if (spsr & 0x2)
1087  return true;
1088  if (target_el == EL0 && spsr.sp)
1089  return true;
1090  } else {
1091  // aarch32
1092  return unknownMode32(mode);
1093  }
1094 
1095  return false;
1096 }
1097 
1098 CPSR
1099 ArmStaticInst::getPSTATEFromPSR(ThreadContext *tc, CPSR cpsr, CPSR spsr) const
1100 {
1101  CPSR new_cpsr = 0;
1102 
1103  // gem5 doesn't implement single-stepping, so force the SS bit to
1104  // 0.
1105  new_cpsr.ss = 0;
1106 
1107  if (illegalExceptionReturn(tc, cpsr, spsr)) {
1108  // If the SPSR specifies an illegal exception return,
1109  // then PSTATE.{M, nRW, EL, SP} are unchanged and PSTATE.IL
1110  // is set to 1.
1111  new_cpsr.il = 1;
1112  if (cpsr.width) {
1113  new_cpsr.mode = cpsr.mode;
1114  } else {
1115  new_cpsr.width = cpsr.width;
1116  new_cpsr.el = cpsr.el;
1117  new_cpsr.sp = cpsr.sp;
1118  }
1119  } else {
1120  new_cpsr.il = spsr.il;
1121  if (spsr.width && unknownMode32((OperatingMode)(uint8_t)spsr.mode)) {
1122  new_cpsr.il = 1;
1123  } else if (spsr.width) {
1124  new_cpsr.mode = spsr.mode;
1125  } else {
1126  new_cpsr.el = spsr.el;
1127  new_cpsr.sp = spsr.sp;
1128  }
1129  }
1130 
1131  new_cpsr.nz = spsr.nz;
1132  new_cpsr.c = spsr.c;
1133  new_cpsr.v = spsr.v;
1134  new_cpsr.pan = spsr.pan;
1135  if (new_cpsr.width) {
1136  // aarch32
1137  const ITSTATE it = getRestoredITBits(tc, spsr);
1138  new_cpsr.q = spsr.q;
1139  new_cpsr.ge = spsr.ge;
1140  new_cpsr.e = spsr.e;
1141  new_cpsr.aif = spsr.aif;
1142  new_cpsr.t = spsr.t;
1143  new_cpsr.it2 = it.top6;
1144  new_cpsr.it1 = it.bottom2;
1145  } else {
1146  // aarch64
1147  new_cpsr.daif = spsr.daif;
1148  }
1149 
1150  return new_cpsr;
1151 }
1152 
1153 bool
1155  ExceptionLevel pstateEL) const
1156 {
1157  // Returns TRUE if exceptions normally routed to EL1 are being handled
1158  // at an Exception level using AArch64, because either EL1 is using
1159  // AArch64 or TGE is in force and EL2 is using AArch64.
1160  HCR hcr = ((HCR)tc->readMiscReg(MISCREG_HCR_EL2));
1161  return (pstateEL == EL0 && !ELIs32(tc, EL1)) ||
1162  (ArmSystem::haveEL(tc, EL2) && !inSecureState(tc) &&
1163  !ELIs32(tc, EL2) && hcr.tge);
1164 }
1165 
1166 unsigned
1168 {
1169  auto *isa = static_cast<ArmISA::ISA *>(tc->getIsaPtr());
1170  return isa->getCurSveVecLenInBits(tc);
1171 }
1172 
1173 }
int32_t shift_rm_imm(uint32_t base, uint32_t shamt, uint32_t type, uint32_t cfval) const
Definition: static_inst.cc:57
CPSR getPSTATEFromPSR(ThreadContext *tc, CPSR cpsr, CPSR spsr) const
Get the new PSTATE from a SPSR register in preparation for an exception return.
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:167
void ccprintf(cp::Print &print)
Definition: cprintf.hh:131
void printMnemonic(std::ostream &os, const std::string &suffix="", bool withPred=true, bool withCond64=false, ConditionCode cond64=COND_UC) const
Definition: static_inst.cc:374
static bool unknownMode(OperatingMode mode)
Definition: types.hh:719
decltype(nullptr) constexpr NoFault
Definition: types.hh:245
static ExceptionLevel currEL(ThreadContext *tc)
Definition: utility.hh:144
IntRegIndex
Definition: intregs.hh:53
Fault checkSveTrap(ThreadContext *tc, CPSR cpsr) const
Check an SVE access against CPTR_EL2 and CPTR_EL3.
Definition: static_inst.cc:989
bool haveSecurity() const
Returns true if this system implements the Security Extensions.
Definition: system.hh:185
Fault checkForWFxTrap32(ThreadContext *tc, ExceptionLevel tgtEl, bool isWfe) const
Check if WFE/WFI instruction execution in aarch32 should be trapped.
Definition: static_inst.cc:802
void printExtendOperand(bool firstOperand, std::ostream &os, IntRegIndex rm, ArmExtendType type, int64_t shiftAmt) const
Definition: static_inst.cc:557
Fault checkSveEnabled(ThreadContext *tc, CPSR cpsr, CPACR cpacr) const
Check an SVE access against CPACR_EL1, CPTR_EL2, and CPTR_EL3.
Bitfield< 3 > exit
Definition: misc.hh:850
ip6_addr_t addr
Definition: inet.hh:335
Bitfield< 15, 12 > rd
Definition: types.hh:124
static uint8_t itState(CPSR psr)
Definition: utility.hh:211
const char * mnemonic
Base mnemonic (e.g., "add").
Definition: static_inst.hh:244
OperatingMode
Definition: types.hh:592
bool shift_carry_imm(uint32_t base, uint32_t shamt, uint32_t type, uint32_t cfval) const
Definition: static_inst.cc:217
bool highestELIs64() const
Returns true if the register width of the highest implemented exception level is 64 bits (ARMv8) ...
Definition: system.hh:221
Bitfield< 7 > itd
Fault undefinedFault64(ThreadContext *tc, ExceptionLevel el) const
UNDEFINED behaviour in AArch64.
Definition: static_inst.cc:952
Definition: ccregs.hh:42
const char *const miscRegName[]
Definition: miscregs.hh:1021
Bitfield< 4, 0 > mode
static Addr readPC(ExecContext *xc)
Definition: static_inst.hh:299
bool isWFxTrapping(ThreadContext *tc, ExceptionLevel targetEL, bool isWfe) const
Definition: static_inst.cc:775
ThreadContext is the external interface to all thread state for anything outside of the CPU...
unsigned getCurSveVecLenInBits(ThreadContext *tc) const
Definition: isa.cc:2136
static unsigned getCurSveVecLenInBits(ThreadContext *tc)
Bitfield< 17 > os
Definition: misc.hh:805
Fault checkFPAdvSIMDEnabled64(ThreadContext *tc, CPSR cpsr, CPACR cpacr) const
Check an Advaned SIMD access against CPACR_EL1, CPTR_EL2, and CPTR_EL3.
Definition: static_inst.cc:686
ExceptionLevel
Definition: types.hh:585
static bool haveEL(ThreadContext *tc, ExceptionLevel el)
Return true if the system implements a specific exception level.
Definition: system.cc:250
Fault undefinedFault32(ThreadContext *tc, ExceptionLevel el) const
UNDEFINED behaviour in AArch32.
Definition: static_inst.cc:933
ConditionCode
Definition: ccregs.hh:64
Bitfield< 3, 0 > rm
Definition: types.hh:128
void printVecPredReg(std::ostream &os, RegIndex reg_idx) const
Definition: static_inst.cc:355
bool ELIs64(ThreadContext *tc, ExceptionLevel el)
Definition: utility.cc:333
const ExtMachInst machInst
The binary machine instruction.
Definition: static_inst.hh:229
uint8_t type
Definition: inet.hh:333
Bitfield< 3, 2 > el
The ExecContext is an abstract base class the provides the interface used by the ISA to manipulate th...
Definition: exec_context.hh:73
Bitfield< 4 > pc
Fault checkForWFxTrap64(ThreadContext *tc, ExceptionLevel tgtEl, bool isWfe) const
Check if WFE/WFI instruction execution in aarch64 should be trapped.
Definition: static_inst.cc:842
Fault sveAccessTrap(ExceptionLevel el) const
Trap an access to SVE registers due to access control bits.
Definition: static_inst.cc:972
Bitfield< 4 > s
uint16_t RegIndex
Definition: types.hh:42
const int ReturnAddressReg
Definition: registers.hh:117
void printCondition(std::ostream &os, unsigned code, bool noImplicit=false) const
Definition: static_inst.cc:413
const char *const ccRegName[NUM_CCREGS]
Definition: ccregs.hh:55
const int PCReg
Definition: registers.hh:118
const int StackPointerReg
Definition: registers.hh:116
void printVecReg(std::ostream &os, RegIndex reg_idx, bool isSveVecReg=false) const
Definition: static_inst.cc:348
const int FramePointerReg
Definition: registers.hh:115
void printIntReg(std::ostream &os, RegIndex reg_idx, uint8_t opWidth=0) const
Print a register name for disassembly given the unique dependence tag number (FP or int)...
Definition: static_inst.cc:296
Bitfield< 51, 12 > base
Definition: pagetable.hh:142
int64_t shiftReg64(uint64_t base, uint64_t shiftAmt, ArmShiftType type, uint8_t width) const
Definition: static_inst.cc:92
bool findNearestSymbol(Addr addr, std::string &symbol, Addr &symaddr, Addr &nextaddr) const
Find the nearest symbol equal to or less than the supplied address (e.g., the label for the enclosing...
Definition: symtab.hh:116
static ExceptionLevel opModeToEL(OperatingMode mode)
Definition: types.hh:690
Fault softwareBreakpoint32(ExecContext *xc, uint16_t imm) const
Trigger a Software Breakpoint.
Definition: static_inst.cc:630
Bitfield< 19, 16 > rn
Definition: types.hh:123
Bitfield< 18, 16 > len
bool ELIs32(ThreadContext *tc, ExceptionLevel el)
Definition: utility.cc:339
void printShiftOperand(std::ostream &os, IntRegIndex rm, bool immShift, uint32_t shiftAmt, IntRegIndex rs, ArmShiftType type) const
Definition: static_inst.cc:493
static bool illegalExceptionReturn(ThreadContext *tc, CPSR cpsr, CPSR spsr)
Bitfield< 21 > ss
std::pair< bool, bool > ELUsingAArch32K(ThreadContext *tc, ExceptionLevel el)
This function checks whether selected EL provided as an argument is using the AArch32 ISA...
Definition: utility.cc:357
bool haveVirtualization() const
Returns true if this system implements the virtualization Extensions.
Definition: system.hh:194
virtual BaseISA * getIsaPtr()=0
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
Bitfield< 7, 0 > imm
Definition: types.hh:142
Fault checkSETENDEnabled(ThreadContext *tc, CPSR cpsr) const
Check if SETEND instruction execution in aarch32 should be trapped.
Definition: static_inst.cc:901
int64_t extendReg64(uint64_t base, ArmExtendType type, uint64_t shiftAmt, uint8_t width) const
Definition: static_inst.cc:131
void printMiscReg(std::ostream &os, RegIndex reg_idx) const
Definition: static_inst.cc:367
bool shift_carry_rs(uint32_t base, uint32_t shamt, uint32_t type, uint32_t cfval) const
Definition: static_inst.cc:257
virtual RegVal readMiscRegNoEffect(RegIndex misc_reg) const =0
static bool unknownMode32(OperatingMode mode)
Definition: types.hh:745
int32_t shift_rm_rs(uint32_t base, uint32_t shamt, uint32_t type, uint32_t cfval) const
Definition: static_inst.cc:177
void printPFflags(std::ostream &os, int flag) const
Definition: static_inst.cc:331
int snsBankedIndex(MiscRegIndex reg, ThreadContext *tc)
Definition: miscregs.cc:1063
Bitfield< 23, 20 > advsimd
Bitfield< 4 > width
virtual ThreadContext * tcBase()=0
Returns a pointer to the ThreadContext.
ArmExtendType
Definition: types.hh:539
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const override
Internal function to generate disassembly string.
Definition: static_inst.cc:621
Fault disabledFault() const
Definition: static_inst.hh:365
Fault checkAdvSIMDOrFPEnabled32(ThreadContext *tc, CPSR cpsr, CPACR cpacr, NSACR nsacr, FPEXC fpexc, bool fpexc_check, bool advsimd) const
Check if a VFP/SIMD access from aarch32 should be allowed.
Definition: static_inst.cc:698
void printFloatReg(std::ostream &os, RegIndex reg_idx) const
Definition: static_inst.cc:342
Bitfield< 3, 0 > mask
Definition: types.hh:64
Fault checkFPAdvSIMDTrap64(ThreadContext *tc, CPSR cpsr) const
Check an Advaned SIMD access against CPTR_EL2 and CPTR_EL3.
Definition: static_inst.cc:668
static uint8_t getRestoredITBits(ThreadContext *tc, CPSR spsr)
bool inSecureState(ThreadContext *tc)
Definition: utility.cc:195
T bits(T val, int first, int last)
Extract the bitfield from position &#39;first&#39; to &#39;last&#39; (inclusive) from &#39;val&#39; and right justify it...
Definition: bitfield.hh:72
Bitfield< 9, 8 > rs
virtual RegVal readMiscReg(RegIndex misc_reg)=0
void printMemSymbol(std::ostream &os, const SymbolTable *symtab, const std::string &prefix, const Addr addr, const std::string &suffix) const
Definition: static_inst.cc:476
Fault trapWFx(ThreadContext *tc, CPSR cpsr, SCR scr, bool isWfe) const
WFE/WFI trapping helper function.
Definition: static_inst.cc:874
std::shared_ptr< FaultBase > Fault
Definition: types.hh:240
void printCCReg(std::ostream &os, RegIndex reg_idx) const
Definition: static_inst.cc:361
bool generalExceptionsToAArch64(ThreadContext *tc, ExceptionLevel pstateEL) const
Return true if exceptions normally routed to EL1 are being handled at an Exception level using AArch6...
ArmShiftType
Definition: types.hh:531
void printTarget(std::ostream &os, Addr target, const SymbolTable *symtab) const
Definition: static_inst.cc:395
void printDataInst(std::ostream &os, bool withImm) const
Bitfield< 8 > sed
Fault advSIMDFPAccessTrap64(ExceptionLevel el) const
Trap an access to Advanced SIMD or FP registers due to access control bits.
Definition: static_inst.cc:648

Generated on Fri Feb 28 2020 16:26:57 for gem5 by doxygen 1.8.13